Refactoring

This commit is contained in:
DahoudG
2025-09-17 17:54:06 +00:00
parent 12d514d866
commit 63fe107f98
165 changed files with 54220 additions and 276 deletions

View File

@@ -0,0 +1,481 @@
import 'package:equatable/equatable.dart';
/// Entité représentant une demande d'aide dans le système de solidarité
///
/// Cette entité encapsule toutes les informations relatives à une demande d'aide,
/// incluant les détails du demandeur, le type d'aide, les montants et le statut.
class DemandeAide extends Equatable {
/// Identifiant unique de la demande
final String id;
/// Numéro de référence unique (format: DA-YYYY-NNNNNN)
final String numeroReference;
/// Titre de la demande d'aide
final String titre;
/// Description détaillée de la demande
final String description;
/// Type d'aide demandée
final TypeAide typeAide;
/// Statut actuel de la demande
final StatutAide statut;
/// Priorité de la demande
final PrioriteAide priorite;
/// Identifiant du demandeur
final String demandeurId;
/// Nom complet du demandeur
final String nomDemandeur;
/// Identifiant de l'organisation
final String organisationId;
/// Montant demandé (si applicable)
final double? montantDemande;
/// Montant approuvé (si applicable)
final double? montantApprouve;
/// Montant versé (si applicable)
final double? montantVerse;
/// Date de création de la demande
final DateTime dateCreation;
/// Date de modification
final DateTime dateModification;
/// Date de soumission
final DateTime? dateSoumission;
/// Date d'évaluation
final DateTime? dateEvaluation;
/// Date d'approbation
final DateTime? dateApprobation;
/// Date limite de traitement
final DateTime? dateLimiteTraitement;
/// Identifiant de l'évaluateur assigné
final String? evaluateurId;
/// Commentaires de l'évaluateur
final String? commentairesEvaluateur;
/// Motif de rejet (si applicable)
final String? motifRejet;
/// Informations complémentaires requises
final String? informationsRequises;
/// Justification de l'urgence
final String? justificationUrgence;
/// Contact d'urgence
final ContactUrgence? contactUrgence;
/// Localisation du demandeur
final Localisation? localisation;
/// Liste des bénéficiaires
final List<BeneficiaireAide> beneficiaires;
/// Liste des pièces justificatives
final List<PieceJustificative> piecesJustificatives;
/// Historique des changements de statut
final List<HistoriqueStatut> historiqueStatuts;
/// Commentaires et échanges
final List<CommentaireAide> commentaires;
/// Données personnalisées
final Map<String, dynamic> donneesPersonnalisees;
/// Indique si la demande est modifiable
final bool estModifiable;
/// Indique si la demande est urgente
final bool estUrgente;
/// Indique si le délai est dépassé
final bool delaiDepasse;
/// Indique si la demande est terminée
final bool estTerminee;
const DemandeAide({
required this.id,
required this.numeroReference,
required this.titre,
required this.description,
required this.typeAide,
required this.statut,
required this.priorite,
required this.demandeurId,
required this.nomDemandeur,
required this.organisationId,
this.montantDemande,
this.montantApprouve,
this.montantVerse,
required this.dateCreation,
required this.dateModification,
this.dateSoumission,
this.dateEvaluation,
this.dateApprobation,
this.dateLimiteTraitement,
this.evaluateurId,
this.commentairesEvaluateur,
this.motifRejet,
this.informationsRequises,
this.justificationUrgence,
this.contactUrgence,
this.localisation,
this.beneficiaires = const [],
this.piecesJustificatives = const [],
this.historiqueStatuts = const [],
this.commentaires = const [],
this.donneesPersonnalisees = const {},
this.estModifiable = false,
this.estUrgente = false,
this.delaiDepasse = false,
this.estTerminee = false,
});
/// Calcule le pourcentage d'avancement de la demande
double get pourcentageAvancement {
return statut.pourcentageAvancement;
}
/// Calcule le délai restant en heures
int? get delaiRestantHeures {
if (dateLimiteTraitement == null) return null;
final maintenant = DateTime.now();
if (maintenant.isAfter(dateLimiteTraitement!)) return 0;
return dateLimiteTraitement!.difference(maintenant).inHours;
}
/// Calcule la durée de traitement en jours
int get dureeTraitementJours {
if (dateSoumission == null) return 0;
final dateFin = dateEvaluation ?? DateTime.now();
return dateFin.difference(dateSoumission!).inDays;
}
/// Indique si la demande nécessite une action urgente
bool get necessiteActionUrgente {
return estUrgente || delaiDepasse || priorite == PrioriteAide.critique;
}
/// Obtient la couleur associée au statut
String get couleurStatut => statut.couleur;
/// Obtient l'icône associée au type d'aide
String get iconeTypeAide => typeAide.icone;
@override
List<Object?> get props => [
id,
numeroReference,
titre,
description,
typeAide,
statut,
priorite,
demandeurId,
nomDemandeur,
organisationId,
montantDemande,
montantApprouve,
montantVerse,
dateCreation,
dateModification,
dateSoumission,
dateEvaluation,
dateApprobation,
dateLimiteTraitement,
evaluateurId,
commentairesEvaluateur,
motifRejet,
informationsRequises,
justificationUrgence,
contactUrgence,
localisation,
beneficiaires,
piecesJustificatives,
historiqueStatuts,
commentaires,
donneesPersonnalisees,
estModifiable,
estUrgente,
delaiDepasse,
estTerminee,
];
DemandeAide copyWith({
String? id,
String? numeroReference,
String? titre,
String? description,
TypeAide? typeAide,
StatutAide? statut,
PrioriteAide? priorite,
String? demandeurId,
String? nomDemandeur,
String? organisationId,
double? montantDemande,
double? montantApprouve,
double? montantVerse,
DateTime? dateCreation,
DateTime? dateModification,
DateTime? dateSoumission,
DateTime? dateEvaluation,
DateTime? dateApprobation,
DateTime? dateLimiteTraitement,
String? evaluateurId,
String? commentairesEvaluateur,
String? motifRejet,
String? informationsRequises,
String? justificationUrgence,
ContactUrgence? contactUrgence,
Localisation? localisation,
List<BeneficiaireAide>? beneficiaires,
List<PieceJustificative>? piecesJustificatives,
List<HistoriqueStatut>? historiqueStatuts,
List<CommentaireAide>? commentaires,
Map<String, dynamic>? donneesPersonnalisees,
bool? estModifiable,
bool? estUrgente,
bool? delaiDepasse,
bool? estTerminee,
}) {
return DemandeAide(
id: id ?? this.id,
numeroReference: numeroReference ?? this.numeroReference,
titre: titre ?? this.titre,
description: description ?? this.description,
typeAide: typeAide ?? this.typeAide,
statut: statut ?? this.statut,
priorite: priorite ?? this.priorite,
demandeurId: demandeurId ?? this.demandeurId,
nomDemandeur: nomDemandeur ?? this.nomDemandeur,
organisationId: organisationId ?? this.organisationId,
montantDemande: montantDemande ?? this.montantDemande,
montantApprouve: montantApprouve ?? this.montantApprouve,
montantVerse: montantVerse ?? this.montantVerse,
dateCreation: dateCreation ?? this.dateCreation,
dateModification: dateModification ?? this.dateModification,
dateSoumission: dateSoumission ?? this.dateSoumission,
dateEvaluation: dateEvaluation ?? this.dateEvaluation,
dateApprobation: dateApprobation ?? this.dateApprobation,
dateLimiteTraitement: dateLimiteTraitement ?? this.dateLimiteTraitement,
evaluateurId: evaluateurId ?? this.evaluateurId,
commentairesEvaluateur: commentairesEvaluateur ?? this.commentairesEvaluateur,
motifRejet: motifRejet ?? this.motifRejet,
informationsRequises: informationsRequises ?? this.informationsRequises,
justificationUrgence: justificationUrgence ?? this.justificationUrgence,
contactUrgence: contactUrgence ?? this.contactUrgence,
localisation: localisation ?? this.localisation,
beneficiaires: beneficiaires ?? this.beneficiaires,
piecesJustificatives: piecesJustificatives ?? this.piecesJustificatives,
historiqueStatuts: historiqueStatuts ?? this.historiqueStatuts,
commentaires: commentaires ?? this.commentaires,
donneesPersonnalisees: donneesPersonnalisees ?? this.donneesPersonnalisees,
estModifiable: estModifiable ?? this.estModifiable,
estUrgente: estUrgente ?? this.estUrgente,
delaiDepasse: delaiDepasse ?? this.delaiDepasse,
estTerminee: estTerminee ?? this.estTerminee,
);
}
}
/// Énumération des types d'aide disponibles
enum TypeAide {
aideFinanciereUrgente('Aide financière urgente', 'emergency_fund', '#F44336'),
aideFinanciereMedicale('Aide financière médicale', 'medical_services', '#2196F3'),
aideFinanciereEducation('Aide financière éducation', 'school', '#4CAF50'),
aideMaterielleVetements('Aide matérielle vêtements', 'checkroom', '#FF9800'),
aideMaterielleNourriture('Aide matérielle nourriture', 'restaurant', '#795548'),
aideProfessionnelleFormation('Aide professionnelle formation', 'work', '#9C27B0'),
aideSocialeAccompagnement('Aide sociale accompagnement', 'support', '#607D8B'),
autre('Autre', 'help', '#9E9E9E');
const TypeAide(this.libelle, this.icone, this.couleur);
final String libelle;
final String icone;
final String couleur;
}
/// Énumération des statuts de demande d'aide
enum StatutAide {
brouillon('Brouillon', 'draft', '#9E9E9E', 5.0),
soumise('Soumise', 'send', '#2196F3', 10.0),
enAttente('En attente', 'schedule', '#FF9800', 20.0),
enCoursEvaluation('En cours d\'évaluation', 'assessment', '#9C27B0', 40.0),
approuvee('Approuvée', 'check_circle', '#4CAF50', 70.0),
approuveePartiellement('Approuvée partiellement', 'check_circle_outline', '#8BC34A', 70.0),
rejetee('Rejetée', 'cancel', '#F44336', 100.0),
informationsRequises('Informations requises', 'info', '#FF5722', 30.0),
enCoursVersement('En cours de versement', 'payment', '#00BCD4', 85.0),
versee('Versée', 'paid', '#4CAF50', 100.0),
livree('Livrée', 'local_shipping', '#4CAF50', 100.0),
terminee('Terminée', 'done_all', '#4CAF50', 100.0),
cloturee('Clôturée', 'archive', '#607D8B', 100.0);
const StatutAide(this.libelle, this.icone, this.couleur, this.pourcentageAvancement);
final String libelle;
final String icone;
final String couleur;
final double pourcentageAvancement;
}
/// Énumération des priorités de demande d'aide
enum PrioriteAide {
critique('Critique', '#F44336', 1, 24),
urgente('Urgente', '#FF5722', 2, 72),
elevee('Élevée', '#FF9800', 3, 168),
normale('Normale', '#4CAF50', 4, 336),
faible('Faible', '#9E9E9E', 5, 720);
const PrioriteAide(this.libelle, this.couleur, this.niveau, this.delaiTraitementHeures);
final String libelle;
final String couleur;
final int niveau;
final int delaiTraitementHeures;
}
/// Classe représentant un contact d'urgence
class ContactUrgence extends Equatable {
final String nom;
final String telephone;
final String? email;
final String relation;
const ContactUrgence({
required this.nom,
required this.telephone,
this.email,
required this.relation,
});
@override
List<Object?> get props => [nom, telephone, email, relation];
}
/// Classe représentant une localisation
class Localisation extends Equatable {
final String adresse;
final String ville;
final String? codePostal;
final String? pays;
final double? latitude;
final double? longitude;
const Localisation({
required this.adresse,
required this.ville,
this.codePostal,
this.pays,
this.latitude,
this.longitude,
});
@override
List<Object?> get props => [adresse, ville, codePostal, pays, latitude, longitude];
}
/// Classe représentant un bénéficiaire d'aide
class BeneficiaireAide extends Equatable {
final String nom;
final String prenom;
final int age;
final String relation;
final String? telephone;
const BeneficiaireAide({
required this.nom,
required this.prenom,
required this.age,
required this.relation,
this.telephone,
});
@override
List<Object?> get props => [nom, prenom, age, relation, telephone];
}
/// Classe représentant une pièce justificative
class PieceJustificative extends Equatable {
final String id;
final String nom;
final String type;
final String url;
final int taille;
final DateTime dateAjout;
const PieceJustificative({
required this.id,
required this.nom,
required this.type,
required this.url,
required this.taille,
required this.dateAjout,
});
@override
List<Object?> get props => [id, nom, type, url, taille, dateAjout];
}
/// Classe représentant l'historique des statuts
class HistoriqueStatut extends Equatable {
final StatutAide ancienStatut;
final StatutAide nouveauStatut;
final DateTime dateChangement;
final String? commentaire;
final String? utilisateurId;
const HistoriqueStatut({
required this.ancienStatut,
required this.nouveauStatut,
required this.dateChangement,
this.commentaire,
this.utilisateurId,
});
@override
List<Object?> get props => [ancienStatut, nouveauStatut, dateChangement, commentaire, utilisateurId];
}
/// Classe représentant un commentaire sur une demande
class CommentaireAide extends Equatable {
final String id;
final String contenu;
final String auteurId;
final String nomAuteur;
final DateTime dateCreation;
final bool estPrive;
const CommentaireAide({
required this.id,
required this.contenu,
required this.auteurId,
required this.nomAuteur,
required this.dateCreation,
this.estPrive = false,
});
@override
List<Object?> get props => [id, contenu, auteurId, nomAuteur, dateCreation, estPrive];
}

