Files
unionflow-server-api/unionflow/unionflow-mobile-apps/docs/DATA_CONSISTENCY.md
dahoud e8ad874015 feat: WebSocket temps réel + Finance Workflow + corrections
- Task #6: WebSocket /ws/dashboard + Kafka events (5 topics)
  * Backend: KafkaEventProducer, KafkaEventConsumer
  * Mobile: WebSocketService (reconnection, heartbeat, typed events)
  * DashboardBloc: Auto-refresh depuis WebSocket events

- Finance Workflow: approbations + budgets (backend + mobile)
  * Backend: entities, services, resources, migrations Flyway V6
  * Mobile: features finance_workflow complète avec BLoC

- Corrections DI: interfaces IRepository partout
  * IProfileRepository, IOrganizationRepository, IMembreRepository
  * GetIt configuré avec @injectable

- Spec-Kit: constitution + templates mis à jour
  * .specify/memory/constitution.md enrichie
  * Templates agent, plan, spec, tasks, checklist

- Nettoyage: fichiers temporaires supprimés

Signed-off-by: lions dev Team
2026-03-15 02:12:17 +00:00

69 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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\<UserDTO\>), `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\<String\>), `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 laffichage.
- **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.