Skip to content

Commit

Permalink
Merge pull request #51 from SWD392-Domus/feature/products-management
Browse files Browse the repository at this point in the history
Feature: products management
  • Loading branch information
duykasama authored Feb 17, 2024
2 parents 9798d18 + 9d0e3ce commit 5bca3a1
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 16 deletions.
10 changes: 9 additions & 1 deletion Domus.Api/Controllers/ProductsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Domus.Api.Controllers;
[Route("api/[controller]")]
public class ProductsController : BaseApiController
{
private IProductService _productService;
private readonly IProductService _productService;

public ProductsController(IProductService productService)
{
Expand Down Expand Up @@ -69,4 +69,12 @@ public async Task<IActionResult> DeleteProduct(Guid id)
async () => await _productService.DeleteProduct(id).ConfigureAwait(false)
).ConfigureAwait(false);
}

[HttpDelete("multiple")]
public async Task<IActionResult> DeleteMultipleProducts(IEnumerable<Guid> ids)
{
return await ExecuteServiceLogic(
async () => await _productService.DeleteMultipleProducts(ids).ConfigureAwait(false)
).ConfigureAwait(false);
}
}
10 changes: 10 additions & 0 deletions Domus.DAL/Implementations/ProductRepository.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
using System.Linq.Expressions;
using Domus.DAL.Interfaces;
using Domus.Domain.Entities;
using Microsoft.EntityFrameworkCore;

namespace Domus.DAL.Implementations;

public class ProductRepository : GenericRepository<Product>, IProductRepository
{
private readonly DbSet<Product> _dbSet;
public ProductRepository(IAppDbContext dbContext) : base(dbContext)
{
_dbSet = dbContext.CreateSet<Product>();
}

public new async Task DeleteManyAsync(Expression<Func<Product, bool>> predicate)
{
var entities = _dbSet.Where(predicate);
await entities.ForEachAsync(p => p.IsDeleted = true);
}
}
2 changes: 2 additions & 0 deletions Domus.DAL/Interfaces/IProductRepository.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System.Linq.Expressions;
using Domus.Common.Interfaces;
using Domus.Domain.Entities;

namespace Domus.DAL.Interfaces;

public interface IProductRepository : IGenericRepository<Product>, IAutoRegisterable
{
new Task DeleteManyAsync(Expression<Func<Product, bool>> predicate);
}
2 changes: 2 additions & 0 deletions Domus.Domain/Dtos/Products/DtoProduct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class DtoProduct

public string? Description { get; set; }

public int TotalQuantity { get; set; }

[JsonPropertyName("category")]
public DtoProductCategory ProductCategory { get; set; } = null!;

Expand Down
4 changes: 1 addition & 3 deletions Domus.Domain/Entities/Product.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Domus.Domain.Entities;

