Premier commit
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
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 PaiementsEndpoints
|
||||
{
|
||||
public static IEndpointRouteBuilder MapPaiementsEndpoints(this IEndpointRouteBuilder app)
|
||||
{
|
||||
var group = app.MapGroup("/api/paiements").WithTags("Paiements").RequireAuthorization();
|
||||
|
||||
group.MapGet("/factures-disponibles", async (SIFinanceDbContext db, CancellationToken ct) =>
|
||||
{
|
||||
var facturesPayeesIds = db.Paiements.Select(p => p.FactureId);
|
||||
return await db.Factures
|
||||
.AsNoTracking()
|
||||
.Include(f => f.Fournisseur)
|
||||
.Where(f => f.Statut == "validee" && !facturesPayeesIds.Contains(f.Id))
|
||||
.OrderBy(f => f.DateFacture)
|
||||
.Select(f => new FactureDisponibleDto(f.Id, f.FournisseurId, f.Fournisseur.RaisonSociale, f.NumeroFacture, f.MontantTtc, f.DateFacture))
|
||||
.ToListAsync(ct);
|
||||
});
|
||||
|
||||
group.MapGet("", async (SIFinanceDbContext db, CancellationToken ct) =>
|
||||
{
|
||||
var paiements = await db.Paiements
|
||||
.AsNoTracking()
|
||||
.Include(p => p.Facture).ThenInclude(f => f.Fournisseur)
|
||||
.Include(p => p.ModeReglement)
|
||||
.ToListAsync(ct);
|
||||
|
||||
return paiements
|
||||
.GroupBy(p => p.ReferencePaiement ?? $"PAI-{p.Id}")
|
||||
.Select(g =>
|
||||
{
|
||||
var first = g.First();
|
||||
return new PaiementGroupeDto(
|
||||
g.Key, first.Facture.FournisseurId, first.Facture.Fournisseur.RaisonSociale,
|
||||
g.Select(p => p.FactureId).ToList(),
|
||||
g.Select(p => p.Facture.NumeroFacture).ToList(),
|
||||
g.Sum(p => p.MontantPaye),
|
||||
first.ModeReglementId, first.ModeReglement.Libelle,
|
||||
first.DatePaiement, first.Statut, first.Rapproche);
|
||||
})
|
||||
.OrderByDescending(p => p.DatePaiement);
|
||||
});
|
||||
|
||||
group.MapPost("", async (CreatePaiementDto input, SIFinanceDbContext db, CurrentUserService currentUser, CancellationToken ct) =>
|
||||
{
|
||||
if (input.FactureIds.Count == 0)
|
||||
return Results.BadRequest(new { error = "Sélectionner au moins une facture." });
|
||||
if (string.IsNullOrWhiteSpace(input.Reference))
|
||||
return Results.BadRequest(new { error = "La référence de paiement est requise." });
|
||||
|
||||
var factures = await db.Factures.Where(f => input.FactureIds.Contains(f.Id)).ToListAsync(ct);
|
||||
if (factures.Count != input.FactureIds.Count)
|
||||
return Results.BadRequest(new { error = "Une ou plusieurs factures sont introuvables." });
|
||||
if (factures.Select(f => f.FournisseurId).Distinct().Count() > 1)
|
||||
return Results.BadRequest(new { error = "Un paiement regroupe uniquement des factures d'un même fournisseur." });
|
||||
|
||||
var dejaCouvertes = await db.Paiements.AnyAsync(p => input.FactureIds.Contains(p.FactureId), ct);
|
||||
if (dejaCouvertes)
|
||||
return Results.BadRequest(new { error = "Une ou plusieurs factures sont déjà couvertes par un paiement." });
|
||||
|
||||
var referenceExistante = await db.Paiements.AnyAsync(p => p.ReferencePaiement == input.Reference, ct);
|
||||
if (referenceExistante)
|
||||
return Results.BadRequest(new { error = "Cette référence de paiement existe déjà." });
|
||||
|
||||
var currentUserId = await currentUser.GetOrCreateCurrentUserIdAsync(ct);
|
||||
var lignes = factures.Select(f => new Paiement
|
||||
{
|
||||
FactureId = f.Id,
|
||||
MontantPaye = f.MontantTtc,
|
||||
DatePaiement = input.DatePaiement,
|
||||
ModeReglementId = input.ModePaiementId,
|
||||
ReferencePaiement = input.Reference,
|
||||
EnregistreParId = currentUserId,
|
||||
DateSaisie = DateTime.UtcNow,
|
||||
Statut = input.Statut,
|
||||
Rapproche = input.Rapproche,
|
||||
}).ToList();
|
||||
|
||||
db.Paiements.AddRange(lignes);
|
||||
try
|
||||
{
|
||||
await db.SaveChangesAsync(ct);
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
return Results.BadRequest(new { error = "Impossible d'enregistrer le paiement.", detail = ex.InnerException?.Message ?? ex.Message });
|
||||
}
|
||||
|
||||
return Results.Created($"/api/paiements/{Uri.EscapeDataString(input.Reference)}", (object?)null);
|
||||
});
|
||||
|
||||
group.MapPatch("/{reference}", async (string reference, UpdatePaiementDto input, SIFinanceDbContext db, CancellationToken ct) =>
|
||||
{
|
||||
var lignes = await db.Paiements.Where(p => p.ReferencePaiement == reference).ToListAsync(ct);
|
||||
if (lignes.Count == 0) return Results.NotFound();
|
||||
|
||||
foreach (var p in lignes)
|
||||
{
|
||||
p.ModeReglementId = input.ModePaiementId;
|
||||
p.DatePaiement = input.DatePaiement;
|
||||
p.ReferencePaiement = input.Reference;
|
||||
p.Statut = input.Statut;
|
||||
p.Rapproche = input.Rapproche;
|
||||
}
|
||||
await db.SaveChangesAsync(ct);
|
||||
return Results.NoContent();
|
||||
});
|
||||
|
||||
group.MapPatch("/{reference}/rapproche", async (string reference, SIFinanceDbContext db, CancellationToken ct) =>
|
||||
{
|
||||
var lignes = await db.Paiements.Where(p => p.ReferencePaiement == reference).ToListAsync(ct);
|
||||
if (lignes.Count == 0) return Results.NotFound();
|
||||
|
||||
var nouvelEtat = !lignes[0].Rapproche;
|
||||
foreach (var p in lignes) p.Rapproche = nouvelEtat;
|
||||
await db.SaveChangesAsync(ct);
|
||||
return Results.Ok(new { rapproche = nouvelEtat });
|
||||
});
|
||||
|
||||
group.MapDelete("/{reference}", async (string reference, SIFinanceDbContext db, CancellationToken ct) =>
|
||||
{
|
||||
var lignes = await db.Paiements.Where(p => p.ReferencePaiement == reference).ToListAsync(ct);
|
||||
if (lignes.Count == 0) return Results.NotFound();
|
||||
db.Paiements.RemoveRange(lignes);
|
||||
await db.SaveChangesAsync(ct);
|
||||
return Results.NoContent();
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user