Refactoring - Version stable

This commit is contained in:
dahoud
2026-03-28 14:21:30 +00:00
parent 00b981c510
commit a740c172ef
4402 changed files with 88517 additions and 1555 deletions

View File

@@ -113,7 +113,14 @@ public class AlerteLcbFtResource {
alerte.setTraitee(true);
alerte.setDateTraitement(LocalDateTime.now());
alerte.setTraitePar(body.get("traitePar"));
String traiteParStr = body.get("traitePar");
if (traiteParStr != null && !traiteParStr.isBlank()) {
try {
alerte.setTraitePar(UUID.fromString(traiteParStr));
} catch (IllegalArgumentException e) {
throw new BadRequestException("traitePar doit être un UUID valide");
}
}
alerte.setCommentaireTraitement(body.get("commentaire"));
alerteLcbFtRepository.persist(alerte);
@@ -154,7 +161,7 @@ public class AlerteLcbFtResource {
.severite(alerte.getSeverite())
.traitee(alerte.getTraitee())
.dateTraitement(alerte.getDateTraitement())
.traitePar(alerte.getTraitePar())
.traitePar(alerte.getTraitePar() != null ? alerte.getTraitePar().toString() : null)
.commentaireTraitement(alerte.getCommentaireTraitement())
.build();
}

View File

@@ -291,25 +291,10 @@ public class AnalyticsResource {
description = "Récupère la liste de tous les types de métriques disponibles")
@APIResponse(responseCode = "200", description = "Types de métriques récupérés avec succès")
public Response obtenirTypesMetriques() {
try {
log.info("Récupération des types de métriques disponibles");
TypeMetrique[] typesMetriques = TypeMetrique.values();
return Response.ok(Map.of("typesMetriques", typesMetriques, "total", typesMetriques.length))
.build();
} catch (Exception e) {
log.error("Erreur lors de la récupération des types de métriques: {}", e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(
Map.of(
"error",
"Erreur lors de la récupération des types de métriques",
"message",
e.getMessage()))
.build();
}
log.info("Récupération des types de métriques disponibles");
TypeMetrique[] typesMetriques = TypeMetrique.values();
return Response.ok(Map.of("typesMetriques", typesMetriques, "total", typesMetriques.length))
.build();
}
/** Obtient les périodes d'analyse disponibles */
@@ -321,25 +306,9 @@ public class AnalyticsResource {
description = "Récupère la liste de toutes les périodes d'analyse disponibles")
@APIResponse(responseCode = "200", description = "Périodes d'analyse récupérées avec succès")
public Response obtenirPeriodesAnalyse() {
try {
log.info("Récupération des périodes d'analyse disponibles");
PeriodeAnalyse[] periodesAnalyse = PeriodeAnalyse.values();
return Response.ok(
Map.of("periodesAnalyse", periodesAnalyse, "total", periodesAnalyse.length))
.build();
} catch (Exception e) {
log.error("Erreur lors de la récupération des périodes d'analyse: {}", e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(
Map.of(
"error",
"Erreur lors de la récupération des périodes d'analyse",
"message",
e.getMessage()))
.build();
}
log.info("Récupération des périodes d'analyse disponibles");
PeriodeAnalyse[] periodesAnalyse = PeriodeAnalyse.values();
return Response.ok(Map.of("periodesAnalyse", periodesAnalyse, "total", periodesAnalyse.length))
.build();
}
}

View File

@@ -47,7 +47,8 @@ public class ApprovalResource {
try {
String transactionId = (String) request.get("transactionId");
String transactionType = (String) request.get("transactionType");
Double amount = ((Number) request.get("amount")).doubleValue();
Number rawAmount = (Number) request.get("amount");
Double amount = rawAmount != null ? rawAmount.doubleValue() : null;
String organizationIdStr = (String) request.get("organizationId");
if (transactionId == null || transactionType == null || amount == null) {

View File

@@ -101,13 +101,8 @@ public class EvenementResource {
// Convertir en DTO mobile
List<EvenementMobileDTO> evenementsDTOs = new ArrayList<>();
for (Evenement evenement : evenements) {
try {
EvenementMobileDTO dto = EvenementMobileDTO.fromEntity(evenement);
evenementsDTOs.add(dto);
} catch (Exception e) {
LOG.errorf("Erreur lors de la conversion de l'événement %s: %s", evenement.getId(), e.getMessage());
// Continuer avec les autres événements
}
EvenementMobileDTO dto = EvenementMobileDTO.fromEntity(evenement);
evenementsDTOs.add(dto);
}
LOG.infof("Nombre de DTOs créés: %d", evenementsDTOs.size());

View File

@@ -40,27 +40,19 @@ public class FinanceWorkflowResource {
@QueryParam("endDate") String endDate) {
LOG.infof("GET /api/finance/stats?organizationId=%s", organizationId);
try {
Map<String, Object> stats = new HashMap<>();
stats.put("totalApprovals", 0);
stats.put("pendingApprovals", 0);
stats.put("approvedCount", 0);
stats.put("rejectedCount", 0);
stats.put("totalBudgets", 0);
stats.put("activeBudgets", 0);
stats.put("averageApprovalTime", "0 hours");
stats.put("period", Map.of(
"startDate", startDate != null ? startDate : LocalDateTime.now().minusMonths(1).toString(),
"endDate", endDate != null ? endDate : LocalDateTime.now().toString()
));
return Response.ok(stats).build();
} catch (Exception e) {
LOG.error("Erreur lors de la récupération des statistiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new ErrorResponse(e.getMessage()))
.build();
}
Map<String, Object> stats = new HashMap<>();
stats.put("totalApprovals", 0);
stats.put("pendingApprovals", 0);
stats.put("approvedCount", 0);
stats.put("rejectedCount", 0);
stats.put("totalBudgets", 0);
stats.put("activeBudgets", 0);
stats.put("averageApprovalTime", "0 hours");
stats.put("period", Map.of(
"startDate", startDate != null ? startDate : LocalDateTime.now().minusMonths(1).toString(),
"endDate", endDate != null ? endDate : LocalDateTime.now().toString()
));
return Response.ok(stats).build();
}
@GET
@@ -78,15 +70,8 @@ public class FinanceWorkflowResource {
@QueryParam("limit") @DefaultValue("100") int limit) {
LOG.infof("GET /api/finance/audit-logs?organizationId=%s&limit=%d", organizationId, limit);
try {
// Retourne une liste vide pour l'instant - à implémenter plus tard avec vraie persistence
return Response.ok(new ArrayList<>()).build();
} catch (Exception e) {
LOG.error("Erreur lors de la récupération des logs d'audit", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new ErrorResponse(e.getMessage()))
.build();
}
// Retourne une liste vide pour l'instant - à implémenter plus tard avec vraie persistence
return Response.ok(new ArrayList<>()).build();
}
@GET
@@ -100,15 +85,8 @@ public class FinanceWorkflowResource {
@QueryParam("endDate") String endDate) {
LOG.infof("GET /api/finance/audit-logs/anomalies?organizationId=%s", organizationId);
try {
// Retourne une liste vide pour l'instant - à implémenter plus tard
return Response.ok(new ArrayList<>()).build();
} catch (Exception e) {
LOG.error("Erreur lors de la récupération des anomalies", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new ErrorResponse(e.getMessage()))
.build();
}
// Retourne une liste vide pour l'instant - à implémenter plus tard
return Response.ok(new ArrayList<>()).build();
}
@POST
@@ -122,24 +100,15 @@ public class FinanceWorkflowResource {
LOG.infof("POST /api/finance/audit-logs/export - format: %s", format);
try {
// Pour l'instant, retourne un URL fictif - à implémenter plus tard
String exportUrl = "/api/finance/exports/" + UUID.randomUUID() + "." + format;
// Pour l'instant, retourne un URL fictif - à implémenter plus tard
String exportUrl = "/api/finance/exports/" + UUID.randomUUID() + "." + format;
Map<String, Object> response = new HashMap<>();
response.put("exportUrl", exportUrl);
response.put("format", format);
response.put("status", "generated");
response.put("expiresAt", LocalDateTime.now().plusHours(24).toString());
Map<String, Object> response = new HashMap<>();
response.put("exportUrl", exportUrl);
response.put("format", format);
response.put("status", "generated");
response.put("expiresAt", LocalDateTime.now().plusHours(24).toString());
return Response.ok(response).build();
} catch (Exception e) {
LOG.error("Erreur lors de l'export des logs d'audit", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new ErrorResponse(e.getMessage()))
.build();
}
return Response.ok(response).build();
}
record ErrorResponse(String message) {}
}

View File

@@ -85,10 +85,8 @@ public class MembreResource {
: Sort.by(sortField).ascending();
// Filtrage par rôle : ADMIN_ORGANISATION ne voit que ses organisations
java.util.Set<String> roles = securityIdentity.getRoles() != null
? securityIdentity.getRoles()
: java.util.Set.of();
boolean onlyOrgAdmin = roles.contains("ADMIN_ORGANISATION")
java.util.Set<String> roles = securityIdentity.getRoles();
boolean onlyOrgAdmin = roles != null && roles.contains("ADMIN_ORGANISATION")
&& !roles.contains("ADMIN")
&& !roles.contains("SUPER_ADMIN");
@@ -96,9 +94,8 @@ public class MembreResource {
long totalElements;
if (onlyOrgAdmin) {
String email = securityIdentity.getPrincipal() != null
? securityIdentity.getPrincipal().getName()
: null;
java.security.Principal p = securityIdentity.getPrincipal();
String email = p != null ? p.getName() : null;
if (email == null || email.isEmpty()) {
LOG.warn("ADMIN_ORGANISATION sans email identifié - retour liste vide");
@@ -184,10 +181,8 @@ public class MembreResource {
Membre nouveauMembre = membreService.creerMembre(membre);
// Validation périmètre ADMIN_ORGANISATION - lier le membre à l'organisation
java.util.Set<String> roles = securityIdentity.getRoles() != null
? securityIdentity.getRoles()
: java.util.Set.of();
boolean onlyOrgAdmin = roles.contains("ADMIN_ORGANISATION")
java.util.Set<String> roles = securityIdentity.getRoles();
boolean onlyOrgAdmin = roles != null && roles.contains("ADMIN_ORGANISATION")
&& !roles.contains("ADMIN")
&& !roles.contains("SUPER_ADMIN");
@@ -199,9 +194,7 @@ public class MembreResource {
}
// Vérifier que l'utilisateur a accès à cette organisation
String email = securityIdentity.getPrincipal() != null
? securityIdentity.getPrincipal().getName()
: null;
String email = securityIdentity.getPrincipal().getName();
List<UUID> userOrgIds = organisationService.listerOrganisationsPourUtilisateur(email)
.stream()
@@ -545,7 +538,7 @@ public class MembreResource {
}
if (fileName == null || fileName.isEmpty()) {
fileName = file.fileName() != null ? file.fileName() : "import.xlsx";
fileName = file.fileName();
}
if (typeMembreDefaut == null || typeMembreDefaut.isEmpty()) {
@@ -557,10 +550,8 @@ public class MembreResource {
: null;
// Validation périmètre ADMIN_ORGANISATION : doit avoir accès à l'organisation
java.util.Set<String> roles = securityIdentity.getRoles() != null
? securityIdentity.getRoles()
: java.util.Set.of();
boolean onlyOrgAdmin = roles.contains("ADMIN_ORGANISATION")
java.util.Set<String> roles = securityIdentity.getRoles();
boolean onlyOrgAdmin = roles != null && roles.contains("ADMIN_ORGANISATION")
&& !roles.contains("ADMIN")
&& !roles.contains("SUPER_ADMIN");
@@ -571,9 +562,8 @@ public class MembreResource {
.build();
}
String email = securityIdentity.getPrincipal() != null
? securityIdentity.getPrincipal().getName()
: null;
java.security.Principal p2 = securityIdentity.getPrincipal();
String email = p2 != null ? p2.getName() : null;
if (email == null || email.isEmpty()) {
return Response.status(Response.Status.UNAUTHORIZED)

View File

@@ -1,8 +1,10 @@
package dev.lions.unionflow.server.resource;
import dev.lions.unionflow.server.api.dto.common.PagedResponse;
import dev.lions.unionflow.server.api.dto.organisation.request.CreateOrganisationRequest;
import dev.lions.unionflow.server.api.dto.organisation.request.UpdateOrganisationRequest;
import dev.lions.unionflow.server.api.dto.organisation.response.OrganisationResponse;
import dev.lions.unionflow.server.api.dto.organisation.response.OrganisationSummaryResponse;
import dev.lions.unionflow.server.entity.Organisation;
import dev.lions.unionflow.server.service.KeycloakService;
import dev.lions.unionflow.server.service.OrganisationService;
@@ -84,7 +86,7 @@ public class OrganisationResource {
/** Crée une nouvelle organisation */
@POST
@RolesAllowed({"ADMIN", "MEMBRE"})
@RolesAllowed({"SUPER_ADMIN", "ADMIN", "MEMBRE"})
@Operation(
summary = "Créer une nouvelle organisation",
@@ -113,7 +115,7 @@ public class OrganisationResource {
return Response.created(URI.create("/api/organisations/" + organisationCreee.getId()))
.entity(dto)
.build();
} catch (IllegalArgumentException e) {
} catch (IllegalArgumentException | IllegalStateException e) {
LOG.warnf("Erreur lors de la création de l'organisation: %s", e.getMessage());
return Response.status(Response.Status.CONFLICT)
.entity(Map.of("error", e.getMessage()))
@@ -139,11 +141,11 @@ public class OrganisationResource {
content =
@Content(
mediaType = MediaType.APPLICATION_JSON,
schema = @Schema(type = SchemaType.ARRAY, implementation = OrganisationResponse.class))),
schema = @Schema(implementation = PagedResponse.class))),
@APIResponse(responseCode = "401", description = "Non authentifié"),
@APIResponse(responseCode = "403", description = "Non autorisé")
})
public Response listerOrganisations(
public PagedResponse<OrganisationSummaryResponse> listerOrganisations(
@Parameter(description = "Numéro de page (commence à 0)", example = "0")
@QueryParam("page")
@DefaultValue("0")
@@ -159,47 +161,44 @@ public class OrganisationResource {
"Récupération des organisations - page: %d, size: %d, recherche: %s",
page, size, recherche);
try {
List<Organisation> organisations;
List<Organisation> organisations;
long totalElements;
// Admin d'organisation (sans rôle ADMIN/SUPER_ADMIN) : ne retourner que ses organisations
java.util.Set<String> roles = securityIdentity.getRoles() != null ? securityIdentity.getRoles() : java.util.Set.of();
boolean onlyOrgAdmin = roles.contains("ADMIN_ORGANISATION")
&& !roles.contains("ADMIN")
&& !roles.contains("SUPER_ADMIN");
if (onlyOrgAdmin && securityIdentity.getPrincipal() != null) {
String email = securityIdentity.getPrincipal().getName();
organisations = organisationService.listerOrganisationsPourUtilisateur(email);
if (recherche != null && !recherche.trim().isEmpty()) {
String term = recherche.trim().toLowerCase();
organisations = organisations.stream()
.filter(o -> (o.getNom() != null && o.getNom().toLowerCase().contains(term))
|| (o.getNomCourt() != null && o.getNomCourt().toLowerCase().contains(term)))
.collect(Collectors.toList());
}
// Pagination en mémoire pour /mes
int from = Math.min(page * size, organisations.size());
int to = Math.min(from + size, organisations.size());
organisations = organisations.subList(from, to);
LOG.infof("ADMIN_ORGANISATION: retour de %d organisation(s) pour %s", organisations.size(), email);
} else if (recherche != null && !recherche.trim().isEmpty()) {
organisations = organisationService.rechercherOrganisations(recherche.trim(), page, size);
} else {
organisations = organisationService.listerOrganisationsActives(page, size);
// Admin d'organisation (sans rôle ADMIN/SUPER_ADMIN) : ne retourner que ses organisations
java.util.Set<String> roles = securityIdentity.getRoles();
boolean onlyOrgAdmin = roles.contains("ADMIN_ORGANISATION")
&& !roles.contains("ADMIN")
&& !roles.contains("SUPER_ADMIN");
if (onlyOrgAdmin && securityIdentity.getPrincipal() != null) {
String email = securityIdentity.getPrincipal().getName();
organisations = organisationService.listerOrganisationsPourUtilisateur(email);
if (recherche != null && !recherche.trim().isEmpty()) {
String term = recherche.trim().toLowerCase();
organisations = organisations.stream()
.filter(o -> (o.getNom() != null && o.getNom().toLowerCase().contains(term))
|| (o.getNomCourt() != null && o.getNomCourt().toLowerCase().contains(term)))
.collect(Collectors.toList());
}
List<OrganisationResponse> dtos =
organisations.stream()
.map(organisationService::convertToResponse)
.collect(Collectors.toList());
return Response.ok(dtos).build();
} catch (Exception e) {
LOG.errorf(e, "Erreur lors de la récupération des organisations");
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur interne du serveur"))
.build();
totalElements = organisations.size();
// Pagination en mémoire pour /mes
int from = Math.min(page * size, organisations.size());
int to = Math.min(from + size, organisations.size());
organisations = organisations.subList(from, to);
LOG.infof("ADMIN_ORGANISATION: retour de %d organisation(s) pour %s", organisations.size(), email);
} else if (recherche != null && !recherche.trim().isEmpty()) {
organisations = organisationService.rechercherOrganisations(recherche.trim(), page, size);
totalElements = organisationService.rechercherOrganisationsCount(recherche.trim());
} else {
organisations = organisationService.listerOrganisationsActives(page, size);
totalElements = organisationService.compterOrganisationsActives();
}
List<OrganisationSummaryResponse> dtos =
organisations.stream()
.map(organisationService::convertToSummaryResponse)
.collect(Collectors.toList());
return new PagedResponse<>(dtos, totalElements, page, size);
}
/** Récupère une organisation par son ID */
@@ -235,7 +234,9 @@ public class OrganisationResource {
})
.orElse(
Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", "Organisation non trouvée"))
.entity(Map.of(
"error", "Organisation non trouvée",
"status", 404))
.build());
}
@@ -309,7 +310,7 @@ public class OrganisationResource {
public Response supprimerOrganisation(
@Parameter(description = "UUID de l'organisation", required = true) @PathParam("id") UUID id) {
LOG.infof("Suppression de l'organisation ID: %d", id);
LOG.infof("Suppression de l'organisation ID: %s", id);
try {
organisationService.supprimerOrganisation(id, "system");
@@ -398,7 +399,7 @@ public class OrganisationResource {
public Response activerOrganisation(
@Parameter(description = "UUID de l'organisation", required = true) @PathParam("id") UUID id) {
LOG.infof("Activation de l'organisation ID: %d", id);
LOG.infof("Activation de l'organisation ID: %s", id);
try {
Organisation organisation = organisationService.activerOrganisation(id, "system");
@@ -433,7 +434,7 @@ public class OrganisationResource {
public Response suspendreOrganisation(
@Parameter(description = "UUID de l'organisation", required = true) @PathParam("id") UUID id) {
LOG.infof("Suspension de l'organisation ID: %d", id);
LOG.infof("Suspension de l'organisation ID: %s", id);
try {
Organisation organisation = organisationService.suspendreOrganisation(id, "system");