View File

@@ -0,0 +1,303 @@
import 'package:equatable/equatable.dart';
/// Entité représentant une évaluation d'aide dans le système de solidarité
///
/// Cette entité encapsule toutes les informations relatives à l'évaluation
/// d'une demande d'aide ou d'une proposition d'aide.
class EvaluationAide extends Equatable {
/// Identifiant unique de l'évaluation
final String id;
/// Identifiant de la demande d'aide évaluée
final String demandeAideId;
/// Identifiant de la proposition d'aide (si applicable)
final String? propositionAideId;
/// Identifiant de l'évaluateur
final String evaluateurId;
/// Nom de l'évaluateur
final String nomEvaluateur;
/// Type d'évaluateur
final TypeEvaluateur typeEvaluateur;
/// Note globale (1 à 5)
final double noteGlobale;
/// Note pour le délai de réponse
final double? noteDelaiReponse;
/// Note pour la communication
final double? noteCommunication;
/// Note pour le professionnalisme
final double? noteProfessionnalisme;
/// Note pour le respect des engagements
final double? noteRespectEngagements;
/// Notes détaillées par critère
final Map<String, double> notesDetaillees;
/// Commentaire principal
final String commentairePrincipal;
/// Points positifs
final String? pointsPositifs;
/// Points d'amélioration
final String? pointsAmelioration;
/// Recommandations
final String? recommandations;
/// Indique si l'évaluateur recommande cette aide
final bool? recommande;
/// Date de création de l'évaluation
final DateTime dateCreation;
/// Date de modification
final DateTime dateModification;
/// Date de vérification (si applicable)
final DateTime? dateVerification;
/// Identifiant du vérificateur
final String? verificateurId;
/// Statut de l'évaluation
final StatutEvaluation statut;
/// Nombre de signalements reçus
final int nombreSignalements;
/// Score de qualité calculé automatiquement
final double scoreQualite;
/// Indique si l'évaluation a été modifiée
final bool estModifie;
/// Indique si l'évaluation est vérifiée
final bool estVerifiee;
/// Données personnalisées
final Map<String, dynamic> donneesPersonnalisees;
const EvaluationAide({
required this.id,
required this.demandeAideId,
this.propositionAideId,
required this.evaluateurId,
required this.nomEvaluateur,
required this.typeEvaluateur,
required this.noteGlobale,
this.noteDelaiReponse,
this.noteCommunication,
this.noteProfessionnalisme,
this.noteRespectEngagements,
this.notesDetaillees = const {},
required this.commentairePrincipal,
this.pointsPositifs,
this.pointsAmelioration,
this.recommandations,
this.recommande,
required this.dateCreation,
required this.dateModification,
this.dateVerification,
this.verificateurId,
this.statut = StatutEvaluation.active,
this.nombreSignalements = 0,
required this.scoreQualite,
this.estModifie = false,
this.estVerifiee = false,
this.donneesPersonnalisees = const {},
});
/// Calcule la note moyenne des critères détaillés
double get noteMoyenneDetaillees {
if (notesDetaillees.isEmpty) return noteGlobale;
double somme = notesDetaillees.values.fold(0.0, (a, b) => a + b);
return somme / notesDetaillees.length;
}
/// Indique si l'évaluation est positive (note >= 4)
bool get estPositive => noteGlobale >= 4.0;
/// Indique si l'évaluation est négative (note <= 2)
bool get estNegative => noteGlobale <= 2.0;
/// Obtient le niveau de satisfaction textuel
String get niveauSatisfaction {
if (noteGlobale >= 4.5) return 'Excellent';
if (noteGlobale >= 4.0) return 'Très bien';
if (noteGlobale >= 3.0) return 'Bien';
if (noteGlobale >= 2.0) return 'Moyen';
return 'Insuffisant';
}
/// Obtient la couleur associée à la note
String get couleurNote {
if (noteGlobale >= 4.0) return '#4CAF50'; // Vert
if (noteGlobale >= 3.0) return '#FF9800'; // Orange
return '#F44336'; // Rouge
}
/// Indique si l'évaluation peut être modifiée
bool get peutEtreModifiee {
return statut == StatutEvaluation.active &&
!estVerifiee &&
nombreSignalements < 3;
}
@override
List<Object?> get props => [
id,
demandeAideId,
propositionAideId,
evaluateurId,
nomEvaluateur,
typeEvaluateur,
noteGlobale,
noteDelaiReponse,
noteCommunication,
noteProfessionnalisme,
noteRespectEngagements,
notesDetaillees,
commentairePrincipal,
pointsPositifs,
pointsAmelioration,
recommandations,
recommande,
dateCreation,
dateModification,
dateVerification,
verificateurId,
statut,
nombreSignalements,
scoreQualite,
estModifie,
estVerifiee,
donneesPersonnalisees,
];
EvaluationAide copyWith({
String? id,
String? demandeAideId,
String? propositionAideId,
String? evaluateurId,
String? nomEvaluateur,
TypeEvaluateur? typeEvaluateur,
double? noteGlobale,
double? noteDelaiReponse,
double? noteCommunication,
double? noteProfessionnalisme,
double? noteRespectEngagements,
Map<String, double>? notesDetaillees,
String? commentairePrincipal,
String? pointsPositifs,
String? pointsAmelioration,
String? recommandations,
bool? recommande,
DateTime? dateCreation,
DateTime? dateModification,
DateTime? dateVerification,
String? verificateurId,
StatutEvaluation? statut,
int? nombreSignalements,
double? scoreQualite,
bool? estModifie,
bool? estVerifiee,
Map<String, dynamic>? donneesPersonnalisees,
}) {
return EvaluationAide(
id: id ?? this.id,
demandeAideId: demandeAideId ?? this.demandeAideId,
propositionAideId: propositionAideId ?? this.propositionAideId,
evaluateurId: evaluateurId ?? this.evaluateurId,
nomEvaluateur: nomEvaluateur ?? this.nomEvaluateur,
typeEvaluateur: typeEvaluateur ?? this.typeEvaluateur,
noteGlobale: noteGlobale ?? this.noteGlobale,
noteDelaiReponse: noteDelaiReponse ?? this.noteDelaiReponse,
noteCommunication: noteCommunication ?? this.noteCommunication,
noteProfessionnalisme: noteProfessionnalisme ?? this.noteProfessionnalisme,
noteRespectEngagements: noteRespectEngagements ?? this.noteRespectEngagements,
notesDetaillees: notesDetaillees ?? this.notesDetaillees,
commentairePrincipal: commentairePrincipal ?? this.commentairePrincipal,
pointsPositifs: pointsPositifs ?? this.pointsPositifs,
pointsAmelioration: pointsAmelioration ?? this.pointsAmelioration,
recommandations: recommandations ?? this.recommandations,
recommande: recommande ?? this.recommande,
dateCreation: dateCreation ?? this.dateCreation,
dateModification: dateModification ?? this.dateModification,
dateVerification: dateVerification ?? this.dateVerification,
verificateurId: verificateurId ?? this.verificateurId,
statut: statut ?? this.statut,
nombreSignalements: nombreSignalements ?? this.nombreSignalements,
scoreQualite: scoreQualite ?? this.scoreQualite,
estModifie: estModifie ?? this.estModifie,
estVerifiee: estVerifiee ?? this.estVerifiee,
donneesPersonnalisees: donneesPersonnalisees ?? this.donneesPersonnalisees,
);
}
}
/// Énumération des types d'évaluateur
enum TypeEvaluateur {
beneficiaire('Bénéficiaire', 'person', '#2196F3'),
proposant('Proposant', 'volunteer_activism', '#4CAF50'),
evaluateurOfficial('Évaluateur officiel', 'verified_user', '#9C27B0'),
administrateur('Administrateur', 'admin_panel_settings', '#FF5722');
const TypeEvaluateur(this.libelle, this.icone, this.couleur);
final String libelle;
final String icone;
final String couleur;
}
/// Énumération des statuts d'évaluation
enum StatutEvaluation {
active('Active', 'check_circle', '#4CAF50'),
signalee('Signalée', 'flag', '#FF9800'),
masquee('Masquée', 'visibility_off', '#F44336'),
supprimee('Supprimée', 'delete', '#9E9E9E');
const StatutEvaluation(this.libelle, this.icone, this.couleur);
final String libelle;
final String icone;
final String couleur;
}
/// Classe représentant les statistiques d'évaluations
class StatistiquesEvaluation extends Equatable {
final double noteMoyenne;
final int nombreEvaluations;
final Map<int, int> repartitionNotes;
final double pourcentagePositives;
final double pourcentageRecommandations;
final DateTime derniereMiseAJour;
const StatistiquesEvaluation({
required this.noteMoyenne,
required this.nombreEvaluations,
required this.repartitionNotes,
required this.pourcentagePositives,
required this.pourcentageRecommandations,
required this.derniereMiseAJour,
});
@override
List<Object?> get props => [
noteMoyenne,
nombreEvaluations,
repartitionNotes,
pourcentagePositives,
pourcentageRecommandations,
derniereMiseAJour,
];
}

