Add category support to products commands and queries

This commit is contained in:
masoodafar-web
2025-11-27 05:39:26 +03:30
parent e2bd966098
commit 23ac9f77a1
9 changed files with 135 additions and 10 deletions

View File

@@ -25,5 +25,7 @@ public record CreateNewProductsCommand : IRequest<CreateNewProductsResponseDto>
public int ViewCount { get; init; }
//
public int RemainingCount { get; init; }
// لیست شناسه دسته‌بندی‌های محصول
public ICollection<long>? CategoryIds { get; init; }
}
}

View File

@@ -1,3 +1,4 @@
using CMSMicroservice.Domain.Entities;
using CMSMicroservice.Domain.Events;
namespace CMSMicroservice.Application.ProductsCQ.Commands.CreateNewProducts;
public class CreateNewProductsCommandHandler : IRequestHandler<CreateNewProductsCommand, CreateNewProductsResponseDto>
@@ -14,8 +15,30 @@ public class CreateNewProductsCommandHandler : IRequestHandler<CreateNewProducts
{
var entity = request.Adapt<Products>();
await _context.Productss.AddAsync(entity, cancellationToken);
entity.AddDomainEvent(new CreateNewProductsEvent(entity));
await _context.SaveChangesAsync(cancellationToken);
// ثبت دسته‌بندی‌های محصول (در صورت ارسال)
if (request.CategoryIds is { Count: > 0 })
{
var distinctCategoryIds = request.CategoryIds
.Where(id => id > 0)
.Distinct()
.ToList();
foreach (var categoryId in distinctCategoryIds)
{
var rel = new PruductCategory
{
ProductId = entity.Id,
CategoryId = categoryId
};
await _context.PruductCategorys.AddAsync(rel, cancellationToken);
}
await _context.SaveChangesAsync(cancellationToken);
}
entity.AddDomainEvent(new CreateNewProductsEvent(entity));
return entity.Adapt<CreateNewProductsResponseDto>();
}
}

View File

@@ -27,5 +27,7 @@ public record UpdateProductsCommand : IRequest<Unit>
public int ViewCount { get; init; }
//
public int RemainingCount { get; init; }
// لیست شناسه دسته‌بندی‌های محصول
public ICollection<long>? CategoryIds { get; init; }
}
}

View File

@@ -1,4 +1,8 @@
using CMSMicroservice.Application.Common.Exceptions;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Entities;
using CMSMicroservice.Domain.Events;
using Microsoft.EntityFrameworkCore;
namespace CMSMicroservice.Application.ProductsCQ.Commands.UpdateProducts;
public class UpdateProductsCommandHandler : IRequestHandler<UpdateProductsCommand, Unit>
{
@@ -12,9 +16,47 @@ public class UpdateProductsCommandHandler : IRequestHandler<UpdateProductsComman
public async Task<Unit> Handle(UpdateProductsCommand request, CancellationToken cancellationToken)
{
var entity = await _context.Productss
.FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken) ?? throw new NotFoundException(nameof(Products), request.Id);
.FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken)
?? throw new NotFoundException(nameof(Products), request.Id);
request.Adapt(entity);
_context.Productss.Update(entity);
// به‌روزرسانی دسته‌بندی‌های محصول در صورت ارسال CategoryIds
if (request.CategoryIds is not null)
{
var targetIds = (request.CategoryIds ?? Array.Empty<long>())
.Where(id => id > 0)
.Distinct()
.ToHashSet();
var existingRelations = await _context.PruductCategorys
.Where(x => x.ProductId == entity.Id)
.ToListAsync(cancellationToken);
var existingIds = existingRelations
.Select(x => x.CategoryId)
.ToHashSet();
var toAdd = targetIds.Except(existingIds).ToList();
var toRemove = existingRelations.Where(x => !targetIds.Contains(x.CategoryId)).ToList();
foreach (var categoryId in toAdd)
{
var rel = new PruductCategory
{
ProductId = entity.Id,
CategoryId = categoryId
};
await _context.PruductCategorys.AddAsync(rel, cancellationToken);
}
if (toRemove.Count > 0)
{
_context.PruductCategorys.RemoveRange(toRemove);
}
}
entity.AddDomainEvent(new UpdateProductsEvent(entity));
await _context.SaveChangesAsync(cancellationToken);
return Unit.Value;

View File

@@ -32,11 +32,35 @@ public class GetAllProductsByFilterQueryHandler : IRequestHandler<GetAllProducts
.Where(x => request.Filter.RemainingCount == null || x.RemainingCount == request.Filter.RemainingCount)
;
}
var meta = await query.GetMetaData(request.PaginationState, cancellationToken);
var models = await query
.PaginatedListAsync(paginationState: request.PaginationState)
.Select(x => new GetAllProductsByFilterResponseModel
{
Id = x.Id,
Title = x.Title,
Description = x.Description,
ShortInfomation = x.ShortInfomation,
FullInformation = x.FullInformation,
Price = x.Price,
Discount = x.Discount,
Rate = x.Rate,
ImagePath = x.ImagePath,
ThumbnailPath = x.ThumbnailPath,
SaleCount = x.SaleCount,
ViewCount = x.ViewCount,
RemainingCount = x.RemainingCount,
CategoryIds = x.PruductCategorys
.Select(pc => pc.CategoryId)
.ToList()
})
.ToListAsync(cancellationToken);
return new GetAllProductsByFilterResponseDto
{
MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
Models = await query.PaginatedListAsync(paginationState: request.PaginationState)
.ProjectToType<GetAllProductsByFilterResponseModel>().ToListAsync(cancellationToken)
MetaData = meta,
Models = models
};
}
}

View File

@@ -6,7 +6,9 @@ public class GetAllProductsByFilterResponseDto
//مدل خروجی
public List<GetAllProductsByFilterResponseModel>? Models { get; set; }
}public class GetAllProductsByFilterResponseModel
}
public class GetAllProductsByFilterResponseModel
{
//
public long Id { get; set; }
@@ -34,4 +36,6 @@ public class GetAllProductsByFilterResponseDto
public int ViewCount { get; set; }
//
public int RemainingCount { get; set; }
// لیست شناسه دسته‌بندی‌های محصول
public List<long> CategoryIds { get; set; } = new();
}

View File

@@ -14,7 +14,25 @@ public class GetProductsQueryHandler : IRequestHandler<GetProductsQuery, GetProd
var response = await _context.Productss
.AsNoTracking()
.Where(x => x.Id == request.Id)
.ProjectToType<GetProductsResponseDto>()
.Select(x => new GetProductsResponseDto
{
Id = x.Id,
Title = x.Title,
Description = x.Description,
ShortInfomation = x.ShortInfomation,
FullInformation = x.FullInformation,
Price = x.Price,
Discount = x.Discount,
Rate = x.Rate,
ImagePath = x.ImagePath,
ThumbnailPath = x.ThumbnailPath,
SaleCount = x.SaleCount,
ViewCount = x.ViewCount,
RemainingCount = x.RemainingCount,
CategoryIds = x.PruductCategorys
.Select(pc => pc.CategoryId)
.ToList()
})
.FirstOrDefaultAsync(cancellationToken);
return response ?? throw new NotFoundException(nameof(Products), request.Id);

View File

@@ -27,5 +27,7 @@ public class GetProductsResponseDto
public int ViewCount { get; set; }
//
public int RemainingCount { get; set; }
// لیست شناسه دسته‌بندی‌های محصول
public List<long> CategoryIds { get; set; } = new();
}
}