Premier commit
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SIFinance.Modules.Achats.Dtos;
|
||||
using SIFinance.Shared;
|
||||
using SIFinance.Shared.Entities;
|
||||
|
||||
namespace SIFinance.Modules.Achats.Endpoints;
|
||||
|
||||
public static class BudgetsEndpoints
|
||||
{
|
||||
public static IEndpointRouteBuilder MapBudgetsEndpoints(this IEndpointRouteBuilder app)
|
||||
{
|
||||
var group = app.MapGroup("/api/budgets").WithTags("Budgets").RequireAuthorization();
|
||||
|
||||
// exercice optionnel : sans filtre, remonte tous les exercices connus (utile pour
|
||||
// un historique) — Pilotage passera l'exercice courant pour ne charger que l'utile.
|
||||
group.MapGet("", async (int? exercice, SIFinanceDbContext db, CancellationToken ct) =>
|
||||
{
|
||||
var query = db.BudgetsServices
|
||||
.AsNoTracking()
|
||||
.Include(b => b.Service)
|
||||
.Include(b => b.Revisions).ThenInclude(r => r.ReviseParUtilisateur)
|
||||
.AsQueryable();
|
||||
if (exercice.HasValue)
|
||||
query = query.Where(b => b.ExerciceAnnee == exercice.Value);
|
||||
|
||||
var budgets = await query.OrderBy(b => b.Service.Libelle).ToListAsync(ct);
|
||||
return budgets.Select(ToDto);
|
||||
});
|
||||
|
||||
group.MapPost("", async (CreateBudgetServiceDto input, SIFinanceDbContext db, CurrentUserService currentUser, CancellationToken ct) =>
|
||||
{
|
||||
if (!await currentUser.HasRoleAsync("FINANCE", db, ct))
|
||||
return Results.Forbid();
|
||||
if (input.MontantInitial <= 0)
|
||||
return Results.BadRequest(new { error = "Le montant initial doit être supérieur à 0." });
|
||||
|
||||
var existeDeja = await db.BudgetsServices
|
||||
.AnyAsync(b => b.ServiceId == input.ServiceId && b.ExerciceAnnee == input.ExerciceAnnee, ct);
|
||||
if (existeDeja)
|
||||
return Results.BadRequest(new { error = "Un budget existe déjà pour ce service sur cet exercice." });
|
||||
|
||||
var budget = new BudgetService
|
||||
{
|
||||
ServiceId = input.ServiceId,
|
||||
ExerciceAnnee = input.ExerciceAnnee,
|
||||
MontantInitial = input.MontantInitial,
|
||||
SaisieParId = await currentUser.GetOrCreateCurrentUserIdAsync(ct),
|
||||
DateCreation = DateTime.UtcNow,
|
||||
};
|
||||
db.BudgetsServices.Add(budget);
|
||||
await db.SaveChangesAsync(ct);
|
||||
|
||||
await db.Entry(budget).Reference(b => b.Service).LoadAsync(ct);
|
||||
return Results.Created($"/api/budgets/{budget.Id}", ToDto(budget));
|
||||
});
|
||||
|
||||
// Réservé à FINANCE : seul le responsable Finance qui gère le budget peut
|
||||
// l'augmenter en cours d'exercice. Chaque appel ajoute une ligne à l'historique
|
||||
// (budgets_service_revisions) plutôt que d'écraser une valeur unique.
|
||||
group.MapPost("/{id:int}/revisions", async (int id, CreateBudgetRevisionDto input, SIFinanceDbContext db, CurrentUserService currentUser, CancellationToken ct) =>
|
||||
{
|
||||
if (!await currentUser.HasRoleAsync("FINANCE", db, ct))
|
||||
return Results.Forbid();
|
||||
|
||||
var budget = await db.BudgetsServices
|
||||
.Include(b => b.Service)
|
||||
.Include(b => b.Revisions).ThenInclude(r => r.ReviseParUtilisateur)
|
||||
.FirstOrDefaultAsync(b => b.Id == id, ct);
|
||||
if (budget is null) return Results.NotFound();
|
||||
if (input.MontantRevise <= 0)
|
||||
return Results.BadRequest(new { error = "Le montant révisé doit être supérieur à 0." });
|
||||
|
||||
var revision = new BudgetServiceRevision
|
||||
{
|
||||
BudgetServiceId = id,
|
||||
MontantRevise = input.MontantRevise,
|
||||
Commentaire = string.IsNullOrWhiteSpace(input.Commentaire) ? null : input.Commentaire.Trim(),
|
||||
RevisePar = await currentUser.GetOrCreateCurrentUserIdAsync(ct),
|
||||
DateRevision = DateTime.UtcNow,
|
||||
};
|
||||
db.BudgetServiceRevisions.Add(revision);
|
||||
budget.DateDerniereMaj = DateTime.UtcNow;
|
||||
await db.SaveChangesAsync(ct);
|
||||
|
||||
await db.Entry(revision).Reference(r => r.ReviseParUtilisateur).LoadAsync(ct);
|
||||
budget.Revisions.Add(revision);
|
||||
return Results.Created($"/api/budgets/{id}/revisions/{revision.Id}", ToDto(budget));
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
private static BudgetServiceDto ToDto(BudgetService b)
|
||||
{
|
||||
var revisions = b.Revisions
|
||||
.OrderByDescending(r => r.DateRevision)
|
||||
.Select(r => new BudgetRevisionDto(
|
||||
r.Id, r.MontantRevise, r.Commentaire,
|
||||
$"{r.ReviseParUtilisateur.Prenom} {r.ReviseParUtilisateur.Nom}".Trim(),
|
||||
r.DateRevision))
|
||||
.ToList();
|
||||
return new BudgetServiceDto(
|
||||
b.Id, b.ServiceId, b.Service.Libelle, b.ExerciceAnnee,
|
||||
b.MontantInitial, revisions.Count > 0 ? revisions[0].MontantRevise : null,
|
||||
revisions);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user