import 'package:json_annotation/json_annotation.dart'; part 'payment_model.g.dart'; /// Modèle de données pour les paiements /// Représente une transaction de paiement de cotisation @JsonSerializable() class PaymentModel { final String id; final String cotisationId; final String numeroReference; final double montant; final String codeDevise; final String methodePaiement; final String statut; final DateTime dateTransaction; final String? numeroTransaction; final String? referencePaiement; final String? description; final Map? metadonnees; final String? operateurMobileMoney; final String? numeroTelephone; final String? nomPayeur; final String? emailPayeur; final double? fraisTransaction; final String? codeAutorisation; final String? messageErreur; final int? nombreTentatives; final DateTime? dateEcheance; final DateTime dateCreation; final DateTime? dateModification; const PaymentModel({ required this.id, required this.cotisationId, required this.numeroReference, required this.montant, required this.codeDevise, required this.methodePaiement, required this.statut, required this.dateTransaction, this.numeroTransaction, this.referencePaiement, this.description, this.metadonnees, this.operateurMobileMoney, this.numeroTelephone, this.nomPayeur, this.emailPayeur, this.fraisTransaction, this.codeAutorisation, this.messageErreur, this.nombreTentatives, this.dateEcheance, required this.dateCreation, this.dateModification, }); /// Factory pour créer depuis JSON factory PaymentModel.fromJson(Map json) => _$PaymentModelFromJson(json); /// Convertit vers JSON Map toJson() => _$PaymentModelToJson(this); /// Vérifie si le paiement est réussi bool get isSuccessful => statut == 'COMPLETED' || statut == 'SUCCESS'; /// Vérifie si le paiement est en cours bool get isPending => statut == 'PENDING' || statut == 'PROCESSING'; /// Vérifie si le paiement a échoué bool get isFailed => statut == 'FAILED' || statut == 'ERROR' || statut == 'CANCELLED'; /// Retourne la couleur associée au statut String get couleurStatut { switch (statut) { case 'COMPLETED': case 'SUCCESS': return '#4CAF50'; // Vert case 'PENDING': case 'PROCESSING': return '#FF9800'; // Orange case 'FAILED': case 'ERROR': return '#F44336'; // Rouge case 'CANCELLED': return '#9E9E9E'; // Gris default: return '#757575'; // Gris foncé } } /// Retourne le libellé du statut en français String get libelleStatut { switch (statut) { case 'COMPLETED': case 'SUCCESS': return 'Réussi'; case 'PENDING': return 'En attente'; case 'PROCESSING': return 'En cours'; case 'FAILED': return 'Échoué'; case 'ERROR': return 'Erreur'; case 'CANCELLED': return 'Annulé'; default: return statut; } } /// Retourne le libellé de la méthode de paiement String get libelleMethodePaiement { switch (methodePaiement) { case 'MOBILE_MONEY': return 'Mobile Money'; case 'ORANGE_MONEY': return 'Orange Money'; case 'WAVE': return 'Wave'; case 'MOOV_MONEY': return 'Moov Money'; case 'CARTE_BANCAIRE': return 'Carte bancaire'; case 'VIREMENT': return 'Virement bancaire'; case 'ESPECES': return 'Espèces'; case 'CHEQUE': return 'Chèque'; default: return methodePaiement; } } /// Retourne l'icône associée à la méthode de paiement String get iconeMethodePaiement { switch (methodePaiement) { case 'MOBILE_MONEY': case 'ORANGE_MONEY': case 'WAVE': case 'MOOV_MONEY': return '📱'; case 'CARTE_BANCAIRE': return '💳'; case 'VIREMENT': return '🏦'; case 'ESPECES': return '💵'; case 'CHEQUE': return '📝'; default: return '💰'; } } /// Calcule le montant net (montant - frais) double get montantNet { return montant - (fraisTransaction ?? 0); } /// Vérifie si des frais sont appliqués bool get hasFrais => fraisTransaction != null && fraisTransaction! > 0; /// Retourne le pourcentage de frais double get pourcentageFrais { if (montant == 0 || fraisTransaction == null) return 0; return (fraisTransaction! / montant * 100); } /// Vérifie si le paiement est expiré bool get isExpired { if (dateEcheance == null) return false; return DateTime.now().isAfter(dateEcheance!) && !isSuccessful; } /// Retourne le temps restant avant expiration Duration? get tempsRestant { if (dateEcheance == null || isExpired) return null; return dateEcheance!.difference(DateTime.now()); } /// Retourne un message d'état détaillé String get messageStatut { switch (statut) { case 'COMPLETED': case 'SUCCESS': return 'Paiement effectué avec succès'; case 'PENDING': return 'Paiement en attente de confirmation'; case 'PROCESSING': return 'Traitement du paiement en cours'; case 'FAILED': return messageErreur ?? 'Le paiement a échoué'; case 'ERROR': return messageErreur ?? 'Erreur lors du paiement'; case 'CANCELLED': return 'Paiement annulé par l\'utilisateur'; default: return 'Statut inconnu'; } } /// Vérifie si le paiement peut être retenté bool get canRetry { return isFailed && (nombreTentatives ?? 0) < 3 && !isExpired; } /// Copie avec modifications PaymentModel copyWith({ String? id, String? cotisationId, String? numeroReference, double? montant, String? codeDevise, String? methodePaiement, String? statut, DateTime? dateTransaction, String? numeroTransaction, String? referencePaiement, String? description, Map? metadonnees, String? operateurMobileMoney, String? numeroTelephone, String? nomPayeur, String? emailPayeur, double? fraisTransaction, String? codeAutorisation, String? messageErreur, int? nombreTentatives, DateTime? dateEcheance, DateTime? dateCreation, DateTime? dateModification, }) { return PaymentModel( id: id ?? this.id, cotisationId: cotisationId ?? this.cotisationId, numeroReference: numeroReference ?? this.numeroReference, montant: montant ?? this.montant, codeDevise: codeDevise ?? this.codeDevise, methodePaiement: methodePaiement ?? this.methodePaiement, statut: statut ?? this.statut, dateTransaction: dateTransaction ?? this.dateTransaction, numeroTransaction: numeroTransaction ?? this.numeroTransaction, referencePaiement: referencePaiement ?? this.referencePaiement, description: description ?? this.description, metadonnees: metadonnees ?? this.metadonnees, operateurMobileMoney: operateurMobileMoney ?? this.operateurMobileMoney, numeroTelephone: numeroTelephone ?? this.numeroTelephone, nomPayeur: nomPayeur ?? this.nomPayeur, emailPayeur: emailPayeur ?? this.emailPayeur, fraisTransaction: fraisTransaction ?? this.fraisTransaction, codeAutorisation: codeAutorisation ?? this.codeAutorisation, messageErreur: messageErreur ?? this.messageErreur, nombreTentatives: nombreTentatives ?? this.nombreTentatives, dateEcheance: dateEcheance ?? this.dateEcheance, dateCreation: dateCreation ?? this.dateCreation, dateModification: dateModification ?? this.dateModification, ); } @override bool operator ==(Object other) { if (identical(this, other)) return true; return other is PaymentModel && other.id == id; } @override int get hashCode => id.hashCode; @override String toString() { return 'PaymentModel(id: $id, numeroReference: $numeroReference, ' 'montant: $montant, methodePaiement: $methodePaiement, statut: $statut)'; } }