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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user