279 lines
7.3 KiB
Dart
279 lines
7.3 KiB
Dart
import 'package:dio/dio.dart';
|
|
|
|
import '../../../../core/models/membre_search_criteria.dart';
|
|
import '../../../../core/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
|
|
class MembreSearchService {
|
|
final Dio _dio;
|
|
|
|
MembreSearchService(this._dio);
|
|
|
|
/// Effectue une recherche avancée de membres
|
|
///
|
|
/// [criteria] Critères de recherche
|
|
/// [page] Numéro de page (0-based)
|
|
/// [size] Taille de la page
|
|
/// [sortField] Champ de tri
|
|
/// [sortDirection] Direction du tri (asc/desc)
|
|
///
|
|
/// Returns [MembreSearchResult] avec les résultats paginés
|
|
Future<MembreSearchResult> searchMembresAdvanced({
|
|
required MembreSearchCriteria criteria,
|
|
int page = 0,
|
|
int size = 20,
|
|
String sortField = 'nom',
|
|
String sortDirection = 'asc',
|
|
}) async {
|
|
print('Recherche avancée de membres: ${criteria.description}');
|
|
|
|
try {
|
|
// Validation des critères
|
|
if (!criteria.hasAnyCriteria) {
|
|
throw Exception('Au moins un critère de recherche doit être spécifié');
|
|
}
|
|
|
|
if (!criteria.isValid) {
|
|
throw Exception('Critères de recherche invalides');
|
|
}
|
|
|
|
// Préparation des paramètres de requête
|
|
final queryParams = {
|
|
'page': page.toString(),
|
|
'size': size.toString(),
|
|
'sort': sortField,
|
|
'direction': sortDirection,
|
|
};
|
|
|
|
// Appel API
|
|
final response = await _dio.post(
|
|
'/api/membres/search/advanced',
|
|
data: criteria.toJson(),
|
|
queryParameters: queryParams,
|
|
);
|
|
|
|
// Parsing de la réponse
|
|
final result = MembreSearchResult.fromJson(response.data);
|
|
|
|
print('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');
|
|
rethrow;
|
|
} catch (e) {
|
|
print('Erreur inattendue lors de la recherche: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Recherche rapide par terme général
|
|
///
|
|
/// [query] Terme de recherche
|
|
/// [page] Numéro de page
|
|
/// [size] Taille de la page
|
|
///
|
|
/// Returns [MembreSearchResult] avec les résultats
|
|
Future<MembreSearchResult> quickSearch({
|
|
required String query,
|
|
int page = 0,
|
|
int size = 20,
|
|
}) async {
|
|
final criteria = MembreSearchCriteria.quickSearch(query);
|
|
return searchMembresAdvanced(
|
|
criteria: criteria,
|
|
page: page,
|
|
size: size,
|
|
);
|
|
}
|
|
|
|
/// Recherche des membres actifs uniquement
|
|
///
|
|
/// [page] Numéro de page
|
|
/// [size] Taille de la page
|
|
///
|
|
/// Returns [MembreSearchResult] avec les membres actifs
|
|
Future<MembreSearchResult> searchActiveMembers({
|
|
int page = 0,
|
|
int size = 20,
|
|
}) async {
|
|
return searchMembresAdvanced(
|
|
criteria: MembreSearchCriteria.activeMembers,
|
|
page: page,
|
|
size: size,
|
|
);
|
|
}
|
|
|
|
/// Recherche des membres du bureau
|
|
///
|
|
/// [page] Numéro de page
|
|
/// [size] Taille de la page
|
|
///
|
|
/// Returns [MembreSearchResult] avec les membres du bureau
|
|
Future<MembreSearchResult> searchBureauMembers({
|
|
int page = 0,
|
|
int size = 20,
|
|
}) async {
|
|
return searchMembresAdvanced(
|
|
criteria: MembreSearchCriteria.bureauMembers,
|
|
page: page,
|
|
size: size,
|
|
);
|
|
}
|
|
|
|
/// Recherche par organisation
|
|
///
|
|
/// [organisationIds] Liste des IDs d'organisations
|
|
/// [page] Numéro de page
|
|
/// [size] Taille de la page
|
|
///
|
|
/// Returns [MembreSearchResult] avec les membres des organisations
|
|
Future<MembreSearchResult> searchByOrganisations({
|
|
required List<String> organisationIds,
|
|
int page = 0,
|
|
int size = 20,
|
|
}) async {
|
|
final criteria = MembreSearchCriteria(
|
|
organisationIds: organisationIds,
|
|
statut: 'ACTIF',
|
|
);
|
|
return searchMembresAdvanced(
|
|
criteria: criteria,
|
|
page: page,
|
|
size: size,
|
|
);
|
|
}
|
|
|
|
/// Recherche par tranche d'âge
|
|
///
|
|
/// [ageMin] Âge minimum
|
|
/// [ageMax] Âge maximum
|
|
/// [page] Numéro de page
|
|
/// [size] Taille de la page
|
|
///
|
|
/// Returns [MembreSearchResult] avec les membres dans la tranche d'âge
|
|
Future<MembreSearchResult> searchByAgeRange({
|
|
int? ageMin,
|
|
int? ageMax,
|
|
int page = 0,
|
|
int size = 20,
|
|
}) async {
|
|
final criteria = MembreSearchCriteria(
|
|
ageMin: ageMin,
|
|
ageMax: ageMax,
|
|
statut: 'ACTIF',
|
|
);
|
|
return searchMembresAdvanced(
|
|
criteria: criteria,
|
|
page: page,
|
|
size: size,
|
|
);
|
|
}
|
|
|
|
/// Recherche par région
|
|
///
|
|
/// [region] Nom de la région
|
|
/// [page] Numéro de page
|
|
/// [size] Taille de la page
|
|
///
|
|
/// Returns [MembreSearchResult] avec les membres de la région
|
|
Future<MembreSearchResult> searchByRegion({
|
|
required String region,
|
|
int page = 0,
|
|
int size = 20,
|
|
}) async {
|
|
final criteria = MembreSearchCriteria(
|
|
region: region,
|
|
statut: 'ACTIF',
|
|
);
|
|
return searchMembresAdvanced(
|
|
criteria: criteria,
|
|
page: page,
|
|
size: size,
|
|
);
|
|
}
|
|
|
|
/// Recherche par rôles
|
|
///
|
|
/// [roles] Liste des rôles
|
|
/// [page] Numéro de page
|
|
/// [size] Taille de la page
|
|
///
|
|
/// Returns [MembreSearchResult] avec les membres ayant ces rôles
|
|
Future<MembreSearchResult> searchByRoles({
|
|
required List<String> roles,
|
|
int page = 0,
|
|
int size = 20,
|
|
}) async {
|
|
final criteria = MembreSearchCriteria(
|
|
roles: roles,
|
|
statut: 'ACTIF',
|
|
);
|
|
return searchMembresAdvanced(
|
|
criteria: criteria,
|
|
page: page,
|
|
size: size,
|
|
);
|
|
}
|
|
|
|
/// Recherche par période d'adhésion
|
|
///
|
|
/// [dateMin] Date minimum (ISO 8601)
|
|
/// [dateMax] Date maximum (ISO 8601)
|
|
/// [page] Numéro de page
|
|
/// [size] Taille de la page
|
|
///
|
|
/// Returns [MembreSearchResult] avec les membres adhérés dans la période
|
|
Future<MembreSearchResult> searchByAdhesionPeriod({
|
|
String? dateMin,
|
|
String? dateMax,
|
|
int page = 0,
|
|
int size = 20,
|
|
}) async {
|
|
final criteria = MembreSearchCriteria(
|
|
dateAdhesionMin: dateMin,
|
|
dateAdhesionMax: dateMax,
|
|
statut: 'ACTIF',
|
|
);
|
|
return searchMembresAdvanced(
|
|
criteria: criteria,
|
|
page: page,
|
|
size: size,
|
|
);
|
|
}
|
|
|
|
/// Valide les critères de recherche avant envoi
|
|
bool validateCriteria(MembreSearchCriteria criteria) {
|
|
if (!criteria.hasAnyCriteria) {
|
|
print('Aucun critère de recherche spécifié');
|
|
return false;
|
|
}
|
|
|
|
if (!criteria.isValid) {
|
|
print('Critères de recherche invalides: ${criteria.description}');
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// Estime le temps de recherche basé sur les critères
|
|
Duration estimateSearchTime(MembreSearchCriteria criteria) {
|
|
// Estimation basique - peut être améliorée avec des métriques réelles
|
|
int complexityScore = 0;
|
|
|
|
if (criteria.query?.isNotEmpty == true) complexityScore += 2;
|
|
if (criteria.organisationIds?.isNotEmpty == true) complexityScore += 1;
|
|
if (criteria.roles?.isNotEmpty == true) complexityScore += 1;
|
|
if (criteria.ageMin != null || criteria.ageMax != null) complexityScore += 1;
|
|
if (criteria.dateAdhesionMin != null || criteria.dateAdhesionMax != null) complexityScore += 1;
|
|
|
|
// Temps de base + complexité
|
|
final baseTime = 100; // 100ms de base
|
|
final additionalTime = complexityScore * 50; // 50ms par critère
|
|
|
|
return Duration(milliseconds: baseTime + additionalTime);
|
|
}
|
|
}
|