GUYCOM_FLUTTER/lib/Models/Client.dart
2026-01-16 12:17:06 +03:00

444 lines
12 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Models/client.dart - Version corrigée pour MySQL
class Client {
final int? id;
final String nom;
final String prenom;
final String email;
final String telephone;
final String? adresse;
final DateTime dateCreation;
final bool actif;
Client({
this.id,
required this.nom,
required this.prenom,
required this.email,
required this.telephone,
this.adresse,
required this.dateCreation,
this.actif = true,
});
Map<String, dynamic> toMap() {
return {
'id': id,
'nom': nom,
'prenom': prenom,
'email': email,
'telephone': telephone,
'adresse': adresse,
'dateCreation': dateCreation.toIso8601String(),
'actif': actif ? 1 : 0,
};
}
// Fonction helper améliorée pour parser les dates
static DateTime _parseDateTime(dynamic dateValue) {
if (dateValue == null) return DateTime.now();
if (dateValue is DateTime) return dateValue;
if (dateValue is String) {
try {
return DateTime.parse(dateValue);
} catch (e) {
print("Erreur parsing date string: $dateValue, erreur: $e");
return DateTime.now();
}
}
// Pour MySQL qui peut retourner un Timestamp
if (dateValue is int) {
return DateTime.fromMillisecondsSinceEpoch(dateValue);
}
print(
"Type de date non reconnu: ${dateValue.runtimeType}, valeur: $dateValue");
return DateTime.now();
}
factory Client.fromMap(Map<String, dynamic> map) {
return Client(
id: map['id'] as int?,
nom: map['nom'] as String,
prenom: map['prenom'] as String,
email: map['email'] as String,
telephone: map['telephone'] as String,
adresse: map['adresse'] as String?,
dateCreation: _parseDateTime(map['dateCreation']),
actif: (map['actif'] as int?) == 1,
);
}
String get nomComplet => '$prenom $nom';
}
enum StatutCommande { enAttente, confirmee, annulee }
class Commande {
final int? id;
final int clientId;
final DateTime dateCommande;
final StatutCommande statut;
final double montantTotal;
final String? notes;
final DateTime? dateLivraison;
final int? commandeurId;
final String? commandeurnom;
final String? commandeurPrenom;
final int? validateurId;
final String? clientNom;
final String? clientPrenom;
final String? clientEmail;
final int? pointDeVenteId;
final String? pointDeVenteDesign;
Commande({
this.id,
required this.clientId,
required this.dateCommande,
required this.statut,
required this.montantTotal,
this.notes,
this.dateLivraison,
this.commandeurId,
this.commandeurnom,
this.commandeurPrenom,
this.validateurId,
this.clientNom,
this.clientPrenom,
this.clientEmail,
this.pointDeVenteId,
this.pointDeVenteDesign,
});
String get clientNomComplet {
if (clientNom != null && clientPrenom != null) {
return '$clientPrenom $clientNom';
}
return 'Client inconnu';
}
String get statutLibelle {
switch (statut) {
case StatutCommande.enAttente:
return 'En attente';
case StatutCommande.confirmee:
return 'Confirmée';
case StatutCommande.annulee:
return 'Annulée';
}
}
Map<String, dynamic> toMap() {
return {
'id': id,
'clientId': clientId,
'dateCommande': dateCommande.toIso8601String(),
'statut': statut.index,
'montantTotal': montantTotal,
'notes': notes,
'dateLivraison': dateLivraison?.toIso8601String(),
'commandeurId': commandeurId,
'validateurId': validateurId,
};
}
factory Commande.fromMap(Map<String, dynamic> map) {
return Commande(
id: map['id'] as int?,
clientId: map['clientId'] as int,
dateCommande: Client._parseDateTime(map['dateCommande']),
statut: StatutCommande.values[(map['statut'] as int)],
montantTotal: (map['montantTotal'] as num).toDouble(),
notes: map['notes'] as String?,
dateLivraison: map['dateLivraison'] != null
? Client._parseDateTime(map['dateLivraison'])
: null,
commandeurId: map['commandeurId'] as int?,
commandeurnom: map['commandeurnom'] as String?,
commandeurPrenom: map['commandeurPrenom'] as String?,
validateurId: map['validateurId'] as int?,
clientNom: map['clientNom'] as String?,
clientPrenom: map['clientPrenom'] as String?,
clientEmail: map['clientEmail'] as String?,
pointDeVenteId: map['pointDeVenteId'] as int?,
pointDeVenteDesign: map['pointDeVenteDesign'] as String?,
);
}
}
// REMPLACEZ COMPLÈTEMENT votre classe DetailCommande dans Models/client.dart par celle-ci :
enum RemiseType { pourcentage, montant }
class DetailCommande {
final int? id;
final int commandeId;
final int produitId;
final int quantite;
final double prixUnitaire;
final double sousTotal; // Prix unitaire × quantité (avant remise)
final RemiseType? remiseType;
final double remiseValeur; // Valeur de la remise (% ou montant)
final double montantRemise; // Montant de la remise calculé
final double prixFinal; // Prix final après remise
final bool estCadeau; // NOUVEAU : Indique si l'article est un cadeau
final String? produitNom;
final String? produitImage;
final String? produitReference;
final String? produitImei; // NOUVEAU : IMEI du produit, si applicable
DetailCommande({
this.id,
required this.commandeId,
required this.produitId,
required this.quantite,
required this.prixUnitaire,
required this.sousTotal,
this.remiseType,
this.remiseValeur = 0.0,
this.montantRemise = 0.0,
required this.prixFinal,
this.estCadeau = false,
this.produitNom,
this.produitImage,
this.produitReference,
this.produitImei,
});
// Constructeur pour créer un détail sans remise
factory DetailCommande.sansRemise({
int? id,
required int commandeId,
required int produitId,
required int quantite,
required double prixUnitaire,
bool estCadeau = false,
String? produitNom,
String? produitImage,
String? produitReference,
String? produitImei,
}) {
final sousTotal = quantite * prixUnitaire;
final prixFinal = estCadeau ? 0.0 : sousTotal;
return DetailCommande(
id: id,
commandeId: commandeId,
produitId: produitId,
quantite: quantite,
prixUnitaire: prixUnitaire,
sousTotal: sousTotal,
prixFinal: prixFinal,
estCadeau: estCadeau,
produitNom: produitNom,
produitImage: produitImage,
produitReference: produitReference,
produitImei: produitImei,
);
}
// NOUVEAU : Constructeur pour créer un cadeau
factory DetailCommande.cadeau({
int? id,
required int commandeId,
required int produitId,
required int quantite,
required double prixUnitaire,
String? produitNom,
String? produitImage,
String? produitReference,
String? produitImei,
}) {
return DetailCommande(
id: id,
commandeId: commandeId,
produitId: produitId,
quantite: quantite,
prixUnitaire: prixUnitaire,
sousTotal: quantite * prixUnitaire,
prixFinal: 0.0, // Prix final à 0 pour un cadeau
estCadeau: true,
produitNom: produitNom,
produitImage: produitImage,
produitReference: produitReference,
produitImei: produitImei,
);
}
// Méthode pour appliquer une remise (ne s'applique pas aux cadeaux)
DetailCommande appliquerRemise({
required RemiseType type,
required double valeur,
}) {
// Les remises ne s'appliquent pas aux cadeaux
if (estCadeau) return this;
double montantRemiseCalcule = 0.0;
if (type == RemiseType.pourcentage) {
final pourcentage = valeur.clamp(0.0, 100.0);
montantRemiseCalcule = sousTotal * (pourcentage / 100);
} else {
montantRemiseCalcule = valeur.clamp(0.0, sousTotal);
}
final prixFinalCalcule = sousTotal - montantRemiseCalcule;
return DetailCommande(
id: id,
commandeId: commandeId,
produitId: produitId,
quantite: quantite,
prixUnitaire: prixUnitaire,
sousTotal: sousTotal,
remiseType: type,
remiseValeur: valeur,
montantRemise: montantRemiseCalcule,
prixFinal: prixFinalCalcule,
estCadeau: estCadeau,
produitNom: produitNom,
produitImage: produitImage,
produitReference: produitReference,
produitImei: produitImei,
);
}
// Méthode pour supprimer la remise
DetailCommande supprimerRemise() {
return DetailCommande(
id: id,
commandeId: commandeId,
produitId: produitId,
quantite: quantite,
prixUnitaire: prixUnitaire,
sousTotal: sousTotal,
remiseType: null,
remiseValeur: 0.0,
montantRemise: 0.0,
prixFinal: estCadeau ? 0.0 : sousTotal,
estCadeau: estCadeau,
produitNom: produitNom,
produitImage: produitImage,
produitReference: produitReference,
produitImei: produitImei,
);
}
// NOUVEAU : Méthode pour convertir en cadeau
DetailCommande convertirEnCadeau() {
return DetailCommande(
id: id,
commandeId: commandeId,
produitId: produitId,
quantite: quantite,
prixUnitaire: prixUnitaire,
sousTotal: sousTotal,
remiseType: null, // Supprimer les remises lors de la conversion en cadeau
remiseValeur: 0.0,
montantRemise: 0.0,
prixFinal: 0.0,
estCadeau: true,
produitNom: produitNom,
produitImage: produitImage,
produitReference: produitReference,
produitImei: produitImei,
);
}
// NOUVEAU : Méthode pour convertir en article normal
DetailCommande convertirEnArticleNormal() {
return DetailCommande(
id: id,
commandeId: commandeId,
produitId: produitId,
quantite: quantite,
prixUnitaire: prixUnitaire,
sousTotal: sousTotal,
remiseType: remiseType,
remiseValeur: remiseValeur,
montantRemise: montantRemise,
prixFinal: estCadeau ? sousTotal - montantRemise : prixFinal,
estCadeau: false,
produitNom: produitNom,
produitImage: produitImage,
produitReference: produitReference,
produitImei: produitImei,
);
}
// Getters utiles
bool get aRemise => remiseType != null && montantRemise > 0 && !estCadeau;
bool get aimei => produitImei != null;
double get pourcentageRemise {
if (!aRemise) return 0.0;
return (montantRemise / sousTotal) * 100;
}
String get remiseDescription {
if (estCadeau) return 'CADEAU';
if (!aRemise) return '';
if (remiseType == RemiseType.pourcentage) {
return '-${remiseValeur.toStringAsFixed(0)}%';
} else {
return '-${montantRemise.toStringAsFixed(2)} MGA';
}
}
// NOUVEAU : Description du statut de l'article
String get statutDescription {
if (estCadeau) return 'CADEAU OFFERT';
if (aRemise) return 'AVEC REMISE';
return 'PRIX NORMAL';
}
Map<String, dynamic> toMap() {
return {
'id': id,
'commandeId': commandeId,
'produitId': produitId,
'quantite': quantite,
'prixUnitaire': prixUnitaire,
'sousTotal': sousTotal,
'remise_type': remiseType?.name,
'remise_valeur': remiseValeur,
'montant_remise': montantRemise,
'prix_final': prixFinal,
'est_cadeau': estCadeau ? 1 : 0,
};
}
factory DetailCommande.fromMap(Map<String, dynamic> map) {
RemiseType? type;
if (map['remise_type'] != null) {
if (map['remise_type'] == 'pourcentage') {
type = RemiseType.pourcentage;
} else if (map['remise_type'] == 'montant') {
type = RemiseType.montant;
}
}
return DetailCommande(
id: map['id'] as int?,
commandeId: map['commandeId'] as int,
produitId: map['produitId'] as int,
quantite: map['quantite'] as int,
prixUnitaire: (map['prixUnitaire'] as num).toDouble(),
sousTotal: (map['sousTotal'] as num).toDouble(),
remiseType: type,
remiseValeur: (map['remise_valeur'] as num?)?.toDouble() ?? 0.0,
montantRemise: (map['montant_remise'] as num?)?.toDouble() ?? 0.0,
prixFinal: (map['prix_final'] as num?)?.toDouble() ??
(map['sousTotal'] as num).toDouble(),
estCadeau: (map['est_cadeau'] as int?) == 1,
produitNom: map['produitNom'] as String?,
produitImage: map['produitImage'] as String?,
produitReference: map['produitReference'] as String?,
produitImei: map['produitImei'] as String?,
);
}
}