Refactor Delivery and Purchase Return services to use StockMover for inventory movements

This commit is contained in:
2026-10-16 15:34:25 +05:30
parent e5f6aa15b9
commit 263e2ea9c0
4 changed files with 21 additions and 99 deletions
@@ -8,7 +8,7 @@ namespace Distribution.Features.LoadingEvent;
public class LoadingSheetService(
ILoadingSheetRepository repo,
IRideRepository rideRepo,
IStockRepository stockRepo,
StockMover mover,
IUnitOfWork uow)
{
public async Task<PagedResponse<LoadingSheetResponse>> GetAllAsync(Guid? rideId, LoadingSheetStatus? status, Guid? routeId, Guid? regionId, int page, int pageSize)
@@ -154,59 +154,14 @@ public class LoadingSheetService(
private async Task ApplyLoadMovementsAsync(Guid sheetId, Guid vehicleId, List<LoadingSheetItem> items, Guid userId)
{
// Vehicle balances created during this confirm are only tracked, not yet saved, so a
// later row for the same item would not find them via the repository and would try to
// insert a duplicate (item, vehicle) balance.
var createdVehicleBalances = new Dictionary<Guid, StockBalance>();
foreach (var item in items.Where(i => i.QuantityDispatched > 0))
{
var warehouseBalance = await stockRepo.GetBalanceAsync(item.FK_ItemId, item.FK_WarehouseId)
?? throw new InvalidOperationException(
$"No stock found for '{item.Item?.Name ?? item.FK_ItemId.ToString()}' in warehouse '{item.Warehouse?.Name ?? item.FK_WarehouseId.ToString()}'");
var label = $"{item.Item?.Name ?? item.FK_ItemId.ToString()} (warehouse {item.Warehouse?.Name ?? item.FK_WarehouseId.ToString()})";
if (warehouseBalance.Quantity < item.QuantityDispatched)
throw new InvalidOperationException(
$"Insufficient stock for '{item.Item?.Name ?? item.FK_ItemId.ToString()}' in warehouse '{item.Warehouse?.Name ?? item.FK_WarehouseId.ToString()}' " +
$"(available {warehouseBalance.Quantity}, needed {item.QuantityDispatched})");
warehouseBalance.Quantity -= item.QuantityDispatched;
warehouseBalance.UpdatedAt = DateTime.Now;
stockRepo.UpdateBalance(warehouseBalance);
var vehicleBalance = createdVehicleBalances.GetValueOrDefault(item.FK_ItemId)
?? await stockRepo.GetBalanceAsync(item.FK_ItemId, vehicleId);
if (vehicleBalance is null)
{
var created = new StockBalance
{
FK_ItemId = item.FK_ItemId,
LocationId = vehicleId,
LocationType = LocationType.Vehicle,
Quantity = item.QuantityDispatched
};
createdVehicleBalances[item.FK_ItemId] = created;
await stockRepo.AddBalanceAsync(created);
}
else
{
vehicleBalance.Quantity += item.QuantityDispatched;
vehicleBalance.UpdatedAt = DateTime.Now;
stockRepo.UpdateBalance(vehicleBalance);
}
await stockRepo.AddMovementAsync(new StockMovement
{
FK_ItemId = item.FK_ItemId,
FromLocationId = item.FK_WarehouseId,
FromLocationType = LocationType.Warehouse,
ToLocationId = vehicleId,
ToLocationType = LocationType.Vehicle,
Quantity = item.QuantityDispatched,
Type = MovementType.Load,
ReferenceId = sheetId,
CreatedBy = userId
});
await mover.MoveAsync(item.FK_ItemId, label,
item.FK_WarehouseId, LocationType.Warehouse,
vehicleId, LocationType.Vehicle,
item.QuantityDispatched, MovementType.Load, sheetId, userId);
}
}