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
This commit is contained in:
dahoud
2026-03-15 02:12:17 +00:00
parent bbc409de9d
commit e8ad874015
635 changed files with 58160 additions and 20674 deletions

View File

@@ -1,120 +0,0 @@
/// Configuration globale de l'injection de dépendances
library app_di;
import 'package:dio/dio.dart';
import 'package:get_it/get_it.dart';
import '../network/dio_client.dart';
import '../network/network_info.dart';
import '../../features/organizations/di/organizations_di.dart';
import '../../features/members/di/membres_di.dart';
import '../../features/events/di/evenements_di.dart';
import '../../features/contributions/di/contributions_di.dart';
import '../../features/adhesions/di/adhesions_di.dart';
import '../../features/solidarity/di/solidarity_di.dart';
import '../../features/admin/di/admin_di.dart';
import '../../features/dashboard/di/dashboard_di.dart';
import '../../features/profile/di/profile_di.dart';
import '../../features/notifications/di/notifications_di.dart';
import '../../features/reports/di/reports_di.dart';
/// Gestionnaire global des dépendances
class AppDI {
static final GetIt _getIt = GetIt.instance;
/// Initialise toutes les dépendances de l'application
static Future<void> initialize() async {
// Configuration du client HTTP
await _setupNetworking();
// Configuration des modules
await _setupModules();
}
/// Configure les services réseau
static Future<void> _setupNetworking() async {
// Client Dio
final dioClient = DioClient();
_getIt.registerSingleton<DioClient>(dioClient);
_getIt.registerSingleton<Dio>(dioClient.dio);
// Network Info (pour l'instant, on simule toujours connecté)
_getIt.registerLazySingleton<NetworkInfo>(
() => _MockNetworkInfo(),
);
}
/// Configure tous les modules de l'application
static Future<void> _setupModules() async {
// Module Organizations
OrganizationsDI.registerDependencies();
// Module Membres
MembresDI.register();
// Module Événements
EvenementsDI.register();
// Module Contributions
registerCotisationsDependencies(_getIt);
// Module Adhésions
registerAdhesionsDependencies(_getIt);
// Module Solidarité (demandes d'aide)
registerSolidarityDependencies(_getIt);
// Module Admin (gestion utilisateurs SUPER_ADMIN)
registerAdminDependencies(_getIt);
// Module Dashboard
DashboardDI.registerDependencies();
// Module Profil utilisateur
ProfileDI.register();
// Module Notifications
NotificationsDI.register();
// Module Rapports & Analytics
ReportsDI.register();
}
/// Nettoie toutes les dépendances
static Future<void> dispose() async {
// Nettoyer les modules
OrganizationsDI.unregisterDependencies();
MembresDI.unregister();
EvenementsDI.unregister();
// Nettoyer les services globaux
if (_getIt.isRegistered<Dio>()) {
_getIt.unregister<Dio>();
}
if (_getIt.isRegistered<DioClient>()) {
_getIt.unregister<DioClient>();
}
// Reset complet
await _getIt.reset();
}
/// Obtient l'instance GetIt
static GetIt get instance => _getIt;
/// Obtient le client Dio
static Dio get dio => _getIt<Dio>();
/// Obtient le client Dio wrapper
static DioClient get dioClient => _getIt<DioClient>();
/// Nettoie toutes les dépendances
static Future<void> cleanup() async {
await _getIt.reset();
}
}
/// Mock de NetworkInfo pour les tests et développement
class _MockNetworkInfo implements NetworkInfo {
@override
Future<bool> get isConnected async => true;
}

View File

@@ -0,0 +1,13 @@
import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'injection.config.dart';
final GetIt getIt = GetIt.instance;
@InjectableInit(
initializerName: 'init', // default
preferRelativeImports: true, // default
asExtension: true, // default
)
void configureDependencies() => getIt.init();

View File

@@ -1,15 +1,19 @@
import 'package:get_it/get_it.dart';
import 'app_di.dart';
/// Service locator global - alias pour faciliter l'utilisation
final GetIt sl = AppDI.instance;
/// Export getIt for convenience
export 'injection.dart' show getIt;
import 'injection.dart';
/// Service locator global
final GetIt sl = getIt;
/// Initialise toutes les dépendances de l'application
Future<void> initializeDependencies() async {
await AppDI.initialize();
configureDependencies();
}
/// Nettoie toutes les dépendances
/// Nettoie toutes les dépendances (optionnel, pour les tests)
Future<void> cleanupDependencies() async {
await AppDI.cleanup();
await sl.reset();
}

View File

@@ -0,0 +1,22 @@
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http/http.dart' as http;
import 'package:injectable/injectable.dart';
import 'package:shared_preferences/shared_preferences.dart';
@module
abstract class RegisterModule {
@lazySingleton
Connectivity get connectivity => Connectivity();
@lazySingleton
FlutterSecureStorage get storage => const FlutterSecureStorage(
aOptions: AndroidOptions(encryptedSharedPreferences: true),
);
@lazySingleton
http.Client get httpClient => http.Client();
@preResolve
Future<SharedPreferences> get sharedPreferences => SharedPreferences.getInstance();
}