View File

@@ -0,0 +1,401 @@
import 'package:equatable/equatable.dart';
import 'demande_aide.dart';
/// Entité représentant une proposition d'aide dans le système de solidarité
///
/// Cette entité encapsule toutes les informations relatives à une proposition d'aide,
/// incluant les détails du proposant, les capacités et les conditions.
class PropositionAide extends Equatable {
/// Identifiant unique de la proposition
final String id;
/// Numéro de référence unique (format: PA-YYYY-NNNNNN)
final String numeroReference;
/// Titre de la proposition d'aide
final String titre;
/// Description détaillée de la proposition
final String description;
/// Type d'aide proposée
final TypeAide typeAide;
/// Statut actuel de la proposition
final StatutProposition statut;
/// Identifiant du proposant
final String proposantId;
/// Nom complet du proposant
final String nomProposant;
/// Identifiant de l'organisation
final String organisationId;
/// Montant maximum proposé (si applicable)
final double? montantMaximum;
/// Montant minimum proposé (si applicable)
final double? montantMinimum;
/// Nombre maximum de bénéficiaires
final int nombreMaxBeneficiaires;
/// Nombre de bénéficiaires déjà aidés
final int nombreBeneficiairesAides;
/// Nombre de demandes traitées
final int nombreDemandesTraitees;
/// Montant total versé
final double montantTotalVerse;
/// Date de création de la proposition
final DateTime dateCreation;
/// Date de modification
final DateTime dateModification;
/// Date d'expiration
final DateTime? dateExpiration;
/// Délai de réponse en heures
final int delaiReponseHeures;
/// Zones géographiques couvertes
final List<String> zonesGeographiques;
/// Créneaux de disponibilité
final List<CreneauDisponibilite> creneauxDisponibilite;
/// Critères de sélection
final List<CritereSelection> criteresSelection;
/// Contact du proposant
final ContactProposant contactProposant;
/// Conditions particulières
final String? conditionsParticulieres;
/// Instructions spéciales
final String? instructionsSpeciales;
/// Note moyenne des évaluations
final double? noteMoyenne;
/// Nombre d'évaluations reçues
final int nombreEvaluations;
/// Nombre de vues de la proposition
final int nombreVues;
/// Nombre de candidatures reçues
final int nombreCandidatures;
/// Score de pertinence calculé
final double scorePertinence;
/// Données personnalisées
final Map<String, dynamic> donneesPersonnalisees;
/// Indique si la proposition est disponible
final bool estDisponible;
/// Indique si la proposition est vérifiée
final bool estVerifiee;
/// Indique si la proposition est expirée
final bool estExpiree;
const PropositionAide({
required this.id,
required this.numeroReference,
required this.titre,
required this.description,
required this.typeAide,
required this.statut,
required this.proposantId,
required this.nomProposant,
required this.organisationId,
this.montantMaximum,
this.montantMinimum,
required this.nombreMaxBeneficiaires,
this.nombreBeneficiairesAides = 0,
this.nombreDemandesTraitees = 0,
this.montantTotalVerse = 0.0,
required this.dateCreation,
required this.dateModification,
this.dateExpiration,
this.delaiReponseHeures = 48,
this.zonesGeographiques = const [],
this.creneauxDisponibilite = const [],
this.criteresSelection = const [],
required this.contactProposant,
this.conditionsParticulieres,
this.instructionsSpeciales,
this.noteMoyenne,
this.nombreEvaluations = 0,
this.nombreVues = 0,
this.nombreCandidatures = 0,
this.scorePertinence = 50.0,
this.donneesPersonnalisees = const {},
this.estDisponible = true,
this.estVerifiee = false,
this.estExpiree = false,
});
/// Calcule le nombre de places restantes
int get placesRestantes {
return nombreMaxBeneficiaires - nombreBeneficiairesAides;
}
/// Calcule le pourcentage de capacité utilisée
double get pourcentageCapaciteUtilisee {
if (nombreMaxBeneficiaires == 0) return 0.0;
return (nombreBeneficiairesAides / nombreMaxBeneficiaires) * 100;
}
/// Indique si la proposition peut accepter de nouveaux bénéficiaires
bool get peutAccepterBeneficiaires {
return estDisponible && !estExpiree && placesRestantes > 0;
}
/// Indique si la proposition est active et disponible
bool get isActiveEtDisponible {
return statut == StatutProposition.active && estDisponible && !estExpiree;
}
/// Calcule un score de compatibilité avec une demande
double calculerScoreCompatibilite(DemandeAide demande) {
double score = 0.0;
// Correspondance du type d'aide (40 points max)
if (demande.typeAide == typeAide) {
score += 40.0;
} else {
// Bonus partiel pour les types similaires
score += 20.0;
}
// Compatibilité financière (25 points max)
if (demande.montantDemande != null && montantMaximum != null) {
if (demande.montantDemande! <= montantMaximum!) {
score += 25.0;
} else {
// Pénalité proportionnelle
double ratio = montantMaximum! / demande.montantDemande!;
score += 25.0 * ratio;
}
} else if (demande.montantDemande == null) {
score += 25.0; // Pas de contrainte financière
}
// Expérience du proposant (15 points max)
if (nombreBeneficiairesAides > 0) {
score += (nombreBeneficiairesAides * 2.0).clamp(0.0, 15.0);
}
// Réputation (10 points max)
if (noteMoyenne != null && nombreEvaluations >= 3) {
score += (noteMoyenne! - 3.0) * 3.33;
}
// Disponibilité (10 points max)
if (peutAccepterBeneficiaires) {
double ratioCapacite = placesRestantes / nombreMaxBeneficiaires;
score += 10.0 * ratioCapacite;
}
return score.clamp(0.0, 100.0);
}
/// Obtient la couleur associée au statut
String get couleurStatut => statut.couleur;
/// Obtient l'icône associée au type d'aide
String get iconeTypeAide => typeAide.icone;
@override
List<Object?> get props => [
id,
numeroReference,
titre,
description,
typeAide,
statut,
proposantId,
nomProposant,
organisationId,
montantMaximum,
montantMinimum,
nombreMaxBeneficiaires,
nombreBeneficiairesAides,
nombreDemandesTraitees,
montantTotalVerse,
dateCreation,
dateModification,
dateExpiration,
delaiReponseHeures,
zonesGeographiques,
creneauxDisponibilite,
criteresSelection,
contactProposant,
conditionsParticulieres,
instructionsSpeciales,
noteMoyenne,
nombreEvaluations,
nombreVues,
nombreCandidatures,
scorePertinence,
donneesPersonnalisees,
estDisponible,
estVerifiee,
estExpiree,
];
PropositionAide copyWith({
String? id,
String? numeroReference,
String? titre,
String? description,
TypeAide? typeAide,
StatutProposition? statut,
String? proposantId,
String? nomProposant,
String? organisationId,
double? montantMaximum,
double? montantMinimum,
int? nombreMaxBeneficiaires,
int? nombreBeneficiairesAides,
int? nombreDemandesTraitees,
double? montantTotalVerse,
DateTime? dateCreation,
DateTime? dateModification,
DateTime? dateExpiration,
int? delaiReponseHeures,
List<String>? zonesGeographiques,
List<CreneauDisponibilite>? creneauxDisponibilite,
List<CritereSelection>? criteresSelection,
ContactProposant? contactProposant,
String? conditionsParticulieres,
String? instructionsSpeciales,
double? noteMoyenne,
int? nombreEvaluations,
int? nombreVues,
int? nombreCandidatures,
double? scorePertinence,
Map<String, dynamic>? donneesPersonnalisees,
bool? estDisponible,
bool? estVerifiee,
bool? estExpiree,
}) {
return PropositionAide(
id: id ?? this.id,
numeroReference: numeroReference ?? this.numeroReference,
titre: titre ?? this.titre,
description: description ?? this.description,
typeAide: typeAide ?? this.typeAide,
statut: statut ?? this.statut,
proposantId: proposantId ?? this.proposantId,
nomProposant: nomProposant ?? this.nomProposant,
organisationId: organisationId ?? this.organisationId,
montantMaximum: montantMaximum ?? this.montantMaximum,
montantMinimum: montantMinimum ?? this.montantMinimum,
nombreMaxBeneficiaires: nombreMaxBeneficiaires ?? this.nombreMaxBeneficiaires,
nombreBeneficiairesAides: nombreBeneficiairesAides ?? this.nombreBeneficiairesAides,
nombreDemandesTraitees: nombreDemandesTraitees ?? this.nombreDemandesTraitees,
montantTotalVerse: montantTotalVerse ?? this.montantTotalVerse,
dateCreation: dateCreation ?? this.dateCreation,
dateModification: dateModification ?? this.dateModification,
dateExpiration: dateExpiration ?? this.dateExpiration,
delaiReponseHeures: delaiReponseHeures ?? this.delaiReponseHeures,
zonesGeographiques: zonesGeographiques ?? this.zonesGeographiques,
creneauxDisponibilite: creneauxDisponibilite ?? this.creneauxDisponibilite,
criteresSelection: criteresSelection ?? this.criteresSelection,
contactProposant: contactProposant ?? this.contactProposant,
conditionsParticulieres: conditionsParticulieres ?? this.conditionsParticulieres,
instructionsSpeciales: instructionsSpeciales ?? this.instructionsSpeciales,
noteMoyenne: noteMoyenne ?? this.noteMoyenne,
nombreEvaluations: nombreEvaluations ?? this.nombreEvaluations,
nombreVues: nombreVues ?? this.nombreVues,
nombreCandidatures: nombreCandidatures ?? this.nombreCandidatures,
scorePertinence: scorePertinence ?? this.scorePertinence,
donneesPersonnalisees: donneesPersonnalisees ?? this.donneesPersonnalisees,
estDisponible: estDisponible ?? this.estDisponible,
estVerifiee: estVerifiee ?? this.estVerifiee,
estExpiree: estExpiree ?? this.estExpiree,
);
}
}
/// Énumération des statuts de proposition d'aide
enum StatutProposition {
active('Active', 'check_circle', '#4CAF50'),
suspendue('Suspendue', 'pause_circle', '#FF9800'),
terminee('Terminée', 'done_all', '#607D8B'),
expiree('Expirée', 'schedule', '#9E9E9E'),
supprimee('Supprimée', 'delete', '#F44336');
const StatutProposition(this.libelle, this.icone, this.couleur);
final String libelle;
final String icone;
final String couleur;
}
/// Classe représentant un créneau de disponibilité
class CreneauDisponibilite extends Equatable {
final String jourSemaine;
final String heureDebut;
final String heureFin;
final String? commentaire;
const CreneauDisponibilite({
required this.jourSemaine,
required this.heureDebut,
required this.heureFin,
this.commentaire,
});
@override
List<Object?> get props => [jourSemaine, heureDebut, heureFin, commentaire];
}
/// Classe représentant un critère de sélection
class CritereSelection extends Equatable {
final String nom;
final String valeur;
final bool estObligatoire;
final String? description;
const CritereSelection({
required this.nom,
required this.valeur,
this.estObligatoire = false,
this.description,
});
@override
List<Object?> get props => [nom, valeur, estObligatoire, description];
}
/// Classe représentant le contact d'un proposant
class ContactProposant extends Equatable {
final String nom;
final String telephone;
final String? email;
final String? adresse;
final String? methodePrefereee;
const ContactProposant({
required this.nom,
required this.telephone,
this.email,
this.adresse,
this.methodePrefereee,
});
@override
List<Object?> get props => [nom, telephone, email, adresse, methodePrefereee];
}