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
@@ -1,11 +1,12 @@
using Distribution.Models;
using Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.DeliveryRide;
[ApiController]
[Route("api")]
public class DeliveryTaskController(DeliveryTaskService service) : ControllerBase
public class DeliveryTaskController(DeliveryTaskService service, ICurrentUserService currentUser) : ControllerBase
{
[HttpPost("rides/{rideId:guid}/tasks/generate")]
public async Task<IActionResult> Generate(Guid rideId, CancellationToken ct)
@@ -61,7 +62,7 @@ public class DeliveryTaskController(DeliveryTaskService service) : ControllerBas
{
try
{
var result = await service.ConfirmAsync(id, ct);
var result = await service.ConfirmAsync(id, currentUser.UserId ?? Guid.Empty, ct);
return Ok(result);
}
catch (KeyNotFoundException) { return NotFound(); }
@@ -12,7 +12,7 @@ public class DeliveryTaskService(
IRideRepository rideRepo,
IShopPORepository shopPORepo,
ILoadingSheetRepository loadingSheetRepo,
IStockRepository stockRepo,
StockMover mover,
IUnitOfWork uow)
{
private static DeliveryTaskResponse ToResponse(DeliveryTask t) =>
@@ -134,7 +134,7 @@ public class DeliveryTaskService(
return ToResponse(saved!);
}
public async Task<DeliveryTaskResponse> ConfirmAsync(Guid taskId, CancellationToken ct = default)
public async Task<DeliveryTaskResponse> ConfirmAsync(Guid taskId, Guid userId, CancellationToken ct = default)
{
var task = await repo.GetByIdAsync(taskId)
?? throw new KeyNotFoundException("Delivery task not found");
@@ -166,29 +166,12 @@ public class DeliveryTaskService(
{
foreach (var item in task.ShopPO.Items.Where(i => i.QuantityFulfilled > 0))
{
var vehicleBalance = await stockRepo.GetBalanceAsync(item.FK_ItemId, vehicleId);
var availableQuantity = vehicleBalance?.Quantity ?? 0;
var itemName = item.Item?.Name ?? item.FK_ItemId.ToString();
if (availableQuantity < item.QuantityFulfilled)
throw new InvalidOperationException(
$"Insufficient vehicle stock for item '{itemName}': available {availableQuantity}, required {item.QuantityFulfilled}");
vehicleBalance!.Quantity -= item.QuantityFulfilled;
vehicleBalance.UpdatedAt = DateTime.Now;
stockRepo.UpdateBalance(vehicleBalance);
await stockRepo.AddMovementAsync(new StockMovement
{
FK_ItemId = item.FK_ItemId,
FromLocationId = vehicleId,
FromLocationType = LocationType.Vehicle,
ToLocationId = StockService.ExternalLocationId,
ToLocationType = LocationType.External,
Quantity = item.QuantityFulfilled,
Type = MovementType.Sale,
ReferenceId = task.FK_ShopPOId
});
await mover.MoveAsync(item.FK_ItemId, itemName,
vehicleId, LocationType.Vehicle,
StockService.ExternalLocationId, LocationType.External,
item.QuantityFulfilled, MovementType.Sale, task.FK_ShopPOId, userId);
}
repo.Update(task);