From 65a9d03c00969b6133e6b337e48773b700daafdb Mon Sep 17 00:00:00 2001 From: dahoud <41957584+DahoudG@users.noreply.github.com> Date: Sat, 25 Apr 2026 12:31:43 +0000 Subject: [PATCH] =?UTF-8?q?feat(sprint-10=20api=202026-04-25):=20bump=201.?= =?UTF-8?q?0.8=20+=20DTOs=20UBO/audit-trail/d=C3=A9l=C3=A9gation=20+=20Upd?= =?UTF-8?q?ateOrganisationRequest=20enrichi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pré-requis pour exposer les features Sprints 1-2 via REST. Architecture stricte : DTOs en module api (contrat public), aucune logique métier. Version : 1.0.7 → 1.0.8 DTOs UBO (Instr. BCEAO 003-03-2025) - CreateBeneficiaireEffectifRequest : validation pays ISO-3, regex natureControle (5 valeurs), pourcentages 0-100 - UpdateBeneficiaireEffectifRequest : tous optionnels (PATCH partiel) - BeneficiaireEffectifResponse : vue read-only DTOs audit trail (Sprint 1) - AuditTrailOperationResponse : payloadAvant/payloadApres/metadata en String JSONB DTOs délégation rôles (Sprint 2) - CreateRoleDelegationRequest : regex rôle uppercase + dates futures - RoleDelegationResponse : statut + estActive (calculé) Enrich UpdateOrganisationRequest - referentielComptable (regex SYSCOHADA|SYCEBNL|PCSFD_UMOA) - complianceOfficerId UUID (Instr. BCEAO 001-03-2025) À publier sur Gitea via script/publish-api.sh — user action requise. --- pom.xml | 2 +- .../response/AuditTrailOperationResponse.java | 36 +++++++++ .../request/CreateRoleDelegationRequest.java | 42 ++++++++++ .../response/RoleDelegationResponse.java | 27 +++++++ .../CreateBeneficiaireEffectifRequest.java | 79 +++++++++++++++++++ .../UpdateBeneficiaireEffectifRequest.java | 40 ++++++++++ .../BeneficiaireEffectifResponse.java | 43 ++++++++++ .../request/UpdateOrganisationRequest.java | 12 ++- 8 files changed, 279 insertions(+), 2 deletions(-) create mode 100644 src/main/java/dev/lions/unionflow/server/api/dto/audit/response/AuditTrailOperationResponse.java create mode 100644 src/main/java/dev/lions/unionflow/server/api/dto/delegation/request/CreateRoleDelegationRequest.java create mode 100644 src/main/java/dev/lions/unionflow/server/api/dto/delegation/response/RoleDelegationResponse.java create mode 100644 src/main/java/dev/lions/unionflow/server/api/dto/kyc/request/CreateBeneficiaireEffectifRequest.java create mode 100644 src/main/java/dev/lions/unionflow/server/api/dto/kyc/request/UpdateBeneficiaireEffectifRequest.java create mode 100644 src/main/java/dev/lions/unionflow/server/api/dto/kyc/response/BeneficiaireEffectifResponse.java diff --git a/pom.xml b/pom.xml index ec85c0c..1451815 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.lions.unionflow unionflow-server-api - 1.0.7 + 1.0.8 jar UnionFlow Server API diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/audit/response/AuditTrailOperationResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/audit/response/AuditTrailOperationResponse.java new file mode 100644 index 0000000..eae8145 --- /dev/null +++ b/src/main/java/dev/lions/unionflow/server/api/dto/audit/response/AuditTrailOperationResponse.java @@ -0,0 +1,36 @@ +package dev.lions.unionflow.server.api.dto.audit.response; + +import java.time.LocalDateTime; +import java.util.UUID; +import lombok.Builder; + +/** + * Vue d'une opération d'audit trail enrichi (Sprint 1, exposée Sprint 10). + * + *

Les payloads JSONB ({@code payloadAvant}, {@code payloadApres}, {@code metadata}) + * sont sérialisés en string ; le frontend les parse selon les besoins. + * + * @since 2026-04-25 (Sprint 10) + */ +@Builder +public record AuditTrailOperationResponse( + UUID id, + UUID userId, + String userEmail, + String roleActif, + UUID organisationActiveId, + String actionType, + String entityType, + UUID entityId, + String description, + String ipAddress, + String userAgent, + UUID requestId, + String payloadAvant, + String payloadApres, + String metadata, + Boolean sodCheckPassed, + String sodViolations, + LocalDateTime operationAt +) { +} diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/delegation/request/CreateRoleDelegationRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/delegation/request/CreateRoleDelegationRequest.java new file mode 100644 index 0000000..740d92e --- /dev/null +++ b/src/main/java/dev/lions/unionflow/server/api/dto/delegation/request/CreateRoleDelegationRequest.java @@ -0,0 +1,42 @@ +package dev.lions.unionflow.server.api.dto.delegation.request; + +import jakarta.validation.constraints.Future; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import java.time.LocalDateTime; +import java.util.UUID; +import lombok.Builder; + +/** + * Requête de création d'une délégation de rôle temporaire. + * + * @since 2026-04-25 (Sprint 10 — service existant Sprint 2) + */ +@Builder +public record CreateRoleDelegationRequest( + @NotNull(message = "L'organisation est obligatoire") + UUID organisationId, + + @NotNull(message = "Le déléguant est obligatoire") + UUID delegantUserId, + + @NotNull(message = "Le délégataire est obligatoire") + UUID delegataireUserId, + + @NotBlank(message = "Le rôle délégué est obligatoire") + @Pattern(regexp = "^[A-Z_]{3,50}$", message = "Format de rôle invalide (uppercase + underscore)") + String roleDelegue, + + @NotNull(message = "La date de début est obligatoire") + LocalDateTime dateDebut, + + @NotNull(message = "La date de fin est obligatoire") + @Future(message = "La date de fin doit être future") + LocalDateTime dateFin, + + @Size(max = 500) + String motif +) { +} diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/delegation/response/RoleDelegationResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/delegation/response/RoleDelegationResponse.java new file mode 100644 index 0000000..0827713 --- /dev/null +++ b/src/main/java/dev/lions/unionflow/server/api/dto/delegation/response/RoleDelegationResponse.java @@ -0,0 +1,27 @@ +package dev.lions.unionflow.server.api.dto.delegation.response; + +import java.time.LocalDateTime; +import java.util.UUID; +import lombok.Builder; + +/** + * Vue d'une délégation de rôle. + * + * @since 2026-04-25 (Sprint 10) + */ +@Builder +public record RoleDelegationResponse( + UUID id, + UUID organisationId, + UUID delegantUserId, + UUID delegataireUserId, + String roleDelegue, + LocalDateTime dateDebut, + LocalDateTime dateFin, + String motif, + String statut, + LocalDateTime dateRevocation, + LocalDateTime dateCreation, + boolean estActive +) { +} diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/kyc/request/CreateBeneficiaireEffectifRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/kyc/request/CreateBeneficiaireEffectifRequest.java new file mode 100644 index 0000000..d6f0573 --- /dev/null +++ b/src/main/java/dev/lions/unionflow/server/api/dto/kyc/request/CreateBeneficiaireEffectifRequest.java @@ -0,0 +1,79 @@ +package dev.lions.unionflow.server.api.dto.kyc.request; + +import dev.lions.unionflow.server.api.enums.membre.TypePieceIdentite; +import jakarta.validation.constraints.DecimalMax; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.UUID; +import lombok.Builder; + +/** + * Création d'un Bénéficiaire Effectif (UBO) — Instruction BCEAO 003-03-2025. + * + *

Lié à un {@code KycDossier} d'entreprise. Au moins un identifiant cible est requis : + * {@code kycDossierId} pour KYC personne morale, ou {@code organisationCibleId} + + * {@code membreId} pour membre individuel à risque. + * + * @since 2026-04-25 (Sprint 10) + */ +@Builder +public record CreateBeneficiaireEffectifRequest( + UUID kycDossierId, + UUID organisationCibleId, + UUID membreId, + + @NotBlank(message = "Le nom est obligatoire") + @Size(max = 100) + String nom, + + @NotBlank(message = "Les prénoms sont obligatoires") + @Size(max = 200) + String prenoms, + + @NotNull(message = "La date de naissance est obligatoire") + LocalDate dateNaissance, + + @Size(max = 200) + String lieuNaissance, + + @NotBlank(message = "La nationalité est obligatoire (ISO-3)") + @Pattern(regexp = "^[A-Z]{3}$", message = "Code ISO-3 (ex: CIV, FRA)") + String nationalite, + + @Pattern(regexp = "^[A-Z]{3}$|^$", message = "Code ISO-3") + String paysResidence, + + TypePieceIdentite typePieceIdentite, + + @Size(max = 50) + String numeroPieceIdentite, + + LocalDate dateExpirationPiece, + + @DecimalMin(value = "0.00") + @DecimalMax(value = "100.00") + BigDecimal pourcentageCapital, + + @DecimalMin(value = "0.00") + @DecimalMax(value = "100.00") + BigDecimal pourcentageDroitsVote, + + @NotBlank(message = "La nature du contrôle est obligatoire") + @Pattern(regexp = "^(DETENTION_CAPITAL|DROITS_VOTE|CONTROLE_DE_FAIT|BENEFICIAIRE_ULTIME|MANDAT_REPRESENTATION)$", + message = "Nature du contrôle invalide") + String natureControle, + + Boolean estPep, + @Size(max = 100) String pepCategorie, + @Pattern(regexp = "^[A-Z]{3}$|^$") String pepPays, + @Size(max = 200) String pepFonction, + + Boolean presenceListesSanctions, + @Size(max = 1000) String detailsListesSanctions +) { +} diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/kyc/request/UpdateBeneficiaireEffectifRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/kyc/request/UpdateBeneficiaireEffectifRequest.java new file mode 100644 index 0000000..bb3166f --- /dev/null +++ b/src/main/java/dev/lions/unionflow/server/api/dto/kyc/request/UpdateBeneficiaireEffectifRequest.java @@ -0,0 +1,40 @@ +package dev.lions.unionflow.server.api.dto.kyc.request; + +import jakarta.validation.constraints.DecimalMax; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import java.math.BigDecimal; +import java.time.LocalDate; +import lombok.Builder; + +/** + * Mise à jour partielle d'un Bénéficiaire Effectif (UBO). + * Tous les champs sont optionnels — seul ce qui est fourni est mis à jour. + * + * @since 2026-04-25 (Sprint 10) + */ +@Builder +public record UpdateBeneficiaireEffectifRequest( + @Size(max = 100) String nom, + @Size(max = 200) String prenoms, + LocalDate dateNaissance, + @Size(max = 200) String lieuNaissance, + @Pattern(regexp = "^[A-Z]{3}$|^$") String nationalite, + @Pattern(regexp = "^[A-Z]{3}$|^$") String paysResidence, + + @DecimalMin("0.00") @DecimalMax("100.00") BigDecimal pourcentageCapital, + @DecimalMin("0.00") @DecimalMax("100.00") BigDecimal pourcentageDroitsVote, + + @Pattern(regexp = "^(DETENTION_CAPITAL|DROITS_VOTE|CONTROLE_DE_FAIT|BENEFICIAIRE_ULTIME|MANDAT_REPRESENTATION)?$") + String natureControle, + + Boolean estPep, + @Size(max = 100) String pepCategorie, + @Pattern(regexp = "^[A-Z]{3}$|^$") String pepPays, + @Size(max = 200) String pepFonction, + + Boolean presenceListesSanctions, + @Size(max = 1000) String detailsListesSanctions +) { +} diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/kyc/response/BeneficiaireEffectifResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/kyc/response/BeneficiaireEffectifResponse.java new file mode 100644 index 0000000..bd93ca3 --- /dev/null +++ b/src/main/java/dev/lions/unionflow/server/api/dto/kyc/response/BeneficiaireEffectifResponse.java @@ -0,0 +1,43 @@ +package dev.lions.unionflow.server.api.dto.kyc.response; + +import dev.lions.unionflow.server.api.enums.membre.TypePieceIdentite; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.UUID; +import lombok.Builder; + +/** + * Vue d'un Bénéficiaire Effectif (UBO). + * + * @since 2026-04-25 (Sprint 10) + */ +@Builder +public record BeneficiaireEffectifResponse( + UUID id, + UUID kycDossierId, + UUID organisationCibleId, + UUID membreId, + String nom, + String prenoms, + LocalDate dateNaissance, + String lieuNaissance, + String nationalite, + String paysResidence, + TypePieceIdentite typePieceIdentite, + String numeroPieceIdentite, + LocalDate dateExpirationPiece, + BigDecimal pourcentageCapital, + BigDecimal pourcentageDroitsVote, + String natureControle, + boolean estPep, + String pepCategorie, + String pepPays, + String pepFonction, + boolean presenceListesSanctions, + String detailsListesSanctions, + LocalDateTime dateCreation, + LocalDateTime dateModification, + Boolean actif +) { +} diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/organisation/request/UpdateOrganisationRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/organisation/request/UpdateOrganisationRequest.java index 0701594..6e22d5d 100644 --- a/src/main/java/dev/lions/unionflow/server/api/dto/organisation/request/UpdateOrganisationRequest.java +++ b/src/main/java/dev/lions/unionflow/server/api/dto/organisation/request/UpdateOrganisationRequest.java @@ -2,9 +2,11 @@ package dev.lions.unionflow.server.api.dto.organisation.request; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; import java.math.BigDecimal; import java.time.LocalDate; +import java.util.UUID; import lombok.Builder; @@ -51,5 +53,13 @@ public record UpdateOrganisationRequest( @Size(max = 100) String pays, @Size(max = 20) String codePostal, Boolean organisationPublique, - Boolean accepteNouveauxMembres) { + Boolean accepteNouveauxMembres, + + /** Référentiel comptable applicable (Sprint 1) — SYSCOHADA / SYCEBNL / PCSFD_UMOA. */ + @Pattern(regexp = "^(SYSCOHADA|SYCEBNL|PCSFD_UMOA)?$", + message = "Référentiel comptable invalide") + String referentielComptable, + + /** UUID du Compliance Officer désigné (Instr. BCEAO 001-03-2025). */ + UUID complianceOfficerId) { }