# Cohérence des données — UnionFlow Mobile Ce document décrit les conventions et alignements API ↔ app pour éviter les incohérences. ## 1. Configuration - **API** : `AppConfig.apiBaseUrl` (initialisé dans `main()` via `AppConfig.initialize()`). Utilisé par `ApiClient` (Dio `baseUrl`). - **Keycloak** : `AppConfig.keycloakBaseUrl`, `keycloakRealmUrl`, `keycloakTokenUrl`. - Toutes les requêtes passent par le même `ApiClient` (token, refresh, timeouts). ## 2. Membres (Annuaire) | Backend (MembreSummaryResponse / PagedResponse) | Mobile (MembreCompletModel / repository) | |-------------------------------------------------|------------------------------------------| | `data` (liste), `total`, `page`, `size`, `totalPages` | `_parseMembreSearchResult` lit `data`, `total` (num→int), `page`, `size`, `totalPages` | | `associationNom` | Normalisé → `organisationNom` dans `_normalizeAndParseMembre` | | `statutCompte` ("ACTIF", etc.) | Normalisé → `statut` (enum StatutMembre) | | `photoUrl` (MembreResponse détail) | Normalisé → `photo` si absent | | `id`, `organisationId` (UUID) | Convertis en `String` avant `fromJson` | | `nom`, `prenom`, `email` requis | Modèle : champs requis ; summary backend les envoie toujours | - **Liste paginée** : GET `/api/membres?page=&size=` → réponse `PagedResponse` avec `data`, `total`, `page`, `size`, `totalPages`. - **Recherche** : GET `/api/membres/recherche?q=&page=&size=` → liste ou même structure paginée selon backend. - **Affichage annuaire** : `members_page_wrapper` convertit `MembreCompletModel` en `Map` avec `status` = libellé français (Actif, En attente, etc.) via `_mapStatutToString(statut)`. ## 3. Cotisations (Contributions) - **Mes cotisations** : GET `/api/cotisations/mes-cotisations?page=&size=` → backend renvoie une **liste** (pas un objet paginé). Le repository gère `data is List`. - **En attente** : GET `/api/cotisations/mes-cotisations/en-attente` → liste. Le repository accepte aussi `data['data']` ou `data['content']` si le format change. - Modèle : `ContributionModel` avec `id`, `statut`, `montantDu`, `montantPaye`, `dateEcheance`, `nomMembre`, etc. alignés sur les champs backend. Côté mobile, `membreNom` utilise `nomMembre` avec fallback sur `nomCompletMembre` (Summary vs Response). ## 4. Épargne - **Comptes** : GET `/api/v1/epargne/comptes/mes-comptes` → liste de comptes. `CompteEpargneModel` : `id`, `membreId`, `organisationId` en `String` (backend UUID sérialisé). - **Transactions** : GET `/api/v1/epargne/transactions/compte/{compteId}` → liste. `TransactionEpargneModel.fromJson` avec `_toDouble` pour montants. - Tous les IDs (compte, membre, org) sont traités en `String` côté mobile (`toString()` si besoin). ## 5. Organisations - **Mes organisations** : GET `/api/organisations/mes` → liste. `OrganizationModel` avec `id`, `nom`, `nomCourt`, etc. - **Liste (admin)** : GET `/api/organisations?page=&size=` → liste ou paginée selon endpoint. Repository parse `response.data as List` ou structure paginée. ## 6. Admin utilisateurs (SUPER_ADMIN) - **Liste** : GET `/api/admin/users?page=&size=&search=` → UnionFlow renvoie `UserSearchResultDTO` (proxy lions-user-manager). Structure vérifiée dans `lions-user-manager-server-api` : - **UserSearchResultDTO** : `users` (List\), `totalCount` (Long), `currentPage` (Integer), `pageSize` (Integer), `totalPages` (Integer), plus optionnels (`hasNextPage`, `criteria`, `executionTimeMs`, etc.). - **UserDTO** (BaseDTO + champs) : `id`, `username`, `email`, `prenom`, `nom`, `enabled`, `realmRoles` (List\), `statut`, `dateCreation`, etc. - Le repository mobile lit `data['users']`, `totalCount`, `currentPage`, `pageSize`, `totalPages` (avec cast `num` → int) et parse chaque élément avec `AdminUserModel.fromJson`. Alignement confirmé. - **Associer organisation** : POST `/api/admin/associer-organisation` avec body `{ "email", "organisationId" }`. ## 7. Dashboard - **Avec organisation** : appel avec `organizationId` et `userId` (chaînes). `DashboardEntity` / `DashboardStatsModel` alignés sur les réponses backend. - **Membre sans org** : GET `/api/dashboard/membre/me` → `MembreDashboardSyntheseModel`, mappé vers la même `DashboardEntity` pour réutilisation UI. ## 8. Bonnes pratiques - **IDs** : toujours normaliser en `String` côté mobile (`.toString()`) pour UUID backend. - **Pagination** : préférer `(data['total'] as num?)?.toInt()` pour accepter `int` ou `double` selon la sérialisation JSON. - **Statut / libellé** : backend envoie souvent `statutCompte` + `statutCompteLibelle` ; le mobile peut normaliser `statutCompte` → `statut` (enum) et utiliser les libellés pour l’affichage. - **Noms de champs** : garder une seule normalisation dans le repository (ex. `_normalizeAndParseMembre`) pour éviter les doublons (associationNom, photoUrl, statutCompte, etc.). ## 9. Vérifications effectuées - Membres : PagedResponse `data`/`total`/`page`/`size`/`totalPages` alignés ; normalisation associationNom, statutCompte, photoUrl, id/organisationId. - Cotisations : liste directe pour mes-cotisations et en-attente. - Épargne : IDs en string, montants avec _toDouble. - Config : une seule base URL et un seul ApiClient.