using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.EntityFrameworkCore; using SIFinance.Modules.Finance.Dtos; using SIFinance.Shared; using SIFinance.Shared.Entities; namespace SIFinance.Modules.Finance.Endpoints; public static class AvoirsEndpoints { public static IEndpointRouteBuilder MapAvoirsEndpoints(this IEndpointRouteBuilder app) { var group = app.MapGroup("/api/avoirs").WithTags("Avoirs").RequireAuthorization(); group.MapGet("", async (SIFinanceDbContext db, CancellationToken ct) => // Projection directe en DTO : EF ne récupère que les colonnes utiles et // ne remonte qu'une seule affectation, au lieu de charger toute la collection. await db.Avoirs .AsNoTracking() .OrderByDescending(a => a.DateCreation) .Select(a => new AvoirDto( a.Id, a.NumeroAvoir, a.FournisseurId, a.Fournisseur.RaisonSociale, a.MontantInitial, a.SoldeDisponible, a.DateAvoir, a.AffectationsAvoirs.Select(af => (int?)af.FactureId).FirstOrDefault(), a.AffectationsAvoirs.Select(af => af.Facture.NumeroFacture).FirstOrDefault())) .ToListAsync(ct)); group.MapPost("", async (CreateAvoirDto input, SIFinanceDbContext db, CurrentUserService currentUser, CancellationToken ct) => { if (string.IsNullOrWhiteSpace(input.Numero)) return Results.BadRequest(new { error = "Le numéro d'avoir est requis." }); if (input.Montant <= 0) return Results.BadRequest(new { error = "Le montant doit être supérieur à 0." }); var avoir = new Avoir { FournisseurId = input.FournisseurId, NumeroAvoir = input.Numero.Trim(), DateAvoir = input.Date, MontantInitial = input.Montant, SoldeDisponible = input.Montant, SaisieParId = await currentUser.GetOrCreateCurrentUserIdAsync(ct), DateCreation = DateTime.UtcNow, }; db.Avoirs.Add(avoir); try { await db.SaveChangesAsync(ct); } catch (DbUpdateException ex) { return Results.BadRequest(new { error = "Impossible d'enregistrer l'avoir — vérifiez le fournisseur.", detail = ex.InnerException?.Message ?? ex.Message }); } await db.Entry(avoir).Reference(a => a.Fournisseur).LoadAsync(ct); return Results.Created($"/api/avoirs/{avoir.Id}", ToDto(avoir)); }); return app; } private static AvoirDto ToDto(Avoir a) { var affectation = a.AffectationsAvoirs.FirstOrDefault(); return new AvoirDto( a.Id, a.NumeroAvoir, a.FournisseurId, a.Fournisseur.RaisonSociale, a.MontantInitial, a.SoldeDisponible, a.DateAvoir, affectation?.FactureId, affectation?.Facture.NumeroFacture); } }