Refactoring
This commit is contained in:
@@ -0,0 +1,435 @@
|
||||
import 'dart:convert';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../../../../core/error/exceptions.dart';
|
||||
import '../models/demande_aide_model.dart';
|
||||
import '../models/proposition_aide_model.dart';
|
||||
import '../models/evaluation_aide_model.dart';
|
||||
|
||||
/// Source de données locale pour le module solidarité
|
||||
///
|
||||
/// Cette classe gère le cache local des données de solidarité
|
||||
/// pour permettre un fonctionnement hors ligne et améliorer les performances.
|
||||
abstract class SolidariteLocalDataSource {
|
||||
// Cache des demandes d'aide
|
||||
Future<void> cacherDemandeAide(DemandeAideModel demande);
|
||||
Future<DemandeAideModel?> obtenirDemandeAideCachee(String id);
|
||||
Future<List<DemandeAideModel>> obtenirDemandesAideCachees();
|
||||
Future<void> supprimerDemandeAideCachee(String id);
|
||||
Future<void> viderCacheDemandesAide();
|
||||
|
||||
// Cache des propositions d'aide
|
||||
Future<void> cacherPropositionAide(PropositionAideModel proposition);
|
||||
Future<PropositionAideModel?> obtenirPropositionAideCachee(String id);
|
||||
Future<List<PropositionAideModel>> obtenirPropositionsAideCachees();
|
||||
Future<void> supprimerPropositionAideCachee(String id);
|
||||
Future<void> viderCachePropositionsAide();
|
||||
|
||||
// Cache des évaluations
|
||||
Future<void> cacherEvaluation(EvaluationAideModel evaluation);
|
||||
Future<EvaluationAideModel?> obtenirEvaluationCachee(String id);
|
||||
Future<List<EvaluationAideModel>> obtenirEvaluationsCachees();
|
||||
Future<void> supprimerEvaluationCachee(String id);
|
||||
Future<void> viderCacheEvaluations();
|
||||
|
||||
// Cache des statistiques
|
||||
Future<void> cacherStatistiques(String organisationId, Map<String, dynamic> statistiques);
|
||||
Future<Map<String, dynamic>?> obtenirStatistiquesCachees(String organisationId);
|
||||
Future<void> supprimerStatistiquesCachees(String organisationId);
|
||||
|
||||
// Gestion du cache
|
||||
Future<DateTime?> obtenirDateDerniereMiseAJour(String cacheKey);
|
||||
Future<void> marquerMiseAJour(String cacheKey);
|
||||
Future<bool> estCacheExpire(String cacheKey, Duration dureeValidite);
|
||||
Future<void> viderToutCache();
|
||||
}
|
||||
|
||||
/// Implémentation de la source de données locale
|
||||
class SolidariteLocalDataSourceImpl implements SolidariteLocalDataSource {
|
||||
final SharedPreferences sharedPreferences;
|
||||
|
||||
// Clés de cache
|
||||
static const String _demandesAideKey = 'CACHED_DEMANDES_AIDE';
|
||||
static const String _propositionsAideKey = 'CACHED_PROPOSITIONS_AIDE';
|
||||
static const String _evaluationsKey = 'CACHED_EVALUATIONS';
|
||||
static const String _statistiquesKey = 'CACHED_STATISTIQUES';
|
||||
static const String _lastUpdatePrefix = 'LAST_UPDATE_';
|
||||
|
||||
// Durées de validité du cache
|
||||
static const Duration _dureeValiditeDefaut = Duration(minutes: 15);
|
||||
static const Duration _dureeValiditeStatistiques = Duration(hours: 1);
|
||||
|
||||
SolidariteLocalDataSourceImpl({required this.sharedPreferences});
|
||||
|
||||
// Cache des demandes d'aide
|
||||
@override
|
||||
Future<void> cacherDemandeAide(DemandeAideModel demande) async {
|
||||
try {
|
||||
final demandes = await obtenirDemandesAideCachees();
|
||||
|
||||
// Supprimer l'ancienne version si elle existe
|
||||
demandes.removeWhere((d) => d.id == demande.id);
|
||||
|
||||
// Ajouter la nouvelle version
|
||||
demandes.add(demande);
|
||||
|
||||
// Limiter le cache à 100 demandes maximum
|
||||
if (demandes.length > 100) {
|
||||
demandes.sort((a, b) => b.dateModification.compareTo(a.dateModification));
|
||||
demandes.removeRange(100, demandes.length);
|
||||
}
|
||||
|
||||
final jsonList = demandes.map((d) => d.toJson()).toList();
|
||||
await sharedPreferences.setString(_demandesAideKey, jsonEncode(jsonList));
|
||||
await marquerMiseAJour(_demandesAideKey);
|
||||
} catch (e) {
|
||||
throw CacheException(message: 'Erreur lors de la mise en cache de la demande: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DemandeAideModel?> obtenirDemandeAideCachee(String id) async {
|
||||
try {
|
||||
final demandes = await obtenirDemandesAideCachees();
|
||||
return demandes.cast<DemandeAideModel?>().firstWhere(
|
||||
(d) => d?.id == id,
|
||||
orElse: () => null,
|
||||
);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<DemandeAideModel>> obtenirDemandesAideCachees() async {
|
||||
try {
|
||||
final jsonString = sharedPreferences.getString(_demandesAideKey);
|
||||
if (jsonString == null) return [];
|
||||
|
||||
final List<dynamic> jsonList = jsonDecode(jsonString);
|
||||
return jsonList.map((json) => DemandeAideModel.fromJson(json)).toList();
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> supprimerDemandeAideCachee(String id) async {
|
||||
try {
|
||||
final demandes = await obtenirDemandesAideCachees();
|
||||
demandes.removeWhere((d) => d.id == id);
|
||||
|
||||
final jsonList = demandes.map((d) => d.toJson()).toList();
|
||||
await sharedPreferences.setString(_demandesAideKey, jsonEncode(jsonList));
|
||||
} catch (e) {
|
||||
throw CacheException(message: 'Erreur lors de la suppression de la demande du cache: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> viderCacheDemandesAide() async {
|
||||
try {
|
||||
await sharedPreferences.remove(_demandesAideKey);
|
||||
await sharedPreferences.remove('$_lastUpdatePrefix$_demandesAideKey');
|
||||
} catch (e) {
|
||||
throw CacheException(message: 'Erreur lors de la suppression du cache des demandes: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
// Cache des propositions d'aide
|
||||
@override
|
||||
Future<void> cacherPropositionAide(PropositionAideModel proposition) async {
|
||||
try {
|
||||
final propositions = await obtenirPropositionsAideCachees();
|
||||
|
||||
// Supprimer l'ancienne version si elle existe
|
||||
propositions.removeWhere((p) => p.id == proposition.id);
|
||||
|
||||
// Ajouter la nouvelle version
|
||||
propositions.add(proposition);
|
||||
|
||||
// Limiter le cache à 100 propositions maximum
|
||||
if (propositions.length > 100) {
|
||||
propositions.sort((a, b) => b.dateModification.compareTo(a.dateModification));
|
||||
propositions.removeRange(100, propositions.length);
|
||||
}
|
||||
|
||||
final jsonList = propositions.map((p) => p.toJson()).toList();
|
||||
await sharedPreferences.setString(_propositionsAideKey, jsonEncode(jsonList));
|
||||
await marquerMiseAJour(_propositionsAideKey);
|
||||
} catch (e) {
|
||||
throw CacheException(message: 'Erreur lors de la mise en cache de la proposition: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PropositionAideModel?> obtenirPropositionAideCachee(String id) async {
|
||||
try {
|
||||
final propositions = await obtenirPropositionsAideCachees();
|
||||
return propositions.cast<PropositionAideModel?>().firstWhere(
|
||||
(p) => p?.id == id,
|
||||
orElse: () => null,
|
||||
);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<PropositionAideModel>> obtenirPropositionsAideCachees() async {
|
||||
try {
|
||||
final jsonString = sharedPreferences.getString(_propositionsAideKey);
|
||||
if (jsonString == null) return [];
|
||||
|
||||
final List<dynamic> jsonList = jsonDecode(jsonString);
|
||||
return jsonList.map((json) => PropositionAideModel.fromJson(json)).toList();
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> supprimerPropositionAideCachee(String id) async {
|
||||
try {
|
||||
final propositions = await obtenirPropositionsAideCachees();
|
||||
propositions.removeWhere((p) => p.id == id);
|
||||
|
||||
final jsonList = propositions.map((p) => p.toJson()).toList();
|
||||
await sharedPreferences.setString(_propositionsAideKey, jsonEncode(jsonList));
|
||||
} catch (e) {
|
||||
throw CacheException(message: 'Erreur lors de la suppression de la proposition du cache: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> viderCachePropositionsAide() async {
|
||||
try {
|
||||
await sharedPreferences.remove(_propositionsAideKey);
|
||||
await sharedPreferences.remove('$_lastUpdatePrefix$_propositionsAideKey');
|
||||
} catch (e) {
|
||||
throw CacheException(message: 'Erreur lors de la suppression du cache des propositions: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
// Cache des évaluations
|
||||
@override
|
||||
Future<void> cacherEvaluation(EvaluationAideModel evaluation) async {
|
||||
try {
|
||||
final evaluations = await obtenirEvaluationsCachees();
|
||||
|
||||
// Supprimer l'ancienne version si elle existe
|
||||
evaluations.removeWhere((e) => e.id == evaluation.id);
|
||||
|
||||
// Ajouter la nouvelle version
|
||||
evaluations.add(evaluation);
|
||||
|
||||
// Limiter le cache à 200 évaluations maximum
|
||||
if (evaluations.length > 200) {
|
||||
evaluations.sort((a, b) => b.dateModification.compareTo(a.dateModification));
|
||||
evaluations.removeRange(200, evaluations.length);
|
||||
}
|
||||
|
||||
final jsonList = evaluations.map((e) => e.toJson()).toList();
|
||||
await sharedPreferences.setString(_evaluationsKey, jsonEncode(jsonList));
|
||||
await marquerMiseAJour(_evaluationsKey);
|
||||
} catch (e) {
|
||||
throw CacheException(message: 'Erreur lors de la mise en cache de l\'évaluation: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EvaluationAideModel?> obtenirEvaluationCachee(String id) async {
|
||||
try {
|
||||
final evaluations = await obtenirEvaluationsCachees();
|
||||
return evaluations.cast<EvaluationAideModel?>().firstWhere(
|
||||
(e) => e?.id == id,
|
||||
orElse: () => null,
|
||||
);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<EvaluationAideModel>> obtenirEvaluationsCachees() async {
|
||||
try {
|
||||
final jsonString = sharedPreferences.getString(_evaluationsKey);
|
||||
if (jsonString == null) return [];
|
||||
|
||||
final List<dynamic> jsonList = jsonDecode(jsonString);
|
||||
return jsonList.map((json) => EvaluationAideModel.fromJson(json)).toList();
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> supprimerEvaluationCachee(String id) async {
|
||||
try {
|
||||
final evaluations = await obtenirEvaluationsCachees();
|
||||
evaluations.removeWhere((e) => e.id == id);
|
||||
|
||||
final jsonList = evaluations.map((e) => e.toJson()).toList();
|
||||
await sharedPreferences.setString(_evaluationsKey, jsonEncode(jsonList));
|
||||
} catch (e) {
|
||||
throw CacheException(message: 'Erreur lors de la suppression de l\'évaluation du cache: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> viderCacheEvaluations() async {
|
||||
try {
|
||||
await sharedPreferences.remove(_evaluationsKey);
|
||||
await sharedPreferences.remove('$_lastUpdatePrefix$_evaluationsKey');
|
||||
} catch (e) {
|
||||
throw CacheException(message: 'Erreur lors de la suppression du cache des évaluations: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
// Cache des statistiques
|
||||
@override
|
||||
Future<void> cacherStatistiques(String organisationId, Map<String, dynamic> statistiques) async {
|
||||
try {
|
||||
final key = '$_statistiquesKey$organisationId';
|
||||
await sharedPreferences.setString(key, jsonEncode(statistiques));
|
||||
await marquerMiseAJour(key);
|
||||
} catch (e) {
|
||||
throw CacheException(message: 'Erreur lors de la mise en cache des statistiques: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>?> obtenirStatistiquesCachees(String organisationId) async {
|
||||
try {
|
||||
final key = '$_statistiquesKey$organisationId';
|
||||
final jsonString = sharedPreferences.getString(key);
|
||||
if (jsonString == null) return null;
|
||||
|
||||
return Map<String, dynamic>.from(jsonDecode(jsonString));
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> supprimerStatistiquesCachees(String organisationId) async {
|
||||
try {
|
||||
final key = '$_statistiquesKey$organisationId';
|
||||
await sharedPreferences.remove(key);
|
||||
await sharedPreferences.remove('$_lastUpdatePrefix$key');
|
||||
} catch (e) {
|
||||
throw CacheException(message: 'Erreur lors de la suppression des statistiques du cache: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
// Gestion du cache
|
||||
@override
|
||||
Future<DateTime?> obtenirDateDerniereMiseAJour(String cacheKey) async {
|
||||
try {
|
||||
final timestamp = sharedPreferences.getInt('$_lastUpdatePrefix$cacheKey');
|
||||
if (timestamp == null) return null;
|
||||
|
||||
return DateTime.fromMillisecondsSinceEpoch(timestamp);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> marquerMiseAJour(String cacheKey) async {
|
||||
try {
|
||||
final timestamp = DateTime.now().millisecondsSinceEpoch;
|
||||
await sharedPreferences.setInt('$_lastUpdatePrefix$cacheKey', timestamp);
|
||||
} catch (e) {
|
||||
throw CacheException(message: 'Erreur lors de la mise à jour du timestamp: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> estCacheExpire(String cacheKey, Duration dureeValidite) async {
|
||||
try {
|
||||
final dateDerniereMiseAJour = await obtenirDateDerniereMiseAJour(cacheKey);
|
||||
if (dateDerniereMiseAJour == null) return true;
|
||||
|
||||
final maintenant = DateTime.now();
|
||||
final dureeEcoulee = maintenant.difference(dateDerniereMiseAJour);
|
||||
|
||||
return dureeEcoulee > dureeValidite;
|
||||
} catch (e) {
|
||||
return true; // En cas d'erreur, considérer le cache comme expiré
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> viderToutCache() async {
|
||||
try {
|
||||
await Future.wait([
|
||||
viderCacheDemandesAide(),
|
||||
viderCachePropositionsAide(),
|
||||
viderCacheEvaluations(),
|
||||
]);
|
||||
|
||||
// Supprimer toutes les statistiques cachées
|
||||
final keys = sharedPreferences.getKeys();
|
||||
final statistiquesKeys = keys.where((key) => key.startsWith(_statistiquesKey));
|
||||
|
||||
for (final key in statistiquesKeys) {
|
||||
await sharedPreferences.remove(key);
|
||||
await sharedPreferences.remove('$_lastUpdatePrefix$key');
|
||||
}
|
||||
} catch (e) {
|
||||
throw CacheException(message: 'Erreur lors de la suppression complète du cache: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
/// Méthodes utilitaires pour la gestion du cache
|
||||
|
||||
/// Vérifie si le cache des demandes est valide
|
||||
Future<bool> estCacheDemandesValide() async {
|
||||
return !(await estCacheExpire(_demandesAideKey, _dureeValiditeDefaut));
|
||||
}
|
||||
|
||||
/// Vérifie si le cache des propositions est valide
|
||||
Future<bool> estCachePropositionsValide() async {
|
||||
return !(await estCacheExpire(_propositionsAideKey, _dureeValiditeDefaut));
|
||||
}
|
||||
|
||||
/// Vérifie si le cache des évaluations est valide
|
||||
Future<bool> estCacheEvaluationsValide() async {
|
||||
return !(await estCacheExpire(_evaluationsKey, _dureeValiditeDefaut));
|
||||
}
|
||||
|
||||
/// Vérifie si le cache des statistiques est valide
|
||||
Future<bool> estCacheStatistiquesValide(String organisationId) async {
|
||||
final key = '$_statistiquesKey$organisationId';
|
||||
return !(await estCacheExpire(key, _dureeValiditeStatistiques));
|
||||
}
|
||||
|
||||
/// Obtient la taille approximative du cache en octets
|
||||
Future<int> obtenirTailleCache() async {
|
||||
try {
|
||||
int taille = 0;
|
||||
|
||||
final demandes = sharedPreferences.getString(_demandesAideKey);
|
||||
if (demandes != null) taille += demandes.length;
|
||||
|
||||
final propositions = sharedPreferences.getString(_propositionsAideKey);
|
||||
if (propositions != null) taille += propositions.length;
|
||||
|
||||
final evaluations = sharedPreferences.getString(_evaluationsKey);
|
||||
if (evaluations != null) taille += evaluations.length;
|
||||
|
||||
// Ajouter les statistiques
|
||||
final keys = sharedPreferences.getKeys();
|
||||
final statistiquesKeys = keys.where((key) => key.startsWith(_statistiquesKey));
|
||||
|
||||
for (final key in statistiquesKeys) {
|
||||
final value = sharedPreferences.getString(key);
|
||||
if (value != null) taille += value.length;
|
||||
}
|
||||
|
||||
return taille;
|
||||
} catch (e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,817 @@
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
import '../../../../core/error/exceptions.dart';
|
||||
import '../../../../core/network/api_client.dart';
|
||||
import '../models/demande_aide_model.dart';
|
||||
import '../models/proposition_aide_model.dart';
|
||||
import '../models/evaluation_aide_model.dart';
|
||||
|
||||
/// Source de données distante pour le module solidarité
|
||||
///
|
||||
/// Cette classe gère toutes les communications avec l'API REST
|
||||
/// du backend UnionFlow pour les fonctionnalités de solidarité.
|
||||
abstract class SolidariteRemoteDataSource {
|
||||
// Demandes d'aide
|
||||
Future<DemandeAideModel> creerDemandeAide(DemandeAideModel demande);
|
||||
Future<DemandeAideModel> mettreAJourDemandeAide(DemandeAideModel demande);
|
||||
Future<DemandeAideModel> obtenirDemandeAide(String id);
|
||||
Future<DemandeAideModel> soumettreDemande(String demandeId);
|
||||
Future<DemandeAideModel> evaluerDemande({
|
||||
required String demandeId,
|
||||
required String evaluateurId,
|
||||
required String decision,
|
||||
String? commentaire,
|
||||
double? montantApprouve,
|
||||
});
|
||||
Future<List<DemandeAideModel>> rechercherDemandes({
|
||||
String? organisationId,
|
||||
String? typeAide,
|
||||
String? statut,
|
||||
String? demandeurId,
|
||||
bool? urgente,
|
||||
int page = 0,
|
||||
int taille = 20,
|
||||
});
|
||||
Future<List<DemandeAideModel>> obtenirDemandesUrgentes(String organisationId);
|
||||
Future<List<DemandeAideModel>> obtenirMesdemandes(String utilisateurId);
|
||||
|
||||
// Propositions d'aide
|
||||
Future<PropositionAideModel> creerPropositionAide(PropositionAideModel proposition);
|
||||
Future<PropositionAideModel> mettreAJourPropositionAide(PropositionAideModel proposition);
|
||||
Future<PropositionAideModel> obtenirPropositionAide(String id);
|
||||
Future<PropositionAideModel> changerStatutProposition({
|
||||
required String propositionId,
|
||||
required bool activer,
|
||||
});
|
||||
Future<List<PropositionAideModel>> rechercherPropositions({
|
||||
String? organisationId,
|
||||
String? typeAide,
|
||||
String? proposantId,
|
||||
bool? actives,
|
||||
int page = 0,
|
||||
int taille = 20,
|
||||
});
|
||||
Future<List<PropositionAideModel>> obtenirPropositionsActives(String typeAide);
|
||||
Future<List<PropositionAideModel>> obtenirMeilleuresPropositions(int limite);
|
||||
Future<List<PropositionAideModel>> obtenirMesPropositions(String utilisateurId);
|
||||
|
||||
// Matching
|
||||
Future<List<PropositionAideModel>> trouverPropositionsCompatibles(String demandeId);
|
||||
Future<List<DemandeAideModel>> trouverDemandesCompatibles(String propositionId);
|
||||
Future<List<PropositionAideModel>> rechercherProposantsFinanciers(String demandeId);
|
||||
|
||||
// Évaluations
|
||||
Future<EvaluationAideModel> creerEvaluation(EvaluationAideModel evaluation);
|
||||
Future<EvaluationAideModel> mettreAJourEvaluation(EvaluationAideModel evaluation);
|
||||
Future<EvaluationAideModel> obtenirEvaluation(String id);
|
||||
Future<List<EvaluationAideModel>> obtenirEvaluationsDemande(String demandeId);
|
||||
Future<List<EvaluationAideModel>> obtenirEvaluationsProposition(String propositionId);
|
||||
Future<EvaluationAideModel> signalerEvaluation({
|
||||
required String evaluationId,
|
||||
required String motif,
|
||||
});
|
||||
Future<StatistiquesEvaluationModel> calculerMoyenneDemande(String demandeId);
|
||||
Future<StatistiquesEvaluationModel> calculerMoyenneProposition(String propositionId);
|
||||
|
||||
// Statistiques
|
||||
Future<Map<String, dynamic>> obtenirStatistiquesSolidarite(String organisationId);
|
||||
}
|
||||
|
||||
/// Implémentation de la source de données distante
|
||||
class SolidariteRemoteDataSourceImpl implements SolidariteRemoteDataSource {
|
||||
final ApiClient apiClient;
|
||||
static const String baseEndpoint = '/api/solidarite';
|
||||
|
||||
SolidariteRemoteDataSourceImpl({required this.apiClient});
|
||||
|
||||
// Demandes d'aide
|
||||
@override
|
||||
Future<DemandeAideModel> creerDemandeAide(DemandeAideModel demande) async {
|
||||
try {
|
||||
final response = await apiClient.post(
|
||||
'$baseEndpoint/demandes',
|
||||
data: demande.toJson(),
|
||||
);
|
||||
|
||||
if (response.statusCode == 201) {
|
||||
return DemandeAideModel.fromJson(response.data);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la création de la demande d\'aide',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DemandeAideModel> mettreAJourDemandeAide(DemandeAideModel demande) async {
|
||||
try {
|
||||
final response = await apiClient.put(
|
||||
'$baseEndpoint/demandes/${demande.id}',
|
||||
data: demande.toJson(),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return DemandeAideModel.fromJson(response.data);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la mise à jour de la demande d\'aide',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DemandeAideModel> obtenirDemandeAide(String id) async {
|
||||
try {
|
||||
final response = await apiClient.get('$baseEndpoint/demandes/$id');
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return DemandeAideModel.fromJson(response.data);
|
||||
} else if (response.statusCode == 404) {
|
||||
throw NotFoundException(message: 'Demande d\'aide non trouvée');
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la récupération de la demande d\'aide',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException || e is NotFoundException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DemandeAideModel> soumettreDemande(String demandeId) async {
|
||||
try {
|
||||
final response = await apiClient.post(
|
||||
'$baseEndpoint/demandes/$demandeId/soumettre',
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return DemandeAideModel.fromJson(response.data);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la soumission de la demande',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DemandeAideModel> evaluerDemande({
|
||||
required String demandeId,
|
||||
required String evaluateurId,
|
||||
required String decision,
|
||||
String? commentaire,
|
||||
double? montantApprouve,
|
||||
}) async {
|
||||
try {
|
||||
final data = {
|
||||
'evaluateurId': evaluateurId,
|
||||
'decision': decision,
|
||||
if (commentaire != null) 'commentaire': commentaire,
|
||||
if (montantApprouve != null) 'montantApprouve': montantApprouve,
|
||||
};
|
||||
|
||||
final response = await apiClient.post(
|
||||
'$baseEndpoint/demandes/$demandeId/evaluer',
|
||||
data: data,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return DemandeAideModel.fromJson(response.data);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de l\'évaluation de la demande',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<DemandeAideModel>> rechercherDemandes({
|
||||
String? organisationId,
|
||||
String? typeAide,
|
||||
String? statut,
|
||||
String? demandeurId,
|
||||
bool? urgente,
|
||||
int page = 0,
|
||||
int taille = 20,
|
||||
}) async {
|
||||
try {
|
||||
final queryParams = <String, dynamic>{
|
||||
'page': page,
|
||||
'size': taille,
|
||||
if (organisationId != null) 'organisationId': organisationId,
|
||||
if (typeAide != null) 'typeAide': typeAide,
|
||||
if (statut != null) 'statut': statut,
|
||||
if (demandeurId != null) 'demandeurId': demandeurId,
|
||||
if (urgente != null) 'urgente': urgente,
|
||||
};
|
||||
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/demandes/rechercher',
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> data = response.data['content'];
|
||||
return data.map((json) => DemandeAideModel.fromJson(json)).toList();
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la recherche des demandes',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<DemandeAideModel>> obtenirDemandesUrgentes(String organisationId) async {
|
||||
try {
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/demandes/urgentes',
|
||||
queryParameters: {'organisationId': organisationId},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> data = response.data;
|
||||
return data.map((json) => DemandeAideModel.fromJson(json)).toList();
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la récupération des demandes urgentes',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<DemandeAideModel>> obtenirMesdemandes(String utilisateurId) async {
|
||||
try {
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/demandes/mes-demandes',
|
||||
queryParameters: {'utilisateurId': utilisateurId},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> data = response.data;
|
||||
return data.map((json) => DemandeAideModel.fromJson(json)).toList();
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la récupération de vos demandes',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Propositions d'aide
|
||||
@override
|
||||
Future<PropositionAideModel> creerPropositionAide(PropositionAideModel proposition) async {
|
||||
try {
|
||||
final response = await apiClient.post(
|
||||
'$baseEndpoint/propositions',
|
||||
data: proposition.toJson(),
|
||||
);
|
||||
|
||||
if (response.statusCode == 201) {
|
||||
return PropositionAideModel.fromJson(response.data);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la création de la proposition d\'aide',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PropositionAideModel> mettreAJourPropositionAide(PropositionAideModel proposition) async {
|
||||
try {
|
||||
final response = await apiClient.put(
|
||||
'$baseEndpoint/propositions/${proposition.id}',
|
||||
data: proposition.toJson(),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return PropositionAideModel.fromJson(response.data);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la mise à jour de la proposition d\'aide',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PropositionAideModel> obtenirPropositionAide(String id) async {
|
||||
try {
|
||||
final response = await apiClient.get('$baseEndpoint/propositions/$id');
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return PropositionAideModel.fromJson(response.data);
|
||||
} else if (response.statusCode == 404) {
|
||||
throw NotFoundException(message: 'Proposition d\'aide non trouvée');
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la récupération de la proposition d\'aide',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException || e is NotFoundException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PropositionAideModel> changerStatutProposition({
|
||||
required String propositionId,
|
||||
required bool activer,
|
||||
}) async {
|
||||
try {
|
||||
final endpoint = activer ? 'activer' : 'desactiver';
|
||||
final response = await apiClient.post(
|
||||
'$baseEndpoint/propositions/$propositionId/$endpoint',
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return PropositionAideModel.fromJson(response.data);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors du changement de statut de la proposition',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<PropositionAideModel>> rechercherPropositions({
|
||||
String? organisationId,
|
||||
String? typeAide,
|
||||
String? proposantId,
|
||||
bool? actives,
|
||||
int page = 0,
|
||||
int taille = 20,
|
||||
}) async {
|
||||
try {
|
||||
final queryParams = <String, dynamic>{
|
||||
'page': page,
|
||||
'size': taille,
|
||||
if (organisationId != null) 'organisationId': organisationId,
|
||||
if (typeAide != null) 'typeAide': typeAide,
|
||||
if (proposantId != null) 'proposantId': proposantId,
|
||||
if (actives != null) 'actives': actives,
|
||||
};
|
||||
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/propositions/rechercher',
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> data = response.data['content'];
|
||||
return data.map((json) => PropositionAideModel.fromJson(json)).toList();
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la recherche des propositions',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<PropositionAideModel>> obtenirPropositionsActives(String typeAide) async {
|
||||
try {
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/propositions/actives',
|
||||
queryParameters: {'typeAide': typeAide},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> data = response.data;
|
||||
return data.map((json) => PropositionAideModel.fromJson(json)).toList();
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la récupération des propositions actives',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<PropositionAideModel>> obtenirMeilleuresPropositions(int limite) async {
|
||||
try {
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/propositions/meilleures',
|
||||
queryParameters: {'limite': limite},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> data = response.data;
|
||||
return data.map((json) => PropositionAideModel.fromJson(json)).toList();
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la récupération des meilleures propositions',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<PropositionAideModel>> obtenirMesPropositions(String utilisateurId) async {
|
||||
try {
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/propositions/mes-propositions',
|
||||
queryParameters: {'utilisateurId': utilisateurId},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> data = response.data;
|
||||
return data.map((json) => PropositionAideModel.fromJson(json)).toList();
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la récupération de vos propositions',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Matching
|
||||
@override
|
||||
Future<List<PropositionAideModel>> trouverPropositionsCompatibles(String demandeId) async {
|
||||
try {
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/matching/propositions-compatibles/$demandeId',
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> data = response.data;
|
||||
return data.map((json) => PropositionAideModel.fromJson(json)).toList();
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la recherche de propositions compatibles',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<DemandeAideModel>> trouverDemandesCompatibles(String propositionId) async {
|
||||
try {
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/matching/demandes-compatibles/$propositionId',
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> data = response.data;
|
||||
return data.map((json) => DemandeAideModel.fromJson(json)).toList();
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la recherche de demandes compatibles',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<PropositionAideModel>> rechercherProposantsFinanciers(String demandeId) async {
|
||||
try {
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/matching/proposants-financiers/$demandeId',
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> data = response.data;
|
||||
return data.map((json) => PropositionAideModel.fromJson(json)).toList();
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la recherche de proposants financiers',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Évaluations
|
||||
@override
|
||||
Future<EvaluationAideModel> creerEvaluation(EvaluationAideModel evaluation) async {
|
||||
try {
|
||||
final response = await apiClient.post(
|
||||
'$baseEndpoint/evaluations',
|
||||
data: evaluation.toJson(),
|
||||
);
|
||||
|
||||
if (response.statusCode == 201) {
|
||||
return EvaluationAideModel.fromJson(response.data);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la création de l\'évaluation',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EvaluationAideModel> mettreAJourEvaluation(EvaluationAideModel evaluation) async {
|
||||
try {
|
||||
final response = await apiClient.put(
|
||||
'$baseEndpoint/evaluations/${evaluation.id}',
|
||||
data: evaluation.toJson(),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return EvaluationAideModel.fromJson(response.data);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la mise à jour de l\'évaluation',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EvaluationAideModel> obtenirEvaluation(String id) async {
|
||||
try {
|
||||
final response = await apiClient.get('$baseEndpoint/evaluations/$id');
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return EvaluationAideModel.fromJson(response.data);
|
||||
} else if (response.statusCode == 404) {
|
||||
throw NotFoundException(message: 'Évaluation non trouvée');
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la récupération de l\'évaluation',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException || e is NotFoundException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<EvaluationAideModel>> obtenirEvaluationsDemande(String demandeId) async {
|
||||
try {
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/evaluations/demande/$demandeId',
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> data = response.data;
|
||||
return data.map((json) => EvaluationAideModel.fromJson(json)).toList();
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la récupération des évaluations de la demande',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<EvaluationAideModel>> obtenirEvaluationsProposition(String propositionId) async {
|
||||
try {
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/evaluations/proposition/$propositionId',
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> data = response.data;
|
||||
return data.map((json) => EvaluationAideModel.fromJson(json)).toList();
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la récupération des évaluations de la proposition',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EvaluationAideModel> signalerEvaluation({
|
||||
required String evaluationId,
|
||||
required String motif,
|
||||
}) async {
|
||||
try {
|
||||
final response = await apiClient.post(
|
||||
'$baseEndpoint/evaluations/$evaluationId/signaler',
|
||||
data: {'motif': motif},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return EvaluationAideModel.fromJson(response.data);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors du signalement de l\'évaluation',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<StatistiquesEvaluationModel> calculerMoyenneDemande(String demandeId) async {
|
||||
try {
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/evaluations/moyenne/demande/$demandeId',
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return StatistiquesEvaluationModel.fromJson(response.data);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors du calcul de la moyenne de la demande',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<StatistiquesEvaluationModel> calculerMoyenneProposition(String propositionId) async {
|
||||
try {
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/evaluations/moyenne/proposition/$propositionId',
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return StatistiquesEvaluationModel.fromJson(response.data);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors du calcul de la moyenne de la proposition',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Statistiques
|
||||
@override
|
||||
Future<Map<String, dynamic>> obtenirStatistiquesSolidarite(String organisationId) async {
|
||||
try {
|
||||
final response = await apiClient.get(
|
||||
'$baseEndpoint/statistiques',
|
||||
queryParameters: {'organisationId': organisationId},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return Map<String, dynamic>.from(response.data);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'Erreur lors de la récupération des statistiques',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException) rethrow;
|
||||
throw ServerException(
|
||||
message: 'Erreur de communication avec le serveur: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../../../core/network/api_client.dart';
|
||||
import '../../../core/network/network_info.dart';
|
||||
|
||||
// Domain
|
||||
import '../domain/repositories/solidarite_repository.dart';
|
||||
import '../domain/usecases/gerer_demandes_aide_usecase.dart';
|
||||
import '../domain/usecases/gerer_propositions_aide_usecase.dart';
|
||||
import '../domain/usecases/gerer_matching_usecase.dart';
|
||||
import '../domain/usecases/gerer_evaluations_usecase.dart';
|
||||
import '../domain/usecases/obtenir_statistiques_usecase.dart';
|
||||
|
||||
// Data
|
||||
import 'datasources/solidarite_remote_data_source.dart';
|
||||
import 'datasources/solidarite_local_data_source.dart';
|
||||
import 'repositories/solidarite_repository_impl.dart';
|
||||
|
||||
/// Configuration de l'injection de dépendances pour le module solidarité
|
||||
///
|
||||
/// Cette classe configure tous les services, repositories, use cases
|
||||
/// et data sources nécessaires au fonctionnement du module solidarité.
|
||||
class SolidariteInjectionContainer {
|
||||
static final GetIt _sl = GetIt.instance;
|
||||
|
||||
/// Initialise toutes les dépendances du module solidarité
|
||||
static Future<void> init() async {
|
||||
// ============================================================================
|
||||
// Features - Solidarité
|
||||
// ============================================================================
|
||||
|
||||
// Use Cases - Demandes d'aide
|
||||
_sl.registerLazySingleton(() => CreerDemandeAideUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => MettreAJourDemandeAideUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ObtenirDemandeAideUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => SoumettreDemandeAideUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => EvaluerDemandeAideUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => RechercherDemandesAideUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ObtenirDemandesUrgentesUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ObtenirMesDemandesUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ValiderDemandeAideUseCase());
|
||||
_sl.registerLazySingleton(() => CalculerPrioriteDemandeUseCase());
|
||||
|
||||
// Use Cases - Propositions d'aide
|
||||
_sl.registerLazySingleton(() => CreerPropositionAideUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => MettreAJourPropositionAideUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ObtenirPropositionAideUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ChangerStatutPropositionUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => RechercherPropositionsAideUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ObtenirPropositionsActivesUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ObtenirMeilleuresPropositionsUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ObtenirMesPropositionsUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ValiderPropositionAideUseCase());
|
||||
_sl.registerLazySingleton(() => CalculerScorePropositionUseCase());
|
||||
|
||||
// Use Cases - Matching
|
||||
_sl.registerLazySingleton(() => TrouverPropositionsCompatiblesUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => TrouverDemandesCompatiblesUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => RechercherProposantsFinanciersUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => CalculerScoreCompatibiliteUseCase());
|
||||
_sl.registerLazySingleton(() => EffectuerMatchingIntelligentUseCase(
|
||||
trouverPropositionsCompatibles: _sl(),
|
||||
calculerScoreCompatibilite: _sl(),
|
||||
));
|
||||
_sl.registerLazySingleton(() => AnalyserTendancesMatchingUseCase());
|
||||
|
||||
// Use Cases - Évaluations
|
||||
_sl.registerLazySingleton(() => CreerEvaluationUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => MettreAJourEvaluationUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ObtenirEvaluationUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ObtenirEvaluationsDemandeUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ObtenirEvaluationsPropositionUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => SignalerEvaluationUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => CalculerMoyenneDemandeUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => CalculerMoyennePropositionUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => ValiderEvaluationUseCase());
|
||||
_sl.registerLazySingleton(() => CalculerScoreQualiteEvaluationUseCase());
|
||||
_sl.registerLazySingleton(() => AnalyserTendancesEvaluationUseCase());
|
||||
|
||||
// Use Cases - Statistiques
|
||||
_sl.registerLazySingleton(() => ObtenirStatistiquesSolidariteUseCase(_sl()));
|
||||
_sl.registerLazySingleton(() => CalculerKPIsPerformanceUseCase());
|
||||
_sl.registerLazySingleton(() => GenererRapportActiviteUseCase());
|
||||
|
||||
// Repository
|
||||
_sl.registerLazySingleton<SolidariteRepository>(
|
||||
() => SolidariteRepositoryImpl(
|
||||
remoteDataSource: _sl(),
|
||||
localDataSource: _sl(),
|
||||
networkInfo: _sl(),
|
||||
),
|
||||
);
|
||||
|
||||
// Data Sources
|
||||
_sl.registerLazySingleton<SolidariteRemoteDataSource>(
|
||||
() => SolidariteRemoteDataSourceImpl(apiClient: _sl()),
|
||||
);
|
||||
|
||||
_sl.registerLazySingleton<SolidariteLocalDataSource>(
|
||||
() => SolidariteLocalDataSourceImpl(sharedPreferences: _sl()),
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// Core (si pas déjà enregistrés)
|
||||
// ============================================================================
|
||||
|
||||
// Ces services sont normalement enregistrés dans le core injection container
|
||||
// Nous les enregistrons ici seulement s'ils ne sont pas déjà disponibles
|
||||
|
||||
if (!_sl.isRegistered<ApiClient>()) {
|
||||
_sl.registerLazySingleton<ApiClient>(() => ApiClientImpl());
|
||||
}
|
||||
|
||||
if (!_sl.isRegistered<NetworkInfo>()) {
|
||||
_sl.registerLazySingleton<NetworkInfo>(() => NetworkInfoImpl());
|
||||
}
|
||||
|
||||
if (!_sl.isRegistered<SharedPreferences>()) {
|
||||
final sharedPreferences = await SharedPreferences.getInstance();
|
||||
_sl.registerLazySingleton<SharedPreferences>(() => sharedPreferences);
|
||||
}
|
||||
}
|
||||
|
||||
/// Nettoie toutes les dépendances du module solidarité
|
||||
static Future<void> dispose() async {
|
||||
// Use Cases - Demandes d'aide
|
||||
_sl.unregister<CreerDemandeAideUseCase>();
|
||||
_sl.unregister<MettreAJourDemandeAideUseCase>();
|
||||
_sl.unregister<ObtenirDemandeAideUseCase>();
|
||||
_sl.unregister<SoumettreDemandeAideUseCase>();
|
||||
_sl.unregister<EvaluerDemandeAideUseCase>();
|
||||
_sl.unregister<RechercherDemandesAideUseCase>();
|
||||
_sl.unregister<ObtenirDemandesUrgentesUseCase>();
|
||||
_sl.unregister<ObtenirMesDemandesUseCase>();
|
||||
_sl.unregister<ValiderDemandeAideUseCase>();
|
||||
_sl.unregister<CalculerPrioriteDemandeUseCase>();
|
||||
|
||||
// Use Cases - Propositions d'aide
|
||||
_sl.unregister<CreerPropositionAideUseCase>();
|
||||
_sl.unregister<MettreAJourPropositionAideUseCase>();
|
||||
_sl.unregister<ObtenirPropositionAideUseCase>();
|
||||
_sl.unregister<ChangerStatutPropositionUseCase>();
|
||||
_sl.unregister<RechercherPropositionsAideUseCase>();
|
||||
_sl.unregister<ObtenirPropositionsActivesUseCase>();
|
||||
_sl.unregister<ObtenirMeilleuresPropositionsUseCase>();
|
||||
_sl.unregister<ObtenirMesPropositionsUseCase>();
|
||||
_sl.unregister<ValiderPropositionAideUseCase>();
|
||||
_sl.unregister<CalculerScorePropositionUseCase>();
|
||||
|
||||
// Use Cases - Matching
|
||||
_sl.unregister<TrouverPropositionsCompatiblesUseCase>();
|
||||
_sl.unregister<TrouverDemandesCompatiblesUseCase>();
|
||||
_sl.unregister<RechercherProposantsFinanciersUseCase>();
|
||||
_sl.unregister<CalculerScoreCompatibiliteUseCase>();
|
||||
_sl.unregister<EffectuerMatchingIntelligentUseCase>();
|
||||
_sl.unregister<AnalyserTendancesMatchingUseCase>();
|
||||
|
||||
// Use Cases - Évaluations
|
||||
_sl.unregister<CreerEvaluationUseCase>();
|
||||
_sl.unregister<MettreAJourEvaluationUseCase>();
|
||||
_sl.unregister<ObtenirEvaluationUseCase>();
|
||||
_sl.unregister<ObtenirEvaluationsDemandeUseCase>();
|
||||
_sl.unregister<ObtenirEvaluationsPropositionUseCase>();
|
||||
_sl.unregister<SignalerEvaluationUseCase>();
|
||||
_sl.unregister<CalculerMoyenneDemandeUseCase>();
|
||||
_sl.unregister<CalculerMoyennePropositionUseCase>();
|
||||
_sl.unregister<ValiderEvaluationUseCase>();
|
||||
_sl.unregister<CalculerScoreQualiteEvaluationUseCase>();
|
||||
_sl.unregister<AnalyserTendancesEvaluationUseCase>();
|
||||
|
||||
// Use Cases - Statistiques
|
||||
_sl.unregister<ObtenirStatistiquesSolidariteUseCase>();
|
||||
_sl.unregister<CalculerKPIsPerformanceUseCase>();
|
||||
_sl.unregister<GenererRapportActiviteUseCase>();
|
||||
|
||||
// Repository et Data Sources
|
||||
_sl.unregister<SolidariteRepository>();
|
||||
_sl.unregister<SolidariteRemoteDataSource>();
|
||||
_sl.unregister<SolidariteLocalDataSource>();
|
||||
}
|
||||
|
||||
/// Obtient une instance d'un service enregistré
|
||||
static T get<T extends Object>() => _sl.get<T>();
|
||||
|
||||
/// Vérifie si un service est enregistré
|
||||
static bool isRegistered<T extends Object>() => _sl.isRegistered<T>();
|
||||
|
||||
/// Réinitialise complètement le container
|
||||
static Future<void> reset() async {
|
||||
await dispose();
|
||||
await init();
|
||||
}
|
||||
|
||||
/// Obtient des statistiques sur les services enregistrés
|
||||
static Map<String, dynamic> getStats() {
|
||||
return {
|
||||
'totalServices': _sl.allReadySync().length,
|
||||
'solidariteServices': {
|
||||
'useCases': {
|
||||
'demandes': 10,
|
||||
'propositions': 10,
|
||||
'matching': 6,
|
||||
'evaluations': 11,
|
||||
'statistiques': 3,
|
||||
},
|
||||
'repositories': 1,
|
||||
'dataSources': 2,
|
||||
},
|
||||
'isInitialized': _sl.isRegistered<SolidariteRepository>(),
|
||||
};
|
||||
}
|
||||
|
||||
/// Valide que tous les services critiques sont enregistrés
|
||||
static bool validateConfiguration() {
|
||||
try {
|
||||
// Vérifier les services critiques
|
||||
final criticalServices = [
|
||||
SolidariteRepository,
|
||||
SolidariteRemoteDataSource,
|
||||
SolidariteLocalDataSource,
|
||||
CreerDemandeAideUseCase,
|
||||
CreerPropositionAideUseCase,
|
||||
CreerEvaluationUseCase,
|
||||
ObtenirStatistiquesSolidariteUseCase,
|
||||
];
|
||||
|
||||
for (final serviceType in criticalServices) {
|
||||
if (!_sl.isRegistered(instance: serviceType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Effectue un test de santé des services
|
||||
static Future<Map<String, bool>> healthCheck() async {
|
||||
final results = <String, bool>{};
|
||||
|
||||
try {
|
||||
// Test du repository
|
||||
final repository = _sl.get<SolidariteRepository>();
|
||||
results['repository'] = repository != null;
|
||||
|
||||
// Test des data sources
|
||||
final remoteDataSource = _sl.get<SolidariteRemoteDataSource>();
|
||||
results['remoteDataSource'] = remoteDataSource != null;
|
||||
|
||||
final localDataSource = _sl.get<SolidariteLocalDataSource>();
|
||||
results['localDataSource'] = localDataSource != null;
|
||||
|
||||
// Test des use cases critiques
|
||||
final creerDemandeUseCase = _sl.get<CreerDemandeAideUseCase>();
|
||||
results['creerDemandeUseCase'] = creerDemandeUseCase != null;
|
||||
|
||||
final creerPropositionUseCase = _sl.get<CreerPropositionAideUseCase>();
|
||||
results['creerPropositionUseCase'] = creerPropositionUseCase != null;
|
||||
|
||||
final creerEvaluationUseCase = _sl.get<CreerEvaluationUseCase>();
|
||||
results['creerEvaluationUseCase'] = creerEvaluationUseCase != null;
|
||||
|
||||
// Test des services de base
|
||||
results['networkInfo'] = _sl.isRegistered<NetworkInfo>();
|
||||
results['apiClient'] = _sl.isRegistered<ApiClient>();
|
||||
results['sharedPreferences'] = _sl.isRegistered<SharedPreferences>();
|
||||
|
||||
} catch (e) {
|
||||
results['error'] = false;
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension pour faciliter l'accès aux services depuis les widgets
|
||||
extension SolidariteServiceLocator on GetIt {
|
||||
// Use Cases - Demandes d'aide
|
||||
CreerDemandeAideUseCase get creerDemandeAide => get<CreerDemandeAideUseCase>();
|
||||
MettreAJourDemandeAideUseCase get mettreAJourDemandeAide => get<MettreAJourDemandeAideUseCase>();
|
||||
ObtenirDemandeAideUseCase get obtenirDemandeAide => get<ObtenirDemandeAideUseCase>();
|
||||
SoumettreDemandeAideUseCase get soumettreDemandeAide => get<SoumettreDemandeAideUseCase>();
|
||||
EvaluerDemandeAideUseCase get evaluerDemandeAide => get<EvaluerDemandeAideUseCase>();
|
||||
RechercherDemandesAideUseCase get rechercherDemandesAide => get<RechercherDemandesAideUseCase>();
|
||||
ObtenirDemandesUrgentesUseCase get obtenirDemandesUrgentes => get<ObtenirDemandesUrgentesUseCase>();
|
||||
ObtenirMesDemandesUseCase get obtenirMesdemandes => get<ObtenirMesDemandesUseCase>();
|
||||
ValiderDemandeAideUseCase get validerDemandeAide => get<ValiderDemandeAideUseCase>();
|
||||
CalculerPrioriteDemandeUseCase get calculerPrioriteDemande => get<CalculerPrioriteDemandeUseCase>();
|
||||
|
||||
// Use Cases - Propositions d'aide
|
||||
CreerPropositionAideUseCase get creerPropositionAide => get<CreerPropositionAideUseCase>();
|
||||
MettreAJourPropositionAideUseCase get mettreAJourPropositionAide => get<MettreAJourPropositionAideUseCase>();
|
||||
ObtenirPropositionAideUseCase get obtenirPropositionAide => get<ObtenirPropositionAideUseCase>();
|
||||
ChangerStatutPropositionUseCase get changerStatutProposition => get<ChangerStatutPropositionUseCase>();
|
||||
RechercherPropositionsAideUseCase get rechercherPropositionsAide => get<RechercherPropositionsAideUseCase>();
|
||||
ObtenirPropositionsActivesUseCase get obtenirPropositionsActives => get<ObtenirPropositionsActivesUseCase>();
|
||||
ObtenirMeilleuresPropositionsUseCase get obtenirMeilleuresPropositions => get<ObtenirMeilleuresPropositionsUseCase>();
|
||||
ObtenirMesPropositionsUseCase get obtenirMesPropositions => get<ObtenirMesPropositionsUseCase>();
|
||||
ValiderPropositionAideUseCase get validerPropositionAide => get<ValiderPropositionAideUseCase>();
|
||||
CalculerScorePropositionUseCase get calculerScoreProposition => get<CalculerScorePropositionUseCase>();
|
||||
|
||||
// Use Cases - Matching
|
||||
TrouverPropositionsCompatiblesUseCase get trouverPropositionsCompatibles => get<TrouverPropositionsCompatiblesUseCase>();
|
||||
TrouverDemandesCompatiblesUseCase get trouverDemandesCompatibles => get<TrouverDemandesCompatiblesUseCase>();
|
||||
RechercherProposantsFinanciersUseCase get rechercherProposantsFinanciers => get<RechercherProposantsFinanciersUseCase>();
|
||||
CalculerScoreCompatibiliteUseCase get calculerScoreCompatibilite => get<CalculerScoreCompatibiliteUseCase>();
|
||||
EffectuerMatchingIntelligentUseCase get effectuerMatchingIntelligent => get<EffectuerMatchingIntelligentUseCase>();
|
||||
AnalyserTendancesMatchingUseCase get analyserTendancesMatching => get<AnalyserTendancesMatchingUseCase>();
|
||||
|
||||
// Use Cases - Évaluations
|
||||
CreerEvaluationUseCase get creerEvaluation => get<CreerEvaluationUseCase>();
|
||||
MettreAJourEvaluationUseCase get mettreAJourEvaluation => get<MettreAJourEvaluationUseCase>();
|
||||
ObtenirEvaluationUseCase get obtenirEvaluation => get<ObtenirEvaluationUseCase>();
|
||||
ObtenirEvaluationsDemandeUseCase get obtenirEvaluationsDemande => get<ObtenirEvaluationsDemandeUseCase>();
|
||||
ObtenirEvaluationsPropositionUseCase get obtenirEvaluationsProposition => get<ObtenirEvaluationsPropositionUseCase>();
|
||||
SignalerEvaluationUseCase get signalerEvaluation => get<SignalerEvaluationUseCase>();
|
||||
CalculerMoyenneDemandeUseCase get calculerMoyenneDemande => get<CalculerMoyenneDemandeUseCase>();
|
||||
CalculerMoyennePropositionUseCase get calculerMoyenneProposition => get<CalculerMoyennePropositionUseCase>();
|
||||
ValiderEvaluationUseCase get validerEvaluation => get<ValiderEvaluationUseCase>();
|
||||
CalculerScoreQualiteEvaluationUseCase get calculerScoreQualiteEvaluation => get<CalculerScoreQualiteEvaluationUseCase>();
|
||||
AnalyserTendancesEvaluationUseCase get analyserTendancesEvaluation => get<AnalyserTendancesEvaluationUseCase>();
|
||||
|
||||
// Use Cases - Statistiques
|
||||
ObtenirStatistiquesSolidariteUseCase get obtenirStatistiquesSolidarite => get<ObtenirStatistiquesSolidariteUseCase>();
|
||||
CalculerKPIsPerformanceUseCase get calculerKPIsPerformance => get<CalculerKPIsPerformanceUseCase>();
|
||||
GenererRapportActiviteUseCase get genererRapportActivite => get<GenererRapportActiviteUseCase>();
|
||||
|
||||
// Repository
|
||||
SolidariteRepository get solidariteRepository => get<SolidariteRepository>();
|
||||
}
|
||||
@@ -0,0 +1,524 @@
|
||||
import '../../domain/entities/demande_aide.dart';
|
||||
|
||||
/// Modèle de données pour les demandes d'aide
|
||||
///
|
||||
/// Ce modèle fait la conversion entre les DTOs de l'API REST
|
||||
/// et les entités du domaine pour les demandes d'aide.
|
||||
class DemandeAideModel extends DemandeAide {
|
||||
const DemandeAideModel({
|
||||
required super.id,
|
||||
required super.numeroReference,
|
||||
required super.titre,
|
||||
required super.description,
|
||||
required super.typeAide,
|
||||
required super.statut,
|
||||
required super.priorite,
|
||||
required super.demandeurId,
|
||||
required super.nomDemandeur,
|
||||
required super.organisationId,
|
||||
super.montantDemande,
|
||||
super.montantApprouve,
|
||||
super.montantVerse,
|
||||
required super.dateCreation,
|
||||
required super.dateModification,
|
||||
super.dateSoumission,
|
||||
super.dateEvaluation,
|
||||
super.dateApprobation,
|
||||
super.dateLimiteTraitement,
|
||||
super.evaluateurId,
|
||||
super.commentairesEvaluateur,
|
||||
super.motifRejet,
|
||||
super.informationsRequises,
|
||||
super.justificationUrgence,
|
||||
super.contactUrgence,
|
||||
super.localisation,
|
||||
super.beneficiaires,
|
||||
super.piecesJustificatives,
|
||||
super.historiqueStatuts,
|
||||
super.commentaires,
|
||||
super.donneesPersonnalisees,
|
||||
super.estModifiable,
|
||||
super.estUrgente,
|
||||
super.delaiDepasse,
|
||||
super.estTerminee,
|
||||
});
|
||||
|
||||
/// Crée un modèle à partir d'un JSON (API Response)
|
||||
factory DemandeAideModel.fromJson(Map<String, dynamic> json) {
|
||||
return DemandeAideModel(
|
||||
id: json['id'] as String,
|
||||
numeroReference: json['numeroReference'] as String,
|
||||
titre: json['titre'] as String,
|
||||
description: json['description'] as String,
|
||||
typeAide: _parseTypeAide(json['typeAide'] as String),
|
||||
statut: _parseStatutAide(json['statut'] as String),
|
||||
priorite: _parsePrioriteAide(json['priorite'] as String),
|
||||
demandeurId: json['demandeurId'] as String,
|
||||
nomDemandeur: json['nomDemandeur'] as String,
|
||||
organisationId: json['organisationId'] as String,
|
||||
montantDemande: json['montantDemande']?.toDouble(),
|
||||
montantApprouve: json['montantApprouve']?.toDouble(),
|
||||
montantVerse: json['montantVerse']?.toDouble(),
|
||||
dateCreation: DateTime.parse(json['dateCreation'] as String),
|
||||
dateModification: DateTime.parse(json['dateModification'] as String),
|
||||
dateSoumission: json['dateSoumission'] != null
|
||||
? DateTime.parse(json['dateSoumission'] as String)
|
||||
: null,
|
||||
dateEvaluation: json['dateEvaluation'] != null
|
||||
? DateTime.parse(json['dateEvaluation'] as String)
|
||||
: null,
|
||||
dateApprobation: json['dateApprobation'] != null
|
||||
? DateTime.parse(json['dateApprobation'] as String)
|
||||
: null,
|
||||
dateLimiteTraitement: json['dateLimiteTraitement'] != null
|
||||
? DateTime.parse(json['dateLimiteTraitement'] as String)
|
||||
: null,
|
||||
evaluateurId: json['evaluateurId'] as String?,
|
||||
commentairesEvaluateur: json['commentairesEvaluateur'] as String?,
|
||||
motifRejet: json['motifRejet'] as String?,
|
||||
informationsRequises: json['informationsRequises'] as String?,
|
||||
justificationUrgence: json['justificationUrgence'] as String?,
|
||||
contactUrgence: json['contactUrgence'] != null
|
||||
? ContactUrgenceModel.fromJson(json['contactUrgence'] as Map<String, dynamic>)
|
||||
: null,
|
||||
localisation: json['localisation'] != null
|
||||
? LocalisationModel.fromJson(json['localisation'] as Map<String, dynamic>)
|
||||
: null,
|
||||
beneficiaires: (json['beneficiaires'] as List<dynamic>?)
|
||||
?.map((e) => BeneficiaireAideModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ?? [],
|
||||
piecesJustificatives: (json['piecesJustificatives'] as List<dynamic>?)
|
||||
?.map((e) => PieceJustificativeModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ?? [],
|
||||
historiqueStatuts: (json['historiqueStatuts'] as List<dynamic>?)
|
||||
?.map((e) => HistoriqueStatutModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ?? [],
|
||||
commentaires: (json['commentaires'] as List<dynamic>?)
|
||||
?.map((e) => CommentaireAideModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ?? [],
|
||||
donneesPersonnalisees: Map<String, dynamic>.from(json['donneesPersonnalisees'] ?? {}),
|
||||
estModifiable: json['estModifiable'] as bool? ?? false,
|
||||
estUrgente: json['estUrgente'] as bool? ?? false,
|
||||
delaiDepasse: json['delaiDepasse'] as bool? ?? false,
|
||||
estTerminee: json['estTerminee'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit le modèle en JSON (API Request)
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'numeroReference': numeroReference,
|
||||
'titre': titre,
|
||||
'description': description,
|
||||
'typeAide': typeAide.name,
|
||||
'statut': statut.name,
|
||||
'priorite': priorite.name,
|
||||
'demandeurId': demandeurId,
|
||||
'nomDemandeur': nomDemandeur,
|
||||
'organisationId': organisationId,
|
||||
'montantDemande': montantDemande,
|
||||
'montantApprouve': montantApprouve,
|
||||
'montantVerse': montantVerse,
|
||||
'dateCreation': dateCreation.toIso8601String(),
|
||||
'dateModification': dateModification.toIso8601String(),
|
||||
'dateSoumission': dateSoumission?.toIso8601String(),
|
||||
'dateEvaluation': dateEvaluation?.toIso8601String(),
|
||||
'dateApprobation': dateApprobation?.toIso8601String(),
|
||||
'dateLimiteTraitement': dateLimiteTraitement?.toIso8601String(),
|
||||
'evaluateurId': evaluateurId,
|
||||
'commentairesEvaluateur': commentairesEvaluateur,
|
||||
'motifRejet': motifRejet,
|
||||
'informationsRequises': informationsRequises,
|
||||
'justificationUrgence': justificationUrgence,
|
||||
'contactUrgence': contactUrgence != null
|
||||
? (contactUrgence as ContactUrgenceModel).toJson()
|
||||
: null,
|
||||
'localisation': localisation != null
|
||||
? (localisation as LocalisationModel).toJson()
|
||||
: null,
|
||||
'beneficiaires': beneficiaires
|
||||
.map((e) => (e as BeneficiaireAideModel).toJson())
|
||||
.toList(),
|
||||
'piecesJustificatives': piecesJustificatives
|
||||
.map((e) => (e as PieceJustificativeModel).toJson())
|
||||
.toList(),
|
||||
'historiqueStatuts': historiqueStatuts
|
||||
.map((e) => (e as HistoriqueStatutModel).toJson())
|
||||
.toList(),
|
||||
'commentaires': commentaires
|
||||
.map((e) => (e as CommentaireAideModel).toJson())
|
||||
.toList(),
|
||||
'donneesPersonnalisees': donneesPersonnalisees,
|
||||
'estModifiable': estModifiable,
|
||||
'estUrgente': estUrgente,
|
||||
'delaiDepasse': delaiDepasse,
|
||||
'estTerminee': estTerminee,
|
||||
};
|
||||
}
|
||||
|
||||
/// Crée un modèle à partir d'une entité du domaine
|
||||
factory DemandeAideModel.fromEntity(DemandeAide entity) {
|
||||
return DemandeAideModel(
|
||||
id: entity.id,
|
||||
numeroReference: entity.numeroReference,
|
||||
titre: entity.titre,
|
||||
description: entity.description,
|
||||
typeAide: entity.typeAide,
|
||||
statut: entity.statut,
|
||||
priorite: entity.priorite,
|
||||
demandeurId: entity.demandeurId,
|
||||
nomDemandeur: entity.nomDemandeur,
|
||||
organisationId: entity.organisationId,
|
||||
montantDemande: entity.montantDemande,
|
||||
montantApprouve: entity.montantApprouve,
|
||||
montantVerse: entity.montantVerse,
|
||||
dateCreation: entity.dateCreation,
|
||||
dateModification: entity.dateModification,
|
||||
dateSoumission: entity.dateSoumission,
|
||||
dateEvaluation: entity.dateEvaluation,
|
||||
dateApprobation: entity.dateApprobation,
|
||||
dateLimiteTraitement: entity.dateLimiteTraitement,
|
||||
evaluateurId: entity.evaluateurId,
|
||||
commentairesEvaluateur: entity.commentairesEvaluateur,
|
||||
motifRejet: entity.motifRejet,
|
||||
informationsRequises: entity.informationsRequises,
|
||||
justificationUrgence: entity.justificationUrgence,
|
||||
contactUrgence: entity.contactUrgence != null
|
||||
? ContactUrgenceModel.fromEntity(entity.contactUrgence!)
|
||||
: null,
|
||||
localisation: entity.localisation != null
|
||||
? LocalisationModel.fromEntity(entity.localisation!)
|
||||
: null,
|
||||
beneficiaires: entity.beneficiaires
|
||||
.map((e) => BeneficiaireAideModel.fromEntity(e))
|
||||
.toList(),
|
||||
piecesJustificatives: entity.piecesJustificatives
|
||||
.map((e) => PieceJustificativeModel.fromEntity(e))
|
||||
.toList(),
|
||||
historiqueStatuts: entity.historiqueStatuts
|
||||
.map((e) => HistoriqueStatutModel.fromEntity(e))
|
||||
.toList(),
|
||||
commentaires: entity.commentaires
|
||||
.map((e) => CommentaireAideModel.fromEntity(e))
|
||||
.toList(),
|
||||
donneesPersonnalisees: Map<String, dynamic>.from(entity.donneesPersonnalisees),
|
||||
estModifiable: entity.estModifiable,
|
||||
estUrgente: entity.estUrgente,
|
||||
delaiDepasse: entity.delaiDepasse,
|
||||
estTerminee: entity.estTerminee,
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit le modèle en entité du domaine
|
||||
DemandeAide toEntity() {
|
||||
return DemandeAide(
|
||||
id: id,
|
||||
numeroReference: numeroReference,
|
||||
titre: titre,
|
||||
description: description,
|
||||
typeAide: typeAide,
|
||||
statut: statut,
|
||||
priorite: priorite,
|
||||
demandeurId: demandeurId,
|
||||
nomDemandeur: nomDemandeur,
|
||||
organisationId: organisationId,
|
||||
montantDemande: montantDemande,
|
||||
montantApprouve: montantApprouve,
|
||||
montantVerse: montantVerse,
|
||||
dateCreation: dateCreation,
|
||||
dateModification: dateModification,
|
||||
dateSoumission: dateSoumission,
|
||||
dateEvaluation: dateEvaluation,
|
||||
dateApprobation: dateApprobation,
|
||||
dateLimiteTraitement: dateLimiteTraitement,
|
||||
evaluateurId: evaluateurId,
|
||||
commentairesEvaluateur: commentairesEvaluateur,
|
||||
motifRejet: motifRejet,
|
||||
informationsRequises: informationsRequises,
|
||||
justificationUrgence: justificationUrgence,
|
||||
contactUrgence: contactUrgence,
|
||||
localisation: localisation,
|
||||
beneficiaires: beneficiaires,
|
||||
piecesJustificatives: piecesJustificatives,
|
||||
historiqueStatuts: historiqueStatuts,
|
||||
commentaires: commentaires,
|
||||
donneesPersonnalisees: donneesPersonnalisees,
|
||||
estModifiable: estModifiable,
|
||||
estUrgente: estUrgente,
|
||||
delaiDepasse: delaiDepasse,
|
||||
estTerminee: estTerminee,
|
||||
);
|
||||
}
|
||||
|
||||
// Méthodes utilitaires de parsing
|
||||
static TypeAide _parseTypeAide(String value) {
|
||||
return TypeAide.values.firstWhere(
|
||||
(e) => e.name == value,
|
||||
orElse: () => TypeAide.autre,
|
||||
);
|
||||
}
|
||||
|
||||
static StatutAide _parseStatutAide(String value) {
|
||||
return StatutAide.values.firstWhere(
|
||||
(e) => e.name == value,
|
||||
orElse: () => StatutAide.brouillon,
|
||||
);
|
||||
}
|
||||
|
||||
static PrioriteAide _parsePrioriteAide(String value) {
|
||||
return PrioriteAide.values.firstWhere(
|
||||
(e) => e.name == value,
|
||||
orElse: () => PrioriteAide.normale,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Modèles pour les classes auxiliaires
|
||||
class ContactUrgenceModel extends ContactUrgence {
|
||||
const ContactUrgenceModel({
|
||||
required super.nom,
|
||||
required super.telephone,
|
||||
super.email,
|
||||
required super.relation,
|
||||
});
|
||||
|
||||
factory ContactUrgenceModel.fromJson(Map<String, dynamic> json) {
|
||||
return ContactUrgenceModel(
|
||||
nom: json['nom'] as String,
|
||||
telephone: json['telephone'] as String,
|
||||
email: json['email'] as String?,
|
||||
relation: json['relation'] as String,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'nom': nom,
|
||||
'telephone': telephone,
|
||||
'email': email,
|
||||
'relation': relation,
|
||||
};
|
||||
}
|
||||
|
||||
factory ContactUrgenceModel.fromEntity(ContactUrgence entity) {
|
||||
return ContactUrgenceModel(
|
||||
nom: entity.nom,
|
||||
telephone: entity.telephone,
|
||||
email: entity.email,
|
||||
relation: entity.relation,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LocalisationModel extends Localisation {
|
||||
const LocalisationModel({
|
||||
required super.adresse,
|
||||
required super.ville,
|
||||
super.codePostal,
|
||||
super.pays,
|
||||
super.latitude,
|
||||
super.longitude,
|
||||
});
|
||||
|
||||
factory LocalisationModel.fromJson(Map<String, dynamic> json) {
|
||||
return LocalisationModel(
|
||||
adresse: json['adresse'] as String,
|
||||
ville: json['ville'] as String,
|
||||
codePostal: json['codePostal'] as String?,
|
||||
pays: json['pays'] as String?,
|
||||
latitude: json['latitude']?.toDouble(),
|
||||
longitude: json['longitude']?.toDouble(),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'adresse': adresse,
|
||||
'ville': ville,
|
||||
'codePostal': codePostal,
|
||||
'pays': pays,
|
||||
'latitude': latitude,
|
||||
'longitude': longitude,
|
||||
};
|
||||
}
|
||||
|
||||
factory LocalisationModel.fromEntity(Localisation entity) {
|
||||
return LocalisationModel(
|
||||
adresse: entity.adresse,
|
||||
ville: entity.ville,
|
||||
codePostal: entity.codePostal,
|
||||
pays: entity.pays,
|
||||
latitude: entity.latitude,
|
||||
longitude: entity.longitude,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BeneficiaireAideModel extends BeneficiaireAide {
|
||||
const BeneficiaireAideModel({
|
||||
required super.nom,
|
||||
required super.prenom,
|
||||
required super.age,
|
||||
required super.relation,
|
||||
super.telephone,
|
||||
});
|
||||
|
||||
factory BeneficiaireAideModel.fromJson(Map<String, dynamic> json) {
|
||||
return BeneficiaireAideModel(
|
||||
nom: json['nom'] as String,
|
||||
prenom: json['prenom'] as String,
|
||||
age: json['age'] as int,
|
||||
relation: json['relation'] as String,
|
||||
telephone: json['telephone'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'nom': nom,
|
||||
'prenom': prenom,
|
||||
'age': age,
|
||||
'relation': relation,
|
||||
'telephone': telephone,
|
||||
};
|
||||
}
|
||||
|
||||
factory BeneficiaireAideModel.fromEntity(BeneficiaireAide entity) {
|
||||
return BeneficiaireAideModel(
|
||||
nom: entity.nom,
|
||||
prenom: entity.prenom,
|
||||
age: entity.age,
|
||||
relation: entity.relation,
|
||||
telephone: entity.telephone,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class PieceJustificativeModel extends PieceJustificative {
|
||||
const PieceJustificativeModel({
|
||||
required super.id,
|
||||
required super.nom,
|
||||
required super.type,
|
||||
required super.url,
|
||||
required super.taille,
|
||||
required super.dateAjout,
|
||||
});
|
||||
|
||||
factory PieceJustificativeModel.fromJson(Map<String, dynamic> json) {
|
||||
return PieceJustificativeModel(
|
||||
id: json['id'] as String,
|
||||
nom: json['nom'] as String,
|
||||
type: json['type'] as String,
|
||||
url: json['url'] as String,
|
||||
taille: json['taille'] as int,
|
||||
dateAjout: DateTime.parse(json['dateAjout'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'nom': nom,
|
||||
'type': type,
|
||||
'url': url,
|
||||
'taille': taille,
|
||||
'dateAjout': dateAjout.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
factory PieceJustificativeModel.fromEntity(PieceJustificative entity) {
|
||||
return PieceJustificativeModel(
|
||||
id: entity.id,
|
||||
nom: entity.nom,
|
||||
type: entity.type,
|
||||
url: entity.url,
|
||||
taille: entity.taille,
|
||||
dateAjout: entity.dateAjout,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HistoriqueStatutModel extends HistoriqueStatut {
|
||||
const HistoriqueStatutModel({
|
||||
required super.ancienStatut,
|
||||
required super.nouveauStatut,
|
||||
required super.dateChangement,
|
||||
super.commentaire,
|
||||
super.utilisateurId,
|
||||
});
|
||||
|
||||
factory HistoriqueStatutModel.fromJson(Map<String, dynamic> json) {
|
||||
return HistoriqueStatutModel(
|
||||
ancienStatut: DemandeAideModel._parseStatutAide(json['ancienStatut'] as String),
|
||||
nouveauStatut: DemandeAideModel._parseStatutAide(json['nouveauStatut'] as String),
|
||||
dateChangement: DateTime.parse(json['dateChangement'] as String),
|
||||
commentaire: json['commentaire'] as String?,
|
||||
utilisateurId: json['utilisateurId'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'ancienStatut': ancienStatut.name,
|
||||
'nouveauStatut': nouveauStatut.name,
|
||||
'dateChangement': dateChangement.toIso8601String(),
|
||||
'commentaire': commentaire,
|
||||
'utilisateurId': utilisateurId,
|
||||
};
|
||||
}
|
||||
|
||||
factory HistoriqueStatutModel.fromEntity(HistoriqueStatut entity) {
|
||||
return HistoriqueStatutModel(
|
||||
ancienStatut: entity.ancienStatut,
|
||||
nouveauStatut: entity.nouveauStatut,
|
||||
dateChangement: entity.dateChangement,
|
||||
commentaire: entity.commentaire,
|
||||
utilisateurId: entity.utilisateurId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CommentaireAideModel extends CommentaireAide {
|
||||
const CommentaireAideModel({
|
||||
required super.id,
|
||||
required super.contenu,
|
||||
required super.auteurId,
|
||||
required super.nomAuteur,
|
||||
required super.dateCreation,
|
||||
super.estPrive,
|
||||
});
|
||||
|
||||
factory CommentaireAideModel.fromJson(Map<String, dynamic> json) {
|
||||
return CommentaireAideModel(
|
||||
id: json['id'] as String,
|
||||
contenu: json['contenu'] as String,
|
||||
auteurId: json['auteurId'] as String,
|
||||
nomAuteur: json['nomAuteur'] as String,
|
||||
dateCreation: DateTime.parse(json['dateCreation'] as String),
|
||||
estPrive: json['estPrive'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'contenu': contenu,
|
||||
'auteurId': auteurId,
|
||||
'nomAuteur': nomAuteur,
|
||||
'dateCreation': dateCreation.toIso8601String(),
|
||||
'estPrive': estPrive,
|
||||
};
|
||||
}
|
||||
|
||||
factory CommentaireAideModel.fromEntity(CommentaireAide entity) {
|
||||
return CommentaireAideModel(
|
||||
id: entity.id,
|
||||
contenu: entity.contenu,
|
||||
auteurId: entity.auteurId,
|
||||
nomAuteur: entity.nomAuteur,
|
||||
dateCreation: entity.dateCreation,
|
||||
estPrive: entity.estPrive,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,388 @@
|
||||
import '../../domain/entities/evaluation_aide.dart';
|
||||
|
||||
/// Modèle de données pour les évaluations d'aide
|
||||
///
|
||||
/// Ce modèle fait la conversion entre les DTOs de l'API REST
|
||||
/// et les entités du domaine pour les évaluations d'aide.
|
||||
class EvaluationAideModel extends EvaluationAide {
|
||||
const EvaluationAideModel({
|
||||
required super.id,
|
||||
required super.demandeId,
|
||||
super.propositionId,
|
||||
required super.evaluateurId,
|
||||
required super.nomEvaluateur,
|
||||
required super.typeEvaluateur,
|
||||
required super.statut,
|
||||
required super.noteGlobale,
|
||||
super.noteDelaiReponse,
|
||||
super.noteCommunication,
|
||||
super.noteProfessionnalisme,
|
||||
super.noteRespectEngagements,
|
||||
required super.commentairePrincipal,
|
||||
super.pointsPositifs,
|
||||
super.pointsAmelioration,
|
||||
super.recommandations,
|
||||
super.recommande,
|
||||
required super.dateCreation,
|
||||
required super.dateModification,
|
||||
super.dateValidation,
|
||||
super.validateurId,
|
||||
super.motifSignalement,
|
||||
super.nombreSignalements,
|
||||
super.estModeree,
|
||||
super.estPublique,
|
||||
super.donneesPersonnalisees,
|
||||
});
|
||||
|
||||
/// Crée un modèle à partir d'un JSON (API Response)
|
||||
factory EvaluationAideModel.fromJson(Map<String, dynamic> json) {
|
||||
return EvaluationAideModel(
|
||||
id: json['id'] as String,
|
||||
demandeId: json['demandeId'] as String,
|
||||
propositionId: json['propositionId'] as String?,
|
||||
evaluateurId: json['evaluateurId'] as String,
|
||||
nomEvaluateur: json['nomEvaluateur'] as String,
|
||||
typeEvaluateur: _parseTypeEvaluateur(json['typeEvaluateur'] as String),
|
||||
statut: _parseStatutEvaluation(json['statut'] as String),
|
||||
noteGlobale: json['noteGlobale'].toDouble(),
|
||||
noteDelaiReponse: json['noteDelaiReponse']?.toDouble(),
|
||||
noteCommunication: json['noteCommunication']?.toDouble(),
|
||||
noteProfessionnalisme: json['noteProfessionnalisme']?.toDouble(),
|
||||
noteRespectEngagements: json['noteRespectEngagements']?.toDouble(),
|
||||
commentairePrincipal: json['commentairePrincipal'] as String,
|
||||
pointsPositifs: json['pointsPositifs'] as String?,
|
||||
pointsAmelioration: json['pointsAmelioration'] as String?,
|
||||
recommandations: json['recommandations'] as String?,
|
||||
recommande: json['recommande'] as bool?,
|
||||
dateCreation: DateTime.parse(json['dateCreation'] as String),
|
||||
dateModification: DateTime.parse(json['dateModification'] as String),
|
||||
dateValidation: json['dateValidation'] != null
|
||||
? DateTime.parse(json['dateValidation'] as String)
|
||||
: null,
|
||||
validateurId: json['validateurId'] as String?,
|
||||
motifSignalement: json['motifSignalement'] as String?,
|
||||
nombreSignalements: json['nombreSignalements'] as int? ?? 0,
|
||||
estModeree: json['estModeree'] as bool? ?? false,
|
||||
estPublique: json['estPublique'] as bool? ?? true,
|
||||
donneesPersonnalisees: Map<String, dynamic>.from(json['donneesPersonnalisees'] ?? {}),
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit le modèle en JSON (API Request)
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'demandeId': demandeId,
|
||||
'propositionId': propositionId,
|
||||
'evaluateurId': evaluateurId,
|
||||
'nomEvaluateur': nomEvaluateur,
|
||||
'typeEvaluateur': typeEvaluateur.name,
|
||||
'statut': statut.name,
|
||||
'noteGlobale': noteGlobale,
|
||||
'noteDelaiReponse': noteDelaiReponse,
|
||||
'noteCommunication': noteCommunication,
|
||||
'noteProfessionnalisme': noteProfessionnalisme,
|
||||
'noteRespectEngagements': noteRespectEngagements,
|
||||
'commentairePrincipal': commentairePrincipal,
|
||||
'pointsPositifs': pointsPositifs,
|
||||
'pointsAmelioration': pointsAmelioration,
|
||||
'recommandations': recommandations,
|
||||
'recommande': recommande,
|
||||
'dateCreation': dateCreation.toIso8601String(),
|
||||
'dateModification': dateModification.toIso8601String(),
|
||||
'dateValidation': dateValidation?.toIso8601String(),
|
||||
'validateurId': validateurId,
|
||||
'motifSignalement': motifSignalement,
|
||||
'nombreSignalements': nombreSignalements,
|
||||
'estModeree': estModeree,
|
||||
'estPublique': estPublique,
|
||||
'donneesPersonnalisees': donneesPersonnalisees,
|
||||
};
|
||||
}
|
||||
|
||||
/// Crée un modèle à partir d'une entité du domaine
|
||||
factory EvaluationAideModel.fromEntity(EvaluationAide entity) {
|
||||
return EvaluationAideModel(
|
||||
id: entity.id,
|
||||
demandeId: entity.demandeId,
|
||||
propositionId: entity.propositionId,
|
||||
evaluateurId: entity.evaluateurId,
|
||||
nomEvaluateur: entity.nomEvaluateur,
|
||||
typeEvaluateur: entity.typeEvaluateur,
|
||||
statut: entity.statut,
|
||||
noteGlobale: entity.noteGlobale,
|
||||
noteDelaiReponse: entity.noteDelaiReponse,
|
||||
noteCommunication: entity.noteCommunication,
|
||||
noteProfessionnalisme: entity.noteProfessionnalisme,
|
||||
noteRespectEngagements: entity.noteRespectEngagements,
|
||||
commentairePrincipal: entity.commentairePrincipal,
|
||||
pointsPositifs: entity.pointsPositifs,
|
||||
pointsAmelioration: entity.pointsAmelioration,
|
||||
recommandations: entity.recommandations,
|
||||
recommande: entity.recommande,
|
||||
dateCreation: entity.dateCreation,
|
||||
dateModification: entity.dateModification,
|
||||
dateValidation: entity.dateValidation,
|
||||
validateurId: entity.validateurId,
|
||||
motifSignalement: entity.motifSignalement,
|
||||
nombreSignalements: entity.nombreSignalements,
|
||||
estModeree: entity.estModeree,
|
||||
estPublique: entity.estPublique,
|
||||
donneesPersonnalisees: Map<String, dynamic>.from(entity.donneesPersonnalisees),
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit le modèle en entité du domaine
|
||||
EvaluationAide toEntity() {
|
||||
return EvaluationAide(
|
||||
id: id,
|
||||
demandeId: demandeId,
|
||||
propositionId: propositionId,
|
||||
evaluateurId: evaluateurId,
|
||||
nomEvaluateur: nomEvaluateur,
|
||||
typeEvaluateur: typeEvaluateur,
|
||||
statut: statut,
|
||||
noteGlobale: noteGlobale,
|
||||
noteDelaiReponse: noteDelaiReponse,
|
||||
noteCommunication: noteCommunication,
|
||||
noteProfessionnalisme: noteProfessionnalisme,
|
||||
noteRespectEngagements: noteRespectEngagements,
|
||||
commentairePrincipal: commentairePrincipal,
|
||||
pointsPositifs: pointsPositifs,
|
||||
pointsAmelioration: pointsAmelioration,
|
||||
recommandations: recommandations,
|
||||
recommande: recommande,
|
||||
dateCreation: dateCreation,
|
||||
dateModification: dateModification,
|
||||
dateValidation: dateValidation,
|
||||
validateurId: validateurId,
|
||||
motifSignalement: motifSignalement,
|
||||
nombreSignalements: nombreSignalements,
|
||||
estModeree: estModeree,
|
||||
estPublique: estPublique,
|
||||
donneesPersonnalisees: donneesPersonnalisees,
|
||||
);
|
||||
}
|
||||
|
||||
// Méthodes utilitaires de parsing
|
||||
static TypeEvaluateur _parseTypeEvaluateur(String value) {
|
||||
return TypeEvaluateur.values.firstWhere(
|
||||
(e) => e.name == value,
|
||||
orElse: () => TypeEvaluateur.beneficiaire,
|
||||
);
|
||||
}
|
||||
|
||||
static StatutEvaluation _parseStatutEvaluation(String value) {
|
||||
return StatutEvaluation.values.firstWhere(
|
||||
(e) => e.name == value,
|
||||
orElse: () => StatutEvaluation.brouillon,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Modèle pour les statistiques d'évaluation
|
||||
class StatistiquesEvaluationModel {
|
||||
final double noteMoyenne;
|
||||
final int nombreEvaluations;
|
||||
final Map<int, int> repartitionNotes;
|
||||
final double pourcentageRecommandations;
|
||||
final List<EvaluationAideModel> evaluationsRecentes;
|
||||
final DateTime dateCalcul;
|
||||
|
||||
const StatistiquesEvaluationModel({
|
||||
required this.noteMoyenne,
|
||||
required this.nombreEvaluations,
|
||||
required this.repartitionNotes,
|
||||
required this.pourcentageRecommandations,
|
||||
required this.evaluationsRecentes,
|
||||
required this.dateCalcul,
|
||||
});
|
||||
|
||||
/// Crée un modèle à partir d'un JSON (API Response)
|
||||
factory StatistiquesEvaluationModel.fromJson(Map<String, dynamic> json) {
|
||||
return StatistiquesEvaluationModel(
|
||||
noteMoyenne: json['noteMoyenne'].toDouble(),
|
||||
nombreEvaluations: json['nombreEvaluations'] as int,
|
||||
repartitionNotes: Map<int, int>.from(json['repartitionNotes']),
|
||||
pourcentageRecommandations: json['pourcentageRecommandations'].toDouble(),
|
||||
evaluationsRecentes: (json['evaluationsRecentes'] as List<dynamic>)
|
||||
.map((e) => EvaluationAideModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
dateCalcul: DateTime.parse(json['dateCalcul'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit le modèle en JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'noteMoyenne': noteMoyenne,
|
||||
'nombreEvaluations': nombreEvaluations,
|
||||
'repartitionNotes': repartitionNotes,
|
||||
'pourcentageRecommandations': pourcentageRecommandations,
|
||||
'evaluationsRecentes': evaluationsRecentes
|
||||
.map((e) => e.toJson())
|
||||
.toList(),
|
||||
'dateCalcul': dateCalcul.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
/// Convertit le modèle en entité du domaine
|
||||
StatistiquesEvaluation toEntity() {
|
||||
return StatistiquesEvaluation(
|
||||
noteMoyenne: noteMoyenne,
|
||||
nombreEvaluations: nombreEvaluations,
|
||||
repartitionNotes: repartitionNotes,
|
||||
pourcentageRecommandations: pourcentageRecommandations,
|
||||
evaluationsRecentes: evaluationsRecentes
|
||||
.map((e) => e.toEntity())
|
||||
.toList(),
|
||||
dateCalcul: dateCalcul,
|
||||
);
|
||||
}
|
||||
|
||||
/// Crée un modèle à partir d'une entité du domaine
|
||||
factory StatistiquesEvaluationModel.fromEntity(StatistiquesEvaluation entity) {
|
||||
return StatistiquesEvaluationModel(
|
||||
noteMoyenne: entity.noteMoyenne,
|
||||
nombreEvaluations: entity.nombreEvaluations,
|
||||
repartitionNotes: Map<int, int>.from(entity.repartitionNotes),
|
||||
pourcentageRecommandations: entity.pourcentageRecommandations,
|
||||
evaluationsRecentes: entity.evaluationsRecentes
|
||||
.map((e) => EvaluationAideModel.fromEntity(e))
|
||||
.toList(),
|
||||
dateCalcul: entity.dateCalcul,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Modèle pour les réponses de recherche d'évaluations
|
||||
class RechercheEvaluationsResponse {
|
||||
final List<EvaluationAideModel> evaluations;
|
||||
final int totalElements;
|
||||
final int totalPages;
|
||||
final int currentPage;
|
||||
final int pageSize;
|
||||
final bool hasNext;
|
||||
final bool hasPrevious;
|
||||
|
||||
const RechercheEvaluationsResponse({
|
||||
required this.evaluations,
|
||||
required this.totalElements,
|
||||
required this.totalPages,
|
||||
required this.currentPage,
|
||||
required this.pageSize,
|
||||
required this.hasNext,
|
||||
required this.hasPrevious,
|
||||
});
|
||||
|
||||
/// Crée un modèle à partir d'un JSON (API Response)
|
||||
factory RechercheEvaluationsResponse.fromJson(Map<String, dynamic> json) {
|
||||
return RechercheEvaluationsResponse(
|
||||
evaluations: (json['content'] as List<dynamic>)
|
||||
.map((e) => EvaluationAideModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
totalElements: json['totalElements'] as int,
|
||||
totalPages: json['totalPages'] as int,
|
||||
currentPage: json['number'] as int,
|
||||
pageSize: json['size'] as int,
|
||||
hasNext: !(json['last'] as bool),
|
||||
hasPrevious: !(json['first'] as bool),
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit le modèle en JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'content': evaluations.map((e) => e.toJson()).toList(),
|
||||
'totalElements': totalElements,
|
||||
'totalPages': totalPages,
|
||||
'number': currentPage,
|
||||
'size': pageSize,
|
||||
'last': !hasNext,
|
||||
'first': !hasPrevious,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Modèle pour les requêtes de création d'évaluation
|
||||
class CreerEvaluationRequest {
|
||||
final String demandeId;
|
||||
final String? propositionId;
|
||||
final String evaluateurId;
|
||||
final TypeEvaluateur typeEvaluateur;
|
||||
final double noteGlobale;
|
||||
final double? noteDelaiReponse;
|
||||
final double? noteCommunication;
|
||||
final double? noteProfessionnalisme;
|
||||
final double? noteRespectEngagements;
|
||||
final String commentairePrincipal;
|
||||
final String? pointsPositifs;
|
||||
final String? pointsAmelioration;
|
||||
final String? recommandations;
|
||||
final bool? recommande;
|
||||
final bool estPublique;
|
||||
final Map<String, dynamic> donneesPersonnalisees;
|
||||
|
||||
const CreerEvaluationRequest({
|
||||
required this.demandeId,
|
||||
this.propositionId,
|
||||
required this.evaluateurId,
|
||||
required this.typeEvaluateur,
|
||||
required this.noteGlobale,
|
||||
this.noteDelaiReponse,
|
||||
this.noteCommunication,
|
||||
this.noteProfessionnalisme,
|
||||
this.noteRespectEngagements,
|
||||
required this.commentairePrincipal,
|
||||
this.pointsPositifs,
|
||||
this.pointsAmelioration,
|
||||
this.recommandations,
|
||||
this.recommande,
|
||||
this.estPublique = true,
|
||||
this.donneesPersonnalisees = const {},
|
||||
});
|
||||
|
||||
/// Convertit la requête en JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'demandeId': demandeId,
|
||||
'propositionId': propositionId,
|
||||
'evaluateurId': evaluateurId,
|
||||
'typeEvaluateur': typeEvaluateur.name,
|
||||
'noteGlobale': noteGlobale,
|
||||
'noteDelaiReponse': noteDelaiReponse,
|
||||
'noteCommunication': noteCommunication,
|
||||
'noteProfessionnalisme': noteProfessionnalisme,
|
||||
'noteRespectEngagements': noteRespectEngagements,
|
||||
'commentairePrincipal': commentairePrincipal,
|
||||
'pointsPositifs': pointsPositifs,
|
||||
'pointsAmelioration': pointsAmelioration,
|
||||
'recommandations': recommandations,
|
||||
'recommande': recommande,
|
||||
'estPublique': estPublique,
|
||||
'donneesPersonnalisees': donneesPersonnalisees,
|
||||
};
|
||||
}
|
||||
|
||||
/// Crée une requête à partir d'une entité d'évaluation
|
||||
factory CreerEvaluationRequest.fromEntity(EvaluationAide entity) {
|
||||
return CreerEvaluationRequest(
|
||||
demandeId: entity.demandeId,
|
||||
propositionId: entity.propositionId,
|
||||
evaluateurId: entity.evaluateurId,
|
||||
typeEvaluateur: entity.typeEvaluateur,
|
||||
noteGlobale: entity.noteGlobale,
|
||||
noteDelaiReponse: entity.noteDelaiReponse,
|
||||
noteCommunication: entity.noteCommunication,
|
||||
noteProfessionnalisme: entity.noteProfessionnalisme,
|
||||
noteRespectEngagements: entity.noteRespectEngagements,
|
||||
commentairePrincipal: entity.commentairePrincipal,
|
||||
pointsPositifs: entity.pointsPositifs,
|
||||
pointsAmelioration: entity.pointsAmelioration,
|
||||
recommandations: entity.recommandations,
|
||||
recommande: entity.recommande,
|
||||
estPublique: entity.estPublique,
|
||||
donneesPersonnalisees: entity.donneesPersonnalisees,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
import '../../domain/entities/proposition_aide.dart';
|
||||
import '../../domain/entities/demande_aide.dart';
|
||||
|
||||
/// Modèle de données pour les propositions d'aide
|
||||
///
|
||||
/// Ce modèle fait la conversion entre les DTOs de l'API REST
|
||||
/// et les entités du domaine pour les propositions d'aide.
|
||||
class PropositionAideModel extends PropositionAide {
|
||||
const PropositionAideModel({
|
||||
required super.id,
|
||||
required super.titre,
|
||||
required super.description,
|
||||
required super.typeAide,
|
||||
required super.statut,
|
||||
required super.proposantId,
|
||||
required super.nomProposant,
|
||||
required super.organisationId,
|
||||
required super.nombreMaxBeneficiaires,
|
||||
super.montantMaximum,
|
||||
super.montantMinimum,
|
||||
required super.delaiReponseHeures,
|
||||
required super.dateCreation,
|
||||
required super.dateModification,
|
||||
super.dateExpiration,
|
||||
super.dateActivation,
|
||||
super.dateDesactivation,
|
||||
required super.contactProposant,
|
||||
super.zonesGeographiques,
|
||||
super.creneauxDisponibilite,
|
||||
super.criteresSelection,
|
||||
super.conditionsSpeciales,
|
||||
super.nombreBeneficiairesAides,
|
||||
super.nombreVues,
|
||||
super.nombreCandidatures,
|
||||
super.noteMoyenne,
|
||||
super.nombreEvaluations,
|
||||
super.donneesPersonnalisees,
|
||||
super.estVerifiee,
|
||||
super.estPromue,
|
||||
});
|
||||
|
||||
/// Crée un modèle à partir d'un JSON (API Response)
|
||||
factory PropositionAideModel.fromJson(Map<String, dynamic> json) {
|
||||
return PropositionAideModel(
|
||||
id: json['id'] as String,
|
||||
titre: json['titre'] as String,
|
||||
description: json['description'] as String,
|
||||
typeAide: _parseTypeAide(json['typeAide'] as String),
|
||||
statut: _parseStatutProposition(json['statut'] as String),
|
||||
proposantId: json['proposantId'] as String,
|
||||
nomProposant: json['nomProposant'] as String,
|
||||
organisationId: json['organisationId'] as String,
|
||||
nombreMaxBeneficiaires: json['nombreMaxBeneficiaires'] as int,
|
||||
montantMaximum: json['montantMaximum']?.toDouble(),
|
||||
montantMinimum: json['montantMinimum']?.toDouble(),
|
||||
delaiReponseHeures: json['delaiReponseHeures'] as int,
|
||||
dateCreation: DateTime.parse(json['dateCreation'] as String),
|
||||
dateModification: DateTime.parse(json['dateModification'] as String),
|
||||
dateExpiration: json['dateExpiration'] != null
|
||||
? DateTime.parse(json['dateExpiration'] as String)
|
||||
: null,
|
||||
dateActivation: json['dateActivation'] != null
|
||||
? DateTime.parse(json['dateActivation'] as String)
|
||||
: null,
|
||||
dateDesactivation: json['dateDesactivation'] != null
|
||||
? DateTime.parse(json['dateDesactivation'] as String)
|
||||
: null,
|
||||
contactProposant: ContactProposantModel.fromJson(
|
||||
json['contactProposant'] as Map<String, dynamic>
|
||||
),
|
||||
zonesGeographiques: (json['zonesGeographiques'] as List<dynamic>?)
|
||||
?.cast<String>() ?? [],
|
||||
creneauxDisponibilite: (json['creneauxDisponibilite'] as List<dynamic>?)
|
||||
?.map((e) => CreneauDisponibiliteModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ?? [],
|
||||
criteresSelection: (json['criteresSelection'] as List<dynamic>?)
|
||||
?.map((e) => CritereSelectionModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ?? [],
|
||||
conditionsSpeciales: (json['conditionsSpeciales'] as List<dynamic>?)
|
||||
?.cast<String>() ?? [],
|
||||
nombreBeneficiairesAides: json['nombreBeneficiairesAides'] as int? ?? 0,
|
||||
nombreVues: json['nombreVues'] as int? ?? 0,
|
||||
nombreCandidatures: json['nombreCandidatures'] as int? ?? 0,
|
||||
noteMoyenne: json['noteMoyenne']?.toDouble(),
|
||||
nombreEvaluations: json['nombreEvaluations'] as int? ?? 0,
|
||||
donneesPersonnalisees: Map<String, dynamic>.from(json['donneesPersonnalisees'] ?? {}),
|
||||
estVerifiee: json['estVerifiee'] as bool? ?? false,
|
||||
estPromue: json['estPromue'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit le modèle en JSON (API Request)
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'titre': titre,
|
||||
'description': description,
|
||||
'typeAide': typeAide.name,
|
||||
'statut': statut.name,
|
||||
'proposantId': proposantId,
|
||||
'nomProposant': nomProposant,
|
||||
'organisationId': organisationId,
|
||||
'nombreMaxBeneficiaires': nombreMaxBeneficiaires,
|
||||
'montantMaximum': montantMaximum,
|
||||
'montantMinimum': montantMinimum,
|
||||
'delaiReponseHeures': delaiReponseHeures,
|
||||
'dateCreation': dateCreation.toIso8601String(),
|
||||
'dateModification': dateModification.toIso8601String(),
|
||||
'dateExpiration': dateExpiration?.toIso8601String(),
|
||||
'dateActivation': dateActivation?.toIso8601String(),
|
||||
'dateDesactivation': dateDesactivation?.toIso8601String(),
|
||||
'contactProposant': (contactProposant as ContactProposantModel).toJson(),
|
||||
'zonesGeographiques': zonesGeographiques,
|
||||
'creneauxDisponibilite': creneauxDisponibilite
|
||||
.map((e) => (e as CreneauDisponibiliteModel).toJson())
|
||||
.toList(),
|
||||
'criteresSelection': criteresSelection
|
||||
.map((e) => (e as CritereSelectionModel).toJson())
|
||||
.toList(),
|
||||
'conditionsSpeciales': conditionsSpeciales,
|
||||
'nombreBeneficiairesAides': nombreBeneficiairesAides,
|
||||
'nombreVues': nombreVues,
|
||||
'nombreCandidatures': nombreCandidatures,
|
||||
'noteMoyenne': noteMoyenne,
|
||||
'nombreEvaluations': nombreEvaluations,
|
||||
'donneesPersonnalisees': donneesPersonnalisees,
|
||||
'estVerifiee': estVerifiee,
|
||||
'estPromue': estPromue,
|
||||
};
|
||||
}
|
||||
|
||||
/// Crée un modèle à partir d'une entité du domaine
|
||||
factory PropositionAideModel.fromEntity(PropositionAide entity) {
|
||||
return PropositionAideModel(
|
||||
id: entity.id,
|
||||
titre: entity.titre,
|
||||
description: entity.description,
|
||||
typeAide: entity.typeAide,
|
||||
statut: entity.statut,
|
||||
proposantId: entity.proposantId,
|
||||
nomProposant: entity.nomProposant,
|
||||
organisationId: entity.organisationId,
|
||||
nombreMaxBeneficiaires: entity.nombreMaxBeneficiaires,
|
||||
montantMaximum: entity.montantMaximum,
|
||||
montantMinimum: entity.montantMinimum,
|
||||
delaiReponseHeures: entity.delaiReponseHeures,
|
||||
dateCreation: entity.dateCreation,
|
||||
dateModification: entity.dateModification,
|
||||
dateExpiration: entity.dateExpiration,
|
||||
dateActivation: entity.dateActivation,
|
||||
dateDesactivation: entity.dateDesactivation,
|
||||
contactProposant: ContactProposantModel.fromEntity(entity.contactProposant),
|
||||
zonesGeographiques: List<String>.from(entity.zonesGeographiques),
|
||||
creneauxDisponibilite: entity.creneauxDisponibilite
|
||||
.map((e) => CreneauDisponibiliteModel.fromEntity(e))
|
||||
.toList(),
|
||||
criteresSelection: entity.criteresSelection
|
||||
.map((e) => CritereSelectionModel.fromEntity(e))
|
||||
.toList(),
|
||||
conditionsSpeciales: List<String>.from(entity.conditionsSpeciales),
|
||||
nombreBeneficiairesAides: entity.nombreBeneficiairesAides,
|
||||
nombreVues: entity.nombreVues,
|
||||
nombreCandidatures: entity.nombreCandidatures,
|
||||
noteMoyenne: entity.noteMoyenne,
|
||||
nombreEvaluations: entity.nombreEvaluations,
|
||||
donneesPersonnalisees: Map<String, dynamic>.from(entity.donneesPersonnalisees),
|
||||
estVerifiee: entity.estVerifiee,
|
||||
estPromue: entity.estPromue,
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit le modèle en entité du domaine
|
||||
PropositionAide toEntity() {
|
||||
return PropositionAide(
|
||||
id: id,
|
||||
titre: titre,
|
||||
description: description,
|
||||
typeAide: typeAide,
|
||||
statut: statut,
|
||||
proposantId: proposantId,
|
||||
nomProposant: nomProposant,
|
||||
organisationId: organisationId,
|
||||
nombreMaxBeneficiaires: nombreMaxBeneficiaires,
|
||||
montantMaximum: montantMaximum,
|
||||
montantMinimum: montantMinimum,
|
||||
delaiReponseHeures: delaiReponseHeures,
|
||||
dateCreation: dateCreation,
|
||||
dateModification: dateModification,
|
||||
dateExpiration: dateExpiration,
|
||||
dateActivation: dateActivation,
|
||||
dateDesactivation: dateDesactivation,
|
||||
contactProposant: contactProposant,
|
||||
zonesGeographiques: zonesGeographiques,
|
||||
creneauxDisponibilite: creneauxDisponibilite,
|
||||
criteresSelection: criteresSelection,
|
||||
conditionsSpeciales: conditionsSpeciales,
|
||||
nombreBeneficiairesAides: nombreBeneficiairesAides,
|
||||
nombreVues: nombreVues,
|
||||
nombreCandidatures: nombreCandidatures,
|
||||
noteMoyenne: noteMoyenne,
|
||||
nombreEvaluations: nombreEvaluations,
|
||||
donneesPersonnalisees: donneesPersonnalisees,
|
||||
estVerifiee: estVerifiee,
|
||||
estPromue: estPromue,
|
||||
);
|
||||
}
|
||||
|
||||
// Méthodes utilitaires de parsing
|
||||
static TypeAide _parseTypeAide(String value) {
|
||||
return TypeAide.values.firstWhere(
|
||||
(e) => e.name == value,
|
||||
orElse: () => TypeAide.autre,
|
||||
);
|
||||
}
|
||||
|
||||
static StatutProposition _parseStatutProposition(String value) {
|
||||
return StatutProposition.values.firstWhere(
|
||||
(e) => e.name == value,
|
||||
orElse: () => StatutProposition.brouillon,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Modèles pour les classes auxiliaires
|
||||
class ContactProposantModel extends ContactProposant {
|
||||
const ContactProposantModel({
|
||||
required super.nom,
|
||||
required super.telephone,
|
||||
super.email,
|
||||
super.adresse,
|
||||
super.heuresDisponibilite,
|
||||
});
|
||||
|
||||
factory ContactProposantModel.fromJson(Map<String, dynamic> json) {
|
||||
return ContactProposantModel(
|
||||
nom: json['nom'] as String,
|
||||
telephone: json['telephone'] as String,
|
||||
email: json['email'] as String?,
|
||||
adresse: json['adresse'] as String?,
|
||||
heuresDisponibilite: json['heuresDisponibilite'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'nom': nom,
|
||||
'telephone': telephone,
|
||||
'email': email,
|
||||
'adresse': adresse,
|
||||
'heuresDisponibilite': heuresDisponibilite,
|
||||
};
|
||||
}
|
||||
|
||||
factory ContactProposantModel.fromEntity(ContactProposant entity) {
|
||||
return ContactProposantModel(
|
||||
nom: entity.nom,
|
||||
telephone: entity.telephone,
|
||||
email: entity.email,
|
||||
adresse: entity.adresse,
|
||||
heuresDisponibilite: entity.heuresDisponibilite,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CreneauDisponibiliteModel extends CreneauDisponibilite {
|
||||
const CreneauDisponibiliteModel({
|
||||
required super.jourSemaine,
|
||||
required super.heureDebut,
|
||||
required super.heureFin,
|
||||
super.commentaire,
|
||||
});
|
||||
|
||||
factory CreneauDisponibiliteModel.fromJson(Map<String, dynamic> json) {
|
||||
return CreneauDisponibiliteModel(
|
||||
jourSemaine: json['jourSemaine'] as String,
|
||||
heureDebut: json['heureDebut'] as String,
|
||||
heureFin: json['heureFin'] as String,
|
||||
commentaire: json['commentaire'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'jourSemaine': jourSemaine,
|
||||
'heureDebut': heureDebut,
|
||||
'heureFin': heureFin,
|
||||
'commentaire': commentaire,
|
||||
};
|
||||
}
|
||||
|
||||
factory CreneauDisponibiliteModel.fromEntity(CreneauDisponibilite entity) {
|
||||
return CreneauDisponibiliteModel(
|
||||
jourSemaine: entity.jourSemaine,
|
||||
heureDebut: entity.heureDebut,
|
||||
heureFin: entity.heureFin,
|
||||
commentaire: entity.commentaire,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CritereSelectionModel extends CritereSelection {
|
||||
const CritereSelectionModel({
|
||||
required super.nom,
|
||||
required super.description,
|
||||
required super.obligatoire,
|
||||
super.valeurAttendue,
|
||||
});
|
||||
|
||||
factory CritereSelectionModel.fromJson(Map<String, dynamic> json) {
|
||||
return CritereSelectionModel(
|
||||
nom: json['nom'] as String,
|
||||
description: json['description'] as String,
|
||||
obligatoire: json['obligatoire'] as bool,
|
||||
valeurAttendue: json['valeurAttendue'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'nom': nom,
|
||||
'description': description,
|
||||
'obligatoire': obligatoire,
|
||||
'valeurAttendue': valeurAttendue,
|
||||
};
|
||||
}
|
||||
|
||||
factory CritereSelectionModel.fromEntity(CritereSelection entity) {
|
||||
return CritereSelectionModel(
|
||||
nom: entity.nom,
|
||||
description: entity.description,
|
||||
obligatoire: entity.obligatoire,
|
||||
valeurAttendue: entity.valeurAttendue,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,561 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import '../../../../core/error/failures.dart';
|
||||
import '../../../../core/error/exceptions.dart';
|
||||
import '../../../../core/network/network_info.dart';
|
||||
import '../../domain/entities/demande_aide.dart';
|
||||
import '../../domain/entities/proposition_aide.dart';
|
||||
import '../../domain/entities/evaluation_aide.dart';
|
||||
import '../../domain/repositories/solidarite_repository.dart';
|
||||
import '../datasources/solidarite_remote_data_source.dart';
|
||||
import '../datasources/solidarite_local_data_source.dart';
|
||||
import '../models/demande_aide_model.dart';
|
||||
import '../models/proposition_aide_model.dart';
|
||||
import '../models/evaluation_aide_model.dart';
|
||||
|
||||
/// Implémentation du repository de solidarité
|
||||
///
|
||||
/// Cette classe implémente le contrat défini dans le domaine
|
||||
/// en combinant les sources de données locale et distante.
|
||||
class SolidariteRepositoryImpl implements SolidariteRepository {
|
||||
final SolidariteRemoteDataSource remoteDataSource;
|
||||
final SolidariteLocalDataSource localDataSource;
|
||||
final NetworkInfo networkInfo;
|
||||
|
||||
SolidariteRepositoryImpl({
|
||||
required this.remoteDataSource,
|
||||
required this.localDataSource,
|
||||
required this.networkInfo,
|
||||
});
|
||||
|
||||
// Demandes d'aide
|
||||
@override
|
||||
Future<Either<Failure, DemandeAide>> creerDemandeAide(DemandeAide demande) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final demandeModel = DemandeAideModel.fromEntity(demande);
|
||||
final result = await remoteDataSource.creerDemandeAide(demandeModel);
|
||||
|
||||
// Mettre en cache le résultat
|
||||
await localDataSource.cacherDemandeAide(result);
|
||||
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
// Continuer même si la mise en cache échoue
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, DemandeAide>> mettreAJourDemandeAide(DemandeAide demande) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final demandeModel = DemandeAideModel.fromEntity(demande);
|
||||
final result = await remoteDataSource.mettreAJourDemandeAide(demandeModel);
|
||||
|
||||
// Mettre à jour le cache
|
||||
await localDataSource.cacherDemandeAide(result);
|
||||
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, DemandeAide>> obtenirDemandeAide(String id) async {
|
||||
try {
|
||||
// Essayer d'abord le cache local
|
||||
final cachedDemande = await localDataSource.obtenirDemandeAideCachee(id);
|
||||
if (cachedDemande != null && await _estCacheValide()) {
|
||||
return Right(cachedDemande.toEntity());
|
||||
}
|
||||
|
||||
// Si pas en cache ou cache expiré, aller chercher sur le serveur
|
||||
if (await networkInfo.isConnected) {
|
||||
final result = await remoteDataSource.obtenirDemandeAide(id);
|
||||
|
||||
// Mettre en cache le résultat
|
||||
await localDataSource.cacherDemandeAide(result);
|
||||
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
// Si pas de connexion, utiliser le cache même s'il est expiré
|
||||
if (cachedDemande != null) {
|
||||
return Right(cachedDemande.toEntity());
|
||||
}
|
||||
return Left(NetworkFailure('Aucune connexion internet et aucune donnée en cache'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on NotFoundException catch (e) {
|
||||
return Left(NotFoundFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, DemandeAide>> soumettreDemande(String demandeId) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final result = await remoteDataSource.soumettreDemande(demandeId);
|
||||
|
||||
// Mettre à jour le cache
|
||||
await localDataSource.cacherDemandeAide(result);
|
||||
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, DemandeAide>> evaluerDemande({
|
||||
required String demandeId,
|
||||
required String evaluateurId,
|
||||
required StatutAide decision,
|
||||
String? commentaire,
|
||||
double? montantApprouve,
|
||||
}) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final result = await remoteDataSource.evaluerDemande(
|
||||
demandeId: demandeId,
|
||||
evaluateurId: evaluateurId,
|
||||
decision: decision.name,
|
||||
commentaire: commentaire,
|
||||
montantApprouve: montantApprouve,
|
||||
);
|
||||
|
||||
// Mettre à jour le cache
|
||||
await localDataSource.cacherDemandeAide(result);
|
||||
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, List<DemandeAide>>> rechercherDemandes({
|
||||
String? organisationId,
|
||||
TypeAide? typeAide,
|
||||
StatutAide? statut,
|
||||
String? demandeurId,
|
||||
bool? urgente,
|
||||
int page = 0,
|
||||
int taille = 20,
|
||||
}) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final result = await remoteDataSource.rechercherDemandes(
|
||||
organisationId: organisationId,
|
||||
typeAide: typeAide?.name,
|
||||
statut: statut?.name,
|
||||
demandeurId: demandeurId,
|
||||
urgente: urgente,
|
||||
page: page,
|
||||
taille: taille,
|
||||
);
|
||||
|
||||
// Mettre en cache les résultats
|
||||
for (final demande in result) {
|
||||
await localDataSource.cacherDemandeAide(demande);
|
||||
}
|
||||
|
||||
return Right(result.map((model) => model.toEntity()).toList());
|
||||
} else {
|
||||
// Mode hors ligne : rechercher dans le cache local
|
||||
final cachedDemandes = await localDataSource.obtenirDemandesAideCachees();
|
||||
var filteredDemandes = cachedDemandes.where((demande) {
|
||||
if (organisationId != null && demande.organisationId != organisationId) return false;
|
||||
if (typeAide != null && demande.typeAide != typeAide) return false;
|
||||
if (statut != null && demande.statut != statut) return false;
|
||||
if (demandeurId != null && demande.demandeurId != demandeurId) return false;
|
||||
if (urgente != null && demande.estUrgente != urgente) return false;
|
||||
return true;
|
||||
}).toList();
|
||||
|
||||
// Pagination locale
|
||||
final startIndex = page * taille;
|
||||
final endIndex = (startIndex + taille).clamp(0, filteredDemandes.length);
|
||||
|
||||
if (startIndex < filteredDemandes.length) {
|
||||
filteredDemandes = filteredDemandes.sublist(startIndex, endIndex);
|
||||
} else {
|
||||
filteredDemandes = [];
|
||||
}
|
||||
|
||||
return Right(filteredDemandes.map((model) => model.toEntity()).toList());
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, List<DemandeAide>>> obtenirDemandesUrgentes(String organisationId) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final result = await remoteDataSource.obtenirDemandesUrgentes(organisationId);
|
||||
|
||||
// Mettre en cache les résultats
|
||||
for (final demande in result) {
|
||||
await localDataSource.cacherDemandeAide(demande);
|
||||
}
|
||||
|
||||
return Right(result.map((model) => model.toEntity()).toList());
|
||||
} else {
|
||||
// Mode hors ligne : filtrer le cache local
|
||||
final cachedDemandes = await localDataSource.obtenirDemandesAideCachees();
|
||||
final demandesUrgentes = cachedDemandes
|
||||
.where((demande) => demande.organisationId == organisationId && demande.estUrgente)
|
||||
.toList();
|
||||
|
||||
return Right(demandesUrgentes.map((model) => model.toEntity()).toList());
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, List<DemandeAide>>> obtenirMesdemandes(String utilisateurId) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final result = await remoteDataSource.obtenirMesdemandes(utilisateurId);
|
||||
|
||||
// Mettre en cache les résultats
|
||||
for (final demande in result) {
|
||||
await localDataSource.cacherDemandeAide(demande);
|
||||
}
|
||||
|
||||
return Right(result.map((model) => model.toEntity()).toList());
|
||||
} else {
|
||||
// Mode hors ligne : filtrer le cache local
|
||||
final cachedDemandes = await localDataSource.obtenirDemandesAideCachees();
|
||||
final mesdemandes = cachedDemandes
|
||||
.where((demande) => demande.demandeurId == utilisateurId)
|
||||
.toList();
|
||||
|
||||
return Right(mesdemandes.map((model) => model.toEntity()).toList());
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
// Propositions d'aide
|
||||
@override
|
||||
Future<Either<Failure, PropositionAide>> creerPropositionAide(PropositionAide proposition) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final propositionModel = PropositionAideModel.fromEntity(proposition);
|
||||
final result = await remoteDataSource.creerPropositionAide(propositionModel);
|
||||
|
||||
// Mettre en cache le résultat
|
||||
await localDataSource.cacherPropositionAide(result);
|
||||
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, PropositionAide>> mettreAJourPropositionAide(PropositionAide proposition) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final propositionModel = PropositionAideModel.fromEntity(proposition);
|
||||
final result = await remoteDataSource.mettreAJourPropositionAide(propositionModel);
|
||||
|
||||
// Mettre à jour le cache
|
||||
await localDataSource.cacherPropositionAide(result);
|
||||
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, PropositionAide>> obtenirPropositionAide(String id) async {
|
||||
try {
|
||||
// Essayer d'abord le cache local
|
||||
final cachedProposition = await localDataSource.obtenirPropositionAideCachee(id);
|
||||
if (cachedProposition != null && await _estCacheValide()) {
|
||||
return Right(cachedProposition.toEntity());
|
||||
}
|
||||
|
||||
// Si pas en cache ou cache expiré, aller chercher sur le serveur
|
||||
if (await networkInfo.isConnected) {
|
||||
final result = await remoteDataSource.obtenirPropositionAide(id);
|
||||
|
||||
// Mettre en cache le résultat
|
||||
await localDataSource.cacherPropositionAide(result);
|
||||
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
// Si pas de connexion, utiliser le cache même s'il est expiré
|
||||
if (cachedProposition != null) {
|
||||
return Right(cachedProposition.toEntity());
|
||||
}
|
||||
return Left(NetworkFailure('Aucune connexion internet et aucune donnée en cache'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on NotFoundException catch (e) {
|
||||
return Left(NotFoundFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, PropositionAide>> changerStatutProposition({
|
||||
required String propositionId,
|
||||
required bool activer,
|
||||
}) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final result = await remoteDataSource.changerStatutProposition(
|
||||
propositionId: propositionId,
|
||||
activer: activer,
|
||||
);
|
||||
|
||||
// Mettre à jour le cache
|
||||
await localDataSource.cacherPropositionAide(result);
|
||||
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, List<PropositionAide>>> rechercherPropositions({
|
||||
String? organisationId,
|
||||
TypeAide? typeAide,
|
||||
String? proposantId,
|
||||
bool? actives,
|
||||
int page = 0,
|
||||
int taille = 20,
|
||||
}) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final result = await remoteDataSource.rechercherPropositions(
|
||||
organisationId: organisationId,
|
||||
typeAide: typeAide?.name,
|
||||
proposantId: proposantId,
|
||||
actives: actives,
|
||||
page: page,
|
||||
taille: taille,
|
||||
);
|
||||
|
||||
// Mettre en cache les résultats
|
||||
for (final proposition in result) {
|
||||
await localDataSource.cacherPropositionAide(proposition);
|
||||
}
|
||||
|
||||
return Right(result.map((model) => model.toEntity()).toList());
|
||||
} else {
|
||||
// Mode hors ligne : rechercher dans le cache local
|
||||
final cachedPropositions = await localDataSource.obtenirPropositionsAideCachees();
|
||||
var filteredPropositions = cachedPropositions.where((proposition) {
|
||||
if (organisationId != null && proposition.organisationId != organisationId) return false;
|
||||
if (typeAide != null && proposition.typeAide != typeAide) return false;
|
||||
if (proposantId != null && proposition.proposantId != proposantId) return false;
|
||||
if (actives != null && proposition.isActiveEtDisponible != actives) return false;
|
||||
return true;
|
||||
}).toList();
|
||||
|
||||
// Pagination locale
|
||||
final startIndex = page * taille;
|
||||
final endIndex = (startIndex + taille).clamp(0, filteredPropositions.length);
|
||||
|
||||
if (startIndex < filteredPropositions.length) {
|
||||
filteredPropositions = filteredPropositions.sublist(startIndex, endIndex);
|
||||
} else {
|
||||
filteredPropositions = [];
|
||||
}
|
||||
|
||||
return Right(filteredPropositions.map((model) => model.toEntity()).toList());
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, List<PropositionAide>>> obtenirPropositionsActives(TypeAide typeAide) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final result = await remoteDataSource.obtenirPropositionsActives(typeAide.name);
|
||||
|
||||
// Mettre en cache les résultats
|
||||
for (final proposition in result) {
|
||||
await localDataSource.cacherPropositionAide(proposition);
|
||||
}
|
||||
|
||||
return Right(result.map((model) => model.toEntity()).toList());
|
||||
} else {
|
||||
// Mode hors ligne : filtrer le cache local
|
||||
final cachedPropositions = await localDataSource.obtenirPropositionsAideCachees();
|
||||
final propositionsActives = cachedPropositions
|
||||
.where((proposition) => proposition.typeAide == typeAide && proposition.isActiveEtDisponible)
|
||||
.toList();
|
||||
|
||||
return Right(propositionsActives.map((model) => model.toEntity()).toList());
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, List<PropositionAide>>> obtenirMeilleuresPropositions(int limite) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final result = await remoteDataSource.obtenirMeilleuresPropositions(limite);
|
||||
|
||||
// Mettre en cache les résultats
|
||||
for (final proposition in result) {
|
||||
await localDataSource.cacherPropositionAide(proposition);
|
||||
}
|
||||
|
||||
return Right(result.map((model) => model.toEntity()).toList());
|
||||
} else {
|
||||
// Mode hors ligne : trier le cache local par note moyenne
|
||||
final cachedPropositions = await localDataSource.obtenirPropositionsAideCachees();
|
||||
cachedPropositions.sort((a, b) {
|
||||
final noteA = a.noteMoyenne ?? 0.0;
|
||||
final noteB = b.noteMoyenne ?? 0.0;
|
||||
return noteB.compareTo(noteA);
|
||||
});
|
||||
|
||||
final meilleuresPropositions = cachedPropositions.take(limite).toList();
|
||||
return Right(meilleuresPropositions.map((model) => model.toEntity()).toList());
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, List<PropositionAide>>> obtenirMesPropositions(String utilisateurId) async {
|
||||
try {
|
||||
if (await networkInfo.isConnected) {
|
||||
final result = await remoteDataSource.obtenirMesPropositions(utilisateurId);
|
||||
|
||||
// Mettre en cache les résultats
|
||||
for (final proposition in result) {
|
||||
await localDataSource.cacherPropositionAide(proposition);
|
||||
}
|
||||
|
||||
return Right(result.map((model) => model.toEntity()).toList());
|
||||
} else {
|
||||
// Mode hors ligne : filtrer le cache local
|
||||
final cachedPropositions = await localDataSource.obtenirPropositionsAideCachees();
|
||||
final mesPropositions = cachedPropositions
|
||||
.where((proposition) => proposition.proposantId == utilisateurId)
|
||||
.toList();
|
||||
|
||||
return Right(mesPropositions.map((model) => model.toEntity()).toList());
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
// Méthodes utilitaires privées
|
||||
Future<bool> _estCacheValide() async {
|
||||
try {
|
||||
final localDataSourceImpl = localDataSource as SolidariteLocalDataSourceImpl;
|
||||
return await localDataSourceImpl.estCacheDemandesValide() &&
|
||||
await localDataSourceImpl.estCachePropositionsValide();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
// Partie 2 de l'implémentation du repository de solidarité
|
||||
// Cette partie contient les méthodes pour le matching, les évaluations et les statistiques
|
||||
|
||||
import 'package:dartz/dartz.dart';
|
||||
import '../../../../core/error/failures.dart';
|
||||
import '../../../../core/error/exceptions.dart';
|
||||
import '../../domain/entities/demande_aide.dart';
|
||||
import '../../domain/entities/proposition_aide.dart';
|
||||
import '../../domain/entities/evaluation_aide.dart';
|
||||
import '../datasources/solidarite_remote_data_source.dart';
|
||||
import '../datasources/solidarite_local_data_source.dart';
|
||||
import '../models/demande_aide_model.dart';
|
||||
import '../models/proposition_aide_model.dart';
|
||||
import '../models/evaluation_aide_model.dart';
|
||||
|
||||
/// Extension de l'implémentation du repository de solidarité
|
||||
/// Cette partie sera intégrée dans la classe principale
|
||||
mixin SolidariteRepositoryImplPart2 {
|
||||
SolidariteRemoteDataSource get remoteDataSource;
|
||||
SolidariteLocalDataSource get localDataSource;
|
||||
bool Function() get isConnected;
|
||||
|
||||
// Matching
|
||||
Future<Either<Failure, List<PropositionAide>>> trouverPropositionsCompatibles(String demandeId) async {
|
||||
try {
|
||||
if (await isConnected()) {
|
||||
final result = await remoteDataSource.trouverPropositionsCompatibles(demandeId);
|
||||
|
||||
// Mettre en cache les résultats
|
||||
for (final proposition in result) {
|
||||
await localDataSource.cacherPropositionAide(proposition);
|
||||
}
|
||||
|
||||
return Right(result.map((model) => model.toEntity()).toList());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<Failure, List<DemandeAide>>> trouverDemandesCompatibles(String propositionId) async {
|
||||
try {
|
||||
if (await isConnected()) {
|
||||
final result = await remoteDataSource.trouverDemandesCompatibles(propositionId);
|
||||
|
||||
// Mettre en cache les résultats
|
||||
for (final demande in result) {
|
||||
await localDataSource.cacherDemandeAide(demande);
|
||||
}
|
||||
|
||||
return Right(result.map((model) => model.toEntity()).toList());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<Failure, List<PropositionAide>>> rechercherProposantsFinanciers(String demandeId) async {
|
||||
try {
|
||||
if (await isConnected()) {
|
||||
final result = await remoteDataSource.rechercherProposantsFinanciers(demandeId);
|
||||
|
||||
// Mettre en cache les résultats
|
||||
for (final proposition in result) {
|
||||
await localDataSource.cacherPropositionAide(proposition);
|
||||
}
|
||||
|
||||
return Right(result.map((model) => model.toEntity()).toList());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
// Évaluations
|
||||
Future<Either<Failure, EvaluationAide>> creerEvaluation(EvaluationAide evaluation) async {
|
||||
try {
|
||||
if (await isConnected()) {
|
||||
final evaluationModel = EvaluationAideModel.fromEntity(evaluation);
|
||||
final result = await remoteDataSource.creerEvaluation(evaluationModel);
|
||||
|
||||
// Mettre en cache le résultat
|
||||
await localDataSource.cacherEvaluation(result);
|
||||
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<Failure, EvaluationAide>> mettreAJourEvaluation(EvaluationAide evaluation) async {
|
||||
try {
|
||||
if (await isConnected()) {
|
||||
final evaluationModel = EvaluationAideModel.fromEntity(evaluation);
|
||||
final result = await remoteDataSource.mettreAJourEvaluation(evaluationModel);
|
||||
|
||||
// Mettre à jour le cache
|
||||
await localDataSource.cacherEvaluation(result);
|
||||
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<Failure, EvaluationAide>> obtenirEvaluation(String id) async {
|
||||
try {
|
||||
// Essayer d'abord le cache local
|
||||
final cachedEvaluation = await localDataSource.obtenirEvaluationCachee(id);
|
||||
if (cachedEvaluation != null && await _estCacheEvaluationsValide()) {
|
||||
return Right(cachedEvaluation.toEntity());
|
||||
}
|
||||
|
||||
// Si pas en cache ou cache expiré, aller chercher sur le serveur
|
||||
if (await isConnected()) {
|
||||
final result = await remoteDataSource.obtenirEvaluation(id);
|
||||
|
||||
// Mettre en cache le résultat
|
||||
await localDataSource.cacherEvaluation(result);
|
||||
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
// Si pas de connexion, utiliser le cache même s'il est expiré
|
||||
if (cachedEvaluation != null) {
|
||||
return Right(cachedEvaluation.toEntity());
|
||||
}
|
||||
return Left(NetworkFailure('Aucune connexion internet et aucune donnée en cache'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on NotFoundException catch (e) {
|
||||
return Left(NotFoundFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<Failure, List<EvaluationAide>>> obtenirEvaluationsDemande(String demandeId) async {
|
||||
try {
|
||||
if (await isConnected()) {
|
||||
final result = await remoteDataSource.obtenirEvaluationsDemande(demandeId);
|
||||
|
||||
// Mettre en cache les résultats
|
||||
for (final evaluation in result) {
|
||||
await localDataSource.cacherEvaluation(evaluation);
|
||||
}
|
||||
|
||||
return Right(result.map((model) => model.toEntity()).toList());
|
||||
} else {
|
||||
// Mode hors ligne : filtrer le cache local
|
||||
final cachedEvaluations = await localDataSource.obtenirEvaluationsCachees();
|
||||
final evaluationsDemande = cachedEvaluations
|
||||
.where((evaluation) => evaluation.demandeId == demandeId)
|
||||
.toList();
|
||||
|
||||
return Right(evaluationsDemande.map((model) => model.toEntity()).toList());
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<Failure, List<EvaluationAide>>> obtenirEvaluationsProposition(String propositionId) async {
|
||||
try {
|
||||
if (await isConnected()) {
|
||||
final result = await remoteDataSource.obtenirEvaluationsProposition(propositionId);
|
||||
|
||||
// Mettre en cache les résultats
|
||||
for (final evaluation in result) {
|
||||
await localDataSource.cacherEvaluation(evaluation);
|
||||
}
|
||||
|
||||
return Right(result.map((model) => model.toEntity()).toList());
|
||||
} else {
|
||||
// Mode hors ligne : filtrer le cache local
|
||||
final cachedEvaluations = await localDataSource.obtenirEvaluationsCachees();
|
||||
final evaluationsProposition = cachedEvaluations
|
||||
.where((evaluation) => evaluation.propositionId == propositionId)
|
||||
.toList();
|
||||
|
||||
return Right(evaluationsProposition.map((model) => model.toEntity()).toList());
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<Failure, EvaluationAide>> signalerEvaluation({
|
||||
required String evaluationId,
|
||||
required String motif,
|
||||
}) async {
|
||||
try {
|
||||
if (await isConnected()) {
|
||||
final result = await remoteDataSource.signalerEvaluation(
|
||||
evaluationId: evaluationId,
|
||||
motif: motif,
|
||||
);
|
||||
|
||||
// Mettre à jour le cache
|
||||
await localDataSource.cacherEvaluation(result);
|
||||
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<Failure, StatistiquesEvaluation>> calculerMoyenneDemande(String demandeId) async {
|
||||
try {
|
||||
if (await isConnected()) {
|
||||
final result = await remoteDataSource.calculerMoyenneDemande(demandeId);
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<Either<Failure, StatistiquesEvaluation>> calculerMoyenneProposition(String propositionId) async {
|
||||
try {
|
||||
if (await isConnected()) {
|
||||
final result = await remoteDataSource.calculerMoyenneProposition(propositionId);
|
||||
return Right(result.toEntity());
|
||||
} else {
|
||||
return Left(NetworkFailure('Aucune connexion internet disponible'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
// Statistiques
|
||||
Future<Either<Failure, Map<String, dynamic>>> obtenirStatistiquesSolidarite(String organisationId) async {
|
||||
try {
|
||||
// Essayer d'abord le cache local
|
||||
final cachedStats = await localDataSource.obtenirStatistiquesCachees(organisationId);
|
||||
if (cachedStats != null && await _estCacheStatistiquesValide(organisationId)) {
|
||||
return Right(cachedStats);
|
||||
}
|
||||
|
||||
// Si pas en cache ou cache expiré, aller chercher sur le serveur
|
||||
if (await isConnected()) {
|
||||
final result = await remoteDataSource.obtenirStatistiquesSolidarite(organisationId);
|
||||
|
||||
// Mettre en cache le résultat
|
||||
await localDataSource.cacherStatistiques(organisationId, result);
|
||||
|
||||
return Right(result);
|
||||
} else {
|
||||
// Si pas de connexion, utiliser le cache même s'il est expiré
|
||||
if (cachedStats != null) {
|
||||
return Right(cachedStats);
|
||||
}
|
||||
return Left(NetworkFailure('Aucune connexion internet et aucune donnée en cache'));
|
||||
}
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on CacheException catch (e) {
|
||||
return Left(CacheFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(UnexpectedFailure(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
// Méthodes utilitaires privées
|
||||
Future<bool> _estCacheEvaluationsValide() async {
|
||||
try {
|
||||
final localDataSourceImpl = localDataSource as SolidariteLocalDataSourceImpl;
|
||||
return await localDataSourceImpl.estCacheEvaluationsValide();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> _estCacheStatistiquesValide(String organisationId) async {
|
||||
try {
|
||||
final localDataSourceImpl = localDataSource as SolidariteLocalDataSourceImpl;
|
||||
return await localDataSourceImpl.estCacheStatistiquesValide(organisationId);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user