feat(sprint-6 P2-NEW-7 2026-04-25): multi-devise + KYC non-résident diaspora + tests
Some checks failed
CI/CD Pipeline / pipeline (push) Failing after 4m11s
Some checks failed
CI/CD Pipeline / pipeline (push) Failing after 4m11s
Ouvre UnionFlow à la diaspora UEMOA (France, USA, Canada, UK, Suisse...). Entités & migration - Enum Devise (10 valeurs : XOF, XAF, EUR, USD, GBP, CAD, CHF, GHS, NGN, MAD) - Zones : UEMOA, CEMAC, CEDEAO, EUROPE, AMERIQUE, MAGHREB - DEVISES_INTERNATIONALES : EUR/USD/GBP/CAD/CHF (déclenchent AML international) - Entité TauxChange (devise_source × devise_cible × date_validite, taux NUMERIC(18,8)) - Repository : trouverExact, trouverPlusRecent (≤ date) - V49 : - Table taux_change (contrainte unicité paire+date, devises distinctes) - Seed BCEAO_FIXED EUR↔XOF + taux indicatifs USD/GBP/CAD au 2026-04-25 - Membres : pays_residence (ISO-3), numero_passeport, numero_fiscal_etranger, est_diaspora, devise_preferee - KycDossiers : pays_origine_fonds, justificatif_residence_etrangere, niveau_due_diligence (SIMPLIFIE/STANDARD/RENFORCE) DeviseConversionService - Stratégie de résolution : direct → inverse → pivot via XOF → fallback récent ≤ date - Cache thread-safe (ConcurrentHashMap, TTL 1h) - TauxIntrouvableException si aucun taux résolvable - invaliderCache() pour reload après import batch KycDiasporaService - validerCoherence : passeport obligatoire si diaspora, pays_residence ≠ UEMOA, format passeport regex - determinerNiveauDueDiligence (Instr. BCEAO 001-03-2025) : - PEP → RENFORCE - Diaspora pays sécurisés (UE/G7/Asie) → STANDARD - Diaspora FATF grey-list → RENFORCE - Diaspora pays inconnu → RENFORCE par prudence - depasseSeuilAmlInternational : seuil 1000 EUR équivalent, false sur devises locales - PAYS_UEMOA hardcodé (8 pays), PAYS_GREY_LIST_FATF snapshot 2026-04-25 Tests Sprint 6 (34/34 verts) - DeviseTest : 5 tests (référence, internationales, zones, libellés) - DeviseConversionServiceTest : 10 tests (identité, direct, inverse, pivot XOF, fallback récent, cache, invalider, exception, inputs invalides) - KycDiasporaServiceTest : 19 tests (cohérence valide/sans passeport/pays UEMOA/pays étranger, due diligence PEP/FRA/grey-list/inconnu/UEMOA, seuil EUR/USD avec taux/sans taux/XOF/null)
This commit is contained in:
@@ -77,6 +77,34 @@ public class Membre extends BaseEntity {
|
||||
@Column(name = "numero_cmu", length = 11)
|
||||
private String numeroCMU;
|
||||
|
||||
/**
|
||||
* Pays de résidence (ISO-3, ex: FRA, USA, CAN). Différent de {@code nationalite} :
|
||||
* un Ivoirien (CIV) résidant en France a paysResidence=FRA. NULL ou CIV = résident UEMOA.
|
||||
*
|
||||
* @since 2026-04-25 (P2-NEW-7)
|
||||
*/
|
||||
@Pattern(regexp = "^[A-Z]{3}$|^$", message = "Pays résidence doit être un code ISO-3")
|
||||
@Column(name = "pays_residence", length = 3)
|
||||
private String paysResidence;
|
||||
|
||||
/** Numéro de passeport pour non-résidents (CNI insuffisante hors UEMOA). */
|
||||
@Column(name = "numero_passeport", length = 50)
|
||||
private String numeroPasseport;
|
||||
|
||||
/** NIF/SSN/SIN — reporting fiscal accord bilatéral CI ↔ pays résidence. */
|
||||
@Column(name = "numero_fiscal_etranger", length = 50)
|
||||
private String numeroFiscalEtranger;
|
||||
|
||||
/** TRUE si le membre est diaspora (résidence ≠ UEMOA). */
|
||||
@Builder.Default
|
||||
@Column(name = "est_diaspora", nullable = false)
|
||||
private Boolean estDiaspora = false;
|
||||
|
||||
/** Devise préférée pour affichages et notifications (XOF par défaut). */
|
||||
@Builder.Default
|
||||
@Column(name = "devise_preferee", nullable = false, length = 3)
|
||||
private String devisePreferee = "XOF";
|
||||
|
||||
@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;
|
||||
|
||||
Reference in New Issue
Block a user