Migrations : - V25 : numero_transaction nullable dans paiements (legacy V1 NOT NULL bloquant INSERT) - V26 : autres colonnes legacy NOT NULL V1 (type_paiement, statut_paiement, etc.) rendues nullables pour alignement avec l'entité Paiement Refactor Paiement/PaiementObjet : mise à jour entités, repository, resource, service pour cohérence avec le nouveau module Versement. Tests associés supprimés/ajustés.
150 lines
4.5 KiB
Java
150 lines
4.5 KiB
Java
package dev.lions.unionflow.server.entity;
|
|
|
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
import jakarta.persistence.*;
|
|
import jakarta.validation.constraints.*;
|
|
import java.math.BigDecimal;
|
|
import java.time.LocalDateTime;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import lombok.AllArgsConstructor;
|
|
import lombok.Builder;
|
|
import lombok.Data;
|
|
import lombok.EqualsAndHashCode;
|
|
import lombok.NoArgsConstructor;
|
|
|
|
/**
|
|
* Entité Paiement centralisée pour tous les types de paiements.
|
|
* Réutilisable pour cotisations, adhésions, événements, aides.
|
|
*
|
|
* @author UnionFlow Team
|
|
* @version 3.0
|
|
* @since 2025-01-29
|
|
*/
|
|
@Entity
|
|
@Table(name = "paiements", indexes = {
|
|
@Index(name = "idx_paiement_numero_reference", columnList = "numero_reference", unique = true),
|
|
@Index(name = "idx_paiement_membre", columnList = "membre_id"),
|
|
@Index(name = "idx_paiement_statut", columnList = "statut_paiement"),
|
|
@Index(name = "idx_paiement_methode", columnList = "methode_paiement"),
|
|
@Index(name = "idx_paiement_date", columnList = "date_paiement")
|
|
})
|
|
@Data
|
|
@NoArgsConstructor
|
|
@AllArgsConstructor
|
|
@Builder
|
|
@EqualsAndHashCode(callSuper = true)
|
|
public class Paiement extends BaseEntity {
|
|
|
|
/** Numéro de référence unique */
|
|
@NotBlank
|
|
@Column(name = "numero_reference", unique = true, nullable = false, length = 50)
|
|
private String numeroReference;
|
|
|
|
/** Montant du paiement */
|
|
@NotNull
|
|
@DecimalMin(value = "0.0", message = "Le montant doit être positif")
|
|
@Digits(integer = 12, fraction = 2)
|
|
@Column(name = "montant", nullable = false, precision = 14, scale = 2)
|
|
private BigDecimal montant;
|
|
|
|
/** Code devise (ISO 3 lettres) */
|
|
@NotBlank
|
|
@Pattern(regexp = "^[A-Z]{3}$", message = "Le code devise doit être un code ISO à 3 lettres")
|
|
@Column(name = "code_devise", nullable = false, length = 3)
|
|
private String codeDevise;
|
|
|
|
/** Méthode de paiement */
|
|
@NotNull
|
|
@Column(name = "methode_paiement", nullable = false, length = 50)
|
|
private String methodePaiement;
|
|
|
|
/** Statut du paiement */
|
|
@NotNull
|
|
@Builder.Default
|
|
@Column(name = "statut_paiement", nullable = false, length = 30)
|
|
private String statutPaiement = "EN_ATTENTE";
|
|
|
|
/** Date de paiement */
|
|
@Column(name = "date_paiement")
|
|
private LocalDateTime datePaiement;
|
|
|
|
/** Date de validation */
|
|
@Column(name = "date_validation")
|
|
private LocalDateTime dateValidation;
|
|
|
|
/** Validateur (email de l'administrateur) */
|
|
@Column(name = "validateur", length = 255)
|
|
private String validateur;
|
|
|
|
/** Référence externe (numéro transaction, URL preuve, etc.) */
|
|
@Column(name = "reference_externe", length = 500)
|
|
private String referenceExterne;
|
|
|
|
/** URL de preuve de paiement */
|
|
@Column(name = "url_preuve", length = 1000)
|
|
private String urlPreuve;
|
|
|
|
/** Commentaires et notes */
|
|
@Column(name = "commentaire", length = 1000)
|
|
private String commentaire;
|
|
|
|
/** Adresse IP de l'initiateur */
|
|
@Column(name = "ip_address", length = 45)
|
|
private String ipAddress;
|
|
|
|
/** User-Agent de l'initiateur */
|
|
@Column(name = "user_agent", length = 500)
|
|
private String userAgent;
|
|
|
|
/** Membre payeur */
|
|
@NotNull
|
|
@ManyToOne(fetch = FetchType.LAZY)
|
|
@JoinColumn(name = "membre_id", nullable = false)
|
|
private Membre membre;
|
|
|
|
/** Objets cibles de ce paiement (polymorphique) */
|
|
@JsonIgnore
|
|
@OneToMany(mappedBy = "paiement", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
|
@Builder.Default
|
|
private List<PaiementObjet> paiementsObjets = new ArrayList<>();
|
|
|
|
/** Relation avec TransactionWave (optionnelle) */
|
|
@ManyToOne(fetch = FetchType.LAZY)
|
|
@JoinColumn(name = "transaction_wave_id")
|
|
private TransactionWave transactionWave;
|
|
|
|
/** Génère un numéro de référence unique */
|
|
public static String genererNumeroReference() {
|
|
return "PAY-"
|
|
+ LocalDateTime.now().getYear()
|
|
+ "-"
|
|
+ String.format("%012d", System.currentTimeMillis() % 1000000000000L);
|
|
}
|
|
|
|
/** Vérifie si le paiement est validé */
|
|
public boolean isValide() {
|
|
return "VALIDE".equals(statutPaiement);
|
|
}
|
|
|
|
/** Vérifie si le paiement peut être modifié */
|
|
public boolean peutEtreModifie() {
|
|
return !"VALIDE".equals(statutPaiement)
|
|
&& !"ANNULE".equals(statutPaiement);
|
|
}
|
|
|
|
@PrePersist
|
|
protected void onCreate() {
|
|
super.onCreate();
|
|
if (numeroReference == null || numeroReference.isEmpty()) {
|
|
numeroReference = genererNumeroReference();
|
|
}
|
|
if (statutPaiement == null) {
|
|
statutPaiement = "EN_ATTENTE";
|
|
}
|
|
if (datePaiement == null) {
|
|
datePaiement = LocalDateTime.now();
|
|
}
|
|
}
|
|
}
|