package dev.lions.unionflow.server.entity; import dev.lions.unionflow.server.api.enums.wave.StatutWebhook; import dev.lions.unionflow.server.api.enums.wave.TypeEvenementWebhook; import jakarta.persistence.*; import jakarta.validation.constraints.NotBlank; import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; /** * Entité WebhookWave pour le traitement des événements Wave * * @author UnionFlow Team * @version 3.0 * @since 2025-01-29 */ @Entity @Table(name = "webhooks_wave", indexes = { @Index(name = "idx_webhook_wave_event_id", columnList = "wave_event_id", unique = true), @Index(name = "idx_webhook_wave_statut", columnList = "statut_traitement"), @Index(name = "idx_webhook_wave_type", columnList = "type_evenement"), @Index(name = "idx_webhook_wave_transaction", columnList = "transaction_wave_id"), @Index(name = "idx_webhook_wave_paiement", columnList = "paiement_id") }) @Data @NoArgsConstructor @AllArgsConstructor @Builder @EqualsAndHashCode(callSuper = true) public class WebhookWave extends BaseEntity { /** Identifiant unique de l'événement Wave */ @NotBlank @Column(name = "wave_event_id", unique = true, nullable = false, length = 100) private String waveEventId; /** Type d'événement */ @Column(name = "type_evenement", length = 50) private String typeEvenement; /** Statut de traitement */ @Builder.Default @Column(name = "statut_traitement", nullable = false, length = 30) private String statutTraitement = StatutWebhook.EN_ATTENTE.name(); /** Payload JSON reçu */ @Column(name = "payload", columnDefinition = "TEXT") private String payload; /** Signature de validation */ @Column(name = "signature", length = 500) private String signature; /** Date de réception */ @Column(name = "date_reception") private LocalDateTime dateReception; /** Date de traitement */ @Column(name = "date_traitement") private LocalDateTime dateTraitement; /** Nombre de tentatives de traitement */ @Builder.Default @Column(name = "nombre_tentatives", nullable = false) private Integer nombreTentatives = 0; /** Message d'erreur (si échec) */ @Column(name = "message_erreur", length = 1000) private String messageErreur; /** Commentaires */ @Column(name = "commentaire", length = 500) private String commentaire; // Relations @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "transaction_wave_id") private TransactionWave transactionWave; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "paiement_id") private Paiement paiement; /** Méthode métier pour vérifier si le webhook est traité */ public boolean isTraite() { return StatutWebhook.TRAITE.name().equals(statutTraitement); } /** Méthode métier pour vérifier si le webhook peut être retenté */ public boolean peutEtreRetente() { return (StatutWebhook.ECHOUE.name().equals(statutTraitement) || StatutWebhook.EN_ATTENTE.name().equals(statutTraitement)) && (nombreTentatives == null || nombreTentatives < 5); } /** Callback JPA avant la persistance */ @PrePersist protected void onCreate() { super.onCreate(); if (statutTraitement == null) { statutTraitement = StatutWebhook.EN_ATTENTE.name(); } if (dateReception == null) { dateReception = LocalDateTime.now(); } if (nombreTentatives == null) { nombreTentatives = 0; } } }