Refactor Return and Ride services to integrate StockMover and enhance error handling

This commit is contained in:
2026-10-16 15:37:05 +05:30
parent 263e2ea9c0
commit c626f56cdb
4 changed files with 92 additions and 21 deletions
+4 -3
View File
@@ -1,11 +1,12 @@
using Distribution.Models;
using Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.Ride;
[ApiController]
[Route("api/rides")]
public class RideController(RideService service) : ControllerBase
public class RideController(RideService service, ICurrentUserService currentUser) : ControllerBase
{
[HttpGet]
public async Task<IActionResult> GetAll(
@@ -54,7 +55,7 @@ public class RideController(RideService service) : ControllerBase
{
try
{
var result = await service.CloseAsync(id, request, ct);
var result = await service.CloseAsync(id, request, currentUser.UserId ?? Guid.Empty, ct);
return Ok(result);
}
catch (KeyNotFoundException) { return NotFound(); }
@@ -66,7 +67,7 @@ public class RideController(RideService service) : ControllerBase
{
try
{
var result = await service.CancelAsync(id, request, ct);
var result = await service.CancelAsync(id, request, currentUser.UserId ?? Guid.Empty, ct);
return Ok(result);
}
catch (KeyNotFoundException) { return NotFound(); }
+16 -14
View File
@@ -10,7 +10,7 @@ public class RideService(
IRideRepository rideRepo,
IDriverProfileRepository driverRepo,
IDriverComplianceConfigRepository complianceRepo,
IStockRepository stockRepo,
StockMover mover,
IUnitOfWork uow)
{
public async Task<PagedResponse<RideResponse>> GetAllAsync(RideStatus? status, Guid? driverProfileId, Guid? vehicleId, int page, int pageSize)
@@ -76,7 +76,7 @@ public class RideService(
return ToResponse(saved!);
}
public async Task<RideResponse> CloseAsync(Guid rideId, CloseRideRequest request, CancellationToken ct = default)
public async Task<RideResponse> CloseAsync(Guid rideId, CloseRideRequest request, Guid userId, CancellationToken ct = default)
{
var ride = await rideRepo.GetByIdAsync(rideId)
?? throw new KeyNotFoundException("Ride not found");
@@ -87,20 +87,24 @@ public class RideService(
if (request.Meterend < ride.Meterstart)
throw new InvalidOperationException($"Meter end ({request.Meterend}) cannot be less than meter start ({ride.Meterstart})");
await EnsureVehicleStockClearedAsync(ride.FK_VehicleId);
ride.Status = RideStatus.Closed;
ride.ClosedAt = DateTime.Now;
ride.Meterend = request.Meterend;
// Whatever wasn't delivered goes back to the warehouse it was loaded from.
await uow.BeginAsync(ct);
try { rideRepo.Update(ride); await uow.CommitAsync(ct); }
try
{
await mover.UnloadVehicleAsync(ride.FK_VehicleId, ride.Id, userId, "RideClosed");
rideRepo.Update(ride);
await uow.CommitAsync(ct);
}
catch { await uow.RollbackAsync(ct); throw; }
return ToResponse(ride);
}
public async Task<RideResponse> CancelAsync(Guid rideId, CancelRideRequest request, CancellationToken ct = default)
public async Task<RideResponse> CancelAsync(Guid rideId, CancelRideRequest request, Guid userId, CancellationToken ct = default)
{
var ride = await rideRepo.GetByIdAsync(rideId)
?? throw new KeyNotFoundException("Ride not found");
@@ -113,7 +117,12 @@ public class RideService(
ride.CancelReason = request.Reason;
await uow.BeginAsync(ct);
try { rideRepo.Update(ride); await uow.CommitAsync(ct); }
try
{
await mover.UnloadVehicleAsync(ride.FK_VehicleId, ride.Id, userId, "RideCancelled");
rideRepo.Update(ride);
await uow.CommitAsync(ct);
}
catch { await uow.RollbackAsync(ct); throw; }
return ToResponse(ride);
@@ -139,13 +148,6 @@ public class RideService(
throw new InvalidOperationException("Driver medical clearance has expired");
}
private async Task EnsureVehicleStockClearedAsync(Guid vehicleId)
{
var balances = await stockRepo.GetBalancesByLocationAsync(vehicleId, LocationType.Vehicle);
if (balances.Any(b => b.Quantity > 0))
throw new InvalidOperationException("All vehicle stock must be returned before this ride can be completed");
}
private static RideResponse ToResponse(DeliveryRun r) =>
new(r.Id, r.Status,
r.FK_VehicleId, r.Vehicle?.NumberPlate ?? string.Empty,