Files
unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/resource/BudgetResource.java

193 lines
7.6 KiB
Java

package dev.lions.unionflow.server.resource;
import dev.lions.unionflow.server.service.BudgetService;
import dev.lions.unionflow.server.common.ErrorResponse;
import dev.lions.unionflow.server.api.dto.finance_workflow.request.CreateBudgetRequest;
import dev.lions.unionflow.server.api.dto.finance_workflow.response.BudgetResponse;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* Resource REST pour la gestion des budgets
*
* @author UnionFlow Team
* @version 1.0
* @since 2026-03-13
*/
@Path("/api/finance/budgets")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Finance - Budgets", description = "Gestion des budgets organisationnels")
public class BudgetResource {
private static final Logger LOG = Logger.getLogger(BudgetResource.class);
@Inject
BudgetService budgetService;
@GET
@RolesAllowed({"ADMIN_ORGANISATION", "SUPER_ADMIN"})
@Operation(summary = "Récupère les budgets",
description = "Liste tous les budgets d'une organisation avec filtres optionnels")
public Response getBudgets(
@QueryParam("organizationId") UUID organizationId,
@QueryParam("status") String status,
@QueryParam("year") Integer year) {
LOG.infof("GET /api/finance/budgets?organizationId=%s&status=%s&year=%s",
organizationId, status, year);
try {
List<BudgetResponse> budgets = budgetService.getBudgets(organizationId, status, year);
return Response.ok(budgets).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(ErrorResponse.of(e.getMessage()))
.build();
} catch (Exception e) {
LOG.error("Erreur lors de la récupération des budgets", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(ErrorResponse.of(e.getMessage()))
.build();
}
}
@GET
@Path("/{budgetId}")
@RolesAllowed({"ADMIN_ORGANISATION", "SUPER_ADMIN"})
@Operation(summary = "Récupère un budget par ID",
description = "Retourne les détails complets d'un budget")
public Response getBudgetById(@PathParam("budgetId") UUID budgetId) {
LOG.infof("GET /api/finance/budgets/%s", budgetId);
try {
BudgetResponse budget = budgetService.getBudgetById(budgetId);
return Response.ok(budget).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(ErrorResponse.of(e.getMessage()))
.build();
} catch (Exception e) {
LOG.error("Erreur lors de la récupération du budget", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(ErrorResponse.of(e.getMessage()))
.build();
}
}
@POST
@RolesAllowed({"ADMIN_ORGANISATION", "SUPER_ADMIN"})
@Operation(summary = "Crée un nouveau budget",
description = "Crée un budget avec ses lignes budgétaires")
public Response createBudget(@Valid CreateBudgetRequest request) {
LOG.infof("POST /api/finance/budgets - Creating budget: %s", request.getName());
try {
BudgetResponse budget = budgetService.createBudget(request);
return Response.status(Response.Status.CREATED)
.entity(budget)
.build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(ErrorResponse.of(e.getMessage()))
.build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(ErrorResponse.of(e.getMessage()))
.build();
} catch (Exception e) {
LOG.error("Erreur lors de la création du budget", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(ErrorResponse.of(e.getMessage()))
.build();
}
}
@GET
@Path("/{budgetId}/tracking")
@RolesAllowed({"ADMIN_ORGANISATION", "SUPER_ADMIN"})
@Operation(summary = "Récupère le suivi budgétaire",
description = "Retourne les statistiques de suivi et réalisation du budget")
public Response getBudgetTracking(@PathParam("budgetId") UUID budgetId) {
LOG.infof("GET /api/finance/budgets/%s/tracking", budgetId);
try {
Map<String, Object> tracking = budgetService.getBudgetTracking(budgetId);
return Response.ok(tracking).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(ErrorResponse.of(e.getMessage()))
.build();
} catch (Exception e) {
LOG.error("Erreur lors de la récupération du suivi budgétaire", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(ErrorResponse.of(e.getMessage()))
.build();
}
}
@PUT
@Path("/{budgetId}")
@RolesAllowed({"ADMIN_ORGANISATION", "SUPER_ADMIN"})
@Operation(summary = "Met à jour un budget",
description = "Modifie un budget existant (nom, description, lignes, statut)")
public Response updateBudget(
@PathParam("budgetId") UUID budgetId,
Map<String, Object> updates) {
LOG.infof("PUT /api/finance/budgets/%s", budgetId);
try {
BudgetResponse budget = budgetService.updateBudget(budgetId, updates);
return Response.ok(budget).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(ErrorResponse.of(e.getMessage()))
.build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(ErrorResponse.of(e.getMessage()))
.build();
} catch (Exception e) {
LOG.error("Erreur lors de la mise à jour du budget", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(ErrorResponse.of(e.getMessage()))
.build();
}
}
@DELETE
@Path("/{budgetId}")
@RolesAllowed({"ADMIN_ORGANISATION", "SUPER_ADMIN"})
@Operation(summary = "Supprime un budget",
description = "Supprime logiquement un budget (soft delete)")
public Response deleteBudget(@PathParam("budgetId") UUID budgetId) {
LOG.infof("DELETE /api/finance/budgets/%s", budgetId);
try {
budgetService.deleteBudget(budgetId);
return Response.noContent().build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(ErrorResponse.of(e.getMessage()))
.build();
} catch (Exception e) {
LOG.error("Erreur lors de la suppression du budget", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(ErrorResponse.of(e.getMessage()))
.build();
}
}
}