feat(sprint-9 mobile 2026-04-25): feature compliance dashboard + Devise enum + selector + tests

Apporte aux compliance officers et controleurs internes l'accès mobile au tableau de bord
de conformité backend (P1-NEW-7). Et prépare la diaspora avec Devise enum + sélecteur
préférence persisté.

Feature Compliance (Clean Architecture)
- Domain : ComplianceSnapshot + ConformiteIndicateur (Equatable), helpers scoreSeverite + hasAlertesCritiques
- Data : ComplianceSnapshotModel.fromJson (parsing tolerant aux nullables), ComplianceRemoteDataSourceImpl Dio (GET /api/compliance/dashboard), ComplianceRepositoryImpl @Injectable
- Presentation : ComplianceBloc (Load/Refresh events, Initial/Loading/Loaded/Error states), ConformiteDashboardPage (Material 3, ScoreCard 0-100 colorée, 9 IndicateurTile, AlertesCard rouge si critiques)

Feature Devise
- Devise enum (10 valeurs miroirs backend, code/libelle/zone)
- fromCode tolérant casse + null/vide → XOF
- estInternationale pour AML
- DeviseSelector widget DropdownButtonFormField + readPreferred/writePreferred via FlutterSecureStorage (clé unionflow.devise.preferee)

Tests (17/17 verts)
- ComplianceSnapshot : 7 tests (scoreSeverite × 3, hasAlertesCritiques × 4)
- ComplianceSnapshotModel.fromJson : 4 tests (complet, fallbacks, string→double, indicateur invalide)
- Devise enum : 6 tests (reference, fromCode parse, fromCode null/inconnu, estInternationale × 2, intégrité valeurs)

Note : feature reporting trimestriel mobile (PDF viewer + bloc liste) reportée à un sprint
dédié — nécessite intégration pdf viewer + cache local non triviale.
This commit is contained in:
dahoud
2026-04-25 11:11:03 +00:00
parent 8356ccc0b0
commit 8c1a254e80
12 changed files with 808 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
/// Devises supportées par UnionFlow (miroir mobile de l'enum backend).
///
/// Les codes ISO-4217 servent aussi d'identifiant pour l'API.
enum Devise {
xof('XOF', 'Franc CFA Ouest', 'UEMOA'),
xaf('XAF', 'Franc CFA Centrale', 'CEMAC'),
eur('EUR', 'Euro', 'EUROPE'),
usd('USD', 'Dollar US', 'AMERIQUE'),
gbp('GBP', 'Livre Sterling', 'EUROPE'),
cad('CAD', 'Dollar Canadien', 'AMERIQUE'),
chf('CHF', 'Franc Suisse', 'EUROPE'),
ghs('GHS', 'Cédi Ghanéen', 'CEDEAO'),
ngn('NGN', 'Naira Nigérian', 'CEDEAO'),
mad('MAD', 'Dirham Marocain', 'MAGHREB');
final String code;
final String libelle;
final String zone;
const Devise(this.code, this.libelle, this.zone);
/// Devise de référence UnionFlow.
static Devise reference() => Devise.xof;
/// Parse un code ISO-4217 en {@link Devise}, fallback sur XOF.
static Devise fromCode(String? code) {
if (code == null || code.isEmpty) return reference();
return Devise.values.firstWhere(
(d) => d.code.toUpperCase() == code.toUpperCase(),
orElse: () => reference(),
);
}
/// True pour les devises internationales (déclenchent AML international).
bool get estInternationale => const {
Devise.eur,
Devise.usd,
Devise.gbp,
Devise.cad,
Devise.chf,
}.contains(this);
}