chore(docker): add root Dockerfile pinning ubi8/openjdk-21:1.21 + UID 1001 for lionsctl pipeline
Some checks failed
CI/CD Pipeline / pipeline (push) Failing after 4m2s
Some checks failed
CI/CD Pipeline / pipeline (push) Failing after 4m2s
This commit is contained in:
@@ -1,122 +1,122 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.paiement.StatutIntentionPaiement;
|
||||
import dev.lions.unionflow.server.api.enums.paiement.TypeObjetIntentionPaiement;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* Hub centralisé pour tout paiement Wave initié depuis UnionFlow.
|
||||
*
|
||||
* <p>Flux :
|
||||
* <ol>
|
||||
* <li>UnionFlow crée une {@code IntentionPaiement} avec les objets cibles (cotisations, etc.)</li>
|
||||
* <li>UnionFlow appelle l'API Wave → récupère {@code waveCheckoutSessionId}</li>
|
||||
* <li>Le membre confirme dans l'app Wave</li>
|
||||
* <li>Wave envoie un webhook → UnionFlow réconcilie via {@code waveCheckoutSessionId}</li>
|
||||
* <li>UnionFlow valide automatiquement les objets listés dans {@code objetsCibles}</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>Table : {@code intentions_paiement}
|
||||
*/
|
||||
@Entity
|
||||
@Table(
|
||||
name = "intentions_paiement",
|
||||
indexes = {
|
||||
@Index(name = "idx_intention_utilisateur", columnList = "utilisateur_id"),
|
||||
@Index(name = "idx_intention_statut", columnList = "statut"),
|
||||
@Index(name = "idx_intention_wave_session", columnList = "wave_checkout_session_id", unique = true),
|
||||
@Index(name = "idx_intention_expiration", columnList = "date_expiration")
|
||||
})
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class IntentionPaiement extends BaseEntity {
|
||||
|
||||
@NotNull
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "utilisateur_id", nullable = false)
|
||||
private Membre utilisateur;
|
||||
|
||||
/** NULL pour les abonnements UnionFlow SA (payés par l'organisation directement) */
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "organisation_id")
|
||||
private Organisation organisation;
|
||||
|
||||
@NotNull
|
||||
@DecimalMin("0.01")
|
||||
@Digits(integer = 12, fraction = 2)
|
||||
@Column(name = "montant_total", nullable = false, precision = 14, scale = 2)
|
||||
private BigDecimal montantTotal;
|
||||
|
||||
@NotBlank
|
||||
@Pattern(regexp = "^[A-Z]{3}$")
|
||||
@Builder.Default
|
||||
@Column(name = "code_devise", nullable = false, length = 3)
|
||||
private String codeDevise = "XOF";
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@NotNull
|
||||
@Column(name = "type_objet", nullable = false, length = 30)
|
||||
private TypeObjetIntentionPaiement typeObjet;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Builder.Default
|
||||
@Column(name = "statut", nullable = false, length = 20)
|
||||
private StatutIntentionPaiement statut = StatutIntentionPaiement.INITIEE;
|
||||
|
||||
/** ID de session Wave — clé de réconciliation sur webhook */
|
||||
@Column(name = "wave_checkout_session_id", unique = true, length = 255)
|
||||
private String waveCheckoutSessionId;
|
||||
|
||||
/** URL de paiement Wave à rediriger l'utilisateur */
|
||||
@Column(name = "wave_launch_url", length = 1000)
|
||||
private String waveLaunchUrl;
|
||||
|
||||
/** ID transaction Wave reçu via webhook */
|
||||
@Column(name = "wave_transaction_id", length = 100)
|
||||
private String waveTransactionId;
|
||||
|
||||
/**
|
||||
* JSON : liste des objets couverts par ce paiement.
|
||||
* Exemple : [{\"type\":\"COTISATION\",\"id\":\"uuid\",\"montant\":5000}, ...]
|
||||
*/
|
||||
@Column(name = "objets_cibles", columnDefinition = "TEXT")
|
||||
private String objetsCibles;
|
||||
|
||||
@Column(name = "date_expiration")
|
||||
private LocalDateTime dateExpiration;
|
||||
|
||||
@Column(name = "date_completion")
|
||||
private LocalDateTime dateCompletion;
|
||||
|
||||
// ── Méthodes métier ────────────────────────────────────────────────────────
|
||||
|
||||
public boolean isActive() {
|
||||
return StatutIntentionPaiement.INITIEE.equals(statut)
|
||||
|| StatutIntentionPaiement.EN_COURS.equals(statut);
|
||||
}
|
||||
|
||||
public boolean isExpiree() {
|
||||
return dateExpiration != null && LocalDateTime.now().isAfter(dateExpiration);
|
||||
}
|
||||
|
||||
public boolean isCompletee() {
|
||||
return StatutIntentionPaiement.COMPLETEE.equals(statut);
|
||||
}
|
||||
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
super.onCreate();
|
||||
if (statut == null) statut = StatutIntentionPaiement.INITIEE;
|
||||
if (codeDevise == null) codeDevise = "XOF";
|
||||
if (dateExpiration == null) {
|
||||
dateExpiration = LocalDateTime.now().plusMinutes(30);
|
||||
}
|
||||
}
|
||||
}
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.paiement.StatutIntentionPaiement;
|
||||
import dev.lions.unionflow.server.api.enums.paiement.TypeObjetIntentionPaiement;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* Hub centralisé pour tout paiement Wave initié depuis UnionFlow.
|
||||
*
|
||||
* <p>Flux :
|
||||
* <ol>
|
||||
* <li>UnionFlow crée une {@code IntentionPaiement} avec les objets cibles (cotisations, etc.)</li>
|
||||
* <li>UnionFlow appelle l'API Wave → récupère {@code waveCheckoutSessionId}</li>
|
||||
* <li>Le membre confirme dans l'app Wave</li>
|
||||
* <li>Wave envoie un webhook → UnionFlow réconcilie via {@code waveCheckoutSessionId}</li>
|
||||
* <li>UnionFlow valide automatiquement les objets listés dans {@code objetsCibles}</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>Table : {@code intentions_paiement}
|
||||
*/
|
||||
@Entity
|
||||
@Table(
|
||||
name = "intentions_paiement",
|
||||
indexes = {
|
||||
@Index(name = "idx_intention_utilisateur", columnList = "utilisateur_id"),
|
||||
@Index(name = "idx_intention_statut", columnList = "statut"),
|
||||
@Index(name = "idx_intention_wave_session", columnList = "wave_checkout_session_id", unique = true),
|
||||
@Index(name = "idx_intention_expiration", columnList = "date_expiration")
|
||||
})
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class IntentionPaiement extends BaseEntity {
|
||||
|
||||
@NotNull
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "utilisateur_id", nullable = false)
|
||||
private Membre utilisateur;
|
||||
|
||||
/** NULL pour les abonnements UnionFlow SA (payés par l'organisation directement) */
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "organisation_id")
|
||||
private Organisation organisation;
|
||||
|
||||
@NotNull
|
||||
@DecimalMin("0.01")
|
||||
@Digits(integer = 12, fraction = 2)
|
||||
@Column(name = "montant_total", nullable = false, precision = 14, scale = 2)
|
||||
private BigDecimal montantTotal;
|
||||
|
||||
@NotBlank
|
||||
@Pattern(regexp = "^[A-Z]{3}$")
|
||||
@Builder.Default
|
||||
@Column(name = "code_devise", nullable = false, length = 3)
|
||||
private String codeDevise = "XOF";
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@NotNull
|
||||
@Column(name = "type_objet", nullable = false, length = 30)
|
||||
private TypeObjetIntentionPaiement typeObjet;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Builder.Default
|
||||
@Column(name = "statut", nullable = false, length = 20)
|
||||
private StatutIntentionPaiement statut = StatutIntentionPaiement.INITIEE;
|
||||
|
||||
/** ID de session Wave — clé de réconciliation sur webhook */
|
||||
@Column(name = "wave_checkout_session_id", unique = true, length = 255)
|
||||
private String waveCheckoutSessionId;
|
||||
|
||||
/** URL de paiement Wave à rediriger l'utilisateur */
|
||||
@Column(name = "wave_launch_url", length = 1000)
|
||||
private String waveLaunchUrl;
|
||||
|
||||
/** ID transaction Wave reçu via webhook */
|
||||
@Column(name = "wave_transaction_id", length = 100)
|
||||
private String waveTransactionId;
|
||||
|
||||
/**
|
||||
* JSON : liste des objets couverts par ce paiement.
|
||||
* Exemple : [{\"type\":\"COTISATION\",\"id\":\"uuid\",\"montant\":5000}, ...]
|
||||
*/
|
||||
@Column(name = "objets_cibles", columnDefinition = "TEXT")
|
||||
private String objetsCibles;
|
||||
|
||||
@Column(name = "date_expiration")
|
||||
private LocalDateTime dateExpiration;
|
||||
|
||||
@Column(name = "date_completion")
|
||||
private LocalDateTime dateCompletion;
|
||||
|
||||
// ── Méthodes métier ────────────────────────────────────────────────────────
|
||||
|
||||
public boolean isActive() {
|
||||
return StatutIntentionPaiement.INITIEE.equals(statut)
|
||||
|| StatutIntentionPaiement.EN_COURS.equals(statut);
|
||||
}
|
||||
|
||||
public boolean isExpiree() {
|
||||
return dateExpiration != null && LocalDateTime.now().isAfter(dateExpiration);
|
||||
}
|
||||
|
||||
public boolean isCompletee() {
|
||||
return StatutIntentionPaiement.COMPLETEE.equals(statut);
|
||||
}
|
||||
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
super.onCreate();
|
||||
if (statut == null) statut = StatutIntentionPaiement.INITIEE;
|
||||
if (codeDevise == null) codeDevise = "XOF";
|
||||
if (dateExpiration == null) {
|
||||
dateExpiration = LocalDateTime.now().plusMinutes(30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user