fix(paiement): rendre colonnes legacy nullables + refactor Paiement/PaiementObjet

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.
This commit is contained in:
dahoud
2026-04-15 20:23:30 +00:00
parent 5d028a10bf
commit 217021933e
12 changed files with 582 additions and 2317 deletions

View File

@@ -5,7 +5,6 @@ import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicLong;
import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
@@ -15,8 +14,8 @@ 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
* 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
@@ -104,7 +103,7 @@ public class Paiement extends BaseEntity {
@JoinColumn(name = "membre_id", nullable = false)
private Membre membre;
/** Objets cibles de ce paiement (Cat.2 — polymorphique) */
/** Objets cibles de ce paiement (polymorphique) */
@JsonIgnore
@OneToMany(mappedBy = "paiement", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Builder.Default
@@ -115,18 +114,15 @@ public class Paiement extends BaseEntity {
@JoinColumn(name = "transaction_wave_id")
private TransactionWave transactionWave;
private static final AtomicLong REFERENCE_COUNTER =
new AtomicLong(System.currentTimeMillis() % 1000000000000L);
/** Méthode métier pour générer un numéro de référence unique */
/** Génère un numéro de référence unique */
public static String genererNumeroReference() {
return "PAY-"
+ LocalDateTime.now().getYear()
+ "-"
+ String.format("%012d", REFERENCE_COUNTER.incrementAndGet() % 1000000000000L);
+ String.format("%012d", System.currentTimeMillis() % 1000000000000L);
}
/** Méthode métier pour vérifier si le paiement est validé */
/** Vérifie si le paiement est validé */
public boolean isValide() {
return "VALIDE".equals(statutPaiement);
}
@@ -137,12 +133,10 @@ public class Paiement extends BaseEntity {
&& !"ANNULE".equals(statutPaiement);
}
/** Callback JPA avant la persistance */
@PrePersist
protected void onCreate() {
super.onCreate();
if (numeroReference == null
|| numeroReference.isEmpty()) {
if (numeroReference == null || numeroReference.isEmpty()) {
numeroReference = genererNumeroReference();
}
if (statutPaiement == null) {

View File

@@ -1,19 +1,7 @@
package dev.lions.unionflow.server.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Index;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.PrePersist;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.UUID;
@@ -24,23 +12,11 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* Table de liaison polymorphique entre un paiement
* et son objet cible.
* Table de liaison polymorphique entre un paiement et son objet cible.
*
* <p>
* Remplace les 4 tables dupliquées
* {@code paiements_cotisations},
* {@code paiements_adhesions},
* {@code paiements_evenements} et
* {@code paiements_aides} par une table unique
* utilisant le pattern
* {@code (type_objet_cible, objet_cible_id)}.
*
* <p>
* Les types d'objet cible sont définis dans le
* domaine {@code OBJET_PAIEMENT} de la table
* {@code types_reference} (ex: COTISATION,
* ADHESION, EVENEMENT, AIDE).
* <p>Remplace les tables dupliquées {@code paiements_cotisations},
* {@code paiements_adhesions}, etc. par une table unique utilisant
* le pattern {@code (type_objet_cible, objet_cible_id)}.
*
* @author UnionFlow Team
* @version 3.0
@@ -48,16 +24,12 @@ import lombok.NoArgsConstructor;
*/
@Entity
@Table(name = "paiements_objets", indexes = {
@Index(name = "idx_po_paiement", columnList = "paiement_id"),
@Index(name = "idx_po_objet", columnList = "type_objet_cible,"
+ " objet_cible_id"),
@Index(name = "idx_po_type", columnList = "type_objet_cible")
@Index(name = "idx_po_paiement", columnList = "paiement_id"),
@Index(name = "idx_po_objet", columnList = "type_objet_cible, objet_cible_id"),
@Index(name = "idx_po_type", columnList = "type_objet_cible")
}, uniqueConstraints = {
@UniqueConstraint(name = "uk_paiement_objet", columnNames = {
"paiement_id",
"type_objet_cible",
"objet_cible_id"
})
@UniqueConstraint(name = "uk_paiement_objet",
columnNames = {"paiement_id", "type_objet_cible", "objet_cible_id"})
})
@Data
@NoArgsConstructor
@@ -66,65 +38,47 @@ import lombok.NoArgsConstructor;
@EqualsAndHashCode(callSuper = true)
public class PaiementObjet extends BaseEntity {
/** Paiement parent. */
@NotNull
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "paiement_id", nullable = false)
private Paiement paiement;
/** Paiement parent. */
@NotNull
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "paiement_id", nullable = false)
private Paiement paiement;
/**
* Type de l'objet cible (code du domaine
* {@code OBJET_PAIEMENT} dans
* {@code types_reference}).
*
* <p>
* Valeurs attendues : {@code COTISATION},
* {@code ADHESION}, {@code EVENEMENT},
* {@code AIDE}.
*/
@NotBlank
@Size(max = 50)
@Column(name = "type_objet_cible", nullable = false, length = 50)
private String typeObjetCible;
/**
* Type de l'objet cible (ex: COTISATION, ADHESION, EVENEMENT, AIDE).
*/
@NotBlank
@Size(max = 50)
@Column(name = "type_objet_cible", nullable = false, length = 50)
private String typeObjetCible;
/**
* UUID de l'objet cible (cotisation, demande
* d'adhésion, inscription événement, ou demande
* d'aide).
*/
@NotNull
@Column(name = "objet_cible_id", nullable = false)
private UUID objetCibleId;
/** UUID de l'objet cible. */
@NotNull
@Column(name = "objet_cible_id", nullable = false)
private UUID objetCibleId;
/** Montant appliqué à cet objet cible. */
@NotNull
@DecimalMin(value = "0.0", message = "Le montant doit être positif")
@Digits(integer = 12, fraction = 2)
@Column(name = "montant_applique", nullable = false, precision = 14, scale = 2)
private BigDecimal montantApplique;
/** Montant appliqué à cet objet cible. */
@NotNull
@DecimalMin(value = "0.0", message = "Le montant doit être positif")
@Digits(integer = 12, fraction = 2)
@Column(name = "montant_applique", nullable = false, precision = 14, scale = 2)
private BigDecimal montantApplique;
/** Date d'application du paiement. */
@Column(name = "date_application")
private LocalDateTime dateApplication;
/** Date d'application du paiement. */
@Column(name = "date_application")
private LocalDateTime dateApplication;
/** Commentaire sur l'application. */
@Size(max = 500)
@Column(name = "commentaire", length = 500)
private String commentaire;
/** Commentaire sur l'application. */
@Size(max = 500)
@Column(name = "commentaire", length = 500)
private String commentaire;
/**
* Callback JPA avant la persistance.
*
* <p>
* Initialise {@code dateApplication} si non
* renseignée.
*/
@Override
@PrePersist
protected void onCreate() {
super.onCreate();
if (dateApplication == null) {
dateApplication = LocalDateTime.now();
}
@Override
@PrePersist
protected void onCreate() {
super.onCreate();
if (dateApplication == null) {
dateApplication = LocalDateTime.now();
}
}
}