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)
63 lines
2.0 KiB
Java
63 lines
2.0 KiB
Java
package dev.lions.unionflow.server.entity;
|
|
|
|
import jakarta.persistence.Column;
|
|
import jakarta.persistence.Entity;
|
|
import jakarta.persistence.EnumType;
|
|
import jakarta.persistence.Enumerated;
|
|
import jakarta.persistence.Index;
|
|
import jakarta.persistence.Table;
|
|
import jakarta.persistence.UniqueConstraint;
|
|
import jakarta.validation.constraints.DecimalMin;
|
|
import java.math.BigDecimal;
|
|
import java.time.LocalDate;
|
|
import lombok.AllArgsConstructor;
|
|
import lombok.Builder;
|
|
import lombok.Data;
|
|
import lombok.EqualsAndHashCode;
|
|
import lombok.NoArgsConstructor;
|
|
|
|
/**
|
|
* Taux de change quotidien entre deux {@link Devise}s.
|
|
*
|
|
* <p>Source : BCEAO (officiel UEMOA), ECB, Fixer.io ou import manuel. Conservation
|
|
* historique pour audit et conversions rétroactives.
|
|
*
|
|
* @since 2026-04-25 (P2-NEW-7)
|
|
*/
|
|
@Entity
|
|
@Table(name = "taux_change",
|
|
uniqueConstraints = @UniqueConstraint(
|
|
name = "uq_taux_change_paire_date",
|
|
columnNames = {"devise_source", "devise_cible", "date_validite"}),
|
|
indexes = {
|
|
@Index(name = "idx_taux_change_paire", columnList = "devise_source,devise_cible"),
|
|
@Index(name = "idx_taux_change_date_validite", columnList = "date_validite")
|
|
})
|
|
@Data
|
|
@NoArgsConstructor
|
|
@AllArgsConstructor
|
|
@Builder
|
|
@EqualsAndHashCode(callSuper = true)
|
|
public class TauxChange extends BaseEntity {
|
|
|
|
@Enumerated(EnumType.STRING)
|
|
@Column(name = "devise_source", nullable = false, length = 3)
|
|
private Devise deviseSource;
|
|
|
|
@Enumerated(EnumType.STRING)
|
|
@Column(name = "devise_cible", nullable = false, length = 3)
|
|
private Devise deviseCible;
|
|
|
|
/** 1 unité de {@code deviseSource} = {@code taux} unités de {@code deviseCible}. */
|
|
@DecimalMin(value = "0.00000001", inclusive = false)
|
|
@Column(name = "taux", nullable = false, precision = 18, scale = 8)
|
|
private BigDecimal taux;
|
|
|
|
@Column(name = "date_validite", nullable = false)
|
|
private LocalDate dateValidite;
|
|
|
|
@Builder.Default
|
|
@Column(name = "source", nullable = false, length = 50)
|
|
private String source = "BCEAO";
|
|
}
|