fix(disaster-recovery 2/2): restaurer 242 fichiers Java modifiés par a72ab54
Some checks failed
CI/CD Pipeline / pipeline (push) Failing after 3m22s

Suite à la récupération précédente (044ca4b) qui n'avait restauré que les
fichiers SUPPRIMÉS, ce commit restaure les MODIFICATIONS d'entités/services
qui étaient nécessaires pour que les fichiers restaurés compilent.

Restaurés depuis a72ab54^ (= 31330d9 + corrections) :
- Entities : Organisation, FormuleAbonnement, AuditService, MembreOrganisation, SouscriptionOrganisation, etc.
- Services : MigrerOrganisationsVersKeycloakService, ComptabilitePdfService, KycAmlService, AuditService.logKycRisqueEleve, etc.
- Resources : PaiementUnifieResource, etc.

Backend compile désormais (BUILD SUCCESS).
This commit is contained in:
2026-04-25 01:05:08 +00:00
parent 044ca4bd7e
commit 6e9841b3bb
242 changed files with 38000 additions and 37312 deletions

View File

@@ -1,169 +1,173 @@
package dev.lions.unionflow.server.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import lombok.*;
/**
* Identité globale unique d'un utilisateur UnionFlow.
*
* <p>
* Un utilisateur possède un seul compte sur toute la plateforme.
* Ses adhésions aux organisations sont gérées dans {@link MembreOrganisation}.
*
* <p>
* Table : {@code utilisateurs}
*/
@Entity
@Table(name = "utilisateurs", indexes = {
@Index(name = "idx_utilisateur_email", columnList = "email", unique = true),
@Index(name = "idx_utilisateur_numero", columnList = "numero_membre", unique = true),
@Index(name = "idx_utilisateur_keycloak", columnList = "keycloak_id", unique = true),
@Index(name = "idx_utilisateur_actif", columnList = "actif"),
@Index(name = "idx_utilisateur_statut", columnList = "statut_compte")
})
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class Membre extends BaseEntity {
/** Identifiant Keycloak (UUID du compte OIDC) */
@Column(name = "keycloak_id", unique = true)
private UUID keycloakId;
/** Numéro de membre — unique globalement sur toute la plateforme */
@NotBlank
@Column(name = "numero_membre", unique = true, nullable = false, length = 20)
private String numeroMembre;
@NotBlank
@Column(name = "prenom", nullable = false, length = 100)
private String prenom;
@NotBlank
@Column(name = "nom", nullable = false, length = 100)
private String nom;
@Email
@NotBlank
@Column(name = "email", unique = true, nullable = false, length = 255)
private String email;
@Column(name = "telephone", length = 20)
private String telephone;
@Pattern(regexp = "^\\+[1-9][0-9]{6,14}$", message = "Le numéro Wave doit être au format international E.164 (ex: +22507XXXXXXXX)")
@Column(name = "telephone_wave", length = 20)
private String telephoneWave;
@NotNull
@Column(name = "date_naissance", nullable = false)
private LocalDate dateNaissance;
@Column(name = "profession", length = 100)
private String profession;
@Column(name = "photo_url", length = 500)
private String photoUrl;
@Builder.Default
@Column(name = "statut_compte", nullable = false, length = 30)
private String statutCompte = "EN_ATTENTE_VALIDATION";
/** Vrai si le membre n'a jamais changé son mot de passe généré par l'admin. */
@Builder.Default
@Column(name = "premiere_connexion", nullable = false)
private Boolean premiereConnexion = true;
/**
* Statut matrimonial (domaine
* {@code STATUT_MATRIMONIAL} dans
* {@code types_reference}).
*/
@Column(name = "statut_matrimonial", length = 50)
private String statutMatrimonial;
/** Nationalité. */
@Column(name = "nationalite", length = 100)
private String nationalite;
/**
* Type de pièce d'identité (domaine
* {@code TYPE_IDENTITE} dans
* {@code types_reference}).
*/
@Column(name = "type_identite", length = 50)
private String typeIdentite;
/** Numéro de la pièce d'identité. */
@Column(name = "numero_identite", length = 100)
private String numeroIdentite;
/** Notes / biographie libre du membre. */
@Column(name = "notes", length = 1000)
private String notes;
/** Niveau de vigilance KYC LCB-FT (SIMPLIFIE, RENFORCE). */
@Column(name = "niveau_vigilance_kyc", length = 20)
private String niveauVigilanceKyc;
/** Statut de vérification d'identité (NON_VERIFIE, EN_COURS, VERIFIE, REFUSE). */
@Column(name = "statut_kyc", length = 20)
private String statutKyc;
/** Date de dernière vérification d'identité. */
@Column(name = "date_verification_identite")
private LocalDate dateVerificationIdentite;
// ── Relations ────────────────────────────────────────────────────────────
/** Adhésions à des organisations */
@JsonIgnore
@OneToMany(mappedBy = "membre", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Builder.Default
private List<MembreOrganisation> membresOrganisations = new ArrayList<>();
@JsonIgnore
@OneToMany(mappedBy = "membre", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Builder.Default
private List<Adresse> adresses = new ArrayList<>();
@JsonIgnore
@OneToMany(mappedBy = "membre", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Builder.Default
private List<CompteWave> comptesWave = new ArrayList<>();
@JsonIgnore
@OneToMany(mappedBy = "membre", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Builder.Default
private List<Paiement> paiements = new ArrayList<>();
// ── Méthodes métier ───────────────────────────────────────────────────────
public String getNomComplet() {
return prenom + " " + nom;
}
public boolean isMajeur() {
return dateNaissance != null && dateNaissance.isBefore(LocalDate.now().minusYears(18));
}
public int getAge() {
return dateNaissance != null ? LocalDate.now().getYear() - dateNaissance.getYear() : 0;
}
@PrePersist
protected void onCreate() {
super.onCreate();
if (statutCompte == null) {
statutCompte = "EN_ATTENTE_VALIDATION";
}
}
}
package dev.lions.unionflow.server.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import lombok.*;
/**
* Identité globale unique d'un utilisateur UnionFlow.
*
* <p>
* Un utilisateur possède un seul compte sur toute la plateforme.
* Ses adhésions aux organisations sont gérées dans {@link MembreOrganisation}.
*
* <p>
* Table : {@code utilisateurs}
*/
@Entity
@Table(name = "utilisateurs", indexes = {
@Index(name = "idx_utilisateur_email", columnList = "email", unique = true),
@Index(name = "idx_utilisateur_numero", columnList = "numero_membre", unique = true),
@Index(name = "idx_utilisateur_keycloak", columnList = "keycloak_id", unique = true),
@Index(name = "idx_utilisateur_actif", columnList = "actif"),
@Index(name = "idx_utilisateur_statut", columnList = "statut_compte")
})
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class Membre extends BaseEntity {
/** Identifiant Keycloak (UUID du compte OIDC) */
@Column(name = "keycloak_id", unique = true)
private UUID keycloakId;
/** Numéro de membre — unique globalement sur toute la plateforme */
@NotBlank
@Column(name = "numero_membre", unique = true, nullable = false, length = 20)
private String numeroMembre;
@NotBlank
@Column(name = "prenom", nullable = false, length = 100)
private String prenom;
@NotBlank
@Column(name = "nom", nullable = false, length = 100)
private String nom;
@Email
@NotBlank
@Column(name = "email", unique = true, nullable = false, length = 255)
private String email;
@Column(name = "telephone", length = 20)
private String telephone;
/** Token FCM pour les notifications push Firebase. NULL si l'app mobile n'est pas installée ou si le membre a refusé les notifications. */
@Column(name = "fcm_token", length = 500)
private String fcmToken;
@Pattern(regexp = "^\\+[1-9][0-9]{6,14}$", message = "Le numéro Wave doit être au format international E.164 (ex: +22507XXXXXXXX)")
@Column(name = "telephone_wave", length = 20)
private String telephoneWave;
@NotNull
@Column(name = "date_naissance", nullable = false)
private LocalDate dateNaissance;
@Column(name = "profession", length = 100)
private String profession;
@Column(name = "photo_url", length = 500)
private String photoUrl;
@Builder.Default
@Column(name = "statut_compte", nullable = false, length = 30)
private String statutCompte = "EN_ATTENTE_VALIDATION";
/** Vrai si le membre n'a jamais changé son mot de passe généré par l'admin. */
@Builder.Default
@Column(name = "premiere_connexion", nullable = false)
private Boolean premiereConnexion = true;
/**
* Statut matrimonial (domaine
* {@code STATUT_MATRIMONIAL} dans
* {@code types_reference}).
*/
@Column(name = "statut_matrimonial", length = 50)
private String statutMatrimonial;
/** Nationalité. */
@Column(name = "nationalite", length = 100)
private String nationalite;
/**
* Type de pièce d'identité (domaine
* {@code TYPE_IDENTITE} dans
* {@code types_reference}).
*/
@Column(name = "type_identite", length = 50)
private String typeIdentite;
/** Numéro de la pièce d'identité. */
@Column(name = "numero_identite", length = 100)
private String numeroIdentite;
/** Notes / biographie libre du membre. */
@Column(name = "notes", length = 1000)
private String notes;
/** Niveau de vigilance KYC LCB-FT (SIMPLIFIE, RENFORCE). */
@Column(name = "niveau_vigilance_kyc", length = 20)
private String niveauVigilanceKyc;
/** Statut de vérification d'identité (NON_VERIFIE, EN_COURS, VERIFIE, REFUSE). */
@Column(name = "statut_kyc", length = 20)
private String statutKyc;
/** Date de dernière vérification d'identité. */
@Column(name = "date_verification_identite")
private LocalDate dateVerificationIdentite;
// ── Relations ────────────────────────────────────────────────────────────
/** Adhésions à des organisations */
@JsonIgnore
@OneToMany(mappedBy = "membre", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Builder.Default
private List<MembreOrganisation> membresOrganisations = new ArrayList<>();
@JsonIgnore
@OneToMany(mappedBy = "membre", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Builder.Default
private List<Adresse> adresses = new ArrayList<>();
@JsonIgnore
@OneToMany(mappedBy = "membre", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Builder.Default
private List<CompteWave> comptesWave = new ArrayList<>();
@JsonIgnore
@OneToMany(mappedBy = "membre", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Builder.Default
private List<Paiement> paiements = new ArrayList<>();
// ── Méthodes métier ───────────────────────────────────────────────────────
public String getNomComplet() {
return prenom + " " + nom;
}
public boolean isMajeur() {
return dateNaissance != null && dateNaissance.isBefore(LocalDate.now().minusYears(18));
}
public int getAge() {
return dateNaissance != null ? LocalDate.now().getYear() - dateNaissance.getYear() : 0;
}
@PrePersist
protected void onCreate() {
super.onCreate();
if (statutCompte == null) {
statutCompte = "EN_ATTENTE_VALIDATION";
}
}
}