diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index e9bdd1a..7a00b33 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -2,7 +2,7 @@
validerTransfert(int demandeId, int validateurId) async {
final sourceId = fields['point_de_vente_source_id'] as int;
final destinationId = fields['point_de_vente_destination_id'] as int;
+
+ final getpointDeventeSource = await db.query(
+ 'Select point_de_vente_source_id FROM demandes_transfert WHERE id=?',[demandeId]
+ );
+ final getpointDeventeDest = await db.query(
+ 'Select point_de_vente_destination_id FROM demandes_transfert WHERE id=?',[demandeId]
+ );
+ final getpointDeventeSourceValue = getpointDeventeSource.first.fields['point_de_vente_source_id'];
+ final getpointDeventedestValue = getpointDeventeDest.first.fields['point_de_vente_destination_id'];
+ if(getpointDeventeSourceValue==getpointDeventedestValue){
+ await db.query('update products set point_de_vente_id=? where id = ?',[getpointDeventedestValue,produitId]);
+ }else{
+
+
+
+
// 2. Vérifier le stock source
final stockSource = await db.query(
'SELECT stock FROM products WHERE id = ? AND point_de_vente_id = ? FOR UPDATE',
@@ -2646,7 +2662,7 @@ Future validerTransfert(int demandeId, int validateurId) async {
null, // IMEI doit être unique donc on ne le copie pas
]);
}
-
+ }
// 5. Mettre à jour le statut de la demande
await db.query('''
UPDATE demandes_transfert
diff --git a/lib/Views/DemandeTransfert.dart b/lib/Views/DemandeTransfert.dart
index c3a8a7d..6b7e784 100644
--- a/lib/Views/DemandeTransfert.dart
+++ b/lib/Views/DemandeTransfert.dart
@@ -205,7 +205,7 @@ class _GestionTransfertsPageState extends State with Tick
),
Text('Référence: ${demande['produit_reference']}'),
Text('Quantité: ${demande['quantite']}'),
- Text('De: ${demande['point_vente_source']}'),
+ Text(demande['point_vente_source'] == demande['point_vente_destination']?'De: Non specifier' : 'De: ${demande['point_vente_source']}'),
Text('Vers: ${demande['point_vente_destination']}'),
Text(
'Stock disponible: $stockDisponible',
@@ -602,7 +602,7 @@ class _GestionTransfertsPageState extends State with Tick
statutIcon = Icons.check_circle;
statutText = 'Validée';
break;
- case 'rejetee':
+ case 'refusee':
statutColor = Colors.red;
statutIcon = Icons.cancel;
statutText = 'Rejetée';
@@ -695,7 +695,7 @@ class _GestionTransfertsPageState extends State with Tick
const SizedBox(width: 8),
Expanded(
child: Text(
- '${demande['point_vente_source'] ?? 'N/A'}',
+ demande['point_vente_source']==demande['point_vente_destination']?"Non specifier" : '${demande['point_vente_source'] ?? 'N/A'}',
style: const TextStyle(fontWeight: FontWeight.w500),
),
),
diff --git a/lib/Views/HandleProduct.dart b/lib/Views/HandleProduct.dart
index f0d6dd5..dd15d6e 100644
--- a/lib/Views/HandleProduct.dart
+++ b/lib/Views/HandleProduct.dart
@@ -26,6 +26,7 @@ class ProductManagementPage extends StatefulWidget {
class _ProductManagementPageState extends State {
final AppDatabase _productDatabase = AppDatabase.instance;
+ final AppDatabase _appDatabase = AppDatabase.instance;
final UserController _userController = Get.find();
List _products = [];
@@ -99,6 +100,494 @@ bool _isUserSuperAdmin() {
bool autoGenerateReference = true;
bool showAddNewPoint = false;
+// 🎨 Widget pour les cartes d'information
+Widget _buildInfoCard(String label, String value, IconData icon, Color color) {
+ return Container(
+ padding: const EdgeInsets.all(12),
+ decoration: BoxDecoration(
+ color: color.withOpacity(0.1),
+ borderRadius: BorderRadius.circular(8),
+ border: Border.all(color: color.withOpacity(0.3)),
+ ),
+ child: Column(
+ children: [
+ Icon(icon, color: color, size: 20),
+ const SizedBox(height: 4),
+ Text(
+ label,
+ style: TextStyle(
+ fontSize: 10,
+ color: Colors.grey.shade600,
+ fontWeight: FontWeight.w500,
+ ),
+ textAlign: TextAlign.center,
+ ),
+ Text(
+ value,
+ style: TextStyle(
+ fontSize: 12,
+ fontWeight: FontWeight.bold,
+ color: color,
+ ),
+ textAlign: TextAlign.center,
+ ),
+ ],
+ ),
+ );
+}
+// 🎨 Widget pour les étapes de transfert
+Widget _buildTransferStep(String label, String pointDeVente, IconData icon, Color color) {
+ return Container(
+ padding: const EdgeInsets.all(12),
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.circular(8),
+ border: Border.all(color: color.withOpacity(0.3)),
+ ),
+ child: Column(
+ children: [
+ Container(
+ padding: const EdgeInsets.all(6),
+ decoration: BoxDecoration(
+ color: color.withOpacity(0.1),
+ borderRadius: BorderRadius.circular(6),
+ ),
+ child: Icon(icon, color: color, size: 16),
+ ),
+ const SizedBox(height: 6),
+ Text(
+ label,
+ style: TextStyle(
+ fontSize: 10,
+ color: Colors.grey.shade600,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ Text(
+ pointDeVente,
+ style: TextStyle(
+ fontSize: 11,
+ fontWeight: FontWeight.w600,
+ color: color,
+ ),
+ textAlign: TextAlign.center,
+ maxLines: 2,
+ overflow: TextOverflow.ellipsis,
+ ),
+ ],
+ ),
+ );
+}
+// 🎨 INTERFACE AMÉLIORÉE: Dialog moderne pour demande de transfert
+Future _showDemandeTransfertDialog(Product product) async {
+ final quantiteController = TextEditingController(text: '1');
+ final notesController = TextEditingController();
+ final _formKey = GlobalKey();
+
+ // Récupérer les infos du point de vente source
+ final pointDeVenteSource = await _appDatabase.getPointDeVenteNomById(product.pointDeVenteId ?? 0);
+ final pointDeVenteDestination = await _appDatabase.getPointDeVenteNomById(_userController.pointDeVenteId);
+
+ await showDialog(
+ context: context,
+ barrierDismissible: false,
+ builder: (context) => AlertDialog(
+ shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
+ contentPadding: EdgeInsets.zero,
+ content: Container(
+ width: 400,
+ child: SingleChildScrollView(
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ // En-tête avec design moderne
+ Container(
+ width: double.infinity,
+ padding: const EdgeInsets.all(20),
+ decoration: BoxDecoration(
+ gradient: LinearGradient(
+ colors: [Colors.blue.shade600, Colors.blue.shade700],
+ begin: Alignment.topLeft,
+ end: Alignment.bottomRight,
+ ),
+ borderRadius: const BorderRadius.only(
+ topLeft: Radius.circular(16),
+ topRight: Radius.circular(16),
+ ),
+ ),
+ child: Column(
+ children: [
+ Icon(
+ Icons.swap_horizontal_circle,
+ size: 48,
+ color: Colors.white,
+ ),
+ const SizedBox(height: 8),
+ Text(
+ 'Demande de transfert',
+ style: TextStyle(
+ fontSize: 20,
+ fontWeight: FontWeight.bold,
+ color: Colors.white,
+ ),
+ ),
+ Text(
+ 'Transférer un produit entre points de vente',
+ style: TextStyle(
+ fontSize: 14,
+ color: Colors.white.withOpacity(0.9),
+ ),
+ ),
+ ],
+ ),
+ ),
+
+ // Contenu principal
+ Padding(
+ padding: const EdgeInsets.all(20),
+ child: Form(
+ key: _formKey,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ // Informations du produit
+ Container(
+ width: double.infinity,
+ padding: const EdgeInsets.all(16),
+ decoration: BoxDecoration(
+ color: Colors.grey.shade50,
+ borderRadius: BorderRadius.circular(12),
+ border: Border.all(color: Colors.grey.shade200),
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ children: [
+ Container(
+ padding: const EdgeInsets.all(8),
+ decoration: BoxDecoration(
+ color: Colors.blue.shade100,
+ borderRadius: BorderRadius.circular(8),
+ ),
+ child: Icon(
+ Icons.inventory_2,
+ color: Colors.blue.shade700,
+ size: 20,
+ ),
+ ),
+ const SizedBox(width: 12),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ 'Produit à transférer',
+ style: TextStyle(
+ fontSize: 12,
+ color: Colors.grey.shade600,
+ fontWeight: FontWeight.w500,
+ ),
+ ),
+ Text(
+ product.name,
+ style: const TextStyle(
+ fontSize: 16,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ const SizedBox(height: 12),
+ Row(
+ children: [
+ Expanded(
+ child: _buildInfoCard(
+ 'Prix unitaire',
+ '${product.price.toStringAsFixed(2)} MGA',
+ Icons.attach_money,
+ Colors.green,
+ ),
+ ),
+ const SizedBox(width: 8),
+ Expanded(
+ child: _buildInfoCard(
+ 'Stock disponible',
+ '${product.stock ?? 0}',
+ Icons.inventory,
+ product.stock != null && product.stock! > 0
+ ? Colors.green
+ : Colors.red,
+ ),
+ ),
+ ],
+ ),
+ if (product.reference != null && product.reference!.isNotEmpty) ...[
+ const SizedBox(height: 8),
+ Text(
+ 'Référence: ${product.reference}',
+ style: TextStyle(
+ fontSize: 12,
+ color: Colors.grey.shade600,
+ fontFamily: 'monospace',
+ ),
+ ),
+ ],
+ ],
+ ),
+ ),
+
+ const SizedBox(height: 20),
+
+ // Informations de transfert
+ Container(
+ width: double.infinity,
+ padding: const EdgeInsets.all(16),
+ decoration: BoxDecoration(
+ color: Colors.orange.shade50,
+ borderRadius: BorderRadius.circular(12),
+ border: Border.all(color: Colors.orange.shade200),
+ ),
+ child: Column(
+ children: [
+ Row(
+ children: [
+ Icon(Icons.arrow_forward, color: Colors.orange.shade700),
+ const SizedBox(width: 8),
+ Text(
+ 'Informations de transfert',
+ style: TextStyle(
+ fontSize: 14,
+ fontWeight: FontWeight.bold,
+ color: Colors.orange.shade700,
+ ),
+ ),
+ ],
+ ),
+ const SizedBox(height: 12),
+ Row(
+ children: [
+ Expanded(
+ child: _buildTransferStep(
+ 'DE',
+ pointDeVenteSource ?? 'Chargement...',
+ Icons.store_outlined,
+ Colors.red.shade600,
+ ),
+ ),
+ Container(
+ margin: const EdgeInsets.symmetric(horizontal: 8),
+ child: Icon(
+ Icons.arrow_forward,
+ color: Colors.orange.shade700,
+ size: 24,
+ ),
+ ),
+ Expanded(
+ child: _buildTransferStep(
+ 'VERS',
+ pointDeVenteDestination ?? 'Chargement...',
+ Icons.store,
+ Colors.green.shade600,
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+
+ const SizedBox(height: 20),
+
+ // Champ quantité avec design amélioré
+ Text(
+ 'Quantité à transférer',
+ style: TextStyle(
+ fontSize: 14,
+ fontWeight: FontWeight.w600,
+ color: Colors.grey.shade700,
+ ),
+ ),
+ const SizedBox(height: 8),
+ Container(
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(12),
+ border: Border.all(color: Colors.grey.shade300),
+ ),
+ child: Row(
+ children: [
+ IconButton(
+ onPressed: () {
+ int currentQty = int.tryParse(quantiteController.text) ?? 1;
+ if (currentQty > 1) {
+ quantiteController.text = (currentQty - 1).toString();
+ }
+ },
+ icon: Icon(Icons.remove, color: Colors.grey.shade600),
+ ),
+ Expanded(
+ child: TextFormField(
+ controller: quantiteController,
+ decoration: const InputDecoration(
+ border: InputBorder.none,
+ contentPadding: EdgeInsets.symmetric(horizontal: 16),
+ hintText: 'Quantité',
+ ),
+ textAlign: TextAlign.center,
+ keyboardType: TextInputType.number,
+ style: const TextStyle(
+ fontSize: 16,
+ fontWeight: FontWeight.bold,
+ ),
+ validator: (value) {
+ if (value == null || value.isEmpty) {
+ return 'Veuillez entrer une quantité';
+ }
+ final qty = int.tryParse(value) ?? 0;
+ if (qty <= 0) {
+ return 'Quantité invalide';
+ }
+ if (product.stock != null && qty > product.stock!) {
+ return 'Quantité supérieure au stock disponible';
+ }
+ return null;
+ },
+ ),
+ ),
+ IconButton(
+ onPressed: () {
+ int currentQty = int.tryParse(quantiteController.text) ?? 1;
+ int maxStock = product.stock ?? 999;
+ if (currentQty < maxStock) {
+ quantiteController.text = (currentQty + 1).toString();
+ }
+ },
+ icon: Icon(Icons.add, color: Colors.grey.shade600),
+ ),
+ ],
+ ),
+ ),
+
+
+
+ // Boutons d'action avec design moderne
+ Row(
+ children: [
+ Expanded(
+ child: TextButton(
+ onPressed: () => Navigator.pop(context),
+ style: TextButton.styleFrom(
+ padding: const EdgeInsets.symmetric(vertical: 16),
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12),
+ side: BorderSide(color: Colors.grey.shade300),
+ ),
+ ),
+ child: Text(
+ 'Annuler',
+ style: TextStyle(
+ fontSize: 16,
+ fontWeight: FontWeight.w600,
+ color: Colors.grey.shade700,
+ ),
+ ),
+ ),
+ ),
+ const SizedBox(width: 12),
+ Expanded(
+ flex: 2,
+ child: ElevatedButton.icon(
+ onPressed: () async {
+ if (!_formKey.currentState!.validate()) return;
+
+ final qty = int.tryParse(quantiteController.text) ?? 0;
+ if (qty <= 0) {
+ Get.snackbar(
+ 'Erreur',
+ 'Quantité invalide',
+ snackPosition: SnackPosition.BOTTOM,
+ backgroundColor: Colors.red,
+ colorText: Colors.white,
+ );
+ return;
+ }
+
+ try {
+ setState(() => _isLoading = true);
+ Navigator.pop(context);
+
+ await _appDatabase.createDemandeTransfert(
+ produitId: product.id!,
+ pointDeVenteSourceId: product.pointDeVenteId!,
+ pointDeVenteDestinationId: _userController.pointDeVenteId,
+ demandeurId: _userController.userId,
+ quantite: qty,
+ notes: notesController.text.isNotEmpty
+ ? notesController.text
+ : 'Demande de transfert depuis l\'application mobile',
+ );
+
+ Get.snackbar(
+ 'Demande envoyée ✅',
+ 'Votre demande de transfert de $qty unité(s) a été enregistrée et sera traitée prochainement.',
+ snackPosition: SnackPosition.BOTTOM,
+ backgroundColor: Colors.green,
+ colorText: Colors.white,
+ duration: const Duration(seconds: 4),
+ icon: const Icon(Icons.check_circle, color: Colors.white),
+ );
+ } catch (e) {
+ Get.snackbar(
+ 'Erreur',
+ 'Impossible d\'envoyer la demande: ${e.toString()}',
+ snackPosition: SnackPosition.BOTTOM,
+ backgroundColor: Colors.red,
+ colorText: Colors.white,
+ duration: const Duration(seconds: 4),
+ );
+ } finally {
+ setState(() => _isLoading = false);
+ }
+ },
+ icon: const Icon(Icons.send, color: Colors.white),
+ label: const Text(
+ 'Envoyer la demande',
+ style: TextStyle(
+ fontSize: 16,
+ fontWeight: FontWeight.bold,
+ color: Colors.white,
+ ),
+ ),
+ style: ElevatedButton.styleFrom(
+ backgroundColor: Colors.blue.shade600,
+ padding: const EdgeInsets.symmetric(vertical: 16),
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12),
+ ),
+ elevation: 2,
+ ),
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ );
+}
+
+
+
+
// Fonction pour mettre à jour le QR preview
void updateQrPreview() {
if (nameController.text.isNotEmpty) {
@@ -1253,25 +1742,32 @@ bool _isUserSuperAdmin() {
}
// Assigner le point de vente de l'utilisateur au produit
- final updatedProduct = Product(
- id: foundProduct.id,
- name: foundProduct.name,
- price: foundProduct.price,
- image: foundProduct.image,
- category: foundProduct.category,
- description: foundProduct.description,
- stock: foundProduct.stock,
- qrCode: foundProduct.qrCode,
- reference: foundProduct.reference,
- marque: foundProduct.marque,
- ram: foundProduct.ram,
- memoireInterne: foundProduct.memoireInterne,
- imei: foundProduct.imei,
- pointDeVenteId:
- _userController.pointDeVenteId, // Nouveau point de vente
- );
-
- await _productDatabase.updateProduct(updatedProduct);
+ // final updatedProduct = Product(
+ // id: foundProduct.id,
+ // name: foundProduct.name,
+ // price: foundProduct.price,
+ // image: foundProduct.image,
+ // category: foundProduct.category,
+ // description: foundProduct.description,
+ // stock: foundProduct.stock,
+ // qrCode: foundProduct.qrCode,
+ // reference: foundProduct.reference,
+ // marque: foundProduct.marque,
+ // ram: foundProduct.ram,
+ // memoireInterne: foundProduct.memoireInterne,
+ // imei: foundProduct.imei,
+ // pointDeVenteId:
+ // _userController.pointDeVenteId, // Nouveau point de vente
+ // );
+ await _appDatabase.createDemandeTransfert(
+ produitId: foundProduct.id!,
+ pointDeVenteSourceId: _userController.pointDeVenteId,
+ pointDeVenteDestinationId: _userController.pointDeVenteId,
+ demandeurId: _userController.userId,
+ quantite: foundProduct.stock,
+ notes: 'produit non assigner',
+ );
+ // await _productDatabase.updateProduct(updatedProduct);
// Recharger les produits pour refléter les changements
_loadProducts();
@@ -1311,7 +1807,7 @@ bool _isUserSuperAdmin() {
child: Icon(Icons.check_circle, color: Colors.green.shade700),
),
const SizedBox(width: 12),
- const Expanded(child: Text('Attribution réussie !')),
+ const Expanded(child: Text( 'demande attribution réussie en attente de validation!')),
],
),
content: Column(
diff --git a/lib/Views/commandManagement.dart b/lib/Views/commandManagement.dart
index 2cc02cd..ef3ebf1 100644
--- a/lib/Views/commandManagement.dart
+++ b/lib/Views/commandManagement.dart
@@ -39,13 +39,8 @@ class _GestionCommandesPageState extends State {
DateTime? _selectedDate;
final TextEditingController _searchController = TextEditingController();
bool _showCancelledOrders = false;
- // final userController = Get.find();
final userController = Get.find();
- bool verifAdmin() {
- return userController.role == 'Super Admin';
- }
-
@override
void initState() {
super.initState();
@@ -78,22 +73,17 @@ class _GestionCommandesPageState extends State {
final matchesDate = _selectedDate == null ||
DateFormat('yyyy-MM-dd').format(commande.dateCommande) ==
DateFormat('yyyy-MM-dd').format(_selectedDate!);
-
- final shouldShowCancelled =
- _showCancelledOrders || commande.statut != StatutCommande.annulee;
-
- return matchesSearch &&
- matchesStatut &&
- matchesDate &&
- shouldShowCancelled;
+
+ final shouldShowCancelled = _showCancelledOrders || commande.statut != StatutCommande.annulee;
+
+ return matchesSearch && matchesStatut && matchesDate && shouldShowCancelled;
}).toList();
});
}
- Future _updateStatut(int commandeId, StatutCommande newStatut,
- {int? validateurId}) async {
+ Future _updateStatut(int commandeId, StatutCommande newStatut, {int? validateurId}) async {
final commandeExistante = await _database.getCommandeById(commandeId);
-
+
if (commandeExistante == null) {
Get.snackbar(
'Erreur',
@@ -123,12 +113,12 @@ class _GestionCommandesPageState extends State {
} else {
await _database.updateStatutCommande(commandeId, newStatut);
}
-
+
await _loadCommandes();
-
+
String message = 'Statut de la commande mis à jour';
Color backgroundColor = Colors.green;
-
+
switch (newStatut) {
case StatutCommande.annulee:
message = 'Commande annulée avec succès';
@@ -141,7 +131,7 @@ class _GestionCommandesPageState extends State {
default:
break;
}
-
+
Get.snackbar(
'Succès',
message,
@@ -162,19 +152,18 @@ class _GestionCommandesPageState extends State {
if (selectedPayment.type == PaymentType.cash) {
await _showCashPaymentDialog(commande, selectedPayment.amountGiven);
}
-
+
await _updateStatut(
- commande.id!,
+ commande.id!,
StatutCommande.confirmee,
validateurId: userController.userId,
);
-
+
await _generateReceipt(commande, selectedPayment);
}
}
- Future _showCashPaymentDialog(
- Commande commande, double amountGiven) async {
+ Future _showCashPaymentDialog(Commande commande, double amountGiven) async {
final amountController = TextEditingController(
text: amountGiven.toStringAsFixed(2),
);
@@ -245,127 +234,117 @@ class _GestionCommandesPageState extends State {
Future buildIconPhoneText() async {
final font = pw.Font.ttf(await rootBundle.load('assets/fa-solid-900.ttf'));
- return pw.Text(String.fromCharCode(0xf095),
- style: pw.TextStyle(font: font));
- }
-
- Future buildIconGift() async {
- final font =
- pw.Font.ttf(await rootBundle.load('assets/NotoEmoji-Regular.ttf'));
- return pw.Text('🎁', style: pw.TextStyle(font: font, fontSize: 16));
+ return pw.Text(String.fromCharCode(0xf095), style: pw.TextStyle(font: font));
}
-
+Future buildIconGift() async {
+ final font = pw.Font.ttf(await rootBundle.load('assets/NotoEmoji-Regular.ttf'));
+ return pw.Text('🎁', style: pw.TextStyle(font: font, fontSize: 16));
+}
Future buildIconCheckedText() async {
final font = pw.Font.ttf(await rootBundle.load('assets/fa-solid-900.ttf'));
- return pw.Text(String.fromCharCode(0xf14a),
- style: pw.TextStyle(font: font));
+ return pw.Text(String.fromCharCode(0xf14a), style: pw.TextStyle(font: font));
}
Future buildIconGlobeText() async {
final font = pw.Font.ttf(await rootBundle.load('assets/fa-solid-900.ttf'));
- return pw.Text(String.fromCharCode(0xf0ac),
- style: pw.TextStyle(font: font));
+ return pw.Text(String.fromCharCode(0xf0ac), style: pw.TextStyle(font: font));
}
// Bon de livraison==============================================
- Future _generateBonLivraison(Commande commande) async {
- final details = await _database.getDetailsCommande(commande.id!);
- final client = await _database.getClientById(commande.clientId);
- final pointDeVente = await _database.getPointDeVenteById(1);
-
- // Récupérer les informations des vendeurs
- final commandeur = commande.commandeurId != null
- ? await _database.getUserById(commande.commandeurId!)
- : null;
- final validateur = commande.validateurId != null
- ? await _database.getUserById(commande.validateurId!)
- : null;
-
- final iconPhone = await buildIconPhoneText();
- final iconChecked = await buildIconCheckedText();
- final iconGlobe = await buildIconGlobeText();
-
- double sousTotal = 0;
- double totalRemises = 0;
- double totalCadeaux = 0;
- int nombreCadeaux = 0;
-
- for (final detail in details) {
- sousTotal += detail.sousTotal;
- if (detail.estCadeau) {
- totalCadeaux += detail.sousTotal;
- nombreCadeaux += detail.quantite;
- } else {
- totalRemises += detail.montantRemise;
- }
- }
-
- final List