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;
///
/// Handler برای ایجاد آیتم موجودی جدید
///
public class CreateInventoryItemCommandHandler : IRequestHandler
{
private readonly IInventoryItemRepository _repository;
private readonly IStockMovementRepository _stockMovementRepository;
public CreateInventoryItemCommandHandler(
IInventoryItemRepository repository,
IStockMovementRepository stockMovementRepository)
{
_repository = repository;
_stockMovementRepository = stockMovementRepository;
}
public async Task 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;
}
}
///
/// Handler برای آپدیت آیتم موجودی
///
public class UpdateInventoryItemCommandHandler : IRequestHandler
{
private readonly IInventoryItemRepository _repository;
public UpdateInventoryItemCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task 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;
}
}
///
/// Handler برای آپدیت موجودی
///
public class UpdateInventoryQuantityCommandHandler : IRequestHandler
{
private readonly IInventoryItemRepository _repository;
public UpdateInventoryQuantityCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task 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;
}
}
///
/// Handler برای رزرو موجودی
///
public class ReserveInventoryCommandHandler : IRequestHandler
{
private readonly IInventoryItemRepository _repository;
public ReserveInventoryCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task 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);
}
}
///
/// Handler برای آزاد کردن موجودی رزرو شده
///
public class ReleaseReservedInventoryCommandHandler : IRequestHandler
{
private readonly IInventoryItemRepository _repository;
public ReleaseReservedInventoryCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task 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);
}
}
///
/// Handler برای کم کردن موجودی
///
public class ReduceInventoryCommandHandler : IRequestHandler
{
private readonly IInventoryItemRepository _repository;
public ReduceInventoryCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task 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);
}
}
///
/// Handler برای اضافه کردن موجودی
///
public class IncreaseInventoryCommandHandler : IRequestHandler
{
private readonly IInventoryItemRepository _repository;
public IncreaseInventoryCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task 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);
}
}
///
/// Handler برای حذف آیتم موجودی
///
public class DeleteInventoryItemCommandHandler : IRequestHandler
{
private readonly IInventoryItemRepository _repository;
public DeleteInventoryItemCommandHandler(IInventoryItemRepository repository)
{
_repository = repository;
}
public async Task Handle(DeleteInventoryItemCommand request, CancellationToken cancellationToken)
{
await _repository.DeleteAsync(request.Id, cancellationToken);
return true;
}
}