Add FlatPaymentController with RESTful payment endpoints

Introduced FlatPaymentController under Distribution.Features.Payment, providing GET and POST endpoints at /api/payments. Supports listing, retrieving, and creating payments with filtering and error handling. Business logic is delegated to PaymentService.
This commit is contained in:
Kalana B. Thilakarathna
2026-08-26 20:18:58 +05:30
parent 83d3272784
commit dc7e7a70fc
27 changed files with 539 additions and 38 deletions
@@ -1,10 +1,15 @@
using Microsoft.AspNetCore.Mvc;
using Distribution.Features.DriverComplianceConfig;
using Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.DriverProfile;
[ApiController]
[Route("api/driver-profiles")]
public class DriverProfileController(DriverProfileService service) : ControllerBase
public class DriverProfileController(
DriverProfileService service,
DriverComplianceConfigService complianceService,
ICurrentUserService currentUser) : ControllerBase
{
[HttpGet]
public async Task<IActionResult> GetAll([FromQuery] int page = 1, [FromQuery] int pageSize = 20)
@@ -23,8 +28,19 @@ public class DriverProfileController(DriverProfileService service) : ControllerB
[HttpPost]
public async Task<IActionResult> Create(CreateDriverProfileRequest request, CancellationToken ct)
{
var result = await service.CreateAsync(request, ct);
return CreatedAtAction(nameof(GetById), new { id = result.Id }, result);
try
{
var result = await service.CreateAsync(request, ct);
return CreatedAtAction(nameof(GetById), new { id = result.Id }, result);
}
catch (KeyNotFoundException ex)
{
return NotFound(new { error = ex.Message });
}
catch (InvalidOperationException ex)
{
return Conflict(new { error = ex.Message });
}
}
[HttpPut("{id:guid}")]
@@ -40,4 +56,19 @@ public class DriverProfileController(DriverProfileService service) : ControllerB
var success = await service.DeactivateAsync(id, ct);
return success ? NoContent() : NotFound();
}
[HttpGet("compliance")]
public async Task<IActionResult> GetCompliance()
{
var result = await complianceService.GetAsync();
return result is null ? NoContent() : Ok(result);
}
[HttpPut("compliance")]
public async Task<IActionResult> UpsertCompliance(UpdateDriverComplianceConfigRequest request, CancellationToken ct)
{
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
var result = await complianceService.UpsertAsync(request, userId, ct);
return Ok(result);
}
}
@@ -11,7 +11,7 @@ public record DriverProfileResponse(
DateTime CreatedAt);
public record CreateDriverProfileRequest(
Guid FK_UserId,
Guid UserId,
string LicenseNumber,
DateTime LicenseExpiry,
DateTime MedicalClearanceExpiry);
@@ -1,9 +1,10 @@
using Distribution.Features.Stock;
using Distribution.Features.User;
using Distribution.Infra.UoW;
namespace Distribution.Features.DriverProfile;
public class DriverProfileService(IDriverProfileRepository repo, IUnitOfWork uow)
public class DriverProfileService(IDriverProfileRepository repo, IUnitOfWork uow, IUserRepository userRepo)
{
public async Task<PagedResponse<DriverProfileResponse>> GetAllAsync(int page, int pageSize)
{
@@ -21,13 +22,17 @@ public class DriverProfileService(IDriverProfileRepository repo, IUnitOfWork uow
public async Task<DriverProfileResponse> CreateAsync(CreateDriverProfileRequest request, CancellationToken ct = default)
{
var existing = await repo.GetByUserIdAsync(request.FK_UserId);
var user = await userRepo.GetByIdAsync(request.UserId);
if (user is null)
throw new KeyNotFoundException($"User {request.UserId} not found");
var existing = await repo.GetByUserIdAsync(request.UserId);
if (existing is not null && existing.IsActive)
throw new InvalidOperationException("An active driver profile already exists for this user");
var profile = new global::Distribution.Models.DriverProfile
{
FK_UserId = request.FK_UserId,
FK_UserId = request.UserId,
LicenseNumber = request.LicenseNumber,
LicenseExpiry = request.LicenseExpiry,
MedicalClearanceExpiry = request.MedicalClearanceExpiry