133 lines
4.4 KiB
Java
133 lines
4.4 KiB
Java
package dev.lions.unionflow.server.entity;
|
|
|
|
import jakarta.persistence.*;
|
|
import jakarta.validation.constraints.*;
|
|
import java.math.BigDecimal;
|
|
import java.time.LocalDateTime;
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
import lombok.*;
|
|
|
|
/**
|
|
* Demande d'adhésion d'un utilisateur à une organisation.
|
|
*
|
|
* <p>Flux :
|
|
* <ol>
|
|
* <li>L'utilisateur crée son compte et choisit une organisation</li>
|
|
* <li>Une {@code DemandeAdhesion} est créée (statut EN_ATTENTE)</li>
|
|
* <li>Si frais d'adhésion : une {@link IntentionPaiement} est créée et liée</li>
|
|
* <li>Le manager valide → {@link MembreOrganisation} créé, quota souscription décrémenté</li>
|
|
* </ol>
|
|
*
|
|
* <p>Remplace l'ancienne entité {@code Adhesion}.
|
|
* Table : {@code demandes_adhesion}
|
|
*/
|
|
@Entity
|
|
@Table(
|
|
name = "demandes_adhesion",
|
|
indexes = {
|
|
@Index(name = "idx_da_utilisateur", columnList = "utilisateur_id"),
|
|
@Index(name = "idx_da_organisation", columnList = "organisation_id"),
|
|
@Index(name = "idx_da_statut", columnList = "statut"),
|
|
@Index(name = "idx_da_date", columnList = "date_demande")
|
|
})
|
|
@Data
|
|
@NoArgsConstructor
|
|
@AllArgsConstructor
|
|
@Builder
|
|
@EqualsAndHashCode(callSuper = true)
|
|
public class DemandeAdhesion extends BaseEntity {
|
|
|
|
@NotBlank
|
|
@Column(name = "numero_reference", unique = true, nullable = false, length = 50)
|
|
private String numeroReference;
|
|
|
|
@NotNull
|
|
@ManyToOne(fetch = FetchType.LAZY)
|
|
@JoinColumn(name = "utilisateur_id", nullable = false)
|
|
private Membre utilisateur;
|
|
|
|
@NotNull
|
|
@ManyToOne(fetch = FetchType.LAZY)
|
|
@JoinColumn(name = "organisation_id", nullable = false)
|
|
private Organisation organisation;
|
|
|
|
@NotBlank
|
|
@Pattern(regexp = "^(EN_ATTENTE|APPROUVEE|REJETEE|ANNULEE)$")
|
|
@Builder.Default
|
|
@Column(name = "statut", nullable = false, length = 20)
|
|
private String statut = "EN_ATTENTE";
|
|
|
|
@Builder.Default
|
|
@DecimalMin("0.00")
|
|
@Digits(integer = 10, fraction = 2)
|
|
@Column(name = "frais_adhesion", nullable = false, precision = 12, scale = 2)
|
|
private BigDecimal fraisAdhesion = BigDecimal.ZERO;
|
|
|
|
@Builder.Default
|
|
@DecimalMin("0.00")
|
|
@Digits(integer = 10, fraction = 2)
|
|
@Column(name = "montant_paye", nullable = false, precision = 12, scale = 2)
|
|
private BigDecimal montantPaye = BigDecimal.ZERO;
|
|
|
|
@Builder.Default
|
|
@Pattern(regexp = "^[A-Z]{3}$")
|
|
@Column(name = "code_devise", nullable = false, length = 3)
|
|
private String codeDevise = "XOF";
|
|
|
|
/** Intention de paiement Wave liée aux frais d'adhésion */
|
|
@ManyToOne(fetch = FetchType.LAZY)
|
|
@JoinColumn(name = "intention_paiement_id")
|
|
private IntentionPaiement intentionPaiement;
|
|
|
|
@Builder.Default
|
|
@Column(name = "date_demande", nullable = false)
|
|
private LocalDateTime dateDemande = LocalDateTime.now();
|
|
|
|
@Column(name = "date_traitement")
|
|
private LocalDateTime dateTraitement;
|
|
|
|
/** Manager/Admin qui a approuvé ou rejeté */
|
|
@ManyToOne(fetch = FetchType.LAZY)
|
|
@JoinColumn(name = "traite_par_id")
|
|
private Membre traitePar;
|
|
|
|
@Column(name = "motif_rejet", length = 1000)
|
|
private String motifRejet;
|
|
|
|
@Column(name = "observations", length = 1000)
|
|
private String observations;
|
|
|
|
// ── Méthodes métier ────────────────────────────────────────────────────────
|
|
|
|
public boolean isEnAttente() { return "EN_ATTENTE".equals(statut); }
|
|
public boolean isApprouvee() { return "APPROUVEE".equals(statut); }
|
|
public boolean isRejetee() { return "REJETEE".equals(statut); }
|
|
|
|
public boolean isPayeeIntegralement() {
|
|
return fraisAdhesion != null
|
|
&& montantPaye != null
|
|
&& montantPaye.compareTo(fraisAdhesion) >= 0;
|
|
}
|
|
|
|
private static final AtomicLong REFERENCE_COUNTER =
|
|
new AtomicLong(System.currentTimeMillis() % 100000000L);
|
|
|
|
public static String genererNumeroReference() {
|
|
return "ADH-" + java.time.LocalDate.now().getYear()
|
|
+ "-" + String.format("%08d", REFERENCE_COUNTER.incrementAndGet() % 100000000L);
|
|
}
|
|
|
|
@PrePersist
|
|
protected void onCreate() {
|
|
super.onCreate();
|
|
if (dateDemande == null) dateDemande = LocalDateTime.now();
|
|
if (statut == null) statut = "EN_ATTENTE";
|
|
if (codeDevise == null) codeDevise = "XOF";
|
|
if (fraisAdhesion == null) fraisAdhesion = BigDecimal.ZERO;
|
|
if (montantPaye == null) montantPaye = BigDecimal.ZERO;
|
|
if (numeroReference == null || numeroReference.isEmpty()) {
|
|
numeroReference = genererNumeroReference();
|
|
}
|
|
}
|
|
}
|