From f41fc922a6bec54ff734e27e13c586fe39acf09f Mon Sep 17 00:00:00 2001 From: andrymodeste Date: Mon, 28 Jul 2025 18:20:54 +0200 Subject: [PATCH] commit de 28072025_02 --- lib/Services/stock_managementDatabase.dart | 88 ++++++++++--------- lib/Views/HandleProduct.dart | 12 ++- lib/Views/commandManagement.dart | 54 ++++++------ lib/Views/historique.dart | 2 +- .../historique_sorties_personnelles_page.dart | 6 +- lib/config/DatabaseConfig.dart | 4 +- pubspec.lock | 48 ++++++++++ pubspec.yaml | 1 + 8 files changed, 141 insertions(+), 74 deletions(-) diff --git a/lib/Services/stock_managementDatabase.dart b/lib/Services/stock_managementDatabase.dart index 88dd8d2..b010336 100644 --- a/lib/Services/stock_managementDatabase.dart +++ b/lib/Services/stock_managementDatabase.dart @@ -3163,54 +3163,60 @@ Future getValeurTotaleStock() async { return []; } } +Future>> getHistoriqueSortiesPersonnelles({ + int? adminId, + String? statut, + int? pointDeVenteId, + int limit = 50, +}) async { + final db = await database; - Future>> getHistoriqueSortiesPersonnelles({ - int? adminId, - String? statut, - int limit = 50, - }) async { - final db = await database; + try { + String whereClause = ''; + List params = []; - try { - String whereClause = ''; - List params = []; + // Filtre par point de vente seulement si pointDeVenteId n'est pas null + // (null signifie que l'utilisateur a pointDeVenteId = 0 et peut tout voir) + if (pointDeVenteId != null) { + whereClause = 'WHERE sp.point_de_vente_id = ?'; + params.add(pointDeVenteId); + } - if (adminId != null) { - whereClause = 'WHERE sp.admin_id = ?'; - params.add(adminId); - } + if (adminId != null) { + whereClause += (whereClause.isEmpty ? 'WHERE' : ' AND') + ' sp.admin_id = ?'; + params.add(adminId); + } - if (statut != null) { - whereClause += - (whereClause.isEmpty ? 'WHERE' : ' AND') + ' sp.statut = ?'; - params.add(statut); - } + if (statut != null) { + whereClause += (whereClause.isEmpty ? 'WHERE' : ' AND') + ' sp.statut = ?'; + params.add(statut); + } - final result = await db.query(''' - SELECT sp.*, - p.name as produit_nom, - p.reference as produit_reference, - u_admin.name as admin_nom, - u_admin.lastname as admin_nom_famille, - u_approb.name as approbateur_nom, - u_approb.lastname as approbateur_nom_famille, - pv.nom as point_vente_nom - FROM sorties_stock_personnelles sp - JOIN products p ON sp.produit_id = p.id - JOIN users u_admin ON sp.admin_id = u_admin.id - LEFT JOIN users u_approb ON sp.approbateur_id = u_approb.id - LEFT JOIN points_de_vente pv ON sp.point_de_vente_id = pv.id - $whereClause - ORDER BY sp.date_sortie DESC - LIMIT ? - ''', [...params, limit]); + final result = await db.query(''' + SELECT sp.*, + p.name as produit_nom, + p.reference as produit_reference, + u_admin.name as admin_nom, + u_admin.lastname as admin_nom_famille, + u_approb.name as approbateur_nom, + u_approb.lastname as approbateur_nom_famille, + pv.nom as point_vente_nom + FROM sorties_stock_personnelles sp + JOIN products p ON sp.produit_id = p.id + JOIN users u_admin ON sp.admin_id = u_admin.id + LEFT JOIN users u_approb ON sp.approbateur_id = u_approb.id + LEFT JOIN points_de_vente pv ON sp.point_de_vente_id = pv.id + $whereClause + ORDER BY sp.date_sortie DESC + LIMIT ? + ''', [...params, limit]); - return result.map((row) => row.fields).toList(); - } catch (e) { - print('Erreur récupération historique sorties: $e'); - return []; - } + return result.map((row) => row.fields).toList(); + } catch (e) { + print('Erreur récupération historique sorties: $e'); + return []; } +} Future> getStatistiquesSortiesPersonnelles() async { final db = await database; diff --git a/lib/Views/HandleProduct.dart b/lib/Views/HandleProduct.dart index e11351b..60f98e4 100644 --- a/lib/Views/HandleProduct.dart +++ b/lib/Views/HandleProduct.dart @@ -1507,7 +1507,13 @@ Future _showDemandeTransfertDialog(Product product) async { // Valeurs par défaut normalizedData['description'] = ''; // Description toujours vide - normalizedData['stock'] = 1; // Stock toujours à 1 + if (mapping.containsKey('stock')) { + final stockValue = _cleanValue(_getColumnValue(row, mapping, 'stock')); + final stock = int.tryParse(stockValue ?? '0') ?? 1; + normalizedData['stock'] = stock > 0 ? stock : 1; + } else { + normalizedData['stock'] = 1; // Valeur par défaut + } // Validation des données obligatoires if (normalizedData['name'] == null || normalizedData['price'] == null) { @@ -1567,6 +1573,9 @@ Future _showDemandeTransfertDialog(Product product) async { } else if (header == 'PRIX' || header == 'PRICE') { columnMapping['price'] = i; print('→ Mappé vers price'); + } else if (header == 'STOCK' || header == 'QUANTITY' || header == 'QTE') { + columnMapping['stock'] = i; + print('→ Mappé vers stock'); } else if (header == 'BOUTIQUE' || header.contains('POINT DE VENTE') || header == 'MAGASIN') { @@ -2175,6 +2184,7 @@ Future _showDemandeTransfertDialog(Product product) async { 'RAM', // ram 'INTERNE', // memoire_interne 'IMEI', // imei + 'STOCK' 'PRIX', // price 'BOUTIQUE', // point_de_vente ]; diff --git a/lib/Views/commandManagement.dart b/lib/Views/commandManagement.dart index c79f75d..5357ade 100644 --- a/lib/Views/commandManagement.dart +++ b/lib/Views/commandManagement.dart @@ -636,7 +636,7 @@ class _GestionCommandesPageState extends State { children: [ if (detail.estCadeau) ...[ pw.Text( - '${detail.prixUnitaire.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixUnitaire)}', style: pw.TextStyle( fontSize: 8, decoration: pw.TextDecoration.lineThrough, @@ -655,7 +655,7 @@ class _GestionCommandesPageState extends State { ), ] else if (detail.aRemise) ...[ pw.Text( - '${detail.prixUnitaire.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixUnitaire)}', style: pw.TextStyle( fontSize: 8, decoration: pw.TextDecoration.lineThrough, @@ -664,7 +664,7 @@ class _GestionCommandesPageState extends State { ) ), pw.Text( - '${(detail.prixFinal / detail.quantite).toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixFinal / detail.quantite)}', style: pw.TextStyle( fontSize: 10, color: PdfColors.orange700, @@ -709,7 +709,7 @@ class _GestionCommandesPageState extends State { ), ] else if (detail.aRemise) ...[ pw.Text( - '${detail.sousTotal.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.sousTotal)}', style: pw.TextStyle( fontSize: 8, decoration: pw.TextDecoration.lineThrough, @@ -718,7 +718,7 @@ class _GestionCommandesPageState extends State { ) ), pw.Text( - '${detail.prixFinal.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixFinal)}', style: pw.TextStyle( fontSize: 10, fontWeight: pw.FontWeight.bold, @@ -727,7 +727,7 @@ class _GestionCommandesPageState extends State { ), ] else pw.Text( - '${detail.prixFinal.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixFinal)}', style: smallTextStyle ), ], @@ -759,7 +759,7 @@ class _GestionCommandesPageState extends State { children: [ pw.Text('SOUS-TOTAL:', style: smallTextStyle), pw.SizedBox(width: 10), - pw.Text('${sousTotal.toStringAsFixed(0)}', style: smallTextStyle), + pw.Text('${NumberFormat('#,##0', 'fr_FR').format(sousTotal)}', style: smallTextStyle), ], ), pw.SizedBox(height: 2), @@ -771,7 +771,7 @@ class _GestionCommandesPageState extends State { children: [ pw.Text('REMISES:', style: pw.TextStyle(color: PdfColors.orange, fontSize: 10, font: regularFont)), pw.SizedBox(width: 10), - pw.Text('-${totalRemises.toStringAsFixed(0)}', 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), @@ -783,7 +783,7 @@ class _GestionCommandesPageState extends State { children: [ pw.Text('CADEAUX ($nombreCadeaux):', style: pw.TextStyle(color: PdfColors.green700, fontSize: 10, font: regularFont)), pw.SizedBox(width: 10), - pw.Text('-${totalCadeaux.toStringAsFixed(0)}', 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), @@ -1197,7 +1197,7 @@ class _GestionCommandesPageState extends State { pw.Container( width: 180, height: 1, color: PdfColors.black), pw.SizedBox(height: 4), - pw.Text('${client?.nom} \n ${client?.prenom}', + pw.Text('${client?.nom} ${client?.prenom}', style: boldTextStyle), pw.SizedBox(height: 4), pw.Text(client?.telephone ?? 'Non spécifié', @@ -1357,7 +1357,7 @@ class _GestionCommandesPageState extends State { children: [ if (detail.estCadeau) ...[ pw.Text( - '${detail.prixUnitaire.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixUnitaire)}', style: pw.TextStyle( fontSize: 7, decoration: pw.TextDecoration.lineThrough, @@ -1373,19 +1373,19 @@ class _GestionCommandesPageState extends State { detail.prixUnitaire != detail.sousTotal / detail.quantite) ...[ pw.Text( - '${detail.prixUnitaire.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixUnitaire)}', style: pw.TextStyle( fontSize: 7, decoration: pw.TextDecoration.lineThrough, color: PdfColors.grey600, )), pw.Text( - '${(detail.prixFinal / detail.quantite).toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixFinal / detail.quantite)}', style: pw.TextStyle( fontSize: 9, color: PdfColors.orange)), ] else pw.Text( - '${detail.prixUnitaire.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixUnitaire)}', style: normalTextStyle), ], ), @@ -1419,7 +1419,7 @@ class _GestionCommandesPageState extends State { children: [ if (detail.estCadeau) ...[ pw.Text( - '${detail.sousTotal.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.sousTotal)}', style: pw.TextStyle( fontSize: 7, decoration: pw.TextDecoration.lineThrough, @@ -1434,20 +1434,20 @@ class _GestionCommandesPageState extends State { ] else if (detail.aRemise && detail.sousTotal != detail.prixFinal) ...[ pw.Text( - '${detail.sousTotal.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.sousTotal)}', style: pw.TextStyle( fontSize: 7, decoration: pw.TextDecoration.lineThrough, color: PdfColors.grey600, )), pw.Text( - '${detail.prixFinal.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixFinal)}', style: pw.TextStyle( fontSize: 9, fontWeight: pw.FontWeight.bold)), ] else pw.Text( - '${detail.prixFinal.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixFinal)}', style: normalTextStyle), ], ), @@ -1475,7 +1475,7 @@ class _GestionCommandesPageState extends State { pw.SizedBox(width: 20), pw.Container( width: 80, - child: pw.Text('${sousTotal.toStringAsFixed(0)}', + child: pw.Text('${NumberFormat('#,##0', 'fr_FR').format(sousTotal)}', style: normalTextStyle, textAlign: pw.TextAlign.right), ), @@ -1494,7 +1494,7 @@ class _GestionCommandesPageState extends State { pw.Container( width: 80, child: pw.Text( - '-${totalRemises.toStringAsFixed(0)}', + '-${NumberFormat('#,##0', 'fr_FR').format(totalRemises)}', style: pw.TextStyle( color: PdfColors.orange, fontWeight: pw.FontWeight.bold, @@ -1516,7 +1516,7 @@ class _GestionCommandesPageState extends State { pw.Container( width: 80, child: pw.Text( - '-${totalCadeaux.toStringAsFixed(0)}', + '-${NumberFormat('#,##0', 'fr_FR').format(totalCadeaux)}', style: pw.TextStyle( color: PdfColors.green700, fontWeight: pw.FontWeight.bold, @@ -1543,7 +1543,7 @@ class _GestionCommandesPageState extends State { pw.Container( width: 80, child: pw.Text( - '${commande.montantTotal.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(commande.montantTotal)}', style: boldTextStyle, textAlign: pw.TextAlign.right), ), @@ -2103,7 +2103,7 @@ class _GestionCommandesPageState extends State { children: [ if (detail.estCadeau) ...[ pw.Text( - '${detail.prixUnitaire.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixUnitaire)}', style: pw.TextStyle( fontSize: 6, decoration: pw.TextDecoration.lineThrough, @@ -2119,18 +2119,18 @@ class _GestionCommandesPageState extends State { detail.prixUnitaire != detail.prixFinal / detail.quantite) ...[ pw.Text( - '${detail.prixUnitaire.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixUnitaire)}', style: pw.TextStyle( fontSize: 6, decoration: pw.TextDecoration.lineThrough, color: PdfColors.grey600, )), pw.Text( - '${(detail.prixFinal / detail.quantite).toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixFinal / detail.quantite)}', style: const pw.TextStyle(fontSize: 7)), ] else pw.Text( - '${detail.prixUnitaire.toStringAsFixed(0)}', + '${NumberFormat('#,##0', 'fr_FR').format(detail.prixUnitaire)}', style: const pw.TextStyle(fontSize: 7)), ], ), @@ -2857,7 +2857,7 @@ class _GestionCommandesPageState extends State { ), const SizedBox(width: 2), Text( - '-${totalRemises.toStringAsFixed(0)}', + '-${NumberFormat('#,##0', 'fr_FR').format(totalRemises)}', style: TextStyle( fontSize: 10, fontWeight: FontWeight.bold, diff --git a/lib/Views/historique.dart b/lib/Views/historique.dart index 66352ab..e06f52f 100644 --- a/lib/Views/historique.dart +++ b/lib/Views/historique.dart @@ -556,7 +556,7 @@ class _HistoriquePageState extends State { .format(commande.dateCommande), Icons.calendar_today), _buildDetailRow( - 'PV', '${_selectedPointDeVente} ', Icons.person), + 'PV', '${commande.pointDeVenteDesign} ', Icons.person), Row( children: [ Icon(Icons.assignment, diff --git a/lib/Views/historique_sorties_personnelles_page.dart b/lib/Views/historique_sorties_personnelles_page.dart index fc29549..3b7994a 100644 --- a/lib/Views/historique_sorties_personnelles_page.dart +++ b/lib/Views/historique_sorties_personnelles_page.dart @@ -31,9 +31,10 @@ class _HistoriqueSortiesPersonnellesPageState extends State _loadHistorique() async { setState(() => _isLoading = true); try { - final historique = await _database.getHistoriqueSortiesPersonnelles( + final historique = await _database.getHistoriqueSortiesPersonnelles( adminId: _afficherSeulementMesDemandes ? _userController.userId : null, statut: _filtreStatut, + pointDeVenteId: _userController.pointDeVenteId == 0 ? null : _userController.pointDeVenteId, // Si pointDeVenteId = 0, ne pas filtrer limit: 100, ); setState(() { @@ -150,8 +151,9 @@ class _HistoriqueSortiesPersonnellesPageState extends State