Add Category protobuf and CQRS implementation

This commit is contained in:
masoodafar-web
2025-11-27 04:18:35 +03:30
parent c3193824c4
commit ad8d166476
27 changed files with 965 additions and 8 deletions
@@ -7,7 +7,7 @@
<ItemGroup>
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.2.2" />
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.119" />
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.128" />
<PackageReference Include="Mapster" Version="7.3.0" />
<PackageReference Include="Mapster.DependencyInjection" Version="1.0.0" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
@@ -0,0 +1,13 @@
namespace BackOffice.BFF.Application.CategoryCQ.Commands.CreateNewCategory;
public record CreateNewCategoryCommand : IRequest<CreateNewCategoryResponseDto>
{
public string Name { get; init; } = string.Empty;
public string Title { get; init; } = string.Empty;
public string? Description { get; init; }
public string? ImagePath { get; init; }
public long? ParentId { get; init; }
public bool IsActive { get; init; }
public int SortOrder { get; init; }
}
@@ -0,0 +1,22 @@
using BackOffice.BFF.Application.Common.Interfaces;
using CMSCategory = CMSMicroservice.Protobuf.Protos.Category;
namespace BackOffice.BFF.Application.CategoryCQ.Commands.CreateNewCategory;
public class CreateNewCategoryCommandHandler : IRequestHandler<CreateNewCategoryCommand, CreateNewCategoryResponseDto>
{
private readonly IApplicationContractContext _context;
public CreateNewCategoryCommandHandler(IApplicationContractContext context)
{
_context = context;
}
public async Task<CreateNewCategoryResponseDto> Handle(CreateNewCategoryCommand request, CancellationToken cancellationToken)
{
var cmsRequest = request.Adapt<CMSCategory.CreateNewCategoryRequest>();
var response = await _context.Categories.CreateNewCategoryAsync(cmsRequest, cancellationToken: cancellationToken);
return response.Adapt<CreateNewCategoryResponseDto>();
}
}
@@ -0,0 +1,24 @@
namespace BackOffice.BFF.Application.CategoryCQ.Commands.CreateNewCategory;
public class CreateNewCategoryCommandValidator : AbstractValidator<CreateNewCategoryCommand>
{
public CreateNewCategoryCommandValidator()
{
RuleFor(x => x.Name).NotEmpty();
RuleFor(x => x.Title).NotEmpty();
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(
ValidationContext<CreateNewCategoryCommand>.CreateWithOptions(
(CreateNewCategoryCommand)model,
x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}
@@ -0,0 +1,7 @@
namespace BackOffice.BFF.Application.CategoryCQ.Commands.CreateNewCategory;
public class CreateNewCategoryResponseDto
{
public long Id { get; set; }
}
@@ -0,0 +1,7 @@
namespace BackOffice.BFF.Application.CategoryCQ.Commands.DeleteCategory;
public record DeleteCategoryCommand : IRequest<Unit>
{
public long Id { get; init; }
}
@@ -0,0 +1,22 @@
using BackOffice.BFF.Application.Common.Interfaces;
using CMSCategory = CMSMicroservice.Protobuf.Protos.Category;
namespace BackOffice.BFF.Application.CategoryCQ.Commands.DeleteCategory;
public class DeleteCategoryCommandHandler : IRequestHandler<DeleteCategoryCommand, Unit>
{
private readonly IApplicationContractContext _context;
public DeleteCategoryCommandHandler(IApplicationContractContext context)
{
_context = context;
}
public async Task<Unit> Handle(DeleteCategoryCommand request, CancellationToken cancellationToken)
{
var cmsRequest = request.Adapt<CMSCategory.DeleteCategoryRequest>();
await _context.Categories.DeleteCategoryAsync(cmsRequest, cancellationToken: cancellationToken);
return Unit.Value;
}
}
@@ -0,0 +1,23 @@
namespace BackOffice.BFF.Application.CategoryCQ.Commands.DeleteCategory;
public class DeleteCategoryCommandValidator : AbstractValidator<DeleteCategoryCommand>
{
public DeleteCategoryCommandValidator()
{
RuleFor(x => x.Id).GreaterThan(0);
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(
ValidationContext<DeleteCategoryCommand>.CreateWithOptions(
(DeleteCategoryCommand)model,
x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}
@@ -0,0 +1,14 @@
namespace BackOffice.BFF.Application.CategoryCQ.Commands.UpdateCategory;
public record UpdateCategoryCommand : IRequest<Unit>
{
public long Id { get; init; }
public string Name { get; init; } = string.Empty;
public string Title { get; init; } = string.Empty;
public string? Description { get; init; }
public string? ImagePath { get; init; }
public long? ParentId { get; init; }
public bool IsActive { get; init; }
public int SortOrder { get; init; }
}
@@ -0,0 +1,22 @@
using BackOffice.BFF.Application.Common.Interfaces;
using CMSCategory = CMSMicroservice.Protobuf.Protos.Category;
namespace BackOffice.BFF.Application.CategoryCQ.Commands.UpdateCategory;
public class UpdateCategoryCommandHandler : IRequestHandler<UpdateCategoryCommand, Unit>
{
private readonly IApplicationContractContext _context;
public UpdateCategoryCommandHandler(IApplicationContractContext context)
{
_context = context;
}
public async Task<Unit> Handle(UpdateCategoryCommand request, CancellationToken cancellationToken)
{
var cmsRequest = request.Adapt<CMSCategory.UpdateCategoryRequest>();
await _context.Categories.UpdateCategoryAsync(cmsRequest, cancellationToken: cancellationToken);
return Unit.Value;
}
}
@@ -0,0 +1,25 @@
namespace BackOffice.BFF.Application.CategoryCQ.Commands.UpdateCategory;
public class UpdateCategoryCommandValidator : AbstractValidator<UpdateCategoryCommand>
{
public UpdateCategoryCommandValidator()
{
RuleFor(x => x.Id).GreaterThan(0);
RuleFor(x => x.Name).NotEmpty();
RuleFor(x => x.Title).NotEmpty();
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(
ValidationContext<UpdateCategoryCommand>.CreateWithOptions(
(UpdateCategoryCommand)model,
x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}
@@ -0,0 +1,23 @@
namespace BackOffice.BFF.Application.CategoryCQ.Queries.GetAllCategoryByFilter;
using BackOffice.BFF.Application.Common.Models;
public record GetAllCategoryByFilterQuery : IRequest<GetAllCategoryByFilterResponseDto>
{
public PaginationState? PaginationState { get; init; }
public string? SortBy { get; init; }
public GetAllCategoryByFilterFilter? Filter { get; init; }
}
public class GetAllCategoryByFilterFilter
{
public long? Id { get; set; }
public string? Name { get; set; }
public string? Title { get; set; }
public string? Description { get; set; }
public string? ImagePath { get; set; }
public long? ParentId { get; set; }
public bool? IsActive { get; set; }
public int? SortOrder { get; set; }
}
@@ -0,0 +1,22 @@
using BackOffice.BFF.Application.Common.Interfaces;
using CMSCategory = CMSMicroservice.Protobuf.Protos.Category;
namespace BackOffice.BFF.Application.CategoryCQ.Queries.GetAllCategoryByFilter;
public class GetAllCategoryByFilterQueryHandler : IRequestHandler<GetAllCategoryByFilterQuery, GetAllCategoryByFilterResponseDto>
{
private readonly IApplicationContractContext _context;
public GetAllCategoryByFilterQueryHandler(IApplicationContractContext context)
{
_context = context;
}
public async Task<GetAllCategoryByFilterResponseDto> Handle(GetAllCategoryByFilterQuery request, CancellationToken cancellationToken)
{
var cmsRequest = request.Adapt<CMSCategory.GetAllCategoryByFilterRequest>();
var response = await _context.Categories.GetAllCategoryByFilterAsync(cmsRequest, cancellationToken: cancellationToken);
return response.Adapt<GetAllCategoryByFilterResponseDto>();
}
}
@@ -0,0 +1,22 @@
namespace BackOffice.BFF.Application.CategoryCQ.Queries.GetAllCategoryByFilter;
using BackOffice.BFF.Application.Common.Models;
public class GetAllCategoryByFilterResponseDto
{
public MetaData MetaData { get; set; } = new();
public List<GetAllCategoryByFilterResponseModel>? Models { get; set; }
}
public class GetAllCategoryByFilterResponseModel
{
public long Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Title { get; set; } = string.Empty;
public string? Description { get; set; }
public string? ImagePath { get; set; }
public long? ParentId { get; set; }
public bool IsActive { get; set; }
public int SortOrder { get; set; }
}
@@ -0,0 +1,7 @@
namespace BackOffice.BFF.Application.CategoryCQ.Queries.GetCategory;
public record GetCategoryQuery : IRequest<GetCategoryResponseDto>
{
public long Id { get; init; }
}
@@ -0,0 +1,22 @@
using BackOffice.BFF.Application.Common.Interfaces;
using CMSCategory = CMSMicroservice.Protobuf.Protos.Category;
namespace BackOffice.BFF.Application.CategoryCQ.Queries.GetCategory;
public class GetCategoryQueryHandler : IRequestHandler<GetCategoryQuery, GetCategoryResponseDto>
{
private readonly IApplicationContractContext _context;
public GetCategoryQueryHandler(IApplicationContractContext context)
{
_context = context;
}
public async Task<GetCategoryResponseDto> Handle(GetCategoryQuery request, CancellationToken cancellationToken)
{
var cmsRequest = request.Adapt<CMSCategory.GetCategoryRequest>();
var response = await _context.Categories.GetCategoryAsync(cmsRequest, cancellationToken: cancellationToken);
return response.Adapt<GetCategoryResponseDto>();
}
}
@@ -0,0 +1,14 @@
namespace BackOffice.BFF.Application.CategoryCQ.Queries.GetCategory;
public class GetCategoryResponseDto
{
public long Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Title { get; set; } = string.Empty;
public string? Description { get; set; }
public string? ImagePath { get; set; }
public long? ParentId { get; set; }
public bool IsActive { get; set; }
public int SortOrder { get; set; }
}
@@ -7,6 +7,7 @@ using CMSMicroservice.Protobuf.Protos.UserRole;
using CMSMicroservice.Protobuf.Protos.Products;
using CMSMicroservice.Protobuf.Protos.ProductImages;
using CMSMicroservice.Protobuf.Protos.ProductGallerys;
using CMSMicroservice.Protobuf.Protos.Category;
using FMSMicroservice.Protobuf.Protos.FileInfo;
namespace BackOffice.BFF.Application.Common.Interfaces;
@@ -22,6 +23,7 @@ public interface IApplicationContractContext
ProductImagesContract.ProductImagesContractClient ProductImages { get; }
ProductGallerysContract.ProductGallerysContractClient ProductGallerys { get; }
RoleContract.RoleContractClient Roles { get; }
CategoryContract.CategoryContractClient Categories { get; }
UserAddressContract.UserAddressContractClient UserAddress { get; }
UserContract.UserContractClient Users { get; }
UserOrderContract.UserOrderContractClient UserOrders { get; }