Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions EcommerceApi.DiegoPetrola/Context/EcommerceDbContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using EcommerceApi.Models;
using Microsoft.EntityFrameworkCore;

namespace EcommerceApi.Context;

public class EcommerceDbContext(DbContextOptions<EcommerceDbContext> options) : DbContext(options)
{
public DbSet<Sale> Sales { get; set; }
public DbSet<SaleItem> SaleItems { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.Entity<Sale>()
.HasMany(s => s.SaleItems)
.WithOne(si => si.Sale)
.HasForeignKey(si => si.SaleId)
.OnDelete(DeleteBehavior.Cascade);

modelBuilder.Entity<Product>()
.HasOne(p => p.Category)
.WithMany(c => c.Products)
.HasForeignKey(p => p.CategoryId)
.OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<Product>()
.HasMany(p => p.SaleItems)
.WithOne(si => si.Product)
.HasForeignKey(si => si.ProductId)
.OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<Product>()
.Property(p => p.Price)
.HasPrecision(18, 2);

modelBuilder.Entity<SaleItem>()
.Property(p => p.ProductPrice)
.HasPrecision(18, 2);

modelBuilder.Entity<SaleItem>()
.HasKey(si => new { si.SaleId, si.ProductId });

modelBuilder.Entity<SaleItem>()
.HasOne(si => si.Product)
.WithMany(p => p.SaleItems)
.IsRequired(false);

modelBuilder.Entity<Category>()
.HasIndex(c => c.Name)
.IsUnique();

modelBuilder.Entity<Product>().HasQueryFilter(p => !p.IsDeleted);
modelBuilder.Entity<Sale>().HasQueryFilter(s => !s.IsDeleted);
modelBuilder.Entity<SaleItem>().HasQueryFilter(si => !si.Sale.IsDeleted);
}
}
47 changes: 47 additions & 0 deletions EcommerceApi.DiegoPetrola/Controllers/CategoriesController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using EcommerceApi.Models.DTOs;
using EcommerceApi.Services;
using Microsoft.AspNetCore.Mvc;

namespace EcommerceApi.Controllers;

[ApiController]
[Route("api/[controller]")]
public class CategoriesController(CategoriesService service) : ControllerBase
{
[HttpGet]
public async Task<ActionResult<IEnumerable<CategoryDto>>> GetCategories()
{
var res = await service.GetCategories();
return this.ToActionResult(res);
}

[HttpGet("{id}")]
public async Task<ActionResult<CategoryDto>> GetCategory(int id)
{
var res = await service.GetCategory(id);
return this.ToActionResult(res);
}

[HttpPost]
public async Task<ActionResult<CategoryDto>> CreateCategory(CreateCategoryDto dto)
{
var res = await service.CreateCategory(dto);
return this.ToActionResult(res);
}

[HttpPut("{id}")]
public async Task<ActionResult> UpdateCategory(int id, CategoryDto dto)
{
if (dto.Id != id)
return BadRequest();
var res = await service.UpdateCategory(dto);
return this.ToActionResult(res);
}

[HttpDelete("{id}")]
public async Task<ActionResult> DeleteCategory(int id)
{
var res = await service.DeleteCategory(id);
return this.ToActionResult(res);
}
}
50 changes: 50 additions & 0 deletions EcommerceApi.DiegoPetrola/Controllers/ProductsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using EcommerceApi.Models.DTOs;
using EcommerceApi.Services;
using EcommerceApi.Utils;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;

namespace EcommerceApi.Controllers;

[ApiController]
[Route("api/[controller]")]
public class ProductsController(ProductsService service, IOptions<PaginationSettings> options) : ControllerBase
{
[HttpGet]
public async Task<ActionResult<List<ProductDto>>> GetProducts([FromQuery] int? pageSize, [FromQuery] int pageNumber = 0)
{
int finalSize = Math.Min(pageSize ?? options.Value.DefaultPageSize, options.Value.MaxPageSize);
var res = await service.GetProducts(pageNumber, finalSize);
return this.ToActionResult(res);
}

[HttpGet("{id}")]
public async Task<ActionResult<ProductDto>> GetProductById(int id)
{
var res = await service.GetProduct(id);
return this.ToActionResult(res);
}

[HttpPost]
public async Task<ActionResult<ProductDto>> CreateProduct(CreateProductDto dto)
{
var res = await service.CreateProduct(dto);
return this.ToActionResult(res);
}

[HttpDelete("{id}")]
public async Task<ActionResult<ProductDto>> DeleteProduct(int id)
{
var res = await service.SoftDeleteProduct(id);
return this.ToActionResult(res);
}

[HttpPut("{id}")]
public async Task<ActionResult<ProductDto>> UpdateProduct(int id, ProductDto dto)
{
if (id != dto.Id)
return BadRequest();
var res = await service.UpdateProduct(dto);
return this.ToActionResult(res);
}
}
36 changes: 36 additions & 0 deletions EcommerceApi.DiegoPetrola/Controllers/ResultExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using EcommerceApi.Models;
using EcommerceApi.Models.DTOs;
using EcommerceApi.Results;
using Microsoft.AspNetCore.Mvc;

namespace EcommerceApi.Controllers;

public static class ResultExtensions
{
public static ActionResult ToActionResult<T>(this ControllerBase controller, Result<T> res)
{
if (res.IsSuccess)
return controller.Ok(res.Value);

return res.Error.ErrorType switch
{
ErrorType.NotFound => controller.NotFound(res.Error.Error),
ErrorType.Invalid => controller.BadRequest(res.Error.Error),
_ => controller.Problem(res.Error.Error)
};
}

public static SaleDto ToSaleDto(Sale sale)
{
return new SaleDto(
sale.Id,
sale.SaleDate,
[.. sale.SaleItems.Select(si => new SaleItemDto(
si.ProductId,
si.Product.Name,
si.Quantity,
si.Product.Price))],
sale.SaleItems.Sum(si => si.Quantity * si.Product.Price)
);
}
}
41 changes: 41 additions & 0 deletions EcommerceApi.DiegoPetrola/Controllers/SalesController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using EcommerceApi.Models.DTOs;
using EcommerceApi.Services;
using EcommerceApi.Utils;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;

namespace EcommerceApi.Controllers;

[ApiController]
[Route("api/[controller]")]
public class SalesController(SalesService service, IOptions<PaginationSettings> options) : ControllerBase
{
[HttpGet("{id}")]
public async Task<ActionResult<SaleDto>> GetSale(int id)
{
var res = await service.GetSale(id);
return this.ToActionResult(res);
}

[HttpGet()]
public async Task<ActionResult<List<SaleDto>>> GetSalePage([FromQuery] int? pageSize, [FromQuery] int pageNumber = 0)
{
int finalSize = Math.Min(pageSize ?? options.Value.DefaultPageSize, options.Value.MaxPageSize);
var res = await service.GetSalesByPage(pageNumber, finalSize);
return this.ToActionResult(res);
}

[HttpPost]
public async Task<ActionResult<SaleDto>> CreateSale(CreateSaleDto dto)
{
var res = await service.CreateSale(dto);
return this.ToActionResult(res);
}

[HttpDelete("{id}")]
public async Task<ActionResult<SaleDto>> DeleteSale(int id)
{
var res = await service.DeleteSale(id);
return this.ToActionResult(res);
}
}
Loading