import 'package:json_annotation/json_annotation.dart'; part 'cotisation_model.g.dart'; /// Modèle de données pour les cotisations /// Correspond au CotisationDTO du backend @JsonSerializable() class CotisationModel { final String id; final String numeroReference; final String membreId; final String? nomMembre; final String? numeroMembre; final String typeCotisation; final double montantDu; final double montantPaye; final String codeDevise; final String statut; final DateTime dateEcheance; final DateTime? datePaiement; final String? description; final String? periode; final int annee; final int? mois; final String? observations; final bool recurrente; final int nombreRappels; final DateTime? dateDernierRappel; final String? valideParId; final String? nomValidateur; final DateTime? dateValidation; final String? methodePaiement; final String? referencePaiement; final DateTime dateCreation; final DateTime? dateModification; const CotisationModel({ required this.id, required this.numeroReference, required this.membreId, this.nomMembre, this.numeroMembre, required this.typeCotisation, required this.montantDu, required this.montantPaye, required this.codeDevise, required this.statut, required this.dateEcheance, this.datePaiement, this.description, this.periode, required this.annee, this.mois, this.observations, required this.recurrente, required this.nombreRappels, this.dateDernierRappel, this.valideParId, this.nomValidateur, this.dateValidation, this.methodePaiement, this.referencePaiement, required this.dateCreation, this.dateModification, }); /// Factory pour créer depuis JSON factory CotisationModel.fromJson(Map json) => _$CotisationModelFromJson(json); /// Convertit vers JSON Map toJson() => _$CotisationModelToJson(this); /// Calcule le montant restant à payer double get montantRestant => montantDu - montantPaye; /// Vérifie si la cotisation est entièrement payée bool get isEntierementPayee => montantRestant <= 0; /// Vérifie si la cotisation est en retard bool get isEnRetard { return dateEcheance.isBefore(DateTime.now()) && !isEntierementPayee; } /// Retourne le pourcentage de paiement double get pourcentagePaiement { if (montantDu == 0) return 0; return (montantPaye / montantDu * 100).clamp(0, 100); } /// Calcule le nombre de jours de retard int get joursRetard { if (!isEnRetard) return 0; return DateTime.now().difference(dateEcheance).inDays; } /// Retourne la couleur associée au statut String get couleurStatut { switch (statut) { case 'PAYEE': return '#4CAF50'; // Vert case 'EN_ATTENTE': return '#FF9800'; // Orange case 'EN_RETARD': return '#F44336'; // Rouge case 'PARTIELLEMENT_PAYEE': return '#2196F3'; // Bleu case 'ANNULEE': return '#9E9E9E'; // Gris default: return '#757575'; // Gris foncé } } /// Retourne le libellé du statut en français String get libelleStatut { switch (statut) { case 'PAYEE': return 'Payée'; case 'EN_ATTENTE': return 'En attente'; case 'EN_RETARD': return 'En retard'; case 'PARTIELLEMENT_PAYEE': return 'Partiellement payée'; case 'ANNULEE': return 'Annulée'; default: return statut; } } /// Retourne le libellé du type de cotisation String get libelleTypeCotisation { switch (typeCotisation) { case 'MENSUELLE': return 'Mensuelle'; case 'TRIMESTRIELLE': return 'Trimestrielle'; case 'SEMESTRIELLE': return 'Semestrielle'; case 'ANNUELLE': return 'Annuelle'; case 'EXCEPTIONNELLE': return 'Exceptionnelle'; case 'ADHESION': return 'Adhésion'; default: return typeCotisation; } } /// Retourne l'icône associée au type de cotisation String get iconeTypeCotisation { switch (typeCotisation) { case 'MENSUELLE': return '📅'; case 'TRIMESTRIELLE': return '📊'; case 'SEMESTRIELLE': return '📈'; case 'ANNUELLE': return '🗓️'; case 'EXCEPTIONNELLE': return '⚡'; case 'ADHESION': return '🎯'; default: return '💰'; } } /// Retourne le nombre de jours jusqu'à l'échéance int get joursJusquEcheance { final maintenant = DateTime.now(); final difference = dateEcheance.difference(maintenant); return difference.inDays; } /// Vérifie si l'échéance approche (moins de 7 jours) bool get echeanceProche { return joursJusquEcheance <= 7 && joursJusquEcheance >= 0; } /// Retourne un message d'urgence basé sur l'échéance String get messageUrgence { final jours = joursJusquEcheance; if (jours < 0) { return 'En retard de ${-jours} jour${-jours > 1 ? 's' : ''}'; } else if (jours == 0) { return 'Échéance aujourd\'hui'; } else if (jours <= 3) { return 'Échéance dans $jours jour${jours > 1 ? 's' : ''}'; } else if (jours <= 7) { return 'Échéance dans $jours jours'; } else { return ''; } } /// Copie avec modifications CotisationModel copyWith({ String? id, String? numeroReference, String? membreId, String? nomMembre, String? numeroMembre, String? typeCotisation, double? montantDu, double? montantPaye, String? codeDevise, String? statut, DateTime? dateEcheance, DateTime? datePaiement, String? description, String? periode, int? annee, int? mois, String? observations, bool? recurrente, int? nombreRappels, DateTime? dateDernierRappel, String? valideParId, String? nomValidateur, DateTime? dateValidation, String? methodePaiement, String? referencePaiement, DateTime? dateCreation, DateTime? dateModification, }) { return CotisationModel( id: id ?? this.id, numeroReference: numeroReference ?? this.numeroReference, membreId: membreId ?? this.membreId, nomMembre: nomMembre ?? this.nomMembre, numeroMembre: numeroMembre ?? this.numeroMembre, typeCotisation: typeCotisation ?? this.typeCotisation, montantDu: montantDu ?? this.montantDu, montantPaye: montantPaye ?? this.montantPaye, codeDevise: codeDevise ?? this.codeDevise, statut: statut ?? this.statut, dateEcheance: dateEcheance ?? this.dateEcheance, datePaiement: datePaiement ?? this.datePaiement, description: description ?? this.description, periode: periode ?? this.periode, annee: annee ?? this.annee, mois: mois ?? this.mois, observations: observations ?? this.observations, recurrente: recurrente ?? this.recurrente, nombreRappels: nombreRappels ?? this.nombreRappels, dateDernierRappel: dateDernierRappel ?? this.dateDernierRappel, valideParId: valideParId ?? this.valideParId, nomValidateur: nomValidateur ?? this.nomValidateur, dateValidation: dateValidation ?? this.dateValidation, methodePaiement: methodePaiement ?? this.methodePaiement, referencePaiement: referencePaiement ?? this.referencePaiement, dateCreation: dateCreation ?? this.dateCreation, dateModification: dateModification ?? this.dateModification, ); } @override bool operator ==(Object other) { if (identical(this, other)) return true; return other is CotisationModel && other.id == id; } @override int get hashCode => id.hashCode; @override String toString() { return 'CotisationModel(id: $id, numeroReference: $numeroReference, ' 'nomMembre: $nomMembre, typeCotisation: $typeCotisation, ' 'montantDu: $montantDu, statut: $statut)'; } }