package dev.lions.unionflow.server.entity; import jakarta.persistence.*; import jakarta.validation.constraints.*; import java.time.LocalDateTime; import java.util.UUID; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; /** * Entité Action d'Approbateur * * Représente l'action (approve/reject) d'un approbateur sur une demande d'approbation. * * @author UnionFlow Team * @version 1.0 * @since 2026-03-13 */ @Entity @Table(name = "approver_actions", indexes = { @Index(name = "idx_approver_action_approval", columnList = "approval_id"), @Index(name = "idx_approver_action_approver", columnList = "approver_id"), @Index(name = "idx_approver_action_decision", columnList = "decision"), @Index(name = "idx_approver_action_decided_at", columnList = "decided_at") }) @Data @NoArgsConstructor @AllArgsConstructor @Builder @EqualsAndHashCode(callSuper = true) public class ApproverAction extends BaseEntity { /** Approbation parente */ @NotNull @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "approval_id", nullable = false) private TransactionApproval approval; /** ID de l'approbateur (membre) */ @NotNull @Column(name = "approver_id", nullable = false) private UUID approverId; /** Nom complet de l'approbateur (cache) */ @NotBlank @Column(name = "approver_name", nullable = false, length = 200) private String approverName; /** Rôle de l'approbateur au moment de l'action */ @NotBlank @Column(name = "approver_role", nullable = false, length = 50) private String approverRole; /** Décision (PENDING, APPROVED, REJECTED) */ @NotBlank @Pattern(regexp = "^(PENDING|APPROVED|REJECTED)$") @Builder.Default @Column(name = "decision", nullable = false, length = 10) private String decision = "PENDING"; /** Commentaire optionnel */ @Size(max = 1000) @Column(name = "comment", length = 1000) private String comment; /** Date de la décision */ @Column(name = "decided_at") private LocalDateTime decidedAt; @PrePersist protected void onCreate() { super.onCreate(); if (decision == null) { decision = "PENDING"; } } /** Méthode métier pour approuver avec commentaire */ public void approve(String comment) { this.decision = "APPROVED"; this.comment = comment; this.decidedAt = LocalDateTime.now(); } /** Méthode métier pour rejeter avec raison */ public void reject(String reason) { this.decision = "REJECTED"; this.comment = reason; this.decidedAt = LocalDateTime.now(); } }