using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.EntityFrameworkCore; using SIFinance.Modules.SousTraitants.Dtos; using SIFinance.Shared; using SIFinance.Shared.Entities; namespace SIFinance.Modules.SousTraitants.Endpoints; public static class ContratsPrestatairesEndpoints { public static IEndpointRouteBuilder MapContratsPrestatairesEndpoints(this IEndpointRouteBuilder app) { var group = app.MapGroup("/api/soustraitants/contrats").WithTags("SousTraitants-Contrats").RequireAuthorization(); group.MapGet("", async (SIFinanceDbContext db, CancellationToken ct) => await db.ContratsPrestataires .AsNoTracking() .Include(c => c.Organisme) .OrderByDescending(c => c.DateCreation) .Select(c => ToDto(c)) .ToListAsync(ct)); group.MapPost("", async (ContratPrestataireCreateDto input, SIFinanceDbContext db, CurrentUserService currentUser, CancellationToken ct) => { if (string.IsNullOrWhiteSpace(input.Objet)) return Results.BadRequest(new { error = "L'objet du contrat est requis." }); if (input.DateFin < input.DateDebut) return Results.BadRequest(new { error = "La date de fin doit être postérieure à la date de début." }); var contrat = new ContratPrestataire { OrganismeId = input.OrganismeId, Reference = await GenererReferenceAsync(db, ct), Objet = input.Objet.Trim(), DateSignature = input.DateSignature, DateDebut = input.DateDebut, DateFin = input.DateFin, MontantTotal = input.MontantTotal, Statut = "ACTIF", SaisieParId = await currentUser.GetOrCreateCurrentUserIdAsync(ct), DateCreation = DateTime.UtcNow, }; db.ContratsPrestataires.Add(contrat); try { await db.SaveChangesAsync(ct); } catch (DbUpdateException ex) { return Results.BadRequest(new { error = "Impossible d'enregistrer le contrat — vérifiez l'organisme.", detail = ex.InnerException?.Message ?? ex.Message }); } await db.Entry(contrat).Reference(c => c.Organisme).LoadAsync(ct); return Results.Created($"/api/soustraitants/contrats/{contrat.Id}", ToDto(contrat)); }); return app; } private static async Task GenererReferenceAsync(SIFinanceDbContext db, CancellationToken ct) { var prefix = $"ST-CONT-{DateTime.UtcNow.Year}-"; var last = await db.ContratsPrestataires .Where(c => c.Reference.StartsWith(prefix)) .OrderByDescending(c => c.Reference) .Select(c => c.Reference) .FirstOrDefaultAsync(ct); var nextSeq = 1; if (last is not null && int.TryParse(last.AsSpan(prefix.Length), out var lastSeq)) nextSeq = lastSeq + 1; return $"{prefix}{nextSeq:D3}"; } private static ContratPrestataireDto ToDto(ContratPrestataire c) => new( c.Id, c.OrganismeId, c.Organisme.RaisonSociale, c.Reference, c.Objet, c.DateSignature, c.DateDebut, c.DateFin, c.MontantTotal, c.Statut); }