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,14 +1,18 @@
import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';
import 'package:unionflow_mobile_apps/core/network/api_client.dart';
import 'package:unionflow_mobile_apps/core/utils/logger.dart';
import '../../../../shared/models/membre_search_criteria.dart';
import '../../../../shared/models/membre_search_result.dart';
/// Service pour la recherche avancée de membres
/// Gère les appels API vers l'endpoint de recherche sophistiquée
@lazySingleton
class MembreSearchService {
final Dio _dio;
final ApiClient _apiClient;
MembreSearchService(this._dio);
MembreSearchService(this._apiClient);
/// Effectue une recherche avancée de membres
///
@@ -26,7 +30,7 @@ class MembreSearchService {
String sortField = 'nom',
String sortDirection = 'asc',
}) async {
print('Recherche avancée de membres: ${criteria.description}');
AppLogger.info('Recherche avancée de membres: ${criteria.description}');
try {
// Validation des critères
@@ -47,7 +51,7 @@ class MembreSearchService {
};
// Appel API
final response = await _dio.post(
final response = await _apiClient.post(
'/api/membres/search/advanced',
data: criteria.toJson(),
queryParameters: queryParams,
@@ -56,14 +60,14 @@ class MembreSearchService {
// Parsing de la réponse
final result = MembreSearchResult.fromJson(response.data);
print('Recherche terminée: ${result.totalElements} résultats en ${result.executionTimeMs}ms');
AppLogger.info('Recherche terminée: ${result.totalElements} résultats en ${result.executionTimeMs}ms');
return result;
} on DioException catch (e) {
print('Erreur lors de la recherche avancée: $e');
} on DioException catch (e, st) {
AppLogger.error('MembreSearchService: recherche avancée échouée', error: e, stackTrace: st);
rethrow;
} catch (e) {
print('Erreur inattendue lors de la recherche: $e');
} catch (e, st) {
AppLogger.error('MembreSearchService: erreur inattendue recherche', error: e, stackTrace: st);
rethrow;
}
}
@@ -246,12 +250,12 @@ class MembreSearchService {
/// Valide les critères de recherche avant envoi
bool validateCriteria(MembreSearchCriteria criteria) {
if (!criteria.hasAnyCriteria) {
print('Aucun critère de recherche spécifié');
AppLogger.warning('MembreSearchService: aucun critère de recherche spécifié');
return false;
}
if (!criteria.isValid) {
print('Critères de recherche invalides: ${criteria.description}');
AppLogger.warning('MembreSearchService: critères invalides', tag: criteria.description);
return false;
}