Compare commits
No commits in common. "5ad019d35e08f7df3b75a7741d28b8ccc90de166" and "3e6a81c2c3b43e2a4ddf400b63dab722e4eedab8" have entirely different histories.
5ad019d35e
...
3e6a81c2c3
@ -8,8 +8,7 @@ plugins {
|
||||
android {
|
||||
namespace = "com.example.my_app"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = "26.3.11579264"
|
||||
|
||||
ndkVersion = flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
|
||||
@ -1464,12 +1464,12 @@ class AppDatabase {
|
||||
commandeMap['clientId'] = clientId;
|
||||
|
||||
final commandeFields = commandeMap.keys.join(', ');
|
||||
final commandePlaceholders = List.filled(commandeMap.length, '?').join(', ');
|
||||
final commandePlaceholders =
|
||||
List.filled(commandeMap.length, '?').join(', ');
|
||||
|
||||
final commandeResult = await db.query(
|
||||
'INSERT INTO commandes ($commandeFields) VALUES ($commandePlaceholders)',
|
||||
commandeMap.values.toList(),
|
||||
);
|
||||
commandeMap.values.toList());
|
||||
final commandeId = commandeResult.insertId!;
|
||||
|
||||
// 3. Créer les détails de commande avec remises
|
||||
@ -1479,18 +1479,16 @@ class AppDatabase {
|
||||
detailMap['commandeId'] = commandeId;
|
||||
|
||||
final detailFields = detailMap.keys.join(', ');
|
||||
final detailPlaceholders = List.filled(detailMap.length, '?').join(', ');
|
||||
final detailPlaceholders =
|
||||
List.filled(detailMap.length, '?').join(', ');
|
||||
|
||||
await db.query(
|
||||
'INSERT INTO details_commandes ($detailFields) VALUES ($detailPlaceholders)',
|
||||
detailMap.values.toList(),
|
||||
);
|
||||
detailMap.values.toList());
|
||||
|
||||
// 4. Mettre à jour le stock
|
||||
await db.query(
|
||||
'UPDATE products SET stock = stock - ? WHERE id = ?',
|
||||
[detail.quantite, detail.produitId],
|
||||
);
|
||||
await db.query('UPDATE products SET stock = stock - ? WHERE id = ?',
|
||||
[detail.quantite, detail.produitId]);
|
||||
}
|
||||
|
||||
await db.query('COMMIT');
|
||||
@ -1502,7 +1500,6 @@ class AppDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Méthode pour mettre à jour un détail de commande (utile pour modifier les remises)
|
||||
Future<int> updateDetailCommande(DetailCommande detail) async {
|
||||
final db = await database;
|
||||
|
||||
@ -52,7 +52,6 @@ class _ApprobationSortiesPageState extends State<ApprobationSortiesPage> {
|
||||
Text('Quantité: ${sortie['quantite']}'),
|
||||
Text('Demandeur: ${sortie['admin_nom']}'),
|
||||
Text('Motif: ${sortie['motif']}'),
|
||||
Text('Note: ${sortie['notes']}'),
|
||||
const SizedBox(height: 16),
|
||||
const Text(
|
||||
'Confirmer l\'approbation de cette demande de sortie personnelle ?',
|
||||
|
||||
@ -289,13 +289,9 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
? await _database.getUserById(commande.validateurId!)
|
||||
: null;
|
||||
|
||||
// ✅ DEBUG: Vérifiez combien de détails vous avez
|
||||
print('=== DEBUG BON DE LIVRAISON ===');
|
||||
print('Nombre de détails récupérés: ${details.length}');
|
||||
|
||||
for (int i = 0; i < details.length; i++) {
|
||||
print('Détail $i: ${details[i].produitNom} x${details[i].quantite}');
|
||||
}
|
||||
final iconPhone = await buildIconPhoneText();
|
||||
final iconChecked = await buildIconCheckedText();
|
||||
final iconGlobe = await buildIconGlobeText();
|
||||
|
||||
double sousTotal = 0;
|
||||
double totalRemises = 0;
|
||||
@ -312,72 +308,43 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ CORRECTION PRINCIPALE: Améliorer la récupération des produits
|
||||
final List<Map<String, dynamic>> detailsAvecProduits = [];
|
||||
|
||||
for (int i = 0; i < details.length; i++) {
|
||||
final detail = details[i];
|
||||
print('Traitement détail $i: ${detail.produitNom}');
|
||||
|
||||
try {
|
||||
for (final detail in details) {
|
||||
final produit = await _database.getProductById(detail.produitId);
|
||||
|
||||
if (produit != null) {
|
||||
detailsAvecProduits.add({
|
||||
'detail': detail,
|
||||
'produit': produit,
|
||||
});
|
||||
print(' ✅ Produit trouvé: ${produit.name}');
|
||||
} else {
|
||||
// ✅ Même si le produit est null, on l'ajoute quand même avec les infos du détail
|
||||
detailsAvecProduits.add({
|
||||
'detail': detail,
|
||||
'produit': null, // On garde null mais on utilisera les infos du détail
|
||||
});
|
||||
print(' ⚠️ Produit non trouvé, utilisation des données du détail');
|
||||
}
|
||||
} catch (e) {
|
||||
print(' ❌ Erreur lors de la récupération du produit: $e');
|
||||
// En cas d'erreur, on ajoute quand même le détail
|
||||
detailsAvecProduits.add({
|
||||
'detail': detail,
|
||||
'produit': null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
print('Total detailsAvecProduits: ${detailsAvecProduits.length}');
|
||||
|
||||
final pdf = pw.Document();
|
||||
final imageBytes = await loadImage();
|
||||
final image = pw.MemoryImage(imageBytes);
|
||||
final italicFont =
|
||||
pw.Font.ttf(await rootBundle.load('assets/fonts/Roboto-Italic.ttf'));
|
||||
|
||||
// ✅ AMÉLIORATION: Gestion des polices avec fallback
|
||||
pw.Font? italicFont;
|
||||
pw.Font? regularFont;
|
||||
// Tailles de texte agrandies pour une meilleure lisibilité
|
||||
final tinyTextStyle = pw.TextStyle(fontSize: 9);
|
||||
final smallTextStyle = pw.TextStyle(fontSize: 10);
|
||||
final normalTextStyle = pw.TextStyle(fontSize: 11);
|
||||
final boldTextStyle =
|
||||
pw.TextStyle(fontSize: 11, fontWeight: pw.FontWeight.bold);
|
||||
final boldClientStyle =
|
||||
pw.TextStyle(fontSize: 12, fontWeight: pw.FontWeight.bold);
|
||||
final frameTextStyle = pw.TextStyle(fontSize: 10);
|
||||
final italicTextStyle = pw.TextStyle(
|
||||
fontSize: 9, fontWeight: pw.FontWeight.bold, font: italicFont);
|
||||
final italicLogoStyle = pw.TextStyle(
|
||||
fontSize: 8, fontWeight: pw.FontWeight.bold, font: italicFont);
|
||||
final titleStyle =
|
||||
pw.TextStyle(fontSize: 14, fontWeight: pw.FontWeight.bold);
|
||||
final headerStyle =
|
||||
pw.TextStyle(fontSize: 12, fontWeight: pw.FontWeight.bold);
|
||||
|
||||
try {
|
||||
italicFont = pw.Font.ttf(await rootBundle.load('assets/fonts/Roboto-Italic.ttf'));
|
||||
regularFont = pw.Font.ttf(await rootBundle.load('assets/fonts/Roboto-Regular.ttf'));
|
||||
} catch (e) {
|
||||
print('⚠️ Impossible de charger les polices personnalisées: $e');
|
||||
// Utiliser les polices par défaut
|
||||
}
|
||||
|
||||
// ✅ DÉFINITION DES STYLES DE TEXTE - Variables globales dans la fonction
|
||||
final tinyTextStyle = pw.TextStyle(fontSize: 9, font: regularFont);
|
||||
final smallTextStyle = pw.TextStyle(fontSize: 10, font: regularFont);
|
||||
final normalTextStyle = pw.TextStyle(fontSize: 11, font: regularFont);
|
||||
final boldTextStyle = pw.TextStyle(fontSize: 11, fontWeight: pw.FontWeight.bold, font: regularFont);
|
||||
final boldClientStyle = pw.TextStyle(fontSize: 12, fontWeight: pw.FontWeight.bold, font: regularFont);
|
||||
final frameTextStyle = pw.TextStyle(fontSize: 10, font: regularFont);
|
||||
final italicTextStyle = pw.TextStyle(fontSize: 9, fontWeight: pw.FontWeight.bold, font: italicFont ?? regularFont);
|
||||
final italicLogoStyle = pw.TextStyle(fontSize: 8, fontWeight: pw.FontWeight.bold, font: italicFont ?? regularFont);
|
||||
|
||||
// ✅ Fonction pour créer un exemplaire - CORRIGÉE
|
||||
// Fonction pour créer un exemplaire en mode paysage
|
||||
pw.Widget buildExemplaire(String typeExemplaire) {
|
||||
return pw.Container(
|
||||
// ✅ PAS DE HAUTEUR FIXE - Elle s'adapte au contenu
|
||||
height: 380, // Hauteur ajustée pour le mode paysage
|
||||
width: double.infinity,
|
||||
decoration: pw.BoxDecoration(
|
||||
border: pw.Border.all(color: PdfColors.black, width: 1.5),
|
||||
@ -390,7 +357,9 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
width: double.infinity,
|
||||
padding: const pw.EdgeInsets.all(5),
|
||||
decoration: pw.BoxDecoration(
|
||||
color: typeExemplaire == "CLIENT" ? PdfColors.blue100 : PdfColors.green100,
|
||||
color: typeExemplaire == "CLIENT"
|
||||
? PdfColors.blue100
|
||||
: PdfColors.green100,
|
||||
),
|
||||
child: pw.Center(
|
||||
child: pw.Text(
|
||||
@ -398,19 +367,21 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
style: pw.TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: pw.FontWeight.bold,
|
||||
color: typeExemplaire == "CLIENT" ? PdfColors.blue800 : PdfColors.green800,
|
||||
font: regularFont,
|
||||
color: typeExemplaire == "CLIENT"
|
||||
? PdfColors.blue800
|
||||
: PdfColors.green800,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
pw.Padding(
|
||||
pw.Expanded(
|
||||
child: pw.Padding(
|
||||
padding: const pw.EdgeInsets.all(8),
|
||||
child: pw.Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
children: [
|
||||
// En-tête principal (logo, infos entreprise, client)
|
||||
// En-tête principal
|
||||
pw.Row(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
|
||||
@ -425,16 +396,26 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
child: pw.Image(image),
|
||||
),
|
||||
pw.SizedBox(height: 3),
|
||||
pw.Text('NOTRE COMPETENCE, A VOTRE SERVICE', style: italicLogoStyle),
|
||||
pw.Text('NOTRE COMPETENCE, A VOTRE SERVICE',
|
||||
style: italicLogoStyle),
|
||||
pw.SizedBox(height: 4),
|
||||
pw.Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
children: [
|
||||
pw.Text('REMAX Andravoangy', style: tinyTextStyle),
|
||||
pw.Text('SUPREME CENTER Behoririka \n BOX 405 | 416 | 119', style: tinyTextStyle),
|
||||
pw.Text('Tripolisa analankely BOX 7', style: tinyTextStyle),
|
||||
pw.Text('033 37 808 18', style: tinyTextStyle),
|
||||
pw.Text('www.guycom.mg', style: tinyTextStyle),
|
||||
pw.Text('📍 REMAX Andravoangy',
|
||||
style: tinyTextStyle),
|
||||
pw.Text(
|
||||
'📍 SUPREME CENTER Behoririka \n BOX 405 | 416 | 119',
|
||||
style: tinyTextStyle),
|
||||
pw.Text('📍 Tripolisa analankely BOX 7',
|
||||
style: tinyTextStyle),
|
||||
pw.Text('📞 033 37 808 18',
|
||||
style: tinyTextStyle),
|
||||
pw.Text('🌐 www.guycom.mg',
|
||||
style: tinyTextStyle),
|
||||
pw.SizedBox(height: 2),
|
||||
// pw.Text('NIF: 4000106673 - STAT 95210 11 2017 1 003651',
|
||||
// style: pw.TextStyle(fontSize: 7, fontWeight: pw.FontWeight.bold)),
|
||||
],
|
||||
),
|
||||
],
|
||||
@ -444,9 +425,12 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
pw.Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.center,
|
||||
children: [
|
||||
pw.Text('Date: ${DateFormat('dd/MM/yyyy').format(DateTime.now())}', style: boldClientStyle),
|
||||
pw.Text(
|
||||
'Date: ${DateFormat('dd/MM/yyyy').format(DateTime.now())}',
|
||||
style: boldClientStyle),
|
||||
pw.SizedBox(height: 4),
|
||||
pw.Container(width: 100, height: 2, color: PdfColors.black),
|
||||
pw.Container(
|
||||
width: 100, height: 2, color: PdfColors.black),
|
||||
pw.SizedBox(height: 4),
|
||||
pw.Container(
|
||||
padding: const pw.EdgeInsets.all(6),
|
||||
@ -456,10 +440,13 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
child: pw.Column(
|
||||
children: [
|
||||
pw.Text('Boutique:', style: frameTextStyle),
|
||||
pw.Text('${pointDeVente?['nom'] ?? 'S405A'}', style: boldTextStyle),
|
||||
pw.Text('${pointDeVente?['nom'] ?? 'S405A'}',
|
||||
style: boldTextStyle),
|
||||
pw.SizedBox(height: 2),
|
||||
pw.Text('Bon N°:', style: frameTextStyle),
|
||||
pw.Text('${pointDeVente?['nom'] ?? 'S405A'}-P${commande.id}', style: boldTextStyle),
|
||||
pw.Text(
|
||||
'${pointDeVente?['nom'] ?? 'S405A'}-P${commande.id}',
|
||||
style: boldTextStyle),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -470,7 +457,8 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
pw.Container(
|
||||
width: 120,
|
||||
decoration: pw.BoxDecoration(
|
||||
border: pw.Border.all(color: PdfColors.black, width: 1),
|
||||
border:
|
||||
pw.Border.all(color: PdfColors.black, width: 1),
|
||||
),
|
||||
padding: const pw.EdgeInsets.all(6),
|
||||
child: pw.Column(
|
||||
@ -478,11 +466,20 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
children: [
|
||||
pw.Text('CLIENT', style: frameTextStyle),
|
||||
pw.SizedBox(height: 2),
|
||||
pw.Text('ID: ${pointDeVente?['nom'] ?? 'S405A'}-${client?.id ?? 'Non spécifié'}', style: smallTextStyle),
|
||||
pw.Container(width: 100, height: 1, color: PdfColors.black, margin: const pw.EdgeInsets.symmetric(vertical: 2)),
|
||||
pw.Text('${client?.nom} ${client?.prenom}', style: boldTextStyle),
|
||||
pw.Text(
|
||||
'ID: ${pointDeVente?['nom'] ?? 'S405A'}-${client?.id ?? 'Non spécifié'}',
|
||||
style: smallTextStyle),
|
||||
pw.Container(
|
||||
width: 100,
|
||||
height: 1,
|
||||
color: PdfColors.black,
|
||||
margin: const pw.EdgeInsets.symmetric(
|
||||
vertical: 2)),
|
||||
pw.Text('${client?.nom} \n ${client?.prenom}',
|
||||
style: boldTextStyle),
|
||||
pw.SizedBox(height: 2),
|
||||
pw.Text(client?.telephone ?? 'Non spécifié', style: tinyTextStyle),
|
||||
pw.Text(client?.telephone ?? 'Non spécifié',
|
||||
style: tinyTextStyle),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -491,245 +488,219 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
|
||||
pw.SizedBox(height: 8),
|
||||
|
||||
// ✅ SOLUTION PRINCIPALE: Tableau avec hauteur dynamique
|
||||
pw.Column(
|
||||
children: [
|
||||
// Debug: Afficher le nombre d'articles
|
||||
pw.Text('Articles trouvés: ${detailsAvecProduits.length}',
|
||||
style: pw.TextStyle(fontSize: 8, color: PdfColors.grey, font: regularFont)),
|
||||
pw.SizedBox(height: 5),
|
||||
|
||||
// ✅ TABLE SANS CONTRAINTE DE HAUTEUR - Elle s'adapte au contenu
|
||||
pw.Table(
|
||||
// Tableau des produits (ajusté pour le mode paysage)
|
||||
pw.Expanded(
|
||||
child: pw.Table(
|
||||
border: pw.TableBorder.all(width: 1),
|
||||
columnWidths: {
|
||||
0: const pw.FlexColumnWidth(5), // Désignations
|
||||
1: const pw.FlexColumnWidth(1.2), // Quantité
|
||||
2: const pw.FlexColumnWidth(1.5), // Prix unitaire
|
||||
3: const pw.FlexColumnWidth(1.5), // Montant
|
||||
0: const pw.FlexColumnWidth(5),
|
||||
1: const pw.FlexColumnWidth(1.2),
|
||||
2: const pw.FlexColumnWidth(1.5),
|
||||
3: const pw.FlexColumnWidth(1.5),
|
||||
4: const pw.FlexColumnWidth(1.5),
|
||||
},
|
||||
children: [
|
||||
// En-tête du tableau
|
||||
pw.TableRow(
|
||||
decoration: const pw.BoxDecoration(color: PdfColors.grey200),
|
||||
decoration: const pw.BoxDecoration(
|
||||
color: PdfColors.grey200),
|
||||
children: [
|
||||
pw.Padding(
|
||||
padding: const pw.EdgeInsets.all(4),
|
||||
child: pw.Text('Désignations', style: boldTextStyle)
|
||||
),
|
||||
padding: const pw.EdgeInsets.all(3),
|
||||
child: pw.Text('Désignations',
|
||||
style: boldTextStyle)),
|
||||
pw.Padding(
|
||||
padding: const pw.EdgeInsets.all(4),
|
||||
child: pw.Text('Qté', style: boldTextStyle, textAlign: pw.TextAlign.center)
|
||||
),
|
||||
padding: const pw.EdgeInsets.all(3),
|
||||
child: pw.Text('Qté',
|
||||
style: boldTextStyle,
|
||||
textAlign: pw.TextAlign.center)),
|
||||
pw.Padding(
|
||||
padding: const pw.EdgeInsets.all(4),
|
||||
child: pw.Text('P.U.', style: boldTextStyle, textAlign: pw.TextAlign.right)
|
||||
),
|
||||
padding: const pw.EdgeInsets.all(3),
|
||||
child: pw.Text('P.U.',
|
||||
style: boldTextStyle,
|
||||
textAlign: pw.TextAlign.right)),
|
||||
// pw.Padding(padding: const pw.EdgeInsets.all(3),
|
||||
// child: pw.Text('Remise/Cadeau', style: boldTextStyle, textAlign: pw.TextAlign.center)),
|
||||
pw.Padding(
|
||||
padding: const pw.EdgeInsets.all(4),
|
||||
child: pw.Text('Montant', style: boldTextStyle, textAlign: pw.TextAlign.right)
|
||||
),
|
||||
padding: const pw.EdgeInsets.all(3),
|
||||
child: pw.Text('Montant',
|
||||
style: boldTextStyle,
|
||||
textAlign: pw.TextAlign.right)),
|
||||
],
|
||||
),
|
||||
|
||||
// ✅ TOUTES LES LIGNES DE PRODUITS - SANS LIMITATION
|
||||
...detailsAvecProduits.asMap().entries.map((entry) {
|
||||
final index = entry.key;
|
||||
final item = entry.value;
|
||||
...detailsAvecProduits.map((item) {
|
||||
final detail = item['detail'] as DetailCommande;
|
||||
final produit = item['produit'];
|
||||
|
||||
// Debug pour chaque ligne
|
||||
print('📋 Ligne PDF $index: ${detail.produitNom} (Quantité: ${detail.quantite})');
|
||||
|
||||
return pw.TableRow(
|
||||
decoration: detail.estCadeau
|
||||
? const pw.BoxDecoration(color: PdfColors.green50)
|
||||
? const pw.BoxDecoration(
|
||||
color: PdfColors.green50)
|
||||
: detail.aRemise
|
||||
? const pw.BoxDecoration(color: PdfColors.orange50)
|
||||
: index % 2 == 0
|
||||
? const pw.BoxDecoration(color: PdfColors.grey50)
|
||||
? const pw.BoxDecoration(
|
||||
color: PdfColors.orange50)
|
||||
: null,
|
||||
children: [
|
||||
// ✅ Colonne Désignations - Plus compacte
|
||||
pw.Padding(
|
||||
padding: const pw.EdgeInsets.all(4),
|
||||
padding: const pw.EdgeInsets.all(3),
|
||||
child: pw.Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
mainAxisSize: pw.MainAxisSize.min,
|
||||
crossAxisAlignment:
|
||||
pw.CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Nom du produit avec badge
|
||||
pw.Row(
|
||||
children: [
|
||||
pw.Expanded(
|
||||
child: pw.Text(
|
||||
'${detail.produitNom ?? 'Produit inconnu'}',
|
||||
detail.produitNom ??
|
||||
'Produit inconnu',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: pw.FontWeight.bold,
|
||||
font: regularFont
|
||||
)
|
||||
),
|
||||
fontWeight:
|
||||
pw.FontWeight.bold)),
|
||||
),
|
||||
if (detail.estCadeau)
|
||||
pw.Container(
|
||||
padding: const pw.EdgeInsets.symmetric(horizontal: 3, vertical: 1),
|
||||
padding:
|
||||
const pw.EdgeInsets.symmetric(
|
||||
horizontal: 2,
|
||||
vertical: 1),
|
||||
decoration: pw.BoxDecoration(
|
||||
color: PdfColors.green600,
|
||||
borderRadius: pw.BorderRadius.circular(3),
|
||||
color: PdfColors.green,
|
||||
borderRadius:
|
||||
pw.BorderRadius.circular(2),
|
||||
),
|
||||
child: pw.Text(
|
||||
'CADEAU',
|
||||
child: pw.Text('🎁',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 6,
|
||||
color: PdfColors.white,
|
||||
font: regularFont,
|
||||
fontWeight: pw.FontWeight.bold
|
||||
)
|
||||
),
|
||||
fontSize: 5,
|
||||
color: PdfColors.white)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
pw.SizedBox(height: 2),
|
||||
|
||||
// Informations complémentaires sur une seule ligne
|
||||
if (produit?.category != null &&
|
||||
produit!.category.isNotEmpty)
|
||||
pw.Text(
|
||||
[
|
||||
if (produit?.category?.isNotEmpty == true) produit!.category,
|
||||
if (produit?.marque?.isNotEmpty == true) produit!.marque,
|
||||
if (produit?.imei?.isNotEmpty == true) 'IMEI: ${produit!.imei}',
|
||||
].where((info) => info != null).join(' , '),
|
||||
style: pw.TextStyle(fontSize: 8, color: PdfColors.grey700, font: regularFont),
|
||||
),
|
||||
|
||||
// Spécifications techniques
|
||||
if (produit?.ram?.isNotEmpty == true || produit?.memoireInterne?.isNotEmpty == true || produit?.reference?.isNotEmpty == true)
|
||||
'${produit.category}${produit?.marque != null && produit!.marque.isNotEmpty ? ' - ${produit.marque}' : ''}',
|
||||
style: tinyTextStyle),
|
||||
if (produit?.imei != null &&
|
||||
produit!.imei!.isNotEmpty)
|
||||
pw.Text('IMEI: ${produit.imei}',
|
||||
style: tinyTextStyle),
|
||||
pw.Row(
|
||||
children: [
|
||||
if (produit?.ram != null &&
|
||||
produit!.ram!.isNotEmpty)
|
||||
pw.Text('${produit.ram}',
|
||||
style: smallTextStyle),
|
||||
if (produit?.memoireInterne != null &&
|
||||
produit!
|
||||
.memoireInterne!.isNotEmpty)
|
||||
pw.Text(
|
||||
[
|
||||
if (produit?.ram?.isNotEmpty == true) 'RAM: ${produit!.ram}',
|
||||
if (produit?.memoireInterne?.isNotEmpty == true) 'Stockage: ${produit!.memoireInterne}',
|
||||
if (produit?.reference?.isNotEmpty == true) 'Ref: ${produit!.reference}',
|
||||
].join(' , '),
|
||||
style: pw.TextStyle(fontSize: 8, color: PdfColors.grey600, font: regularFont),
|
||||
' | ${produit.memoireInterne}',
|
||||
style: smallTextStyle),
|
||||
pw.Text(' | ${produit.reference}',
|
||||
style: smallTextStyle),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Colonne Quantité
|
||||
pw.Padding(
|
||||
padding: const pw.EdgeInsets.all(4),
|
||||
child: pw.Text(
|
||||
'${detail.quantite}',
|
||||
padding: const pw.EdgeInsets.all(3),
|
||||
child: pw.Text('${detail.quantite}',
|
||||
style: normalTextStyle,
|
||||
textAlign: pw.TextAlign.center
|
||||
textAlign: pw.TextAlign.center),
|
||||
),
|
||||
),
|
||||
|
||||
// Colonne Prix Unitaire
|
||||
pw.Padding(
|
||||
padding: const pw.EdgeInsets.all(4),
|
||||
padding: const pw.EdgeInsets.all(3),
|
||||
child: pw.Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.end,
|
||||
mainAxisSize: pw.MainAxisSize.min,
|
||||
crossAxisAlignment:
|
||||
pw.CrossAxisAlignment.end,
|
||||
children: [
|
||||
if (detail.estCadeau) ...[
|
||||
pw.Text(
|
||||
'${detail.prixUnitaire.toStringAsFixed(0)}',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 8,
|
||||
decoration: pw.TextDecoration.lineThrough,
|
||||
color: PdfColors.grey600,
|
||||
font: regularFont
|
||||
)
|
||||
),
|
||||
pw.Text(
|
||||
'GRATUIT',
|
||||
decoration: pw
|
||||
.TextDecoration.lineThrough,
|
||||
color: PdfColors.grey600)),
|
||||
pw.Text('GRATUIT',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 9,
|
||||
color: PdfColors.green700,
|
||||
fontWeight: pw.FontWeight.bold,
|
||||
font: regularFont
|
||||
)
|
||||
),
|
||||
fontWeight:
|
||||
pw.FontWeight.bold)),
|
||||
] else if (detail.aRemise) ...[
|
||||
pw.Text(
|
||||
'${detail.prixUnitaire.toStringAsFixed(0)}',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 8,
|
||||
decoration: pw.TextDecoration.lineThrough,
|
||||
color: PdfColors.grey600,
|
||||
font: regularFont
|
||||
)
|
||||
),
|
||||
decoration: pw
|
||||
.TextDecoration.lineThrough,
|
||||
color: PdfColors.grey600)),
|
||||
pw.Text(
|
||||
'${(detail.prixFinal / detail.quantite).toStringAsFixed(0)}',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 10,
|
||||
color: PdfColors.orange700,
|
||||
fontWeight: pw.FontWeight.bold,
|
||||
font: regularFont
|
||||
)
|
||||
),
|
||||
fontSize: 9,
|
||||
color: PdfColors.orange)),
|
||||
] else
|
||||
pw.Text(
|
||||
'${detail.prixUnitaire.toStringAsFixed(0)}',
|
||||
style: smallTextStyle
|
||||
),
|
||||
style: smallTextStyle),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Colonne Montant
|
||||
// pw.Padding(
|
||||
// padding: const pw.EdgeInsets.all(3),
|
||||
// child: pw.Text(
|
||||
// detail.estCadeau
|
||||
// ? 'CADEAU'
|
||||
// : detail.aRemise
|
||||
// ? 'REMISE'
|
||||
// : '-',
|
||||
// style: pw.TextStyle(
|
||||
// fontSize: 9,
|
||||
// color: detail.estCadeau ? PdfColors.green700 : detail.aRemise ? PdfColors.orange : PdfColors.grey600,
|
||||
// fontWeight: detail.estCadeau ? pw.FontWeight.bold : pw.FontWeight.normal,
|
||||
// ),
|
||||
// textAlign: pw.TextAlign.center,
|
||||
// ),
|
||||
// ),
|
||||
pw.Padding(
|
||||
padding: const pw.EdgeInsets.all(4),
|
||||
padding: const pw.EdgeInsets.all(3),
|
||||
child: pw.Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.end,
|
||||
mainAxisSize: pw.MainAxisSize.min,
|
||||
crossAxisAlignment:
|
||||
pw.CrossAxisAlignment.end,
|
||||
children: [
|
||||
if (detail.estCadeau) ...[
|
||||
pw.Text(
|
||||
'${detail.sousTotal.toStringAsFixed(0)}',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 8,
|
||||
decoration: pw.TextDecoration.lineThrough,
|
||||
color: PdfColors.grey600,
|
||||
font: regularFont
|
||||
)
|
||||
),
|
||||
pw.Text(
|
||||
'GRATUIT',
|
||||
decoration: pw
|
||||
.TextDecoration.lineThrough,
|
||||
color: PdfColors.grey600)),
|
||||
pw.Text('GRATUIT',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 9,
|
||||
fontWeight: pw.FontWeight.bold,
|
||||
color: PdfColors.green700,
|
||||
font: regularFont
|
||||
)
|
||||
),
|
||||
color: PdfColors.green700)),
|
||||
] else if (detail.aRemise) ...[
|
||||
pw.Text(
|
||||
'${detail.sousTotal.toStringAsFixed(0)}',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 8,
|
||||
decoration: pw.TextDecoration.lineThrough,
|
||||
color: PdfColors.grey600,
|
||||
font: regularFont
|
||||
)
|
||||
),
|
||||
decoration: pw
|
||||
.TextDecoration.lineThrough,
|
||||
color: PdfColors.grey600)),
|
||||
pw.Text(
|
||||
'${detail.prixFinal.toStringAsFixed(0)}',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: pw.FontWeight.bold,
|
||||
font: regularFont
|
||||
)
|
||||
),
|
||||
fontSize: 9,
|
||||
fontWeight:
|
||||
pw.FontWeight.bold)),
|
||||
] else
|
||||
pw.Text(
|
||||
'${detail.prixFinal.toStringAsFixed(0)}',
|
||||
style: smallTextStyle
|
||||
),
|
||||
style: smallTextStyle),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -738,12 +709,11 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
}).toList(),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
pw.SizedBox(height: 12),
|
||||
pw.SizedBox(height: 8),
|
||||
|
||||
// Section finale - Totaux et signatures
|
||||
// Section finale (ajustée pour le mode paysage)
|
||||
pw.Row(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
children: [
|
||||
@ -757,55 +727,89 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
pw.Row(
|
||||
mainAxisAlignment: pw.MainAxisAlignment.end,
|
||||
children: [
|
||||
pw.Text('SOUS-TOTAL:', style: smallTextStyle),
|
||||
pw.Text('SOUS-TOTAL:',
|
||||
style: smallTextStyle),
|
||||
pw.SizedBox(width: 10),
|
||||
pw.Text('${sousTotal.toStringAsFixed(0)}', style: smallTextStyle),
|
||||
pw.Text('${sousTotal.toStringAsFixed(0)}',
|
||||
style: smallTextStyle),
|
||||
],
|
||||
),
|
||||
pw.SizedBox(height: 2),
|
||||
],
|
||||
|
||||
if (totalRemises > 0) ...[
|
||||
pw.Row(
|
||||
mainAxisAlignment: pw.MainAxisAlignment.end,
|
||||
children: [
|
||||
pw.Text('REMISES:', style: pw.TextStyle(color: PdfColors.orange, fontSize: 10, font: regularFont)),
|
||||
pw.Text('REMISES:',
|
||||
style: pw.TextStyle(
|
||||
color: PdfColors.orange,
|
||||
fontSize: 10)),
|
||||
pw.SizedBox(width: 10),
|
||||
pw.Text('-${totalRemises.toStringAsFixed(0)}', style: pw.TextStyle(color: PdfColors.orange, fontSize: 10, font: regularFont)),
|
||||
pw.Text(
|
||||
'-${totalRemises.toStringAsFixed(0)}',
|
||||
style: pw.TextStyle(
|
||||
color: PdfColors.orange,
|
||||
fontSize: 10)),
|
||||
],
|
||||
),
|
||||
pw.SizedBox(height: 2),
|
||||
],
|
||||
|
||||
if (totalCadeaux > 0) ...[
|
||||
pw.Row(
|
||||
mainAxisAlignment: pw.MainAxisAlignment.end,
|
||||
children: [
|
||||
pw.Text('CADEAUX ($nombreCadeaux):', style: pw.TextStyle(color: PdfColors.green700, fontSize: 10, font: regularFont)),
|
||||
pw.Text('CADEAUX ($nombreCadeaux):',
|
||||
style: pw.TextStyle(
|
||||
color: PdfColors.green700,
|
||||
fontSize: 10)),
|
||||
pw.SizedBox(width: 10),
|
||||
pw.Text('-${totalCadeaux.toStringAsFixed(0)}', style: pw.TextStyle(color: PdfColors.green700, fontSize: 10, font: regularFont)),
|
||||
pw.Text(
|
||||
'-${totalCadeaux.toStringAsFixed(0)}',
|
||||
style: pw.TextStyle(
|
||||
color: PdfColors.green700,
|
||||
fontSize: 10)),
|
||||
],
|
||||
),
|
||||
pw.SizedBox(height: 2),
|
||||
],
|
||||
|
||||
pw.Container(width: 120, height: 1.5, color: PdfColors.black, margin: const pw.EdgeInsets.symmetric(vertical: 2)),
|
||||
|
||||
pw.Container(
|
||||
width: 120,
|
||||
height: 1.5,
|
||||
color: PdfColors.black,
|
||||
margin: const pw.EdgeInsets.symmetric(
|
||||
vertical: 2)),
|
||||
pw.Row(
|
||||
mainAxisAlignment: pw.MainAxisAlignment.end,
|
||||
children: [
|
||||
pw.Text('TOTAL:', style: boldTextStyle),
|
||||
pw.SizedBox(width: 10),
|
||||
pw.Text('${commande.montantTotal.toStringAsFixed(0)} MGA', style: boldTextStyle),
|
||||
pw.Text(
|
||||
'${commande.montantTotal.toStringAsFixed(0)} MGA',
|
||||
style: boldTextStyle),
|
||||
],
|
||||
),
|
||||
if (totalCadeaux > 0) ...[
|
||||
pw.SizedBox(height: 3),
|
||||
pw.Container(
|
||||
padding: const pw.EdgeInsets.all(3),
|
||||
decoration: pw.BoxDecoration(
|
||||
color: PdfColors.green50,
|
||||
borderRadius: pw.BorderRadius.circular(3),
|
||||
),
|
||||
child: pw.Text(
|
||||
'🎁 $nombreCadeaux cadeau(s) offert(s) (${totalCadeaux.toStringAsFixed(0)} MGA)',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 9, color: PdfColors.green700),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
pw.SizedBox(width: 15),
|
||||
|
||||
// Section vendeurs et signatures
|
||||
// Informations vendeurs et signatures
|
||||
pw.Expanded(
|
||||
flex: 3,
|
||||
child: pw.Column(
|
||||
@ -819,32 +823,48 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
borderRadius: pw.BorderRadius.circular(3),
|
||||
),
|
||||
child: pw.Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
pw.CrossAxisAlignment.start,
|
||||
children: [
|
||||
pw.Text('VENDEURS', style: pw.TextStyle(fontSize: 10, fontWeight: pw.FontWeight.bold, font: regularFont)),
|
||||
pw.Text('VENDEURS',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: pw.FontWeight.bold)),
|
||||
pw.SizedBox(height: 3),
|
||||
pw.Row(
|
||||
children: [
|
||||
pw.Expanded(
|
||||
child: pw.Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
pw.CrossAxisAlignment.start,
|
||||
children: [
|
||||
pw.Text('Initiateur:', style: tinyTextStyle),
|
||||
pw.Text('Initiateur:',
|
||||
style: tinyTextStyle),
|
||||
pw.Text(
|
||||
commandeur != null ? '${commandeur.name} ${commandeur.lastName ?? ''}'.trim() : 'N/A',
|
||||
style: pw.TextStyle(fontSize: 9, font: regularFont),
|
||||
commandeur != null
|
||||
? '${commandeur.name} ${commandeur.lastName ?? ''}'
|
||||
.trim()
|
||||
: 'N/A',
|
||||
style:
|
||||
pw.TextStyle(fontSize: 9),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
pw.Expanded(
|
||||
child: pw.Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
pw.CrossAxisAlignment.start,
|
||||
children: [
|
||||
pw.Text('Validateur:', style: tinyTextStyle),
|
||||
pw.Text('Validateur:',
|
||||
style: tinyTextStyle),
|
||||
pw.Text(
|
||||
validateur != null ? '${validateur.name} ${validateur.lastName ?? ''}'.trim() : 'N/A',
|
||||
style: pw.TextStyle(fontSize: 9, font: regularFont),
|
||||
validateur != null
|
||||
? '${validateur.name} ${validateur.lastName ?? ''}'
|
||||
.trim()
|
||||
: 'N/A',
|
||||
style:
|
||||
pw.TextStyle(fontSize: 9),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -859,20 +879,33 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
|
||||
// Signatures
|
||||
pw.Row(
|
||||
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment:
|
||||
pw.MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
pw.Column(
|
||||
children: [
|
||||
pw.Text('Vendeur', style: pw.TextStyle(fontSize: 9, fontWeight: pw.FontWeight.bold, font: regularFont)),
|
||||
pw.Text('Vendeur',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 9,
|
||||
fontWeight: pw.FontWeight.bold)),
|
||||
pw.SizedBox(height: 15),
|
||||
pw.Container(width: 70, height: 1, color: PdfColors.black),
|
||||
pw.Container(
|
||||
width: 70,
|
||||
height: 1,
|
||||
color: PdfColors.black),
|
||||
],
|
||||
),
|
||||
pw.Column(
|
||||
children: [
|
||||
pw.Text('Client', style: pw.TextStyle(fontSize: 9, fontWeight: pw.FontWeight.bold, font: regularFont)),
|
||||
pw.Text('Client',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 9,
|
||||
fontWeight: pw.FontWeight.bold)),
|
||||
pw.SizedBox(height: 15),
|
||||
pw.Container(width: 70, height: 1, color: PdfColors.black),
|
||||
pw.Container(
|
||||
width: 70,
|
||||
height: 1,
|
||||
color: PdfColors.black),
|
||||
],
|
||||
),
|
||||
],
|
||||
@ -883,7 +916,7 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
],
|
||||
),
|
||||
|
||||
pw.SizedBox(height: 6),
|
||||
pw.SizedBox(height: 4),
|
||||
|
||||
// Note finale
|
||||
pw.Text(
|
||||
@ -893,70 +926,61 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// PAGE EN MODE PAYSAGE
|
||||
// PAGE EN MODE PAYSAGE : Les deux exemplaires sur une seule page
|
||||
pdf.addPage(
|
||||
pw.Page(
|
||||
pageFormat: PdfPageFormat.a4.landscape,
|
||||
pageFormat: PdfPageFormat.a4.landscape, // Mode paysage
|
||||
margin: const pw.EdgeInsets.all(12),
|
||||
build: (pw.Context context) {
|
||||
return pw.Row(
|
||||
// Utilisation de Row au lieu de Column pour placer côte à côte
|
||||
children: [
|
||||
pw.Expanded(child: buildExemplaire("CLIENT")),
|
||||
// Premier exemplaire (CLIENT)
|
||||
pw.Expanded(
|
||||
child: buildExemplaire("CLIENT"),
|
||||
),
|
||||
|
||||
pw.SizedBox(width: 15),
|
||||
// ✅ AMÉLIORATION: Remplacer les caractères Unicode par du texte simple
|
||||
|
||||
// Trait de séparation vertical
|
||||
pw.Container(
|
||||
width: 2,
|
||||
height: double.infinity,
|
||||
child: pw.Column(
|
||||
mainAxisAlignment: pw.MainAxisAlignment.center,
|
||||
children: [
|
||||
pw.Container(
|
||||
width: 20,
|
||||
height: 20,
|
||||
decoration: pw.BoxDecoration(
|
||||
shape: pw.BoxShape.circle,
|
||||
border: pw.Border.all(color: PdfColors.black, width: 2),
|
||||
),
|
||||
child: pw.Center(
|
||||
child: pw.Text('X', style: pw.TextStyle(fontSize: 12, fontWeight: pw.FontWeight.bold, font: regularFont)),
|
||||
),
|
||||
),
|
||||
pw.Text('✂️', style: pw.TextStyle(fontSize: 14)),
|
||||
pw.SizedBox(height: 10),
|
||||
pw.Transform.rotate(
|
||||
angle: 1.5708,
|
||||
child: pw.Text('DÉCOUPER ICI', style: pw.TextStyle(fontSize: 10, fontWeight: pw.FontWeight.bold, font: regularFont)),
|
||||
angle: 1.5708, // 90 degrés en radians (π/2)
|
||||
child: pw.Text('DÉCOUPER ICI',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 10, fontWeight: pw.FontWeight.bold)),
|
||||
),
|
||||
pw.SizedBox(height: 10),
|
||||
pw.Container(
|
||||
width: 20,
|
||||
height: 20,
|
||||
decoration: pw.BoxDecoration(
|
||||
shape: pw.BoxShape.circle,
|
||||
border: pw.Border.all(color: PdfColors.black, width: 2),
|
||||
),
|
||||
child: pw.Center(
|
||||
child: pw.Text('X', style: pw.TextStyle(fontSize: 12, fontWeight: pw.FontWeight.bold, font: regularFont)),
|
||||
),
|
||||
),
|
||||
pw.Text('✂️', style: pw.TextStyle(fontSize: 14)),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
pw.SizedBox(width: 15),
|
||||
pw.Expanded(child: buildExemplaire("MAGASIN")),
|
||||
|
||||
// Deuxième exemplaire (MAGASIN)
|
||||
pw.Expanded(
|
||||
child: buildExemplaire("MAGASIN"),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
print('=== RÉSULTAT FINAL ===');
|
||||
print('PDF généré avec ${detailsAvecProduits.length} produits');
|
||||
|
||||
// Sauvegarder le PDF
|
||||
final output = await getTemporaryDirectory();
|
||||
final file = File("${output.path}/bon_livraison_${commande.id}.pdf");
|
||||
@ -2260,6 +2284,14 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> {
|
||||
textAlign: pw.TextAlign.center,
|
||||
),
|
||||
]),
|
||||
pw.Text(
|
||||
'$nombreCadeaux article(s) offert(s)',
|
||||
style: pw.TextStyle(
|
||||
fontSize: 6,
|
||||
color: PdfColors.green600,
|
||||
),
|
||||
textAlign: pw.TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import 'package:youmazgestion/Components/appDrawer.dart';
|
||||
import 'package:youmazgestion/Models/client.dart';
|
||||
import 'package:youmazgestion/Services/stock_managementDatabase.dart';
|
||||
import 'package:youmazgestion/controller/userController.dart';
|
||||
|
||||
class HistoriquePage extends StatefulWidget {
|
||||
const HistoriquePage({super.key});
|
||||
|
||||
@ -20,10 +20,6 @@
|
||||
final List<Commande> _commandes = [];
|
||||
final List<Commande> _filteredCommandes = [];
|
||||
|
||||
List<Map<String, dynamic>> _pointsDeVente = [];
|
||||
String? _selectedPointDeVente;
|
||||
final UserController _userController = Get.find<UserController>();
|
||||
|
||||
bool _isLoading = true;
|
||||
DateTimeRange? _dateRange;
|
||||
|
||||
@ -42,7 +38,6 @@
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadCommandes();
|
||||
_loadPointsDeVenteWithDefault();
|
||||
|
||||
// Listeners pour les filtres
|
||||
_searchController.addListener(_filterCommandes);
|
||||
@ -50,37 +45,6 @@
|
||||
_searchCommandeIdController.addListener(_filterCommandes);
|
||||
}
|
||||
|
||||
|
||||
Future<void> _loadPointsDeVenteWithDefault() async {
|
||||
try {
|
||||
print(_userController.userId);
|
||||
final points = await _appDatabase.getPointsDeVente();
|
||||
setState(() {
|
||||
_pointsDeVente = points;
|
||||
|
||||
if (points.isNotEmpty) {
|
||||
if (_userController.pointDeVenteId > 0) {
|
||||
final userPointDeVente = points.firstWhere(
|
||||
(point) => point['id'] == _userController.pointDeVenteId,
|
||||
orElse: () => <String, dynamic>{},
|
||||
);
|
||||
|
||||
if (userPointDeVente.isNotEmpty) {
|
||||
_selectedPointDeVente = userPointDeVente['nom'] as String;
|
||||
} else {
|
||||
_selectedPointDeVente = points[0]['nom'] as String;
|
||||
}
|
||||
} else {
|
||||
_selectedPointDeVente = points[0]['nom'] as String;
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
Get.snackbar('Erreur', 'Impossible de charger les points de vente: $e');
|
||||
print('❌ Erreur chargement points de vente: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadCommandes() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
@ -88,7 +52,6 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
||||
|
||||
try {
|
||||
final commandes = await _appDatabase.getCommandes();
|
||||
|
||||
setState(() {
|
||||
_commandes.clear();
|
||||
_commandes.addAll(commandes);
|
||||
@ -535,7 +498,6 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
||||
children: [
|
||||
_buildDetailRow('Client', '${client?.nom} ${client?.prenom}', Icons.person),
|
||||
_buildDetailRow('Date', DateFormat('dd/MM/yyyy à HH:mm').format(commande.dateCommande), Icons.calendar_today),
|
||||
_buildDetailRow('Client', '${_selectedPointDeVente} ', Icons.person),
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.assignment, size: 16, color: Colors.grey.shade600),
|
||||
@ -767,8 +729,6 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
||||
// Widget pour l'item de commande (adapté pour mobile)
|
||||
Widget _buildCommandeListItem(Commande commande) {
|
||||
final isMobile = MediaQuery.of(context).size.width < 600;
|
||||
// print(commande.commandeurId);
|
||||
print(_userController.userId);
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
@ -816,13 +776,6 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${_selectedPointDeVente}',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
DateFormat('dd/MM/yyyy').format(commande.dateCommande),
|
||||
style: TextStyle(
|
||||
|
||||
@ -177,7 +177,7 @@ void _login() async {
|
||||
|
||||
// 6. Navigation immédiate
|
||||
if (mounted) {
|
||||
if (userCredentials['role'] == 'commercial' || userCredentials['role'] == 'caisse') {
|
||||
if (userCredentials['role'] == 'commercial') {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const MainLayout()),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
16
pubspec.lock
16
pubspec.lock
@ -37,10 +37,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
|
||||
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.12.0"
|
||||
version: "2.13.0"
|
||||
barcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -181,10 +181,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
version: "1.3.3"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -516,10 +516,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
|
||||
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.8"
|
||||
version: "10.0.9"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1193,10 +1193,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
|
||||
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.3.1"
|
||||
version: "15.0.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user