|
|
@ -189,7 +189,8 @@ class _GestionCommandesPageState extends State<GestionCommandesPage> { |
|
|
content: Column( |
|
|
content: Column( |
|
|
mainAxisSize: MainAxisSize.min, |
|
|
mainAxisSize: MainAxisSize.min, |
|
|
children: [ |
|
|
children: [ |
|
|
Text('Montant total: ${NumberFormat('#,##0', 'fr_FR').format(montantFinal)} MGA'), |
|
|
Text( |
|
|
|
|
|
'Montant total: ${NumberFormat('#,##0', 'fr_FR').format(montantFinal)} MGA'), |
|
|
const SizedBox(height: 10), |
|
|
const SizedBox(height: 10), |
|
|
TextField( |
|
|
TextField( |
|
|
controller: amountController, |
|
|
controller: amountController, |
|
|
@ -293,7 +294,6 @@ Future<void> _generateBonLivraison(Commande commande) async { |
|
|
} |
|
|
} |
|
|
final pointDeVente = pointDeVenteComplet; |
|
|
final pointDeVente = pointDeVenteComplet; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Récupérer les informations des vendeurs |
|
|
// Récupérer les informations des vendeurs |
|
|
final commandeur = commande.commandeurId != null |
|
|
final commandeur = commande.commandeurId != null |
|
|
? await _database.getUserById(commande.commandeurId!) |
|
|
? await _database.getUserById(commande.commandeurId!) |
|
|
@ -318,7 +318,6 @@ Future<void> _generateBonLivraison(Commande commande) async { |
|
|
print('==============================='); |
|
|
print('==============================='); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Infos par défaut si aucune info personnalisée |
|
|
// Infos par défaut si aucune info personnalisée |
|
|
final infosLivraisonDefaut = [ |
|
|
final infosLivraisonDefaut = [ |
|
|
'REMAX Andravoangy', |
|
|
'REMAX Andravoangy', |
|
|
@ -394,8 +393,10 @@ Future<void> _generateBonLivraison(Commande commande) async { |
|
|
pw.Font? regularFont; |
|
|
pw.Font? regularFont; |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
italicFont = pw.Font.ttf(await rootBundle.load('assets/fonts/Roboto-Italic.ttf')); |
|
|
italicFont = |
|
|
regularFont = pw.Font.ttf(await rootBundle.load('assets/fonts/Roboto-Regular.ttf')); |
|
|
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) { |
|
|
} catch (e) { |
|
|
print('⚠️ Impossible de charger les polices personnalisées: $e'); |
|
|
print('⚠️ Impossible de charger les polices personnalisées: $e'); |
|
|
} |
|
|
} |
|
|
@ -404,11 +405,19 @@ Future<void> _generateBonLivraison(Commande commande) async { |
|
|
final tinyTextStyle = pw.TextStyle(fontSize: 9, font: regularFont); |
|
|
final tinyTextStyle = pw.TextStyle(fontSize: 9, font: regularFont); |
|
|
final smallTextStyle = pw.TextStyle(fontSize: 10, font: regularFont); |
|
|
final smallTextStyle = pw.TextStyle(fontSize: 10, font: regularFont); |
|
|
final normalTextStyle = pw.TextStyle(fontSize: 11, font: regularFont); |
|
|
final normalTextStyle = pw.TextStyle(fontSize: 11, font: regularFont); |
|
|
final boldTextStyle = pw.TextStyle(fontSize: 11, fontWeight: pw.FontWeight.bold, font: regularFont); |
|
|
final boldTextStyle = pw.TextStyle( |
|
|
final boldClientStyle = pw.TextStyle(fontSize: 12, fontWeight: pw.FontWeight.bold, font: regularFont); |
|
|
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 frameTextStyle = pw.TextStyle(fontSize: 10, font: regularFont); |
|
|
final italicTextStyle = pw.TextStyle(fontSize: 9, fontWeight: pw.FontWeight.bold, font: italicFont ?? regularFont); |
|
|
final italicTextStyle = pw.TextStyle( |
|
|
final italicLogoStyle = pw.TextStyle(fontSize: 8, fontWeight: pw.FontWeight.bold, font: italicFont ?? regularFont); |
|
|
fontSize: 9, |
|
|
|
|
|
fontWeight: pw.FontWeight.bold, |
|
|
|
|
|
font: italicFont ?? regularFont); |
|
|
|
|
|
final italicLogoStyle = pw.TextStyle( |
|
|
|
|
|
fontSize: 8, |
|
|
|
|
|
fontWeight: pw.FontWeight.bold, |
|
|
|
|
|
font: italicFont ?? regularFont); |
|
|
Future<pw.Widget> buildLogoWidget() async { |
|
|
Future<pw.Widget> buildLogoWidget() async { |
|
|
final logoRaw = pointDeVenteComplet?['logo']; |
|
|
final logoRaw = pointDeVenteComplet?['logo']; |
|
|
|
|
|
|
|
|
@ -424,7 +433,8 @@ Future<void> _generateBonLivraison(Commande commande) async { |
|
|
dynamic blobDynamic = logoRaw; |
|
|
dynamic blobDynamic = logoRaw; |
|
|
bytes = blobDynamic.toBytes(); |
|
|
bytes = blobDynamic.toBytes(); |
|
|
} else { |
|
|
} else { |
|
|
throw Exception("Format de logo non supporté: ${logoRaw.runtimeType}"); |
|
|
throw Exception( |
|
|
|
|
|
"Format de logo non supporté: ${logoRaw.runtimeType}"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
final imageLogo = pw.MemoryImage(bytes); |
|
|
final imageLogo = pw.MemoryImage(bytes); |
|
|
@ -436,12 +446,12 @@ Future<void> _generateBonLivraison(Commande commande) async { |
|
|
return pw.Image(image, width: 100, height: 100); |
|
|
return pw.Image(image, width: 100, height: 100); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final logoWidget = await buildLogoWidget(); |
|
|
final logoWidget = await buildLogoWidget(); |
|
|
|
|
|
|
|
|
// ✅ FONCTION POUR CONSTRUIRE L'EN-TÊTE DYNAMIQUE |
|
|
// ✅ FONCTION POUR CONSTRUIRE L'EN-TÊTE DYNAMIQUE |
|
|
pw.Widget buildEnteteInfos() { |
|
|
pw.Widget buildEnteteInfos() { |
|
|
final infosAUtiliser = infosLivraison.isNotEmpty ? infosLivraison : infosLivraisonDefaut; |
|
|
final infosAUtiliser = |
|
|
|
|
|
infosLivraison.isNotEmpty ? infosLivraison : infosLivraisonDefaut; |
|
|
|
|
|
|
|
|
return pw.Column( |
|
|
return pw.Column( |
|
|
crossAxisAlignment: pw.CrossAxisAlignment.start, |
|
|
crossAxisAlignment: pw.CrossAxisAlignment.start, |
|
|
@ -469,7 +479,9 @@ final logoWidget = await buildLogoWidget(); |
|
|
width: double.infinity, |
|
|
width: double.infinity, |
|
|
padding: const pw.EdgeInsets.all(5), |
|
|
padding: const pw.EdgeInsets.all(5), |
|
|
decoration: pw.BoxDecoration( |
|
|
decoration: pw.BoxDecoration( |
|
|
color: typeExemplaire == "CLIENT" ? PdfColors.blue100 : PdfColors.green100, |
|
|
color: typeExemplaire == "CLIENT" |
|
|
|
|
|
? PdfColors.blue100 |
|
|
|
|
|
: PdfColors.green100, |
|
|
), |
|
|
), |
|
|
child: pw.Center( |
|
|
child: pw.Center( |
|
|
child: pw.Text( |
|
|
child: pw.Text( |
|
|
@ -477,7 +489,9 @@ final logoWidget = await buildLogoWidget(); |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 14, |
|
|
fontSize: 14, |
|
|
fontWeight: pw.FontWeight.bold, |
|
|
fontWeight: pw.FontWeight.bold, |
|
|
color: typeExemplaire == "CLIENT" ? PdfColors.blue800 : PdfColors.green800, |
|
|
color: typeExemplaire == "CLIENT" |
|
|
|
|
|
? PdfColors.blue800 |
|
|
|
|
|
: PdfColors.green800, |
|
|
font: regularFont, |
|
|
font: regularFont, |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
@ -500,7 +514,8 @@ final logoWidget = await buildLogoWidget(); |
|
|
children: [ |
|
|
children: [ |
|
|
logoWidget, |
|
|
logoWidget, |
|
|
pw.SizedBox(height: 3), |
|
|
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.SizedBox(height: 4), |
|
|
buildEnteteInfos(), // ✅ EN-TÊTE DYNAMIQUE ICI |
|
|
buildEnteteInfos(), // ✅ EN-TÊTE DYNAMIQUE ICI |
|
|
], |
|
|
], |
|
|
@ -510,9 +525,12 @@ final logoWidget = await buildLogoWidget(); |
|
|
pw.Column( |
|
|
pw.Column( |
|
|
crossAxisAlignment: pw.CrossAxisAlignment.center, |
|
|
crossAxisAlignment: pw.CrossAxisAlignment.center, |
|
|
children: [ |
|
|
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.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.SizedBox(height: 4), |
|
|
pw.Container( |
|
|
pw.Container( |
|
|
padding: const pw.EdgeInsets.all(6), |
|
|
padding: const pw.EdgeInsets.all(6), |
|
|
@ -522,10 +540,13 @@ final logoWidget = await buildLogoWidget(); |
|
|
child: pw.Column( |
|
|
child: pw.Column( |
|
|
children: [ |
|
|
children: [ |
|
|
pw.Text('Boutique:', style: frameTextStyle), |
|
|
pw.Text('Boutique:', style: frameTextStyle), |
|
|
pw.Text('${pointDeVente?['nom'] ?? 'S405A'}', style: boldTextStyle), |
|
|
pw.Text('${pointDeVente?['nom'] ?? 'S405A'}', |
|
|
|
|
|
style: boldTextStyle), |
|
|
pw.SizedBox(height: 2), |
|
|
pw.SizedBox(height: 2), |
|
|
pw.Text('Bon N°:', style: frameTextStyle), |
|
|
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), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
@ -536,7 +557,8 @@ final logoWidget = await buildLogoWidget(); |
|
|
pw.Container( |
|
|
pw.Container( |
|
|
width: 120, |
|
|
width: 120, |
|
|
decoration: pw.BoxDecoration( |
|
|
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), |
|
|
padding: const pw.EdgeInsets.all(6), |
|
|
child: pw.Column( |
|
|
child: pw.Column( |
|
|
@ -544,11 +566,20 @@ final logoWidget = await buildLogoWidget(); |
|
|
children: [ |
|
|
children: [ |
|
|
pw.Text('CLIENT', style: frameTextStyle), |
|
|
pw.Text('CLIENT', style: frameTextStyle), |
|
|
pw.SizedBox(height: 2), |
|
|
pw.SizedBox(height: 2), |
|
|
pw.Text('ID: ${pointDeVente?['nom'] ?? 'S405A'}-${client?.id ?? 'Non spécifié'}', style: smallTextStyle), |
|
|
pw.Text( |
|
|
pw.Container(width: 100, height: 1, color: PdfColors.black, margin: const pw.EdgeInsets.symmetric(vertical: 2)), |
|
|
'ID: ${pointDeVente?['nom'] ?? 'S405A'}-${client?.id ?? 'Non spécifié'}', |
|
|
pw.Text('${client?.nom} ${client?.prenom}', style: boldTextStyle), |
|
|
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.SizedBox(height: 2), |
|
|
pw.SizedBox(height: 2), |
|
|
pw.Text(client?.telephone ?? 'Non spécifié', style: tinyTextStyle), |
|
|
pw.Text(client?.telephone ?? 'Non spécifié', |
|
|
|
|
|
style: tinyTextStyle), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
@ -562,7 +593,10 @@ final logoWidget = await buildLogoWidget(); |
|
|
children: [ |
|
|
children: [ |
|
|
// Debug: Afficher le nombre d'articles |
|
|
// Debug: Afficher le nombre d'articles |
|
|
pw.Text('Articles trouvés: ${detailsAvecProduits.length}', |
|
|
pw.Text('Articles trouvés: ${detailsAvecProduits.length}', |
|
|
style: pw.TextStyle(fontSize: 8, color: PdfColors.grey, font: regularFont)), |
|
|
style: pw.TextStyle( |
|
|
|
|
|
fontSize: 8, |
|
|
|
|
|
color: PdfColors.grey, |
|
|
|
|
|
font: regularFont)), |
|
|
pw.SizedBox(height: 5), |
|
|
pw.SizedBox(height: 5), |
|
|
|
|
|
|
|
|
// ✅ TABLE SANS CONTRAINTE DE HAUTEUR - Elle s'adapte au contenu |
|
|
// ✅ TABLE SANS CONTRAINTE DE HAUTEUR - Elle s'adapte au contenu |
|
|
@ -577,24 +611,28 @@ final logoWidget = await buildLogoWidget(); |
|
|
children: [ |
|
|
children: [ |
|
|
// En-tête du tableau |
|
|
// En-tête du tableau |
|
|
pw.TableRow( |
|
|
pw.TableRow( |
|
|
decoration: const pw.BoxDecoration(color: PdfColors.grey200), |
|
|
decoration: const pw.BoxDecoration( |
|
|
|
|
|
color: PdfColors.grey200), |
|
|
children: [ |
|
|
children: [ |
|
|
pw.Padding( |
|
|
pw.Padding( |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
child: pw.Text('Désignations', style: boldTextStyle) |
|
|
child: pw.Text('Désignations', |
|
|
), |
|
|
style: boldTextStyle)), |
|
|
pw.Padding( |
|
|
pw.Padding( |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
child: pw.Text('Qté', style: boldTextStyle, textAlign: pw.TextAlign.center) |
|
|
child: pw.Text('Qté', |
|
|
), |
|
|
style: boldTextStyle, |
|
|
|
|
|
textAlign: pw.TextAlign.center)), |
|
|
pw.Padding( |
|
|
pw.Padding( |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
child: pw.Text('P.U.', style: boldTextStyle, textAlign: pw.TextAlign.right) |
|
|
child: pw.Text('P.U.', |
|
|
), |
|
|
style: boldTextStyle, |
|
|
|
|
|
textAlign: pw.TextAlign.right)), |
|
|
pw.Padding( |
|
|
pw.Padding( |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
child: pw.Text('Montant', style: boldTextStyle, textAlign: pw.TextAlign.right) |
|
|
child: pw.Text('Montant', |
|
|
), |
|
|
style: boldTextStyle, |
|
|
|
|
|
textAlign: pw.TextAlign.right)), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
|
|
|
|
|
|
@ -606,22 +644,27 @@ final logoWidget = await buildLogoWidget(); |
|
|
final produit = item['produit']; |
|
|
final produit = item['produit']; |
|
|
|
|
|
|
|
|
// Debug pour chaque ligne |
|
|
// Debug pour chaque ligne |
|
|
print('📋 Ligne PDF $index: ${detail.produitNom} (Quantité: ${detail.quantite})'); |
|
|
print( |
|
|
|
|
|
'📋 Ligne PDF $index: ${detail.produitNom} (Quantité: ${detail.quantite})'); |
|
|
|
|
|
|
|
|
return pw.TableRow( |
|
|
return pw.TableRow( |
|
|
decoration: detail.estCadeau |
|
|
decoration: detail.estCadeau |
|
|
? const pw.BoxDecoration(color: PdfColors.green50) |
|
|
? const pw.BoxDecoration( |
|
|
|
|
|
color: PdfColors.green50) |
|
|
: detail.aRemise |
|
|
: detail.aRemise |
|
|
? const pw.BoxDecoration(color: PdfColors.orange50) |
|
|
? const pw.BoxDecoration( |
|
|
|
|
|
color: PdfColors.orange50) |
|
|
: index % 2 == 0 |
|
|
: index % 2 == 0 |
|
|
? const pw.BoxDecoration(color: PdfColors.grey50) |
|
|
? const pw.BoxDecoration( |
|
|
|
|
|
color: PdfColors.grey50) |
|
|
: null, |
|
|
: null, |
|
|
children: [ |
|
|
children: [ |
|
|
// ✅ Colonne Désignations - Plus compacte |
|
|
// ✅ Colonne Désignations - Plus compacte |
|
|
pw.Padding( |
|
|
pw.Padding( |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
child: pw.Column( |
|
|
child: pw.Column( |
|
|
crossAxisAlignment: pw.CrossAxisAlignment.start, |
|
|
crossAxisAlignment: |
|
|
|
|
|
pw.CrossAxisAlignment.start, |
|
|
mainAxisSize: pw.MainAxisSize.min, |
|
|
mainAxisSize: pw.MainAxisSize.min, |
|
|
children: [ |
|
|
children: [ |
|
|
// Nom du produit avec badge |
|
|
// Nom du produit avec badge |
|
|
@ -632,27 +675,28 @@ final logoWidget = await buildLogoWidget(); |
|
|
'${detail.produitNom ?? 'Produit inconnu'}', |
|
|
'${detail.produitNom ?? 'Produit inconnu'}', |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 10, |
|
|
fontSize: 10, |
|
|
fontWeight: pw.FontWeight.bold, |
|
|
fontWeight: |
|
|
font: regularFont |
|
|
pw.FontWeight.bold, |
|
|
) |
|
|
font: regularFont)), |
|
|
), |
|
|
|
|
|
), |
|
|
), |
|
|
if (detail.estCadeau) |
|
|
if (detail.estCadeau) |
|
|
pw.Container( |
|
|
pw.Container( |
|
|
padding: const pw.EdgeInsets.symmetric(horizontal: 3, vertical: 1), |
|
|
padding: |
|
|
|
|
|
const pw.EdgeInsets.symmetric( |
|
|
|
|
|
horizontal: 3, |
|
|
|
|
|
vertical: 1), |
|
|
decoration: pw.BoxDecoration( |
|
|
decoration: pw.BoxDecoration( |
|
|
color: PdfColors.green600, |
|
|
color: PdfColors.green600, |
|
|
borderRadius: pw.BorderRadius.circular(3), |
|
|
borderRadius: |
|
|
|
|
|
pw.BorderRadius.circular(3), |
|
|
), |
|
|
), |
|
|
child: pw.Text( |
|
|
child: pw.Text('CADEAU', |
|
|
'CADEAU', |
|
|
|
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 6, |
|
|
fontSize: 6, |
|
|
color: PdfColors.white, |
|
|
color: PdfColors.white, |
|
|
font: regularFont, |
|
|
font: regularFont, |
|
|
fontWeight: pw.FontWeight.bold |
|
|
fontWeight: |
|
|
) |
|
|
pw.FontWeight.bold)), |
|
|
), |
|
|
|
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
@ -662,22 +706,47 @@ final logoWidget = await buildLogoWidget(); |
|
|
// Informations complémentaires sur une seule ligne |
|
|
// Informations complémentaires sur une seule ligne |
|
|
pw.Text( |
|
|
pw.Text( |
|
|
[ |
|
|
[ |
|
|
if (produit?.category?.isNotEmpty == true) produit!.category, |
|
|
if (produit?.category?.isNotEmpty == |
|
|
if (produit?.marque?.isNotEmpty == true) produit!.marque, |
|
|
true) |
|
|
if (produit?.imei?.isNotEmpty == true) 'IMEI: ${produit!.imei}', |
|
|
produit!.category, |
|
|
].where((info) => info != null).join(' , '), |
|
|
if (produit?.marque?.isNotEmpty == |
|
|
style: pw.TextStyle(fontSize: 8, color: PdfColors.grey700, font: regularFont), |
|
|
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 |
|
|
// Spécifications techniques |
|
|
if (produit?.ram?.isNotEmpty == true || produit?.memoireInterne?.isNotEmpty == true || produit?.reference?.isNotEmpty == true) |
|
|
if (produit?.ram?.isNotEmpty == true || |
|
|
|
|
|
produit?.memoireInterne?.isNotEmpty == |
|
|
|
|
|
true || |
|
|
|
|
|
produit?.reference?.isNotEmpty == |
|
|
|
|
|
true) |
|
|
pw.Text( |
|
|
pw.Text( |
|
|
[ |
|
|
[ |
|
|
if (produit?.ram?.isNotEmpty == true) 'RAM: ${produit!.ram}', |
|
|
if (produit?.ram?.isNotEmpty == |
|
|
if (produit?.memoireInterne?.isNotEmpty == true) 'Stockage: ${produit!.memoireInterne}', |
|
|
true) |
|
|
if (produit?.reference?.isNotEmpty == true) 'Ref: ${produit!.reference}', |
|
|
'RAM: ${produit!.ram}', |
|
|
|
|
|
if (produit?.memoireInterne |
|
|
|
|
|
?.isNotEmpty == |
|
|
|
|
|
true) |
|
|
|
|
|
'Stockage: ${produit!.memoireInterne}', |
|
|
|
|
|
if (produit |
|
|
|
|
|
?.reference?.isNotEmpty == |
|
|
|
|
|
true) |
|
|
|
|
|
'Ref: ${produit!.reference}', |
|
|
].join(' , '), |
|
|
].join(' , '), |
|
|
style: pw.TextStyle(fontSize: 8, color: PdfColors.grey600, font: regularFont), |
|
|
style: pw.TextStyle( |
|
|
|
|
|
fontSize: 8, |
|
|
|
|
|
color: PdfColors.grey600, |
|
|
|
|
|
font: regularFont), |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
@ -686,18 +755,17 @@ final logoWidget = await buildLogoWidget(); |
|
|
// Colonne Quantité |
|
|
// Colonne Quantité |
|
|
pw.Padding( |
|
|
pw.Padding( |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
child: pw.Text( |
|
|
child: pw.Text('${detail.quantite}', |
|
|
'${detail.quantite}', |
|
|
|
|
|
style: normalTextStyle, |
|
|
style: normalTextStyle, |
|
|
textAlign: pw.TextAlign.center |
|
|
textAlign: pw.TextAlign.center), |
|
|
), |
|
|
|
|
|
), |
|
|
), |
|
|
|
|
|
|
|
|
// Colonne Prix Unitaire |
|
|
// Colonne Prix Unitaire |
|
|
pw.Padding( |
|
|
pw.Padding( |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
child: pw.Column( |
|
|
child: pw.Column( |
|
|
crossAxisAlignment: pw.CrossAxisAlignment.end, |
|
|
crossAxisAlignment: |
|
|
|
|
|
pw.CrossAxisAlignment.end, |
|
|
mainAxisSize: pw.MainAxisSize.min, |
|
|
mainAxisSize: pw.MainAxisSize.min, |
|
|
children: [ |
|
|
children: [ |
|
|
if (detail.estCadeau) ...[ |
|
|
if (detail.estCadeau) ...[ |
|
|
@ -705,44 +773,37 @@ final logoWidget = await buildLogoWidget(); |
|
|
'${NumberFormat('#,##0', 'fr_FR').format(detail.prixUnitaire)}', |
|
|
'${NumberFormat('#,##0', 'fr_FR').format(detail.prixUnitaire)}', |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 8, |
|
|
fontSize: 8, |
|
|
decoration: pw.TextDecoration.lineThrough, |
|
|
decoration: pw |
|
|
|
|
|
.TextDecoration.lineThrough, |
|
|
color: PdfColors.grey600, |
|
|
color: PdfColors.grey600, |
|
|
font: regularFont |
|
|
font: regularFont)), |
|
|
) |
|
|
pw.Text('GRATUIT', |
|
|
), |
|
|
|
|
|
pw.Text( |
|
|
|
|
|
'GRATUIT', |
|
|
|
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 9, |
|
|
fontSize: 9, |
|
|
color: PdfColors.green700, |
|
|
color: PdfColors.green700, |
|
|
fontWeight: pw.FontWeight.bold, |
|
|
fontWeight: pw.FontWeight.bold, |
|
|
font: regularFont |
|
|
font: regularFont)), |
|
|
) |
|
|
|
|
|
), |
|
|
|
|
|
] else if (detail.aRemise) ...[ |
|
|
] else if (detail.aRemise) ...[ |
|
|
pw.Text( |
|
|
pw.Text( |
|
|
'${NumberFormat('#,##0', 'fr_FR').format(detail.prixUnitaire)}', |
|
|
'${NumberFormat('#,##0', 'fr_FR').format(detail.prixUnitaire)}', |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 8, |
|
|
fontSize: 8, |
|
|
decoration: pw.TextDecoration.lineThrough, |
|
|
decoration: pw |
|
|
|
|
|
.TextDecoration.lineThrough, |
|
|
color: PdfColors.grey600, |
|
|
color: PdfColors.grey600, |
|
|
font: regularFont |
|
|
font: regularFont)), |
|
|
) |
|
|
|
|
|
), |
|
|
|
|
|
pw.Text( |
|
|
pw.Text( |
|
|
'${NumberFormat('#,##0', 'fr_FR').format(detail.prixFinal / detail.quantite)}', |
|
|
'${NumberFormat('#,##0', 'fr_FR').format(detail.prixFinal / detail.quantite)}', |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 10, |
|
|
fontSize: 10, |
|
|
color: PdfColors.orange700, |
|
|
color: PdfColors.orange700, |
|
|
fontWeight: pw.FontWeight.bold, |
|
|
fontWeight: pw.FontWeight.bold, |
|
|
font: regularFont |
|
|
font: regularFont)), |
|
|
) |
|
|
|
|
|
), |
|
|
|
|
|
] else |
|
|
] else |
|
|
pw.Text( |
|
|
pw.Text( |
|
|
NumberFormat('#,##0', 'fr_FR').format(detail.prixUnitaire), |
|
|
NumberFormat('#,##0', 'fr_FR') |
|
|
style: smallTextStyle |
|
|
.format(detail.prixUnitaire), |
|
|
), |
|
|
style: smallTextStyle), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
@ -751,51 +812,45 @@ final logoWidget = await buildLogoWidget(); |
|
|
pw.Padding( |
|
|
pw.Padding( |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
padding: const pw.EdgeInsets.all(4), |
|
|
child: pw.Column( |
|
|
child: pw.Column( |
|
|
crossAxisAlignment: pw.CrossAxisAlignment.end, |
|
|
crossAxisAlignment: |
|
|
|
|
|
pw.CrossAxisAlignment.end, |
|
|
mainAxisSize: pw.MainAxisSize.min, |
|
|
mainAxisSize: pw.MainAxisSize.min, |
|
|
children: [ |
|
|
children: [ |
|
|
if (detail.estCadeau) ...[ |
|
|
if (detail.estCadeau) ...[ |
|
|
pw.Text( |
|
|
pw.Text( |
|
|
NumberFormat('#,##0', 'fr_FR').format(detail.sousTotal), |
|
|
NumberFormat('#,##0', 'fr_FR') |
|
|
|
|
|
.format(detail.sousTotal), |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 8, |
|
|
fontSize: 8, |
|
|
decoration: pw.TextDecoration.lineThrough, |
|
|
decoration: pw |
|
|
|
|
|
.TextDecoration.lineThrough, |
|
|
color: PdfColors.grey600, |
|
|
color: PdfColors.grey600, |
|
|
font: regularFont |
|
|
font: regularFont)), |
|
|
) |
|
|
pw.Text('GRATUIT', |
|
|
), |
|
|
|
|
|
pw.Text( |
|
|
|
|
|
'GRATUIT', |
|
|
|
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 9, |
|
|
fontSize: 9, |
|
|
fontWeight: pw.FontWeight.bold, |
|
|
fontWeight: pw.FontWeight.bold, |
|
|
color: PdfColors.green700, |
|
|
color: PdfColors.green700, |
|
|
font: regularFont |
|
|
font: regularFont)), |
|
|
) |
|
|
|
|
|
), |
|
|
|
|
|
] else if (detail.aRemise) ...[ |
|
|
] else if (detail.aRemise) ...[ |
|
|
pw.Text( |
|
|
pw.Text( |
|
|
'${NumberFormat('#,##0', 'fr_FR').format(detail.sousTotal)}', |
|
|
'${NumberFormat('#,##0', 'fr_FR').format(detail.sousTotal)}', |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 8, |
|
|
fontSize: 8, |
|
|
decoration: pw.TextDecoration.lineThrough, |
|
|
decoration: pw |
|
|
|
|
|
.TextDecoration.lineThrough, |
|
|
color: PdfColors.grey600, |
|
|
color: PdfColors.grey600, |
|
|
font: regularFont |
|
|
font: regularFont)), |
|
|
) |
|
|
|
|
|
), |
|
|
|
|
|
pw.Text( |
|
|
pw.Text( |
|
|
'${NumberFormat('#,##0', 'fr_FR').format(detail.prixFinal)}', |
|
|
'${NumberFormat('#,##0', 'fr_FR').format(detail.prixFinal)}', |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 10, |
|
|
fontSize: 10, |
|
|
fontWeight: pw.FontWeight.bold, |
|
|
fontWeight: pw.FontWeight.bold, |
|
|
font: regularFont |
|
|
font: regularFont)), |
|
|
) |
|
|
|
|
|
), |
|
|
|
|
|
] else |
|
|
] else |
|
|
pw.Text( |
|
|
pw.Text( |
|
|
'${NumberFormat('#,##0', 'fr_FR').format(detail.prixFinal)}', |
|
|
'${NumberFormat('#,##0', 'fr_FR').format(detail.prixFinal)}', |
|
|
style: smallTextStyle |
|
|
style: smallTextStyle), |
|
|
), |
|
|
|
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
@ -825,44 +880,67 @@ final logoWidget = await buildLogoWidget(); |
|
|
children: [ |
|
|
children: [ |
|
|
pw.Text('SOUS-TOTAL:', style: smallTextStyle), |
|
|
pw.Text('SOUS-TOTAL:', style: smallTextStyle), |
|
|
pw.SizedBox(width: 10), |
|
|
pw.SizedBox(width: 10), |
|
|
pw.Text('${NumberFormat('#,##0', 'fr_FR').format(sousTotal)}', style: smallTextStyle), |
|
|
pw.Text( |
|
|
|
|
|
'${NumberFormat('#,##0', 'fr_FR').format(sousTotal)}', |
|
|
|
|
|
style: smallTextStyle), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
pw.SizedBox(height: 2), |
|
|
pw.SizedBox(height: 2), |
|
|
], |
|
|
], |
|
|
|
|
|
|
|
|
if (totalRemises > 0) ...[ |
|
|
if (totalRemises > 0) ...[ |
|
|
pw.Row( |
|
|
pw.Row( |
|
|
mainAxisAlignment: pw.MainAxisAlignment.end, |
|
|
mainAxisAlignment: pw.MainAxisAlignment.end, |
|
|
children: [ |
|
|
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, |
|
|
|
|
|
font: regularFont)), |
|
|
pw.SizedBox(width: 10), |
|
|
pw.SizedBox(width: 10), |
|
|
pw.Text('-${NumberFormat('#,##0', 'fr_FR').format(totalRemises)}', style: pw.TextStyle(color: PdfColors.orange, fontSize: 10, font: regularFont)), |
|
|
pw.Text( |
|
|
|
|
|
'-${NumberFormat('#,##0', 'fr_FR').format(totalRemises)}', |
|
|
|
|
|
style: pw.TextStyle( |
|
|
|
|
|
color: PdfColors.orange, |
|
|
|
|
|
fontSize: 10, |
|
|
|
|
|
font: regularFont)), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
pw.SizedBox(height: 2), |
|
|
pw.SizedBox(height: 2), |
|
|
], |
|
|
], |
|
|
|
|
|
|
|
|
if (totalCadeaux > 0) ...[ |
|
|
if (totalCadeaux > 0) ...[ |
|
|
pw.Row( |
|
|
pw.Row( |
|
|
mainAxisAlignment: pw.MainAxisAlignment.end, |
|
|
mainAxisAlignment: pw.MainAxisAlignment.end, |
|
|
children: [ |
|
|
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, |
|
|
|
|
|
font: regularFont)), |
|
|
pw.SizedBox(width: 10), |
|
|
pw.SizedBox(width: 10), |
|
|
pw.Text('-${NumberFormat('#,##0', 'fr_FR').format(totalCadeaux)}', style: pw.TextStyle(color: PdfColors.green700, fontSize: 10, font: regularFont)), |
|
|
pw.Text( |
|
|
|
|
|
'-${NumberFormat('#,##0', 'fr_FR').format(totalCadeaux)}', |
|
|
|
|
|
style: pw.TextStyle( |
|
|
|
|
|
color: PdfColors.green700, |
|
|
|
|
|
fontSize: 10, |
|
|
|
|
|
font: regularFont)), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
pw.SizedBox(height: 2), |
|
|
pw.SizedBox(height: 2), |
|
|
], |
|
|
], |
|
|
|
|
|
pw.Container( |
|
|
pw.Container(width: 120, height: 1.5, color: PdfColors.black, margin: const pw.EdgeInsets.symmetric(vertical: 2)), |
|
|
width: 120, |
|
|
|
|
|
height: 1.5, |
|
|
|
|
|
color: PdfColors.black, |
|
|
|
|
|
margin: |
|
|
|
|
|
const pw.EdgeInsets.symmetric(vertical: 2)), |
|
|
pw.Row( |
|
|
pw.Row( |
|
|
mainAxisAlignment: pw.MainAxisAlignment.end, |
|
|
mainAxisAlignment: pw.MainAxisAlignment.end, |
|
|
children: [ |
|
|
children: [ |
|
|
pw.Text('TOTAL:', style: boldTextStyle), |
|
|
pw.Text('TOTAL:', style: boldTextStyle), |
|
|
pw.SizedBox(width: 10), |
|
|
pw.SizedBox(width: 10), |
|
|
pw.Text('${NumberFormat('#,##0', 'fr_FR').format(commande.montantTotal)} MGA', style: boldTextStyle), |
|
|
pw.Text( |
|
|
|
|
|
'${NumberFormat('#,##0', 'fr_FR').format(commande.montantTotal)} MGA', |
|
|
|
|
|
style: boldTextStyle), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
@ -887,30 +965,48 @@ final logoWidget = await buildLogoWidget(); |
|
|
child: pw.Column( |
|
|
child: pw.Column( |
|
|
crossAxisAlignment: pw.CrossAxisAlignment.start, |
|
|
crossAxisAlignment: pw.CrossAxisAlignment.start, |
|
|
children: [ |
|
|
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, |
|
|
|
|
|
font: regularFont)), |
|
|
pw.SizedBox(height: 3), |
|
|
pw.SizedBox(height: 3), |
|
|
pw.Row( |
|
|
pw.Row( |
|
|
children: [ |
|
|
children: [ |
|
|
pw.Expanded( |
|
|
pw.Expanded( |
|
|
child: pw.Column( |
|
|
child: pw.Column( |
|
|
crossAxisAlignment: pw.CrossAxisAlignment.start, |
|
|
crossAxisAlignment: |
|
|
|
|
|
pw.CrossAxisAlignment.start, |
|
|
children: [ |
|
|
children: [ |
|
|
pw.Text('Initiateur:', style: tinyTextStyle), |
|
|
pw.Text('Initiateur:', |
|
|
|
|
|
style: tinyTextStyle), |
|
|
pw.Text( |
|
|
pw.Text( |
|
|
commandeur != null ? '${commandeur.name} ${commandeur.lastName ?? ''}'.trim() : 'N/A', |
|
|
commandeur != null |
|
|
style: pw.TextStyle(fontSize: 9, font: regularFont), |
|
|
? '${commandeur.name} ${commandeur.lastName ?? ''}' |
|
|
|
|
|
.trim() |
|
|
|
|
|
: 'N/A', |
|
|
|
|
|
style: pw.TextStyle( |
|
|
|
|
|
fontSize: 9, |
|
|
|
|
|
font: regularFont), |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
pw.Expanded( |
|
|
pw.Expanded( |
|
|
child: pw.Column( |
|
|
child: pw.Column( |
|
|
crossAxisAlignment: pw.CrossAxisAlignment.start, |
|
|
crossAxisAlignment: |
|
|
|
|
|
pw.CrossAxisAlignment.start, |
|
|
children: [ |
|
|
children: [ |
|
|
pw.Text('Validateur:', style: tinyTextStyle), |
|
|
pw.Text('Validateur:', |
|
|
|
|
|
style: tinyTextStyle), |
|
|
pw.Text( |
|
|
pw.Text( |
|
|
validateur != null ? '${validateur.name} ${validateur.lastName ?? ''}'.trim() : 'N/A', |
|
|
validateur != null |
|
|
style: pw.TextStyle(fontSize: 9, font: regularFont), |
|
|
? '${validateur.name} ${validateur.lastName ?? ''}' |
|
|
|
|
|
.trim() |
|
|
|
|
|
: 'N/A', |
|
|
|
|
|
style: pw.TextStyle( |
|
|
|
|
|
fontSize: 9, |
|
|
|
|
|
font: regularFont), |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
@ -925,20 +1021,35 @@ final logoWidget = await buildLogoWidget(); |
|
|
|
|
|
|
|
|
// Signatures |
|
|
// Signatures |
|
|
pw.Row( |
|
|
pw.Row( |
|
|
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, |
|
|
mainAxisAlignment: |
|
|
|
|
|
pw.MainAxisAlignment.spaceBetween, |
|
|
children: [ |
|
|
children: [ |
|
|
pw.Column( |
|
|
pw.Column( |
|
|
children: [ |
|
|
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, |
|
|
|
|
|
font: regularFont)), |
|
|
pw.SizedBox(height: 15), |
|
|
pw.SizedBox(height: 15), |
|
|
pw.Container(width: 70, height: 1, color: PdfColors.black), |
|
|
pw.Container( |
|
|
|
|
|
width: 70, |
|
|
|
|
|
height: 1, |
|
|
|
|
|
color: PdfColors.black), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
pw.Column( |
|
|
pw.Column( |
|
|
children: [ |
|
|
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, |
|
|
|
|
|
font: regularFont)), |
|
|
pw.SizedBox(height: 15), |
|
|
pw.SizedBox(height: 15), |
|
|
pw.Container(width: 70, height: 1, color: PdfColors.black), |
|
|
pw.Container( |
|
|
|
|
|
width: 70, |
|
|
|
|
|
height: 1, |
|
|
|
|
|
color: PdfColors.black), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
@ -989,13 +1100,21 @@ final logoWidget = await buildLogoWidget(); |
|
|
border: pw.Border.all(color: PdfColors.black, width: 2), |
|
|
border: pw.Border.all(color: PdfColors.black, width: 2), |
|
|
), |
|
|
), |
|
|
child: pw.Center( |
|
|
child: pw.Center( |
|
|
child: pw.Text('X', style: pw.TextStyle(fontSize: 12, fontWeight: pw.FontWeight.bold, font: regularFont)), |
|
|
child: pw.Text('X', |
|
|
|
|
|
style: pw.TextStyle( |
|
|
|
|
|
fontSize: 12, |
|
|
|
|
|
fontWeight: pw.FontWeight.bold, |
|
|
|
|
|
font: regularFont)), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
pw.SizedBox(height: 10), |
|
|
pw.SizedBox(height: 10), |
|
|
pw.Transform.rotate( |
|
|
pw.Transform.rotate( |
|
|
angle: 1.5708, |
|
|
angle: 1.5708, |
|
|
child: pw.Text('DÉCOUPER ICI', style: pw.TextStyle(fontSize: 10, fontWeight: pw.FontWeight.bold, font: regularFont)), |
|
|
child: pw.Text('DÉCOUPER ICI', |
|
|
|
|
|
style: pw.TextStyle( |
|
|
|
|
|
fontSize: 10, |
|
|
|
|
|
fontWeight: pw.FontWeight.bold, |
|
|
|
|
|
font: regularFont)), |
|
|
), |
|
|
), |
|
|
pw.SizedBox(height: 10), |
|
|
pw.SizedBox(height: 10), |
|
|
pw.Container( |
|
|
pw.Container( |
|
|
@ -1006,7 +1125,11 @@ final logoWidget = await buildLogoWidget(); |
|
|
border: pw.Border.all(color: PdfColors.black, width: 2), |
|
|
border: pw.Border.all(color: PdfColors.black, width: 2), |
|
|
), |
|
|
), |
|
|
child: pw.Center( |
|
|
child: pw.Center( |
|
|
child: pw.Text('X', style: pw.TextStyle(fontSize: 12, fontWeight: pw.FontWeight.bold, font: regularFont)), |
|
|
child: pw.Text('X', |
|
|
|
|
|
style: pw.TextStyle( |
|
|
|
|
|
fontSize: 12, |
|
|
|
|
|
fontWeight: pw.FontWeight.bold, |
|
|
|
|
|
font: regularFont)), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
@ -1149,11 +1272,13 @@ final logoWidget = await buildLogoWidget(); |
|
|
dynamic blobDynamic = logoRaw; |
|
|
dynamic blobDynamic = logoRaw; |
|
|
bytes = blobDynamic.toBytes(); |
|
|
bytes = blobDynamic.toBytes(); |
|
|
} else { |
|
|
} else { |
|
|
throw Exception("Format de logo non supporté: ${logoRaw.runtimeType}"); |
|
|
throw Exception( |
|
|
|
|
|
"Format de logo non supporté: ${logoRaw.runtimeType}"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
final imageLogo = pw.MemoryImage(bytes); |
|
|
final imageLogo = pw.MemoryImage(bytes); |
|
|
return pw.Container(width: 200, height: 120, child: pw.Image(imageLogo)); |
|
|
return pw.Container( |
|
|
|
|
|
width: 200, height: 120, child: pw.Image(imageLogo)); |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
print('Erreur chargement logo BDD: $e'); |
|
|
print('Erreur chargement logo BDD: $e'); |
|
|
} |
|
|
} |
|
|
@ -1163,7 +1288,8 @@ final logoWidget = await buildLogoWidget(); |
|
|
|
|
|
|
|
|
final logoWidget = await buildLogoWidget(); |
|
|
final logoWidget = await buildLogoWidget(); |
|
|
pw.Widget buildEnteteFactureInfos() { |
|
|
pw.Widget buildEnteteFactureInfos() { |
|
|
final infosAUtiliser = infosFacture.isNotEmpty ? infosFacture : infosFactureDefaut; |
|
|
final infosAUtiliser = |
|
|
|
|
|
infosFacture.isNotEmpty ? infosFacture : infosFactureDefaut; |
|
|
|
|
|
|
|
|
return pw.Column( |
|
|
return pw.Column( |
|
|
crossAxisAlignment: pw.CrossAxisAlignment.start, |
|
|
crossAxisAlignment: pw.CrossAxisAlignment.start, |
|
|
@ -1182,7 +1308,6 @@ pw.Widget buildEnteteFactureInfos() { |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pdf.addPage( |
|
|
pdf.addPage( |
|
|
pw.Page( |
|
|
pw.Page( |
|
|
pageFormat: PdfPageFormat.a4, // Mode portrait |
|
|
pageFormat: PdfPageFormat.a4, // Mode portrait |
|
|
@ -1566,7 +1691,8 @@ pw.Widget buildEnteteFactureInfos() { |
|
|
pw.SizedBox(width: 20), |
|
|
pw.SizedBox(width: 20), |
|
|
pw.Container( |
|
|
pw.Container( |
|
|
width: 80, |
|
|
width: 80, |
|
|
child: pw.Text('${NumberFormat('#,##0', 'fr_FR').format(sousTotal)}', |
|
|
child: pw.Text( |
|
|
|
|
|
'${NumberFormat('#,##0', 'fr_FR').format(sousTotal)}', |
|
|
style: normalTextStyle, |
|
|
style: normalTextStyle, |
|
|
textAlign: pw.TextAlign.right), |
|
|
textAlign: pw.TextAlign.right), |
|
|
), |
|
|
), |
|
|
@ -2001,7 +2127,6 @@ pw.Widget buildEnteteFactureInfos() { |
|
|
|
|
|
|
|
|
Future<void> _generateReceipt( |
|
|
Future<void> _generateReceipt( |
|
|
Commande commande, PaymentMethod payment) async { |
|
|
Commande commande, PaymentMethod payment) async { |
|
|
|
|
|
|
|
|
final details = await _database.getDetailsCommande(commande.id!); |
|
|
final details = await _database.getDetailsCommande(commande.id!); |
|
|
final client = await _database.getClientById(commande.clientId); |
|
|
final client = await _database.getClientById(commande.clientId); |
|
|
final commandeur = commande.commandeurId != null |
|
|
final commandeur = commande.commandeurId != null |
|
|
@ -2242,7 +2367,8 @@ pw.Widget buildEnteteFactureInfos() { |
|
|
children: [ |
|
|
children: [ |
|
|
pw.Text('SOUS-TOTAL:', |
|
|
pw.Text('SOUS-TOTAL:', |
|
|
style: const pw.TextStyle(fontSize: 8)), |
|
|
style: const pw.TextStyle(fontSize: 8)), |
|
|
pw.Text('${NumberFormat('#,##0', 'fr_FR').format(sousTotal)} MGA', |
|
|
pw.Text( |
|
|
|
|
|
'${NumberFormat('#,##0', 'fr_FR').format(sousTotal)} MGA', |
|
|
style: const pw.TextStyle(fontSize: 8)), |
|
|
style: const pw.TextStyle(fontSize: 8)), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
@ -2253,7 +2379,8 @@ pw.Widget buildEnteteFactureInfos() { |
|
|
pw.Text('REMISES:', |
|
|
pw.Text('REMISES:', |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 8, color: PdfColors.orange)), |
|
|
fontSize: 8, color: PdfColors.orange)), |
|
|
pw.Text('-${NumberFormat('#,##0', 'fr_FR').format(totalRemises)} MGA', |
|
|
pw.Text( |
|
|
|
|
|
'-${NumberFormat('#,##0', 'fr_FR').format(totalRemises)} MGA', |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 8, color: PdfColors.orange)), |
|
|
fontSize: 8, color: PdfColors.orange)), |
|
|
], |
|
|
], |
|
|
@ -2266,7 +2393,8 @@ pw.Widget buildEnteteFactureInfos() { |
|
|
pw.Text('CADEAUX ($nombreCadeaux):', |
|
|
pw.Text('CADEAUX ($nombreCadeaux):', |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 8, color: PdfColors.green700)), |
|
|
fontSize: 8, color: PdfColors.green700)), |
|
|
pw.Text('-${NumberFormat('#,##0', 'fr_FR').format(totalCadeaux)} MGA', |
|
|
pw.Text( |
|
|
|
|
|
'-${NumberFormat('#,##0', 'fr_FR').format(totalCadeaux)} MGA', |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 8, color: PdfColors.green700)), |
|
|
fontSize: 8, color: PdfColors.green700)), |
|
|
], |
|
|
], |
|
|
@ -2282,7 +2410,8 @@ pw.Widget buildEnteteFactureInfos() { |
|
|
pw.Text('TOTAL:', |
|
|
pw.Text('TOTAL:', |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 9, fontWeight: pw.FontWeight.bold)), |
|
|
fontSize: 9, fontWeight: pw.FontWeight.bold)), |
|
|
pw.Text('${NumberFormat('#,##0', 'fr_FR').format(commande.montantTotal)} MGA', |
|
|
pw.Text( |
|
|
|
|
|
'${NumberFormat('#,##0', 'fr_FR').format(commande.montantTotal)} MGA', |
|
|
style: pw.TextStyle( |
|
|
style: pw.TextStyle( |
|
|
fontSize: 9, fontWeight: pw.FontWeight.bold)), |
|
|
fontSize: 9, fontWeight: pw.FontWeight.bold)), |
|
|
], |
|
|
], |
|
|
@ -2974,7 +3103,8 @@ pw.Widget buildEnteteFactureInfos() { |
|
|
borderRadius: BorderRadius.circular(8), |
|
|
borderRadius: BorderRadius.circular(8), |
|
|
boxShadow: [ |
|
|
boxShadow: [ |
|
|
BoxShadow( |
|
|
BoxShadow( |
|
|
color: Colors.black.withOpacity(0.1), |
|
|
color: |
|
|
|
|
|
Colors.black.withOpacity(0.1), |
|
|
blurRadius: 2, |
|
|
blurRadius: 2, |
|
|
offset: const Offset(0, 1), |
|
|
offset: const Offset(0, 1), |
|
|
), |
|
|
), |
|
|
@ -2985,8 +3115,10 @@ pw.Widget buildEnteteFactureInfos() { |
|
|
Icons.payment, |
|
|
Icons.payment, |
|
|
color: Colors.green.shade600, |
|
|
color: Colors.green.shade600, |
|
|
), |
|
|
), |
|
|
onPressed: () => _showPaymentOptions(commande), |
|
|
onPressed: () => |
|
|
tooltip: 'Générer le ticket de la commande', |
|
|
_showPaymentOptions(commande), |
|
|
|
|
|
tooltip: |
|
|
|
|
|
'Générer le ticket de la commande', |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
const SizedBox( |
|
|
const SizedBox( |
|
|
@ -3067,8 +3199,8 @@ pw.Widget buildEnteteFactureInfos() { |
|
|
CommandeActions( |
|
|
CommandeActions( |
|
|
commande: commande, |
|
|
commande: commande, |
|
|
onStatutChanged: _updateStatut, |
|
|
onStatutChanged: _updateStatut, |
|
|
onGenerateBonLivraison:_generateBon_lifraisonWithPasswordVerification |
|
|
onGenerateBonLivraison: |
|
|
), |
|
|
_generateBon_lifraisonWithPasswordVerification), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
|