diff --git a/src/BackOffice.BFF.Application/Common/Interfaces/IApplicationContractContext.cs b/src/BackOffice.BFF.Application/Common/Interfaces/IApplicationContractContext.cs index 494169d..89562dd 100644 --- a/src/BackOffice.BFF.Application/Common/Interfaces/IApplicationContractContext.cs +++ b/src/BackOffice.BFF.Application/Common/Interfaces/IApplicationContractContext.cs @@ -8,6 +8,7 @@ using CMSMicroservice.Protobuf.Protos.Products; using CMSMicroservice.Protobuf.Protos.ProductImages; using CMSMicroservice.Protobuf.Protos.ProductGallerys; using CMSMicroservice.Protobuf.Protos.Category; +using CMSMicroservice.Protobuf.Protos.PruductCategory; using FMSMicroservice.Protobuf.Protos.FileInfo; namespace BackOffice.BFF.Application.Common.Interfaces; @@ -24,6 +25,7 @@ public interface IApplicationContractContext ProductGallerysContract.ProductGallerysContractClient ProductGallerys { get; } RoleContract.RoleContractClient Roles { get; } CategoryContract.CategoryContractClient Categories { get; } + PruductCategoryContract.PruductCategoryContractClient ProductCategories { get; } UserAddressContract.UserAddressContractClient UserAddress { get; } UserContract.UserContractClient Users { get; } UserOrderContract.UserOrderContractClient UserOrders { get; } diff --git a/src/BackOffice.BFF.Application/ProductsCQ/Commands/UpdateProductCategories/UpdateProductCategoriesCommandHandler.cs b/src/BackOffice.BFF.Application/ProductsCQ/Commands/UpdateProductCategories/UpdateProductCategoriesCommandHandler.cs index 802d634..3ec7813 100644 --- a/src/BackOffice.BFF.Application/ProductsCQ/Commands/UpdateProductCategories/UpdateProductCategoriesCommandHandler.cs +++ b/src/BackOffice.BFF.Application/ProductsCQ/Commands/UpdateProductCategories/UpdateProductCategoriesCommandHandler.cs @@ -1,4 +1,5 @@ using BackOffice.BFF.Application.Common.Interfaces; +using CMSPruductCategory = CMSMicroservice.Protobuf.Protos.PruductCategory; namespace BackOffice.BFF.Application.ProductsCQ.Commands.UpdateProductCategories; @@ -13,9 +14,49 @@ public class UpdateProductCategoriesCommandHandler : IRequestHandler Handle(UpdateProductCategoriesCommand request, CancellationToken cancellationToken) { - // Stub: until CMS Category services are available via the protobuf package, - // this handler is a no-op to keep the pipeline consistent. - await Task.CompletedTask; + var targetIds = request.CategoryIds?.ToHashSet() ?? new HashSet(); + + // Load existing product-category relations + var existingRequest = new CMSPruductCategory.GetAllPruductCategoryByFilterRequest + { + Filter = new CMSPruductCategory.GetAllPruductCategoryByFilterFilter + { + ProductId = request.ProductId + }, + PaginationState = new CMSMicroservice.Protobuf.Protos.PaginationState + { + PageNumber = 1, + PageSize = 1000 + } + }; + + var existingResponse = await _context.ProductCategories.GetAllPruductCategoryByFilterAsync(existingRequest, cancellationToken: cancellationToken); + var existing = existingResponse.Models ?? new(); + + var existingIds = existing.Select(x => x.CategoryId).ToHashSet(); + + // Determine which relations to add and which to remove + var toAdd = targetIds.Except(existingIds).ToList(); + var toRemove = existing.Where(x => !targetIds.Contains(x.CategoryId)).ToList(); + + foreach (var categoryId in toAdd) + { + var createRequest = new CMSPruductCategory.CreateNewPruductCategoryRequest + { + ProductId = request.ProductId, + CategoryId = categoryId + }; + + await _context.ProductCategories.CreateNewPruductCategoryAsync(createRequest, cancellationToken: cancellationToken); + } + + foreach (var rel in toRemove) + { + await _context.ProductCategories.DeletePruductCategoryAsync( + new CMSPruductCategory.DeletePruductCategoryRequest { Id = rel.Id }, + cancellationToken: cancellationToken); + } + return Unit.Value; } } diff --git a/src/BackOffice.BFF.Application/ProductsCQ/Queries/GetCategories/GetCategoriesQueryHandler.cs b/src/BackOffice.BFF.Application/ProductsCQ/Queries/GetCategories/GetCategoriesQueryHandler.cs index d7cb1c7..977706f 100644 --- a/src/BackOffice.BFF.Application/ProductsCQ/Queries/GetCategories/GetCategoriesQueryHandler.cs +++ b/src/BackOffice.BFF.Application/ProductsCQ/Queries/GetCategories/GetCategoriesQueryHandler.cs @@ -1,20 +1,67 @@ using BackOffice.BFF.Application.Common.Interfaces; +using CMSCategory = CMSMicroservice.Protobuf.Protos.Category; +using CMSPruductCategory = CMSMicroservice.Protobuf.Protos.PruductCategory; namespace BackOffice.BFF.Application.ProductsCQ.Queries.GetCategories; public class GetCategoriesQueryHandler : IRequestHandler { + private readonly IApplicationContractContext _context; + public GetCategoriesQueryHandler(IApplicationContractContext context) { - // context is currently unused; reserved for future CMS integration + _context = context; } public async Task Handle(GetCategoriesQuery request, CancellationToken cancellationToken) { - // Stub implementation: returns empty list. - // When CMS protobuf package with Category support is available, - // this handler can be updated to call Category and PruductCategory services. - await Task.CompletedTask; - return new GetCategoriesResponseDto(); + // Load all categories + var categoryRequest = new CMSCategory.GetAllCategoryByFilterRequest + { + Filter = new CMSCategory.GetAllCategoryByFilterFilter(), + PaginationState = new CMSMicroservice.Protobuf.Protos.PaginationState + { + PageNumber = 1, + PageSize = 1000 + } + }; + + var categoriesResponse = await _context.Categories.GetAllCategoryByFilterAsync(categoryRequest, cancellationToken: cancellationToken); + var categories = categoriesResponse.Models ?? new(); + + // Load existing product-category relations for this product + var productCategoryRequest = new CMSPruductCategory.GetAllPruductCategoryByFilterRequest + { + Filter = new CMSPruductCategory.GetAllPruductCategoryByFilterFilter + { + ProductId = request.ProductId + }, + PaginationState = new CMSMicroservice.Protobuf.Protos.PaginationState + { + PageNumber = 1, + PageSize = 1000 + } + }; + + var productCategoriesResponse = await _context.ProductCategories.GetAllPruductCategoryByFilterAsync(productCategoryRequest, cancellationToken: cancellationToken); + var productCategories = productCategoriesResponse.Models ?? new(); + + var selectedIds = productCategories + .Select(pc => pc.CategoryId) + .ToHashSet(); + + var result = new GetCategoriesResponseDto + { + Items = categories + .Select(c => new CategoryItemDto + { + Id = c.Id, + Title = c.Title, + Selected = selectedIds.Contains(c.Id) + }) + .ToList() + }; + + return result; } } diff --git a/src/BackOffice.BFF.Infrastructure/Services/ApplicationContractContext.cs b/src/BackOffice.BFF.Infrastructure/Services/ApplicationContractContext.cs index 298f8da..1e5c3f5 100644 --- a/src/BackOffice.BFF.Infrastructure/Services/ApplicationContractContext.cs +++ b/src/BackOffice.BFF.Infrastructure/Services/ApplicationContractContext.cs @@ -9,6 +9,7 @@ using CMSMicroservice.Protobuf.Protos.Products; using CMSMicroservice.Protobuf.Protos.ProductImages; using CMSMicroservice.Protobuf.Protos.ProductGallerys; using CMSMicroservice.Protobuf.Protos.Category; +using CMSMicroservice.Protobuf.Protos.PruductCategory; using FMSMicroservice.Protobuf.Protos.FileInfo; using Microsoft.Extensions.DependencyInjection; @@ -48,6 +49,7 @@ public class ApplicationContractContext : IApplicationContractContext public ProductGallerysContract.ProductGallerysContractClient ProductGallerys => GetService(); public RoleContract.RoleContractClient Roles => GetService(); public CategoryContract.CategoryContractClient Categories => GetService(); + public PruductCategoryContract.PruductCategoryContractClient ProductCategories => GetService(); public UserAddressContract.UserAddressContractClient UserAddress => GetService(); public UserContract.UserContractClient Users => GetService(); public UserOrderContract.UserOrderContractClient UserOrders => GetService();