public partial class Product : BaseEntity<Guid>
public partial class Product : DeletableEntity<Guid>
{
public Guid ProductCategoryId { get; set; }

Expand All @@ -12,8 +12,6 @@ public partial class Product : BaseEntity<Guid>

public string? Description { get; set; }

public bool? IsDeleted { get; set; }

public string? ConcurrencyStamp { get; set; }

public virtual ProductCategory ProductCategory { get; set; } = null!;
Expand Down
7 changes: 0 additions & 7 deletions Domus.Service/Implementations/ProductDetailService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Collections;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using Domus.Common.Helpers;
Expand All @@ -19,25 +18,19 @@ public class ProductDetailService : IProductDetailService
private readonly IProductRepository _productRepository;
private readonly IMapper _mapper;
private readonly IUnitOfWork _unitOfWork;
private readonly IProductPriceRepository _productPriceRepository;
private readonly IProductAttributeValueRepository _productAttributeValueRepository;
private readonly IProductAttributeRepository _productAttributeRepository;

public ProductDetailService(
IProductDetailRepository productDetailRepository,
IMapper mapper,
IUnitOfWork unitOfWork,
IProductRepository productRepository,
IProductPriceRepository productPriceRepository,
IProductAttributeValueRepository productAttributeValueRepository,
IProductAttributeRepository productAttributeRepository)
{
_productDetailRepository = productDetailRepository;
_mapper = mapper;
_unitOfWork = unitOfWork;
_productRepository = productRepository;
_productPriceRepository = productPriceRepository;
_productAttributeValueRepository = productAttributeValueRepository;
_productAttributeRepository = productAttributeRepository;
}

Expand Down
35 changes: 30 additions & 5 deletions Domus.Service/Implementations/ProductService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public async Task<ServiceActionResult> CreateProduct(CreateProductRequest reques

public async Task<ServiceActionResult> DeleteProduct(Guid id)
{
var product = await _productRepository.GetAsync(p => p.Id == id);
var product = await _productRepository.GetAsync(p => !p.IsDeleted && p.Id == id);
if (product is null)
throw new ProductNotFoundException();

Expand All @@ -60,33 +60,50 @@ public async Task<ServiceActionResult> DeleteProduct(Guid id)

public async Task<ServiceActionResult> GetAllProducts()
{
var products = await (await _productRepository.GetAllAsync()).ProjectTo<DtoProduct>(_mapper.ConfigurationProvider)
var products = await (await _productRepository.GetAllAsync())
.Where(p => !p.IsDeleted)
.ProjectTo<DtoProduct>(_mapper.ConfigurationProvider)
.ToListAsync();

foreach (var product in products)
{
product.TotalQuantity = (int)product.ProductDetails.Sum(d => d.ProductPrices.Sum(p => p.Quantity));
}

return new ServiceActionResult(true) { Data = products };
}

public async Task<ServiceActionResult> GetPaginatedProducts(BasePaginatedRequest request)
{
var queryableProducts = (await _productRepository.GetAllAsync()).ProjectTo<DtoProduct>(_mapper.ConfigurationProvider);
var queryableProducts = (await _productRepository.GetAllAsync())
.Where(p => !p.IsDeleted)
.ProjectTo<DtoProduct>(_mapper.ConfigurationProvider);
var paginatedResult = PaginationHelper.BuildPaginatedResult(queryableProducts, request.PageSize, request.PageIndex);
var products = await ((IQueryable<DtoProduct>)paginatedResult.Items!).ToListAsync();

foreach (var product in products)
{
product.TotalQuantity = (int)product.ProductDetails.Sum(d => d.ProductPrices.Sum(p => p.Quantity));
}

paginatedResult.Items = products;

return new ServiceActionResult(true) { Data = paginatedResult };
}

public async Task<ServiceActionResult> GetProduct(Guid id)
{
var product = await (await _productRepository.GetAllAsync())
.Where(p => !p.IsDeleted && p.Id == id)
.ProjectTo<DtoProductWithoutCategory>(_mapper.ConfigurationProvider)
.Where(p => p.Id == id)
.FirstOrDefaultAsync() ?? throw new ProductNotFoundException();

return new ServiceActionResult(true) { Data = product };
}

public async Task<ServiceActionResult> UpdateProduct(UpdateProductRequest request, Guid id)
{
var product = await _productRepository.GetAsync(p => p.Id == id);
var product = await _productRepository.GetAsync(p => !p.IsDeleted && p.Id == id);
if (product is null)
throw new ProductNotFoundException();
if (!await _productCategoryRepository.ExistsAsync(c => c.Id == request.ProductCategoryId))
Expand All @@ -98,4 +115,12 @@ public async Task<ServiceActionResult> UpdateProduct(UpdateProductRequest reques

return new ServiceActionResult(true);
}

public async Task<ServiceActionResult> DeleteMultipleProducts(IEnumerable<Guid> ids)
{
await _productRepository.DeleteManyAsync(p => !p.IsDeleted && ids.Contains(p.Id));
await _unitOfWork.CommitAsync();

return new ServiceActionResult(true) { Detail = "Products deleted successfully"};
}
}
1 change: 1 addition & 0 deletions Domus.Service/Interfaces/IProductService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ public interface IProductService : IAutoRegisterable
Task<ServiceActionResult> GetPaginatedProducts(BasePaginatedRequest request);
Task<ServiceActionResult> GetProduct(Guid id);
Task<ServiceActionResult> UpdateProduct(UpdateProductRequest request, Guid id);
Task<ServiceActionResult> DeleteMultipleProducts(IEnumerable<Guid> ids);
}

0 comments on commit 5bca3a1

Please sign in to comment.