package dev.lions.unionflow.server.entity; import dev.lions.unionflow.server.api.enums.solidarite.StatutValidationEtape; import jakarta.persistence.*; import jakarta.validation.constraints.*; import java.time.LocalDateTime; import lombok.*; /** * Historique des validations pour une demande d'aide. * *

Chaque ligne représente l'état d'une étape du workflow pour une demande. * La délégation de véto (valideur absent) est tracée avec motif — conformité BCEAO/OHADA. * *

Table : {@code validation_etapes_demande} */ @Entity @Table( name = "validation_etapes_demande", indexes = { @Index(name = "idx_ved_demande", columnList = "demande_aide_id"), @Index(name = "idx_ved_valideur", columnList = "valideur_id"), @Index(name = "idx_ved_statut", columnList = "statut") }) @Data @NoArgsConstructor @AllArgsConstructor @Builder @EqualsAndHashCode(callSuper = true) public class ValidationEtapeDemande extends BaseEntity { @NotNull @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "demande_aide_id", nullable = false) private DemandeAide demandeAide; @NotNull @Min(1) @Max(3) @Column(name = "etape_numero", nullable = false) private Integer etapeNumero; /** Valideur assigné à cette étape */ @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "valideur_id") private Membre valideur; @Enumerated(EnumType.STRING) @Builder.Default @Column(name = "statut", nullable = false, length = 20) private StatutValidationEtape statut = StatutValidationEtape.EN_ATTENTE; @Column(name = "date_validation") private LocalDateTime dateValidation; @Column(name = "commentaire", length = 1000) private String commentaire; /** * Valideur supérieur qui a désactivé le véto de {@code valideur}. * Renseigné uniquement en cas de délégation. */ @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "delegue_par_id") private Membre deleguePar; /** * Motif et trace de la délégation — obligatoire si {@code deleguePar} est renseigné. * Conservé 10 ans — exigence BCEAO/OHADA/Fiscalité ivoirienne. */ @Column(name = "trace_delegation", columnDefinition = "TEXT") private String traceDelegation; // ── Méthodes métier ──────────────────────────────────────────────────────── public boolean estEnAttente() { return StatutValidationEtape.EN_ATTENTE.equals(statut); } public boolean estFinalisee() { return StatutValidationEtape.APPROUVEE.equals(statut) || StatutValidationEtape.REJETEE.equals(statut) || StatutValidationEtape.DELEGUEE.equals(statut) || StatutValidationEtape.EXPIREE.equals(statut); } @PrePersist protected void onCreate() { super.onCreate(); if (statut == null) statut = StatutValidationEtape.EN_ATTENTE; } }