feat: Implement inventory and warehouse management features
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 2m33s

- Add GetLowStockItemsResponseDto and LowStockItemDto for low stock item queries.
- Create CreateStockMovementCommand and its handler for managing stock movements.
- Implement CreateStockMovementCommandValidator for validating stock movement commands.
- Add GetStockMovementsQuery and its handler to retrieve stock movement records.
- Create GetStockMovementsResponseDto and StockMovementListDto for stock movement responses.
- Implement GetStockMovementsByInventoryItemQuery and its handler for fetching movements by inventory item.
- Add CreateWarehouseCommand and its handler for creating new warehouses.
- Implement CreateWarehouseCommandValidator for warehouse creation validation.
- Add DeleteWarehouseCommand and its handler for removing warehouses.
- Implement SetDefaultWarehouseCommand and its handler for setting a default warehouse.
- Create UpdateWarehouseCommand and its handler for updating warehouse details.
- Implement GetAllWarehousesQuery and its handler to retrieve all warehouses.
- Add GetWarehouseQuery and its handler for fetching a specific warehouse by ID.
- Implement SearchWarehousesQuery and its handler for searching warehouses based on criteria.
This commit is contained in:
masoodafar-web
2026-01-03 11:59:08 +03:30
parent 8c3d710253
commit dde4c68b2f
102 changed files with 2715 additions and 3721 deletions
@@ -1,102 +0,0 @@
using MediatR;
namespace CMSMicroservice.Application.Features.InventoryItems.Commands;
/// <summary>
/// Command برای ایجاد آیتم موجودی جدید
/// </summary>
public record CreateInventoryItemCommand : IRequest<long>
{
public long? ProductId { get; init; }
public long? DiscountProductId { get; init; }
public long WarehouseId { get; init; }
public int Quantity { get; init; }
public int MinQuantity { get; init; }
public int MaxQuantity { get; init; }
public bool IsActive { get; init; } = true;
}
/// <summary>
/// Command برای آپدیت آیتم موجودی
/// </summary>
public record UpdateInventoryItemCommand : IRequest<bool>
{
public long Id { get; init; }
public int? Quantity { get; init; }
public int? MinQuantity { get; init; }
public int? MaxQuantity { get; init; }
public long? WarehouseId { get; init; }
public bool? IsActive { get; init; }
}
/// <summary>
/// Command برای آپدیت کردن موجودی یک آیتم
/// </summary>
public record UpdateInventoryQuantityCommand : IRequest<bool>
{
public long Id { get; init; }
public int NewQuantity { get; init; }
public string? ReferenceNumber { get; init; }
public long? PerformedByUserId { get; init; }
public string? Note { get; init; }
}
/// <summary>
/// Command برای رزرو کردن موجودی
/// </summary>
public record ReserveInventoryCommand : IRequest<bool>
{
public long Id { get; init; }
public int Quantity { get; init; }
public long? OrderId { get; init; }
public long? DiscountOrderId { get; init; }
public string? ReferenceNumber { get; init; }
public long? PerformedByUserId { get; init; }
}
/// <summary>
/// Command برای آزاد کردن موجودی رزرو شده
/// </summary>
public record ReleaseReservedInventoryCommand : IRequest<bool>
{
public long Id { get; init; }
public int Quantity { get; init; }
public long? OrderId { get; init; }
public long? DiscountOrderId { get; init; }
public string? ReferenceNumber { get; init; }
public long? PerformedByUserId { get; init; }
}
/// <summary>
/// Command برای کم کردن موجودی (فروش)
/// </summary>
public record ReduceInventoryCommand : IRequest<bool>
{
public long Id { get; init; }
public int Quantity { get; init; }
public long? OrderId { get; init; }
public long? DiscountOrderId { get; init; }
public string? ReferenceNumber { get; init; }
public long? PerformedByUserId { get; init; }
public bool FromReserved { get; init; } = true; // آیا از موجودی رزرو شده کم شود؟
}
/// <summary>
/// Command برای اضافه کردن موجودی (خرید)
/// </summary>
public record IncreaseInventoryCommand : IRequest<bool>
{
public long Id { get; init; }
public int Quantity { get; init; }
public string? ReferenceNumber { get; init; }
public long? PerformedByUserId { get; init; }
public string? Note { get; init; }
}
/// <summary>
/// Command برای حذف آیتم موجودی
/// </summary>
public record DeleteInventoryItemCommand : IRequest<bool>
{
public long Id { get; init; }
}
@@ -1,289 +0,0 @@
using MediatR;
using CMSMicroservice.Application.Common.Interfaces.Repositories;
using CMSMicroservice.Application.Features.InventoryItems.Commands;
using CMSMicroservice.Domain.Entities;
using CMSMicroservice.Domain.Enums;
namespace CMSMicroservice.Application.Features.InventoryItems.Handlers;
/// <summary>
/// Handler برای ایجاد آیتم موجودی جدید
/// </summary>
public class CreateInventoryItemCommandHandler : IRequestHandler<CreateInventoryItemCommand, long>
{
private readonly IInventoryItemRepository _repository;
private readonly IStockMovementRepository _stockMovementRepository;
public CreateInventoryItemCommandHandler(
IInventoryItemRepository repository,
IStockMovementRepository stockMovementRepository)
{
_repository = repository;
_stockMovementRepository = stockMovementRepository;
}
public async Task<long> Handle(CreateInventoryItemCommand request, CancellationToken cancellationToken)
{
// بررسی اینکه حداقل یکی از Product یا DiscountProduct تعریف شده باشد
if (request.ProductId == null && request.DiscountProductId == null)
{
throw new ArgumentException("Either ProductId or DiscountProductId must be provided");
}
// بررسی اینکه هر دو ProductId و DiscountProductId تعریف نشده باشند
if (request.ProductId != null && request.DiscountProductId != null)
{
throw new ArgumentException("Only one of ProductId or DiscountProductId can be provided");
}
// بررسی وجود آیتم موجودی قبلی برای همین محصول در همین انبار
InventoryItem? existingItem = null;
if (request.ProductId.HasValue)
{
existingItem = await _repository.GetByProductIdAsync(request.ProductId.Value, request.WarehouseId, cancellationToken);
}
else if (request.DiscountProductId.HasValue)
{
existingItem = await _repository.GetByDiscountProductIdAsync(request.DiscountProductId.Value, request.WarehouseId, cancellationToken);
}
if (existingItem != null)
{
throw new InvalidOperationException("Inventory item already exists for this product in this warehouse");
}
var productType = request.ProductId.HasValue ? ProductType.RegularProduct : ProductType.DiscountProduct;
var inventoryItem = new InventoryItem
{
ProductId = request.ProductId,
DiscountProductId = request.DiscountProductId,
ProductType = productType,
WarehouseId = request.WarehouseId,
Quantity = request.Quantity,
LowStockThreshold = request.MinQuantity,
MaxStockLevel = request.MaxQuantity,
ReservedQuantity = 0
};
var createdItem = await _repository.AddAsync(inventoryItem, cancellationToken);
// ثبت حرکت موجودی اولیه اگر موجودی اولیه بیشتر از صفر باشد
if (request.Quantity > 0)
{
var stockMovement = new StockMovement
{
InventoryItemId = createdItem.Id,
MovementType = StockMovementType.InitialStock,
Quantity = request.Quantity,
Note = "Initial stock creation",
ReferenceNumber = $"INIT-{createdItem.Id}"
};
await _stockMovementRepository.AddAsync(stockMovement, cancellationToken);
}
return createdItem.Id;
}
}
/// <summary>
/// Handler برای آپدیت آیتم موجودی
/// </summary>
public class UpdateInventoryItemCommandHandler : IRequestHandler<UpdateInventoryItemCommand, bool>
{
private readonly IInventoryItemRepository _repository;
public UpdateInventoryItemCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(UpdateInventoryItemCommand request, CancellationToken cancellationToken)
{
var inventoryItem = await _repository.GetByIdAsync(request.Id, cancellationToken);
if (inventoryItem == null)
{
return false;
}
if (request.WarehouseId.HasValue && request.WarehouseId.Value != inventoryItem.WarehouseId)
{
inventoryItem.WarehouseId = request.WarehouseId.Value;
}
if (request.Quantity.HasValue)
{
inventoryItem.Quantity = request.Quantity.Value;
}
if (request.MinQuantity.HasValue)
{
inventoryItem.LowStockThreshold = request.MinQuantity.Value;
}
if (request.MaxQuantity.HasValue)
{
inventoryItem.MaxStockLevel = request.MaxQuantity.Value;
}
await _repository.UpdateAsync(inventoryItem, cancellationToken);
return true;
}
}
/// <summary>
/// Handler برای آپدیت موجودی
/// </summary>
public class UpdateInventoryQuantityCommandHandler : IRequestHandler<UpdateInventoryQuantityCommand, bool>
{
private readonly IInventoryItemRepository _repository;
public UpdateInventoryQuantityCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(UpdateInventoryQuantityCommand request, CancellationToken cancellationToken)
{
var inventoryItem = await _repository.GetByIdAsync(request.Id, cancellationToken);
if (inventoryItem == null)
{
return false;
}
var quantityChange = request.NewQuantity - inventoryItem.Quantity;
var movementType = quantityChange >= 0 ? StockMovementType.AdjustmentPlus : StockMovementType.AdjustmentMinus;
var result = await _repository.UpdateQuantityAsync(
request.Id,
quantityChange,
movementType,
note: request.Note,
referenceNumber: request.ReferenceNumber,
performedByUserId: request.PerformedByUserId,
cancellationToken: cancellationToken);
return result;
}
}
/// <summary>
/// Handler برای رزرو موجودی
/// </summary>
public class ReserveInventoryCommandHandler : IRequestHandler<ReserveInventoryCommand, bool>
{
private readonly IInventoryItemRepository _repository;
public ReserveInventoryCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(ReserveInventoryCommand request, CancellationToken cancellationToken)
{
return await _repository.ReserveQuantityAsync(
request.Id,
request.Quantity,
referenceNumber: request.ReferenceNumber,
orderId: request.OrderId,
discountOrderId: request.DiscountOrderId,
performedByUserId: request.PerformedByUserId,
cancellationToken: cancellationToken);
}
}
/// <summary>
/// Handler برای آزاد کردن موجودی رزرو شده
/// </summary>
public class ReleaseReservedInventoryCommandHandler : IRequestHandler<ReleaseReservedInventoryCommand, bool>
{
private readonly IInventoryItemRepository _repository;
public ReleaseReservedInventoryCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(ReleaseReservedInventoryCommand request, CancellationToken cancellationToken)
{
return await _repository.ReleaseReservedQuantityAsync(
request.Id,
request.Quantity,
referenceNumber: request.ReferenceNumber,
orderId: request.OrderId,
discountOrderId: request.DiscountOrderId,
performedByUserId: request.PerformedByUserId,
cancellationToken: cancellationToken);
}
}
/// <summary>
/// Handler برای کم کردن موجودی
/// </summary>
public class ReduceInventoryCommandHandler : IRequestHandler<ReduceInventoryCommand, bool>
{
private readonly IInventoryItemRepository _repository;
public ReduceInventoryCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(ReduceInventoryCommand request, CancellationToken cancellationToken)
{
return await _repository.UpdateQuantityAsync(
request.Id,
-request.Quantity,
StockMovementType.Sale,
referenceNumber: request.ReferenceNumber,
orderId: request.OrderId,
discountOrderId: request.DiscountOrderId,
performedByUserId: request.PerformedByUserId,
cancellationToken: cancellationToken);
}
}
/// <summary>
/// Handler برای اضافه کردن موجودی
/// </summary>
public class IncreaseInventoryCommandHandler : IRequestHandler<IncreaseInventoryCommand, bool>
{
private readonly IInventoryItemRepository _repository;
public IncreaseInventoryCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(IncreaseInventoryCommand request, CancellationToken cancellationToken)
{
return await _repository.UpdateQuantityAsync(
request.Id,
request.Quantity,
StockMovementType.Restock,
note: request.Note,
referenceNumber: request.ReferenceNumber,
performedByUserId: request.PerformedByUserId,
cancellationToken: cancellationToken);
}
}
/// <summary>
/// Handler برای حذف آیتم موجودی
/// </summary>
public class DeleteInventoryItemCommandHandler : IRequestHandler<DeleteInventoryItemCommand, bool>
{
private readonly IInventoryItemRepository _repository;
public DeleteInventoryItemCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(DeleteInventoryItemCommand request, CancellationToken cancellationToken)
{
await _repository.DeleteAsync(request.Id, cancellationToken);
return true;
}
}
@@ -1,197 +0,0 @@
using MediatR;
using CMSMicroservice.Application.Common.Interfaces.Repositories;
using CMSMicroservice.Application.Features.InventoryItems.Queries;
using CMSMicroservice.Domain.Entities;
namespace CMSMicroservice.Application.Features.InventoryItems.Handlers;
/// <summary>
/// Handler برای دریافت آیتم موجودی به ID
/// </summary>
public class GetInventoryItemByIdQueryHandler : IRequestHandler<GetInventoryItemByIdQuery, InventoryItem?>
{
private readonly IInventoryItemRepository _repository;
public GetInventoryItemByIdQueryHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<InventoryItem?> Handle(GetInventoryItemByIdQuery request, CancellationToken cancellationToken)
{
return await _repository.GetByIdAsync(request.Id, cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت آیتم موجودی به Product ID
/// </summary>
public class GetInventoryItemByProductIdQueryHandler : IRequestHandler<GetInventoryItemByProductIdQuery, InventoryItem?>
{
private readonly IInventoryItemRepository _repository;
public GetInventoryItemByProductIdQueryHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<InventoryItem?> Handle(GetInventoryItemByProductIdQuery request, CancellationToken cancellationToken)
{
return await _repository.GetByProductIdAsync(request.ProductId, request.WarehouseId ?? 1, cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت آیتم موجودی به DiscountProduct ID
/// </summary>
public class GetInventoryItemByDiscountProductIdQueryHandler : IRequestHandler<GetInventoryItemByDiscountProductIdQuery, InventoryItem?>
{
private readonly IInventoryItemRepository _repository;
public GetInventoryItemByDiscountProductIdQueryHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<InventoryItem?> Handle(GetInventoryItemByDiscountProductIdQuery request, CancellationToken cancellationToken)
{
return await _repository.GetByDiscountProductIdAsync(request.DiscountProductId, request.WarehouseId ?? 1, cancellationToken);
}
}
/// <summary>
/// Handler برای جستجوی آیتم های موجودی
/// </summary>
public class SearchInventoryItemsQueryHandler : IRequestHandler<SearchInventoryItemsQuery, List<InventoryItem>>
{
private readonly IInventoryItemRepository _repository;
public SearchInventoryItemsQueryHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<List<InventoryItem>> Handle(SearchInventoryItemsQuery request, CancellationToken cancellationToken)
{
return await _repository.SearchAsync(
searchTerm: request.ProductName,
warehouseId: request.WarehouseId,
skip: request.Skip,
take: request.Take,
cancellationToken: cancellationToken);
}
}
/// <summary>
/// Handler برای شمارش آیتم های موجودی
/// </summary>
public class GetInventoryItemsCountQueryHandler : IRequestHandler<GetInventoryItemsCountQuery, int>
{
private readonly IInventoryItemRepository _repository;
public GetInventoryItemsCountQueryHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<int> Handle(GetInventoryItemsCountQuery request, CancellationToken cancellationToken)
{
return await _repository.CountAsync(
searchTerm: request.ProductName,
warehouseId: request.WarehouseId,
cancellationToken: cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت آیتم های کم موجود
/// </summary>
public class GetLowStockItemsQueryHandler : IRequestHandler<GetLowStockItemsQuery, List<InventoryItem>>
{
private readonly IInventoryItemRepository _repository;
public GetLowStockItemsQueryHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<List<InventoryItem>> Handle(GetLowStockItemsQuery request, CancellationToken cancellationToken)
{
return await _repository.GetLowStockItemsAsync(warehouseId: request.WarehouseId ?? 1, cancellationToken: cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت آیتم های ناموجود
/// </summary>
public class GetOutOfStockItemsQueryHandler : IRequestHandler<GetOutOfStockItemsQuery, List<InventoryItem>>
{
private readonly IInventoryItemRepository _repository;
public GetOutOfStockItemsQueryHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<List<InventoryItem>> Handle(GetOutOfStockItemsQuery request, CancellationToken cancellationToken)
{
return await _repository.GetOutOfStockItemsAsync(warehouseId: request.WarehouseId ?? 1, cancellationToken: cancellationToken);
}
}
/// <summary>
/// Handler برای چک کردن دسترسی موجودی
/// </summary>
public class CheckInventoryAvailabilityQueryHandler : IRequestHandler<CheckInventoryAvailabilityQuery, bool>
{
private readonly IInventoryItemRepository _repository;
public CheckInventoryAvailabilityQueryHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(CheckInventoryAvailabilityQuery request, CancellationToken cancellationToken)
{
var item = await _repository.GetByIdAsync(request.InventoryItemId, cancellationToken);
if (item == null) return false;
return item.AvailableQuantity >= request.RequiredQuantity;
}
}
/// <summary>
/// Handler برای دریافت موجودی قابل دسترس
/// </summary>
public class GetAvailableQuantityQueryHandler : IRequestHandler<GetAvailableQuantityQuery, int>
{
private readonly IInventoryItemRepository _repository;
public GetAvailableQuantityQueryHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<int> Handle(GetAvailableQuantityQuery request, CancellationToken cancellationToken)
{
var item = await _repository.GetByIdAsync(request.InventoryItemId, cancellationToken);
return item?.AvailableQuantity ?? 0;
}
}
/// <summary>
/// Handler برای دریافت آیتم های موجودی در انبار
/// </summary>
public class GetWarehouseInventoryItemsQueryHandler : IRequestHandler<GetWarehouseInventoryItemsQuery, List<InventoryItem>>
{
private readonly IInventoryItemRepository _repository;
public GetWarehouseInventoryItemsQueryHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task<List<InventoryItem>> Handle(GetWarehouseInventoryItemsQuery request, CancellationToken cancellationToken)
{
return await _repository.GetByWarehouseIdAsync(request.WarehouseId, cancellationToken);
}
}
@@ -1,93 +0,0 @@
using MediatR;
using CMSMicroservice.Domain.Entities;
namespace CMSMicroservice.Application.Features.InventoryItems.Queries;
/// <summary>
/// Query برای دریافت آیتم موجودی به ID
/// </summary>
public record GetInventoryItemByIdQuery(long Id) : IRequest<InventoryItem?>;
/// <summary>
/// Query برای دریافت آیتم موجودی به Product ID
/// </summary>
public record GetInventoryItemByProductIdQuery(long ProductId, long? WarehouseId = null) : IRequest<InventoryItem?>;
/// <summary>
/// Query برای دریافت آیتم موجودی به DiscountProduct ID
/// </summary>
public record GetInventoryItemByDiscountProductIdQuery(long DiscountProductId, long? WarehouseId = null) : IRequest<InventoryItem?>;
/// <summary>
/// Query برای جستجوی آیتم های موجودی
/// </summary>
public record SearchInventoryItemsQuery : IRequest<List<InventoryItem>>
{
public long? WarehouseId { get; init; }
public long? ProductId { get; init; }
public long? DiscountProductId { get; init; }
public string? ProductName { get; init; }
public bool? IsActive { get; init; }
public bool? IsLowStock { get; init; }
public bool? IsOutOfStock { get; init; }
public int Skip { get; init; } = 0;
public int Take { get; init; } = 100;
}
/// <summary>
/// Query برای دریافت تعداد آیتم های موجودی
/// </summary>
public record GetInventoryItemsCountQuery : IRequest<int>
{
public long? WarehouseId { get; init; }
public long? ProductId { get; init; }
public long? DiscountProductId { get; init; }
public string? ProductName { get; init; }
public bool? IsActive { get; init; }
public bool? IsLowStock { get; init; }
public bool? IsOutOfStock { get; init; }
}
/// <summary>
/// Query برای دریافت آیتم های کم موجود
/// </summary>
public record GetLowStockItemsQuery : IRequest<List<InventoryItem>>
{
public long? WarehouseId { get; init; }
public int Count { get; init; } = 50;
}
/// <summary>
/// Query برای دریافت آیتم های ناموجود
/// </summary>
public record GetOutOfStockItemsQuery : IRequest<List<InventoryItem>>
{
public long? WarehouseId { get; init; }
public int Count { get; init; } = 50;
}
/// <summary>
/// Query برای چک کردن دسترسی موجودی
/// </summary>
public record CheckInventoryAvailabilityQuery : IRequest<bool>
{
public long InventoryItemId { get; init; }
public int RequiredQuantity { get; init; }
}
/// <summary>
/// Query برای دریافت موجودی قابل دسترس
/// </summary>
public record GetAvailableQuantityQuery(long InventoryItemId) : IRequest<int>;
/// <summary>
/// Query برای دریافت آیتم های موجودی در انبار
/// </summary>
public record GetWarehouseInventoryItemsQuery : IRequest<List<InventoryItem>>
{
public long WarehouseId { get; init; }
public bool? IsActive { get; init; }
public bool? IsLowStock { get; init; }
public int Skip { get; init; } = 0;
public int Take { get; init; } = 100;
}
@@ -1,44 +0,0 @@
using MediatR;
using CMSMicroservice.Domain.Enums;
namespace CMSMicroservice.Application.Features.StockMovements.Commands;
/// <summary>
/// Command برای ثبت حرکت موجودی
/// </summary>
public record CreateStockMovementCommand : IRequest<long>
{
public long InventoryItemId { get; init; }
public StockMovementType MovementType { get; init; }
public int Quantity { get; init; }
public long? OrderId { get; init; }
public long? DiscountOrderId { get; init; }
public string? ReferenceNumber { get; init; }
public string? Note { get; init; }
public long? PerformedByUserId { get; init; }
}
/// <summary>
/// Command برای ثبت چندین حرکت موجودی به صورت bulk
/// </summary>
public record BulkCreateStockMovementCommand : IRequest<List<long>>
{
public List<StockMovementItem> Movements { get; init; } = new();
public record StockMovementItem
{
public long InventoryItemId { get; init; }
public StockMovementType MovementType { get; init; }
public int Quantity { get; init; }
public long? OrderId { get; init; }
public long? DiscountOrderId { get; init; }
public string? ReferenceNumber { get; init; }
public string? Note { get; init; }
public long? PerformedByUserId { get; init; }
}
}
/// <summary>
/// Command برای حذف حرکت موجودی
/// </summary>
public record DeleteStockMovementCommand(long Id) : IRequest<bool>;
@@ -1,119 +0,0 @@
using MediatR;
using CMSMicroservice.Application.Common.Interfaces.Repositories;
using CMSMicroservice.Application.Features.StockMovements.Commands;
using CMSMicroservice.Domain.Entities;
namespace CMSMicroservice.Application.Features.StockMovements.Handlers;
/// <summary>
/// Handler برای ثبت حرکت موجودی
/// </summary>
public class CreateStockMovementCommandHandler : IRequestHandler<CreateStockMovementCommand, long>
{
private readonly IStockMovementRepository _repository;
private readonly IInventoryItemRepository _inventoryRepository;
public CreateStockMovementCommandHandler(
IStockMovementRepository repository,
IInventoryItemRepository inventoryRepository)
{
_repository = repository;
_inventoryRepository = inventoryRepository;
}
public async Task<long> Handle(CreateStockMovementCommand request, CancellationToken cancellationToken)
{
// بررسی وجود آیتم موجودی
var inventoryItem = await _inventoryRepository.GetByIdAsync(request.InventoryItemId, cancellationToken);
if (inventoryItem == null)
{
throw new ArgumentException("Inventory item not found");
}
var stockMovement = new StockMovement
{
InventoryItemId = request.InventoryItemId,
MovementType = request.MovementType,
Quantity = request.Quantity,
OrderId = request.OrderId,
DiscountOrderId = request.DiscountOrderId,
ReferenceNumber = request.ReferenceNumber,
Note = request.Note,
PerformedByUserId = request.PerformedByUserId
};
var createdMovement = await _repository.AddAsync(stockMovement, cancellationToken);
return createdMovement.Id;
}
}
/// <summary>
/// Handler برای ثبت چندین حرکت موجودی bulk
/// </summary>
public class BulkCreateStockMovementCommandHandler : IRequestHandler<BulkCreateStockMovementCommand, List<long>>
{
private readonly IStockMovementRepository _repository;
private readonly IInventoryItemRepository _inventoryRepository;
public BulkCreateStockMovementCommandHandler(
IStockMovementRepository repository,
IInventoryItemRepository inventoryRepository)
{
_repository = repository;
_inventoryRepository = inventoryRepository;
}
public async Task<List<long>> Handle(BulkCreateStockMovementCommand request, CancellationToken cancellationToken)
{
var stockMovements = new List<StockMovement>();
// بررسی وجود تمام آیتم های موجودی
var inventoryItemIds = request.Movements.Select(m => m.InventoryItemId).Distinct().ToList();
foreach (var inventoryItemId in inventoryItemIds)
{
var item = await _inventoryRepository.GetByIdAsync(inventoryItemId, cancellationToken);
if (item == null)
{
throw new ArgumentException($"Inventory item with ID {inventoryItemId} not found");
}
}
foreach (var movement in request.Movements)
{
var stockMovement = new StockMovement
{
InventoryItemId = movement.InventoryItemId,
MovementType = movement.MovementType,
Quantity = movement.Quantity,
OrderId = movement.OrderId,
DiscountOrderId = movement.DiscountOrderId,
ReferenceNumber = movement.ReferenceNumber,
Note = movement.Note,
PerformedByUserId = movement.PerformedByUserId
};
stockMovements.Add(stockMovement);
}
var createdMovements = await _repository.BulkAddAsync(stockMovements, cancellationToken);
return createdMovements.Select(m => m.Id).ToList();
}
}
/// <summary>
/// Handler برای حذف حرکت موجودی
/// </summary>
public class DeleteStockMovementCommandHandler : IRequestHandler<DeleteStockMovementCommand, bool>
{
private readonly IStockMovementRepository _repository;
public DeleteStockMovementCommandHandler(IStockMovementRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(DeleteStockMovementCommand request, CancellationToken cancellationToken)
{
await _repository.DeleteAsync(request.Id, cancellationToken);
return true;
}
}
@@ -1,269 +0,0 @@
using MediatR;
using CMSMicroservice.Application.Common.Interfaces.Repositories;
using CMSMicroservice.Application.Features.StockMovements.Queries;
using CMSMicroservice.Domain.Entities;
using CMSMicroservice.Domain.Enums;
namespace CMSMicroservice.Application.Features.StockMovements.Handlers;
/// <summary>
/// Handler برای دریافت حرکت موجودی به ID
/// </summary>
public class GetStockMovementByIdQueryHandler : IRequestHandler<GetStockMovementByIdQuery, StockMovement?>
{
private readonly IStockMovementRepository _repository;
public GetStockMovementByIdQueryHandler(IStockMovementRepository repository)
{
_repository = repository;
}
public async Task<StockMovement?> Handle(GetStockMovementByIdQuery request, CancellationToken cancellationToken)
{
return await _repository.GetByIdAsync(request.Id, cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت تاریخچه حرکت موجودی یک آیتم
/// </summary>
public class GetInventoryItemMovementHistoryQueryHandler : IRequestHandler<GetInventoryItemMovementHistoryQuery, List<StockMovement>>
{
private readonly IStockMovementRepository _repository;
public GetInventoryItemMovementHistoryQueryHandler(IStockMovementRepository repository)
{
_repository = repository;
}
public async Task<List<StockMovement>> Handle(GetInventoryItemMovementHistoryQuery request, CancellationToken cancellationToken)
{
return await _repository.GetByInventoryItemIdAsync(
request.InventoryItemId,
request.MovementType,
request.FromDate,
request.ToDate,
request.Skip,
request.Take,
cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت حرکات موجودی بر اساس سفارش
/// </summary>
public class GetStockMovementsByOrderQueryHandler : IRequestHandler<GetStockMovementsByOrderQuery, List<StockMovement>>
{
private readonly IStockMovementRepository _repository;
public GetStockMovementsByOrderQueryHandler(IStockMovementRepository repository)
{
_repository = repository;
}
public async Task<List<StockMovement>> Handle(GetStockMovementsByOrderQuery request, CancellationToken cancellationToken)
{
return await _repository.GetByOrderIdAsync(request.OrderId, cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت حرکات موجودی بر اساس سفارش تخفیف
/// </summary>
public class GetStockMovementsByDiscountOrderQueryHandler : IRequestHandler<GetStockMovementsByDiscountOrderQuery, List<StockMovement>>
{
private readonly IStockMovementRepository _repository;
public GetStockMovementsByDiscountOrderQueryHandler(IStockMovementRepository repository)
{
_repository = repository;
}
public async Task<List<StockMovement>> Handle(GetStockMovementsByDiscountOrderQuery request, CancellationToken cancellationToken)
{
return await _repository.GetByDiscountOrderIdAsync(request.DiscountOrderId, cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت حرکات موجودی بر اساس شماره مرجع
/// </summary>
public class GetStockMovementsByReferenceQueryHandler : IRequestHandler<GetStockMovementsByReferenceQuery, List<StockMovement>>
{
private readonly IStockMovementRepository _repository;
public GetStockMovementsByReferenceQueryHandler(IStockMovementRepository repository)
{
_repository = repository;
}
public async Task<List<StockMovement>> Handle(GetStockMovementsByReferenceQuery request, CancellationToken cancellationToken)
{
return await _repository.GetByReferenceNumberAsync(request.ReferenceNumber, cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت حرکات موجودی بر اساس نوع
/// </summary>
public class GetStockMovementsByTypeQueryHandler : IRequestHandler<GetStockMovementsByTypeQuery, List<StockMovement>>
{
private readonly IStockMovementRepository _repository;
public GetStockMovementsByTypeQueryHandler(IStockMovementRepository repository)
{
_repository = repository;
}
public async Task<List<StockMovement>> Handle(GetStockMovementsByTypeQuery request, CancellationToken cancellationToken)
{
return await _repository.GetByMovementTypeAsync(
request.MovementType,
request.FromDate,
request.ToDate,
request.Skip,
request.Take,
cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت آخرین حرکات موجودی
/// </summary>
public class GetRecentStockMovementsQueryHandler : IRequestHandler<GetRecentStockMovementsQuery, List<StockMovement>>
{
private readonly IStockMovementRepository _repository;
public GetRecentStockMovementsQueryHandler(IStockMovementRepository repository)
{
_repository = repository;
}
public async Task<List<StockMovement>> Handle(GetRecentStockMovementsQuery request, CancellationToken cancellationToken)
{
return await _repository.GetRecentMovementsAsync(request.Count, request.MovementType, cancellationToken);
}
}
/// <summary>
/// Handler برای جستجوی حرکات موجودی
/// </summary>
public class SearchStockMovementsQueryHandler : IRequestHandler<SearchStockMovementsQuery, List<StockMovement>>
{
private readonly IStockMovementRepository _repository;
public SearchStockMovementsQueryHandler(IStockMovementRepository repository)
{
_repository = repository;
}
public async Task<List<StockMovement>> Handle(SearchStockMovementsQuery request, CancellationToken cancellationToken)
{
return await _repository.SearchAsync(
request.InventoryItemId,
request.MovementType,
request.FromDate,
request.ToDate,
request.ReferenceNumber,
request.OrderId,
request.DiscountOrderId,
request.PerformedByUserId,
request.Skip,
request.Take,
cancellationToken);
}
}
/// <summary>
/// Handler برای شمارش حرکات موجودی
/// </summary>
public class GetStockMovementsCountQueryHandler : IRequestHandler<GetStockMovementsCountQuery, int>
{
private readonly IStockMovementRepository _repository;
public GetStockMovementsCountQueryHandler(IStockMovementRepository repository)
{
_repository = repository;
}
public async Task<int> Handle(GetStockMovementsCountQuery request, CancellationToken cancellationToken)
{
return await _repository.CountAsync(
request.InventoryItemId,
request.MovementType,
request.FromDate,
request.ToDate,
request.ReferenceNumber,
request.OrderId,
request.DiscountOrderId,
request.PerformedByUserId,
cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت خلاصه حرکات موجودی
/// </summary>
public class GetMovementSummaryQueryHandler : IRequestHandler<GetMovementSummaryQuery, Dictionary<StockMovementType, int>>
{
private readonly IStockMovementRepository _repository;
public GetMovementSummaryQueryHandler(IStockMovementRepository repository)
{
_repository = repository;
}
public async Task<Dictionary<StockMovementType, int>> Handle(GetMovementSummaryQuery request, CancellationToken cancellationToken)
{
return await _repository.GetMovementSummaryAsync(
request.FromDate,
request.ToDate,
request.InventoryItemId,
cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت حجم حرکات روزانه
/// </summary>
public class GetDailyMovementVolumeQueryHandler : IRequestHandler<GetDailyMovementVolumeQuery, List<(DateTime Date, int InboundQuantity, int OutboundQuantity)>>
{
private readonly IStockMovementRepository _repository;
public GetDailyMovementVolumeQueryHandler(IStockMovementRepository repository)
{
_repository = repository;
}
public async Task<List<(DateTime Date, int InboundQuantity, int OutboundQuantity)>> Handle(GetDailyMovementVolumeQuery request, CancellationToken cancellationToken)
{
return await _repository.GetDailyMovementVolumeAsync(
request.FromDate,
request.ToDate,
request.InventoryItemId,
cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت محصولات پر حرکت
/// </summary>
public class GetTopMovingProductsQueryHandler : IRequestHandler<GetTopMovingProductsQuery, List<(long InventoryItemId, string ProductName, int MovementCount, int TotalQuantityChange)>>
{
private readonly IStockMovementRepository _repository;
public GetTopMovingProductsQueryHandler(IStockMovementRepository repository)
{
_repository = repository;
}
public async Task<List<(long InventoryItemId, string ProductName, int MovementCount, int TotalQuantityChange)>> Handle(GetTopMovingProductsQuery request, CancellationToken cancellationToken)
{
return await _repository.GetTopMovingProductsAsync(
request.FromDate,
request.ToDate,
request.Count,
request.MovementType,
cancellationToken);
}
}
@@ -1,122 +0,0 @@
using MediatR;
using CMSMicroservice.Domain.Entities;
using CMSMicroservice.Domain.Enums;
namespace CMSMicroservice.Application.Features.StockMovements.Queries;
/// <summary>
/// Query برای دریافت حرکت موجودی به ID
/// </summary>
public record GetStockMovementByIdQuery(long Id) : IRequest<StockMovement?>;
/// <summary>
/// Query برای دریافت تاریخچه حرکت موجودی یک آیتم
/// </summary>
public record GetInventoryItemMovementHistoryQuery : IRequest<List<StockMovement>>
{
public long InventoryItemId { get; init; }
public StockMovementType? MovementType { get; init; }
public DateTime? FromDate { get; init; }
public DateTime? ToDate { get; init; }
public int Skip { get; init; } = 0;
public int Take { get; init; } = 100;
}
/// <summary>
/// Query برای دریافت حرکات موجودی بر اساس سفارش
/// </summary>
public record GetStockMovementsByOrderQuery(long OrderId) : IRequest<List<StockMovement>>;
/// <summary>
/// Query برای دریافت حرکات موجودی بر اساس سفارش تخفیف
/// </summary>
public record GetStockMovementsByDiscountOrderQuery(long DiscountOrderId) : IRequest<List<StockMovement>>;
/// <summary>
/// Query برای دریافت حرکات موجودی بر اساس شماره مرجع
/// </summary>
public record GetStockMovementsByReferenceQuery(string ReferenceNumber) : IRequest<List<StockMovement>>;
/// <summary>
/// Query برای دریافت حرکات موجودی بر اساس نوع
/// </summary>
public record GetStockMovementsByTypeQuery : IRequest<List<StockMovement>>
{
public StockMovementType MovementType { get; init; }
public DateTime? FromDate { get; init; }
public DateTime? ToDate { get; init; }
public int Skip { get; init; } = 0;
public int Take { get; init; } = 100;
}
/// <summary>
/// Query برای دریافت آخرین حرکات موجودی
/// </summary>
public record GetRecentStockMovementsQuery : IRequest<List<StockMovement>>
{
public int Count { get; init; } = 50;
public StockMovementType? MovementType { get; init; }
}
/// <summary>
/// Query برای جستجوی حرکات موجودی
/// </summary>
public record SearchStockMovementsQuery : IRequest<List<StockMovement>>
{
public long? InventoryItemId { get; init; }
public StockMovementType? MovementType { get; init; }
public DateTime? FromDate { get; init; }
public DateTime? ToDate { get; init; }
public string? ReferenceNumber { get; init; }
public long? OrderId { get; init; }
public long? DiscountOrderId { get; init; }
public long? PerformedByUserId { get; init; }
public int Skip { get; init; } = 0;
public int Take { get; init; } = 100;
}
/// <summary>
/// Query برای شمارش حرکات موجودی
/// </summary>
public record GetStockMovementsCountQuery : IRequest<int>
{
public long? InventoryItemId { get; init; }
public StockMovementType? MovementType { get; init; }
public DateTime? FromDate { get; init; }
public DateTime? ToDate { get; init; }
public string? ReferenceNumber { get; init; }
public long? OrderId { get; init; }
public long? DiscountOrderId { get; init; }
public long? PerformedByUserId { get; init; }
}
/// <summary>
/// Query برای دریافت خلاصه حرکات موجودی
/// </summary>
public record GetMovementSummaryQuery : IRequest<Dictionary<StockMovementType, int>>
{
public DateTime FromDate { get; init; }
public DateTime ToDate { get; init; }
public long? InventoryItemId { get; init; }
}
/// <summary>
/// Query برای دریافت حجم حرکات روزانه
/// </summary>
public record GetDailyMovementVolumeQuery : IRequest<List<(DateTime Date, int InboundQuantity, int OutboundQuantity)>>
{
public DateTime FromDate { get; init; }
public DateTime ToDate { get; init; }
public long? InventoryItemId { get; init; }
}
/// <summary>
/// Query برای دریافت محصولات پر حرکت
/// </summary>
public record GetTopMovingProductsQuery : IRequest<List<(long InventoryItemId, string ProductName, int MovementCount, int TotalQuantityChange)>>
{
public DateTime FromDate { get; init; }
public DateTime ToDate { get; init; }
public int Count { get; init; } = 10;
public StockMovementType? MovementType { get; init; }
}
@@ -1,66 +0,0 @@
using MediatR;
namespace CMSMicroservice.Application.Features.Warehouses.Commands;
/// <summary>
/// Command برای ایجاد انبار جدید
/// </summary>
public record CreateWarehouseCommand : IRequest<long>
{
public string Name { get; init; } = string.Empty;
public string Code { get; init; } = string.Empty;
public string? Description { get; init; }
public string? Address { get; init; }
public string? CityName { get; init; }
public bool IsActive { get; init; } = true;
public bool IsDefault { get; init; } = false;
}
/// <summary>
/// Command برای آپدیت انبار
/// </summary>
public record UpdateWarehouseCommand : IRequest<bool>
{
public long Id { get; init; }
public string? Name { get; init; }
public string? Code { get; init; }
public string? Description { get; init; }
public string? Address { get; init; }
public string? CityName { get; init; }
public bool? IsActive { get; init; }
public bool? IsDefault { get; init; }
}
/// <summary>
/// Command برای حذف انبار
/// </summary>
public record DeleteWarehouseCommand(long Id) : IRequest<bool>;
/// <summary>
/// Command برای تعیین انبار پیش‌فرض
/// </summary>
public record SetDefaultWarehouseCommand(long Id) : IRequest<bool>;
/// <summary>
/// Command برای فعال/غیرفعال کردن انبار
/// </summary>
public record ActivateWarehouseCommand(long Id, bool IsActive) : IRequest<bool>;
/// <summary>
/// Command برای ایجاد چندین انبار به صورت bulk
/// </summary>
public record BulkCreateWarehousesCommand : IRequest<List<long>>
{
public List<WarehouseItem> Warehouses { get; init; } = new();
public record WarehouseItem
{
public string Name { get; init; } = string.Empty;
public string Code { get; init; } = string.Empty;
public string? Description { get; init; }
public string? Address { get; init; }
public string? CityName { get; init; }
public bool IsActive { get; init; } = true;
public bool IsDefault { get; init; } = false;
}
}
@@ -1,208 +0,0 @@
using MediatR;
using CMSMicroservice.Application.Common.Interfaces.Repositories;
using CMSMicroservice.Application.Features.Warehouses.Commands;
using CMSMicroservice.Domain.Entities;
namespace CMSMicroservice.Application.Features.Warehouses.Handlers;
/// <summary>
/// Handler برای ایجاد انبار جدید
/// </summary>
public class CreateWarehouseCommandHandler : IRequestHandler<CreateWarehouseCommand, long>
{
private readonly IWarehouseRepository _repository;
public CreateWarehouseCommandHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<long> Handle(CreateWarehouseCommand request, CancellationToken cancellationToken)
{
// بررسی تکراری نبودن کد
var codeExists = await _repository.ExistsByCodeAsync(request.Code, cancellationToken: cancellationToken);
if (codeExists)
{
throw new InvalidOperationException($"Warehouse with code '{request.Code}' already exists");
}
var warehouse = new Warehouse
{
Name = request.Name,
Code = request.Code,
Address = request.Address,
IsActive = request.IsActive,
IsDefault = request.IsDefault
};
var createdWarehouse = await _repository.AddAsync(warehouse, cancellationToken);
return createdWarehouse.Id;
}
}
/// <summary>
/// Handler برای آپدیت انبار
/// </summary>
public class UpdateWarehouseCommandHandler : IRequestHandler<UpdateWarehouseCommand, bool>
{
private readonly IWarehouseRepository _repository;
public UpdateWarehouseCommandHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(UpdateWarehouseCommand request, CancellationToken cancellationToken)
{
var warehouse = await _repository.GetByIdAsync(request.Id, cancellationToken);
if (warehouse == null)
{
return false;
}
// بررسی تکراری نبودن کد جدید
if (!string.IsNullOrEmpty(request.Code) && request.Code != warehouse.Code)
{
var codeExists = await _repository.ExistsByCodeAsync(request.Code, request.Id, cancellationToken);
if (codeExists)
{
throw new InvalidOperationException($"Warehouse with code '{request.Code}' already exists");
}
warehouse.Code = request.Code;
}
if (!string.IsNullOrEmpty(request.Name))
{
warehouse.Name = request.Name;
}
if (request.Address != null)
{
warehouse.Address = request.Address;
}
if (request.IsActive.HasValue)
{
warehouse.IsActive = request.IsActive.Value;
}
if (request.IsDefault.HasValue)
{
warehouse.IsDefault = request.IsDefault.Value;
}
await _repository.UpdateAsync(warehouse, cancellationToken);
return true;
}
}
/// <summary>
/// Handler برای حذف انبار
/// </summary>
public class DeleteWarehouseCommandHandler : IRequestHandler<DeleteWarehouseCommand, bool>
{
private readonly IWarehouseRepository _repository;
public DeleteWarehouseCommandHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(DeleteWarehouseCommand request, CancellationToken cancellationToken)
{
try
{
await _repository.DeleteAsync(request.Id, cancellationToken);
return true;
}
catch (InvalidOperationException)
{
// انبار دارای موجودی است
return false;
}
}
}
/// <summary>
/// Handler برای تعیین انبار پیش‌فرض
/// </summary>
public class SetDefaultWarehouseCommandHandler : IRequestHandler<SetDefaultWarehouseCommand, bool>
{
private readonly IWarehouseRepository _repository;
public SetDefaultWarehouseCommandHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(SetDefaultWarehouseCommand request, CancellationToken cancellationToken)
{
await _repository.SetAsDefaultAsync(request.Id, cancellationToken);
return true;
}
}
/// <summary>
/// Handler برای فعال/غیرفعال کردن انبار
/// </summary>
public class ActivateWarehouseCommandHandler : IRequestHandler<ActivateWarehouseCommand, bool>
{
private readonly IWarehouseRepository _repository;
public ActivateWarehouseCommandHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(ActivateWarehouseCommand request, CancellationToken cancellationToken)
{
await _repository.SetActiveStatusAsync(request.Id, request.IsActive, cancellationToken);
return true;
}
}
/// <summary>
/// Handler برای ایجاد چندین انبار bulk
/// </summary>
public class BulkCreateWarehousesCommandHandler : IRequestHandler<BulkCreateWarehousesCommand, List<long>>
{
private readonly IWarehouseRepository _repository;
public BulkCreateWarehousesCommandHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<List<long>> Handle(BulkCreateWarehousesCommand request, CancellationToken cancellationToken)
{
var ids = new List<long>();
// بررسی تکراری نبودن کدها
var codes = request.Warehouses.Select(w => w.Code).ToList();
foreach (var code in codes.Distinct())
{
var codeExists = await _repository.ExistsByCodeAsync(code, cancellationToken: cancellationToken);
if (codeExists)
{
throw new InvalidOperationException($"Warehouse with code '{code}' already exists");
}
}
foreach (var warehouseItem in request.Warehouses)
{
var warehouse = new Warehouse
{
Name = warehouseItem.Name,
Code = warehouseItem.Code,
Address = warehouseItem.Address,
IsActive = warehouseItem.IsActive,
IsDefault = warehouseItem.IsDefault
};
var created = await _repository.AddAsync(warehouse, cancellationToken);
ids.Add(created.Id);
}
return ids;
}
}
@@ -1,202 +0,0 @@
using MediatR;
using CMSMicroservice.Application.Common.Interfaces.Repositories;
using CMSMicroservice.Application.Features.Warehouses.Queries;
using CMSMicroservice.Domain.Entities;
namespace CMSMicroservice.Application.Features.Warehouses.Handlers;
/// <summary>
/// Handler برای دریافت انبار به ID
/// </summary>
public class GetWarehouseByIdQueryHandler : IRequestHandler<GetWarehouseByIdQuery, Warehouse?>
{
private readonly IWarehouseRepository _repository;
public GetWarehouseByIdQueryHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<Warehouse?> Handle(GetWarehouseByIdQuery request, CancellationToken cancellationToken)
{
return await _repository.GetByIdAsync(request.Id, cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت انبار به کد
/// </summary>
public class GetWarehouseByCodeQueryHandler : IRequestHandler<GetWarehouseByCodeQuery, Warehouse?>
{
private readonly IWarehouseRepository _repository;
public GetWarehouseByCodeQueryHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<Warehouse?> Handle(GetWarehouseByCodeQuery request, CancellationToken cancellationToken)
{
return await _repository.GetByCodeAsync(request.Code, cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت انبار پیش‌فرض
/// </summary>
public class GetDefaultWarehouseQueryHandler : IRequestHandler<GetDefaultWarehouseQuery, Warehouse?>
{
private readonly IWarehouseRepository _repository;
public GetDefaultWarehouseQueryHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<Warehouse?> Handle(GetDefaultWarehouseQuery request, CancellationToken cancellationToken)
{
return await _repository.GetDefaultWarehouseAsync(cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت انبارهای فعال
/// </summary>
public class GetActiveWarehousesQueryHandler : IRequestHandler<GetActiveWarehousesQuery, List<Warehouse>>
{
private readonly IWarehouseRepository _repository;
public GetActiveWarehousesQueryHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<List<Warehouse>> Handle(GetActiveWarehousesQuery request, CancellationToken cancellationToken)
{
return await _repository.GetActiveWarehousesAsync(cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت تمام انبارها
/// </summary>
public class GetAllWarehousesQueryHandler : IRequestHandler<GetAllWarehousesQuery, List<Warehouse>>
{
private readonly IWarehouseRepository _repository;
public GetAllWarehousesQueryHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<List<Warehouse>> Handle(GetAllWarehousesQuery request, CancellationToken cancellationToken)
{
return await _repository.GetAllAsync(includeInactive: true, cancellationToken);
}
}
/// <summary>
/// Handler برای جستجوی انبارها
/// </summary>
public class SearchWarehousesQueryHandler : IRequestHandler<SearchWarehousesQuery, List<Warehouse>>
{
private readonly IWarehouseRepository _repository;
public SearchWarehousesQueryHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<List<Warehouse>> Handle(SearchWarehousesQuery request, CancellationToken cancellationToken)
{
return await _repository.SearchAsync(
request.SearchTerm,
request.IsActive,
request.Skip,
request.Take,
cancellationToken);
}
}
/// <summary>
/// Handler برای شمارش انبارها
/// </summary>
public class GetWarehousesCountQueryHandler : IRequestHandler<GetWarehousesCountQuery, int>
{
private readonly IWarehouseRepository _repository;
public GetWarehousesCountQueryHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<int> Handle(GetWarehousesCountQuery request, CancellationToken cancellationToken)
{
return await _repository.CountAsync(
request.SearchTerm,
request.IsActive,
cancellationToken);
}
}
/// <summary>
/// Handler برای بررسی وجود انبار
/// </summary>
public class WarehouseExistsQueryHandler : IRequestHandler<WarehouseExistsQuery, bool>
{
private readonly IWarehouseRepository _repository;
public WarehouseExistsQueryHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(WarehouseExistsQuery request, CancellationToken cancellationToken)
{
var warehouse = await _repository.GetByIdAsync(request.Id, cancellationToken);
return warehouse != null;
}
}
/// <summary>
/// Handler برای بررسی وجود انبار با کد
/// </summary>
public class WarehouseExistsByCodeQueryHandler : IRequestHandler<WarehouseExistsByCodeQuery, bool>
{
private readonly IWarehouseRepository _repository;
public WarehouseExistsByCodeQueryHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<bool> Handle(WarehouseExistsByCodeQuery request, CancellationToken cancellationToken)
{
return await _repository.ExistsByCodeAsync(request.Code, request.ExcludeId, cancellationToken);
}
}
/// <summary>
/// Handler برای دریافت آمار انبار
/// </summary>
public class GetWarehouseStatisticsQueryHandler : IRequestHandler<GetWarehouseStatisticsQuery, Dictionary<string, object>>
{
private readonly IWarehouseRepository _repository;
public GetWarehouseStatisticsQueryHandler(IWarehouseRepository repository)
{
_repository = repository;
}
public async Task<Dictionary<string, object>> Handle(GetWarehouseStatisticsQuery request, CancellationToken cancellationToken)
{
var stats = await _repository.GetWarehouseStatisticsAsync(request.Id, cancellationToken);
return new Dictionary<string, object>
{
["TotalProducts"] = stats.TotalProducts,
["LowStockProducts"] = stats.LowStockProducts,
["OutOfStockProducts"] = stats.OutOfStockProducts,
["TotalValue"] = stats.TotalValue
};
}
}
@@ -1,68 +0,0 @@
using MediatR;
using CMSMicroservice.Domain.Entities;
namespace CMSMicroservice.Application.Features.Warehouses.Queries;
/// <summary>
/// Query برای دریافت انبار به ID
/// </summary>
public record GetWarehouseByIdQuery(long Id) : IRequest<Warehouse?>;
/// <summary>
/// Query برای دریافت انبار به کد
/// </summary>
public record GetWarehouseByCodeQuery(string Code) : IRequest<Warehouse?>;
/// <summary>
/// Query برای دریافت انبار پیش‌فرض
/// </summary>
public record GetDefaultWarehouseQuery : IRequest<Warehouse?>;
/// <summary>
/// Query برای دریافت انبارهای فعال
/// </summary>
public record GetActiveWarehousesQuery : IRequest<List<Warehouse>>;
/// <summary>
/// Query برای دریافت تمام انبارها
/// </summary>
public record GetAllWarehousesQuery : IRequest<List<Warehouse>>;
/// <summary>
/// Query برای جستجوی انبارها
/// </summary>
public record SearchWarehousesQuery : IRequest<List<Warehouse>>
{
public string? SearchTerm { get; init; }
public bool? IsActive { get; init; }
public int Skip { get; init; } = 0;
public int Take { get; init; } = 100;
}
/// <summary>
/// Query برای شمارش انبارها
/// </summary>
public record GetWarehousesCountQuery : IRequest<int>
{
public string? SearchTerm { get; init; }
public bool? IsActive { get; init; }
}
/// <summary>
/// Query برای بررسی وجود انبار
/// </summary>
public record WarehouseExistsQuery(long Id) : IRequest<bool>;
/// <summary>
/// Query برای بررسی وجود انبار با کد
/// </summary>
public record WarehouseExistsByCodeQuery : IRequest<bool>
{
public string Code { get; init; } = string.Empty;
public long? ExcludeId { get; init; }
}
/// <summary>
/// Query برای دریافت آمار انبار
/// </summary>
public record GetWarehouseStatisticsQuery(long Id) : IRequest<Dictionary<string, object>>;