- NotImplementedFailure: ajout userFriendlyMessage et icon construction (blue) - ErrorDisplayWidget: support spécial pour NotImplementedFailure (bientôt disponible) - SnackbarHelper: classe centralisée pour messages cohérents (success, error, warning, info, notImplemented) - budgets_list_page: remplace generic snackbar par SnackbarHelper.showNotImplemented - conversations_page: remplace 2 TODOs par SnackbarHelper.showNotImplemented - export_members: met à jour TODO obsolète (endpoint PDF maintenant disponible) - cache_service: fix AppLogger.error calls (error: named param) - cached_datasource_decorator: fix AppLogger.error call Task #64 - Fix Snackbar Placeholders + NotImplementedFailure UX
Finance Workflow Feature
Vue d'ensemble
Module complet de workflow financier avec approbations multi-niveaux et gestion budgétaire pour UnionFlow.
Architecture Clean Architecture + BLoC
finance_workflow/
├── domain/ # Couche métier (entités, repositories interfaces, use cases)
│ ├── entities/
│ │ ├── transaction_approval.dart # Entité approbation avec statuts
│ │ ├── budget.dart # Entité budget avec lignes
│ │ └── financial_audit_log.dart # Entité audit trail
│ ├── repositories/
│ │ └── finance_workflow_repository.dart # Interface repository
│ └── usecases/
│ ├── get_pending_approvals.dart
│ ├── get_approval_by_id.dart
│ ├── approve_transaction.dart
│ ├── reject_transaction.dart
│ ├── get_budgets.dart
│ ├── get_budget_by_id.dart
│ ├── create_budget.dart
│ └── get_budget_tracking.dart
│
├── data/ # Couche données (models, datasources, repository impl)
│ ├── models/
│ │ ├── transaction_approval_model.dart
│ │ ├── transaction_approval_model.g.dart
│ │ ├── budget_model.dart
│ │ └── budget_model.g.dart
│ ├── datasources/
│ │ └── finance_workflow_remote_datasource.dart
│ └── repositories/
│ └── finance_workflow_repository_impl.dart
│
└── presentation/ # Couche présentation (BLoC, pages, widgets)
├── bloc/
│ ├── approval_bloc.dart
│ ├── approval_event.dart
│ ├── approval_state.dart
│ ├── budget_bloc.dart
│ ├── budget_event.dart
│ └── budget_state.dart
├── pages/
│ ├── pending_approvals_page.dart
│ └── budgets_list_page.dart
└── widgets/
├── approve_dialog.dart
└── reject_dialog.dart
Fonctionnalités
1. Approbations de Transactions
Statuts d'approbation
pending: En attente d'approbationapproved: Approuvée (niveau 1)validated: Validée (niveau 2 - validation finale)rejected: Rejetéeexpired: Expirée (timeout)cancelled: Annulée
Niveaux d'approbation (selon montant)
none: Aucune approbation requise (< seuil)level1: Un approbateur requislevel2: Deux approbateurs requislevel3: Trois approbateurs requis (montants très élevés)
Types de transactions
contribution: Cotisation/contributiondeposit: Dépôt épargnewithdrawal: Retrait épargnetransfer: Transfertsolidarity: Dépense solidaritéevent: Dépense événementother: Autre dépense
Cas d'usage implémentés
- Consulter les approbations en attente : Liste filtrée par organisation
- Voir détail d'une approbation : Informations complètes avec historique
- Approuver une transaction : Avec commentaire optionnel
- Rejeter une transaction : Avec raison obligatoire (min 10 caractères)
- Rafraîchir la liste : Pull-to-refresh
UI/UX
- Liste des approbations avec filtres
- Card d'approbation affichant :
- Type de transaction avec badge coloré selon niveau
- Montant en devise locale (XOF par défaut)
- Demandeur et date de création
- Progression des approbations (X/Y)
- Boutons Approuver/Rejeter
- Dialog d'approbation avec récapitulatif et champ commentaire
- Dialog de rejet avec validation de raison (min 10 chars)
- États : Loading, Empty, Error avec retry
- Notifications Snackbar pour succès/erreur
2. Gestion des Budgets
Périodes budgétaires
monthly: Budget mensuelquarterly: Budget trimestrielsemiannual: Budget semestrielannual: Budget annuel
Statuts de budget
draft: Brouillon (en cours de création)active: Actifclosed: Clos (période terminée)cancelled: Annulé
Catégories budgétaires
contributions: Cotisations/contributionssavings: Épargnesolidarity: Solidaritéevents: Événementsoperational: Fonctionnement (frais généraux)investments: Investissementsother: Autres
Cas d'usage implémentés
- Consulter les budgets : Liste avec filtres (statut, année)
- Voir détail d'un budget : Informations complètes avec lignes
- Créer un budget : Avec validation (nom, période, lignes)
- Suivre l'exécution budgétaire : Taux de réalisation, écart
- Filtrer les budgets : Par statut et année
UI/UX
- Liste des budgets avec filtres avancés
- Card de budget affichant :
- Nom et période (Mensuel/Annuel YYYY)
- Statut avec badge coloré
- Montant prévu vs réalisé
- Barre de progression avec taux de réalisation
- Indicateur de dépassement (rouge si > 100%)
- Dialog de filtres avec chips (statut + année)
- Chips de filtres actifs supprimables
- FAB pour créer un nouveau budget
- États : Loading, Empty, Error avec retry
3. Audit Trail
Types d'opérations auditées
create,read,update,deleteapprove,reject,validate,cancelexport
Types d'entités auditées
contribution,savingsTransaction,approval,budget
Niveaux de sévérité
info: Informationwarning: Avertissementerror: Erreurcritical: Critique
Données capturées
- Utilisateur, rôle, IP, user agent
- Date/heure de l'opération
- Entité et ID de l'entité
- Données avant/après (JSON)
- Montants impliqués
API Endpoints
Approbations
GET /api/finance/approvals/pending?organizationId={id}: Liste des approbations en attenteGET /api/finance/approvals/{approvalId}: Détail d'une approbationPOST /api/finance/approvals/{approvalId}/approve: Approuver (body: {comment?})POST /api/finance/approvals/{approvalId}/reject: Rejeter (body: {reason})
Budgets
GET /api/finance/budgets?organizationId={id}&status={status}&year={year}: Liste des budgetsGET /api/finance/budgets/{budgetId}: Détail d'un budgetPOST /api/finance/budgets: Créer un budgetGET /api/finance/budgets/{budgetId}/tracking: Suivi budgétaire
Permissions RBAC
OrgAdmin + SuperAdmin
- ✅ Consulter toutes les approbations de l'organisation
- ✅ Approuver/Rejeter les transactions
- ✅ Consulter tous les budgets de l'organisation
- ✅ Créer/Modifier les budgets
- ✅ Accéder aux logs d'audit
Autres rôles
- ❌ Pas d'accès au workflow financier (gap P0 identifié dans audit métier)
État d'implémentation
✅ Terminé (Mobile)
- Entities (TransactionApproval, Budget, FinancialAuditLog)
- Repository interface
- Data models avec JSON serialization (custom @JsonKey pour nested types)
- Remote datasource (8 endpoints API)
- Repository implementation avec gestion d'erreurs
- 8 Use cases avec validation
- 2 BLoCs complets (Approval, Budget) avec états/événements
- 2 Pages fonctionnelles (Pending Approvals, Budgets List)
- 2 Dialogs (Approve, Reject) avec validation
- Integration navigation (routes + menu RBAC)
- Build runner successful (génération .g.dart)
⏳ En cours
- Budget detail page (voir détail + tracking)
- Create budget page (formulaire création avec lignes)
- Audit logs page (consultation logs d'audit)
📋 À faire (Backend Quarkus)
- POST /api/finance/approvals/pending (endpoint backend)
- POST /api/finance/approvals/{id}/approve (endpoint backend)
- POST /api/finance/approvals/{id}/reject (endpoint backend)
- GET /api/finance/budgets (endpoint backend)
- POST /api/finance/budgets (endpoint backend)
- GET /api/finance/budgets/{id}/tracking (endpoint backend)
- Audit log persistence et endpoints
- Tests unitaires (use cases, BLoCs)
- Tests d'intégration (API)
Patterns techniques
JSON Serialization pour types nested
Fix appliqué pour les listes de types custom (ApproverAction, BudgetLine) :
@JsonSerializable(explicitToJson: true)
class TransactionApprovalModel extends TransactionApproval {
@JsonKey(
fromJson: _approversFromJson,
toJson: _approversToJson,
)
@override
final List<ApproverAction> approvers;
const TransactionApprovalModel({
// ... autres params
this.approvers = const [],
// ... autres params
}) : super(approvers: approvers);
static List<ApproverAction> _approversFromJson(List<dynamic>? json) =>
json?.map((e) => ApproverActionModel.fromJson(e as Map<String, dynamic>)).toList() ?? [];
static List<Map<String, dynamic>> _approversToJson(List<ApproverAction>? approvers) =>
approvers?.map((a) => ApproverActionModel(
approverId: a.approverId,
approverName: a.approverName,
approverRole: a.approverRole,
decision: a.decision,
comment: a.comment,
decidedAt: a.decidedAt,
).toJson()).toList() ?? [];
}
Gestion d'erreurs avec Either
final result = await approveTransaction(approvalId: id);
result.fold(
(failure) => emit(ApprovalError(failure.message)),
(approval) => emit(TransactionApproved(approval: approval)),
);
BLoC Pattern
@injectable
class ApprovalBloc extends Bloc<ApprovalEvent, ApprovalState> {
final GetPendingApprovals getPendingApprovals;
final ApproveTransaction approveTransaction;
final RejectTransaction rejectTransaction;
ApprovalBloc({
required this.getPendingApprovals,
required this.approveTransaction,
required this.rejectTransaction,
}) : super(const ApprovalInitial()) {
on<LoadPendingApprovals>(_onLoadPendingApprovals);
on<ApproveTransactionEvent>(_onApproveTransaction);
on<RejectTransactionEvent>(_onRejectTransaction);
}
}
Dépendances
Déjà présentes dans pubspec.yaml :
flutter_bloc: ^8.1.6injectable: ^2.4.4get_it: ^8.0.2dartz: ^0.10.1equatable: ^2.0.7json_annotation: ^4.9.0http: ^1.2.2flutter_secure_storage: ^9.2.2intl: ^0.19.0
Notes techniques
- Custom JSON serialization requise pour
List<ApproverAction>etList<BudgetLine>(types nested) - Network check avant chaque appel API (NetworkInfo)
- Error mapping : Exceptions → Failures (ValidationFailure, NetworkFailure, ServerFailure, etc.)
- RBAC check dans navigation (OrgAdmin/SuperAdmin uniquement)
- Pull-to-refresh sur toutes les listes
- Snackbar notifications pour succès/erreur
- Form validation sur reject dialog (raison min 10 chars)
Prochaines étapes
- Créer Budget Detail Page avec suivi détaillé par ligne
- Créer Create Budget Page avec formulaire multi-steps
- Créer Audit Logs Page avec filtres avancés
- Implémenter endpoints backend Quarkus
- Ajouter tests unitaires pour use cases et BLoCs
- Ajouter tests d'intégration API
- Optimiser avec caching (budget actif, approvals count)
- Ajouter notifications push pour approbations urgentes