03_ride_lifecycle implemented and not tested

This commit is contained in:
Kalana B. Thilakarathna
2026-08-21 02:08:11 +05:30
parent 942a39b0eb
commit c9f5006727
62 changed files with 10736 additions and 77 deletions
@@ -0,0 +1,50 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.DriverProfile;
[ApiController]
[Route("api/driver-profiles")]
[Authorize]
public class DriverProfileController(DriverProfileService service) : ControllerBase
{
[HttpGet]
[Authorize(Policy = "driver_profiles.view")]
public async Task<IActionResult> GetAll([FromQuery] int page = 1, [FromQuery] int pageSize = 20)
{
var result = await service.GetAllAsync(page, pageSize);
return Ok(result);
}
[HttpGet("{id:guid}")]
[Authorize(Policy = "driver_profiles.view")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await service.GetByIdAsync(id);
return result is null ? NotFound() : Ok(result);
}
[HttpPost]
[Authorize(Policy = "driver_profiles.create")]
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);
}
[HttpPut("{id:guid}")]
[Authorize(Policy = "driver_profiles.update")]
public async Task<IActionResult> Update(Guid id, UpdateDriverProfileRequest request, CancellationToken ct)
{
var result = await service.UpdateAsync(id, request, ct);
return result is null ? NotFound() : Ok(result);
}
[HttpDelete("{id:guid}")]
[Authorize(Policy = "driver_profiles.deactivate")]
public async Task<IActionResult> Deactivate(Guid id, CancellationToken ct)
{
var success = await service.DeactivateAsync(id, ct);
return success ? NoContent() : NotFound();
}
}
@@ -0,0 +1,22 @@
namespace Distribution.Features.DriverProfile;
public record DriverProfileResponse(
Guid Id,
Guid UserId,
string UserFullName,
string LicenseNumber,
DateTime LicenseExpiry,
DateTime MedicalClearanceExpiry,
bool IsActive,
DateTime CreatedAt);
public record CreateDriverProfileRequest(
Guid FK_UserId,
string LicenseNumber,
DateTime LicenseExpiry,
DateTime MedicalClearanceExpiry);
public record UpdateDriverProfileRequest(
string LicenseNumber,
DateTime LicenseExpiry,
DateTime MedicalClearanceExpiry);
@@ -0,0 +1,40 @@
using Distribution.Data;
using Microsoft.EntityFrameworkCore;
namespace Distribution.Features.DriverProfile;
public class DriverProfileRepository(AppDBContext context) : IDriverProfileRepository
{
public async Task<global::Distribution.Models.DriverProfile?> GetByIdAsync(Guid id) =>
await context.DriverProfiles
.Include(p => p.User)
.FirstOrDefaultAsync(p => p.Id == id);
public async Task<global::Distribution.Models.DriverProfile?> GetByUserIdAsync(Guid userId) =>
await context.DriverProfiles
.Include(p => p.User)
.FirstOrDefaultAsync(p => p.FK_UserId == userId);
public async Task<List<global::Distribution.Models.DriverProfile>> GetAllAsync(int page, int pageSize) =>
await context.DriverProfiles
.Include(p => p.User)
.Where(p => p.IsActive)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
public async Task<int> GetCountAsync() =>
await context.DriverProfiles.CountAsync(p => p.IsActive);
public async Task AddAsync(global::Distribution.Models.DriverProfile profile) =>
await context.DriverProfiles.AddAsync(profile);
public void Update(global::Distribution.Models.DriverProfile profile) =>
context.DriverProfiles.Update(profile);
public void Deactivate(global::Distribution.Models.DriverProfile profile)
{
profile.IsActive = false;
context.DriverProfiles.Update(profile);
}
}
@@ -0,0 +1,100 @@
using Distribution.Features.Stock;
using Distribution.Infra.UoW;
namespace Distribution.Features.DriverProfile;
public class DriverProfileService(IDriverProfileRepository repo, IUnitOfWork uow)
{
public async Task<PagedResponse<DriverProfileResponse>> GetAllAsync(int page, int pageSize)
{
var total = await repo.GetCountAsync();
var items = await repo.GetAllAsync(page, pageSize);
return new PagedResponse<DriverProfileResponse>(page, pageSize, total,
items.Select(ToResponse).ToList());
}
public async Task<DriverProfileResponse?> GetByIdAsync(Guid id)
{
var profile = await repo.GetByIdAsync(id);
return profile is null || !profile.IsActive ? null : ToResponse(profile);
}
public async Task<DriverProfileResponse> CreateAsync(CreateDriverProfileRequest request, CancellationToken ct = default)
{
var existing = await repo.GetByUserIdAsync(request.FK_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,
LicenseNumber = request.LicenseNumber,
LicenseExpiry = request.LicenseExpiry,
MedicalClearanceExpiry = request.MedicalClearanceExpiry
};
await uow.BeginAsync(ct);
try
{
await repo.AddAsync(profile);
await uow.CommitAsync(ct);
}
catch
{
await uow.RollbackAsync(ct);
throw;
}
var saved = await repo.GetByIdAsync(profile.Id);
return ToResponse(saved!);
}
public async Task<DriverProfileResponse?> UpdateAsync(Guid id, UpdateDriverProfileRequest request, CancellationToken ct = default)
{
var profile = await repo.GetByIdAsync(id);
if (profile is null || !profile.IsActive) return null;
profile.LicenseNumber = request.LicenseNumber;
profile.LicenseExpiry = request.LicenseExpiry;
profile.MedicalClearanceExpiry = request.MedicalClearanceExpiry;
await uow.BeginAsync(ct);
try
{
repo.Update(profile);
await uow.CommitAsync(ct);
}
catch
{
await uow.RollbackAsync(ct);
throw;
}
return ToResponse(profile);
}
public async Task<bool> DeactivateAsync(Guid id, CancellationToken ct = default)
{
var profile = await repo.GetByIdAsync(id);
if (profile is null || !profile.IsActive) return false;
await uow.BeginAsync(ct);
try
{
repo.Deactivate(profile);
await uow.CommitAsync(ct);
}
catch
{
await uow.RollbackAsync(ct);
throw;
}
return true;
}
private static DriverProfileResponse ToResponse(global::Distribution.Models.DriverProfile p) =>
new(p.Id, p.FK_UserId, p.User?.FullName ?? string.Empty,
p.LicenseNumber, p.LicenseExpiry, p.MedicalClearanceExpiry,
p.IsActive, p.CreatedAt);
}
@@ -0,0 +1,12 @@
namespace Distribution.Features.DriverProfile;
public interface IDriverProfileRepository
{
Task<global::Distribution.Models.DriverProfile?> GetByIdAsync(Guid id);
Task<global::Distribution.Models.DriverProfile?> GetByUserIdAsync(Guid userId);
Task<List<global::Distribution.Models.DriverProfile>> GetAllAsync(int page, int pageSize);
Task<int> GetCountAsync();
Task AddAsync(global::Distribution.Models.DriverProfile profile);
void Update(global::Distribution.Models.DriverProfile profile);
void Deactivate(global::Distribution.Models.DriverProfile profile);
}