|
|
@ -45,6 +45,11 @@ class AppDatabase { |
|
|
await insertDefaultPointsDeVente(); |
|
|
await insertDefaultPointsDeVente(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String _formatDate(DateTime date) { |
|
|
|
|
|
return DateFormat('yyyy-MM-dd HH:mm:ss').format(date); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
Future<MySqlConnection> _initDB() async { |
|
|
Future<MySqlConnection> _initDB() async { |
|
|
try { |
|
|
try { |
|
|
final config = await DatabaseConfig.getSmartConfig(); |
|
|
final config = await DatabaseConfig.getSmartConfig(); |
|
|
@ -2395,44 +2400,94 @@ Future<double> getValeurTotaleStock() async { |
|
|
return erreurs; |
|
|
return erreurs; |
|
|
} |
|
|
} |
|
|
// --- MÉTHODES POUR LES VENTES PAR POINT DE VENTE --- |
|
|
// --- MÉTHODES POUR LES VENTES PAR POINT DE VENTE --- |
|
|
|
|
|
Future<List<Map<String, dynamic>>> getVentesParPointDeVente({ |
|
|
Future<List<Map<String, dynamic>>> getVentesParPointDeVente() async { |
|
|
DateTime? dateDebut, |
|
|
|
|
|
DateTime? dateFin, |
|
|
|
|
|
bool? aujourdHuiSeulement = false, |
|
|
|
|
|
}) async { |
|
|
final db = await database; |
|
|
final db = await database; |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
|
|
|
String whereClause = 'WHERE c.statut != 5'; |
|
|
|
|
|
List<dynamic> whereArgs = []; |
|
|
|
|
|
|
|
|
|
|
|
if (aujourdHuiSeulement == true) { |
|
|
|
|
|
final today = DateTime.now(); |
|
|
|
|
|
final startOfDay = DateTime(today.year, today.month, today.day); |
|
|
|
|
|
final endOfDay = DateTime(today.year, today.month, today.day, 23, 59, 59); |
|
|
|
|
|
|
|
|
|
|
|
whereClause += ' AND c.dateCommande >= ? AND c.dateCommande <= ?'; |
|
|
|
|
|
whereArgs.addAll([ |
|
|
|
|
|
_formatDate(startOfDay), |
|
|
|
|
|
_formatDate(endOfDay), |
|
|
|
|
|
]); |
|
|
|
|
|
} else if (dateDebut != null && dateFin != null) { |
|
|
|
|
|
final adjustedEndDate = DateTime(dateFin.year, dateFin.month, dateFin.day, 23, 59, 59); |
|
|
|
|
|
whereClause += ' AND c.dateCommande >= ? AND c.dateCommande <= ?'; |
|
|
|
|
|
whereArgs.addAll([ |
|
|
|
|
|
_formatDate(dateDebut), |
|
|
|
|
|
_formatDate(adjustedEndDate), |
|
|
|
|
|
]); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
final result = await db.query(''' |
|
|
final result = await db.query(''' |
|
|
SELECT |
|
|
SELECT |
|
|
pv.id as point_vente_id, |
|
|
pv.id AS point_vente_id, |
|
|
pv.nom as point_vente_nom, |
|
|
pv.nom AS point_vente_nom, |
|
|
COUNT(DISTINCT c.id) as nombre_commandes, |
|
|
COUNT(DISTINCT c.id) AS nombre_commandes, |
|
|
COUNT(dc.id) as nombre_articles_vendus, |
|
|
COUNT(dc.id) AS nombre_articles_vendus, |
|
|
SUM(dc.quantite) as quantite_totale_vendue, |
|
|
SUM(dc.quantite) AS quantite_totale_vendue, |
|
|
SUM(c.montantTotal) as chiffre_affaires, |
|
|
SUM(c.montantTotal) AS chiffre_affaires, |
|
|
AVG(c.montantTotal) as panier_moyen, |
|
|
AVG(c.montantTotal) AS panier_moyen, |
|
|
MIN(c.dateCommande) as premiere_vente, |
|
|
MIN(c.dateCommande) AS premiere_vente, |
|
|
MAX(c.dateCommande) as derniere_vente |
|
|
MAX(c.dateCommande) AS derniere_vente |
|
|
FROM points_de_vente pv |
|
|
FROM points_de_vente pv |
|
|
LEFT JOIN products p ON pv.id = p.point_de_vente_id |
|
|
LEFT JOIN users u ON u.point_de_vente_id = pv.id |
|
|
LEFT JOIN details_commandes dc ON p.id = dc.produitId |
|
|
LEFT JOIN commandes c ON c.commandeurId = u.id |
|
|
LEFT JOIN commandes c ON dc.commandeId = c.id |
|
|
LEFT JOIN details_commandes dc ON dc.commandeId = c.id |
|
|
WHERE c.statut != 5 -- Exclure les commandes annulées |
|
|
$whereClause |
|
|
GROUP BY pv.id, pv.nom |
|
|
GROUP BY pv.id, pv.nom |
|
|
ORDER BY chiffre_affaires DESC |
|
|
ORDER BY chiffre_affaires DESC; |
|
|
'''); |
|
|
''', whereArgs); |
|
|
|
|
|
|
|
|
return result.map((row) => row.fields).toList(); |
|
|
return result.map((row) => row.fields).toList(); |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
print("Erreur getVentesParPointDeVente: $e"); |
|
|
print("Erreur getVentesParPointDeVente: $e"); |
|
|
return []; |
|
|
return []; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
Future<List<Map<String, dynamic>>> getTopProduitsParPointDeVente( |
|
|
Future<List<Map<String, dynamic>>> getTopProduitsParPointDeVente( |
|
|
int pointDeVenteId, { |
|
|
int pointDeVenteId, |
|
|
int limit = 5, |
|
|
{int limit = 5}) async { |
|
|
DateTime? dateDebut, |
|
|
|
|
|
DateTime? dateFin, |
|
|
|
|
|
bool? aujourdHuiSeulement = false, |
|
|
|
|
|
}) async { |
|
|
final db = await database; |
|
|
final db = await database; |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
|
|
|
String whereClause = 'WHERE p.point_de_vente_id = ? AND c.statut != 5'; |
|
|
|
|
|
List<dynamic> whereArgs = [pointDeVenteId]; |
|
|
|
|
|
|
|
|
|
|
|
if (aujourdHuiSeulement == true) { |
|
|
|
|
|
final today = DateTime.now(); |
|
|
|
|
|
final startOfDay = DateTime(today.year, today.month, today.day); |
|
|
|
|
|
final endOfDay = DateTime(today.year, today.month, today.day, 23, 59, 59); |
|
|
|
|
|
|
|
|
|
|
|
whereClause += ' AND c.dateCommande >= ? AND c.dateCommande <= ?'; |
|
|
|
|
|
whereArgs.addAll([ |
|
|
|
|
|
_formatDate(startOfDay), |
|
|
|
|
|
_formatDate(endOfDay), |
|
|
|
|
|
]); |
|
|
|
|
|
} else if (dateDebut != null && dateFin != null) { |
|
|
|
|
|
final adjustedEndDate = DateTime(dateFin.year, dateFin.month, dateFin.day, 23, 59, 59); |
|
|
|
|
|
whereClause += ' AND c.dateCommande >= ? AND c.dateCommande <= ?'; |
|
|
|
|
|
whereArgs.addAll([ |
|
|
|
|
|
_formatDate(dateDebut), |
|
|
|
|
|
_formatDate(adjustedEndDate), |
|
|
|
|
|
]); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
final result = await db.query(''' |
|
|
final result = await db.query(''' |
|
|
SELECT |
|
|
SELECT |
|
|
p.id, |
|
|
p.id, |
|
|
@ -2445,18 +2500,18 @@ Future<double> getValeurTotaleStock() async { |
|
|
FROM products p |
|
|
FROM products p |
|
|
INNER JOIN details_commandes dc ON p.id = dc.produitId |
|
|
INNER JOIN details_commandes dc ON p.id = dc.produitId |
|
|
INNER JOIN commandes c ON dc.commandeId = c.id |
|
|
INNER JOIN commandes c ON dc.commandeId = c.id |
|
|
WHERE p.point_de_vente_id = ? AND c.statut != 5 |
|
|
$whereClause |
|
|
GROUP BY p.id, p.name, p.price, p.category |
|
|
GROUP BY p.id, p.name, p.price, p.category |
|
|
ORDER BY quantite_vendue DESC |
|
|
ORDER BY quantite_vendue DESC |
|
|
LIMIT ? |
|
|
LIMIT ? |
|
|
''', [pointDeVenteId, limit]); |
|
|
''', [...whereArgs, limit]); |
|
|
|
|
|
|
|
|
return result.map((row) => row.fields).toList(); |
|
|
return result.map((row) => row.fields).toList(); |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
print("Erreur getTopProduitsParPointDeVente: $e"); |
|
|
print("Erreur getTopProduitsParPointDeVente: $e"); |
|
|
return []; |
|
|
return []; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Future<List<Map<String, dynamic>>> getVentesParPointDeVenteParMois( |
|
|
Future<List<Map<String, dynamic>>> getVentesParPointDeVenteParMois( |
|
|
int pointDeVenteId) async { |
|
|
int pointDeVenteId) async { |
|
|
@ -2487,7 +2542,7 @@ Future<double> getValeurTotaleStock() async { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Dans la classe AppDatabase, ajoutez cette méthode : |
|
|
// Dans la classe AppDatabase, ajoutez cette méthode : |
|
|
Future<bool> verifyCurrentUserPassword(String password) async { |
|
|
Future<bool> verifyCurrentUserPassword(String password) async { |
|
|
final db = await database; |
|
|
final db = await database; |
|
|
final userController = Get.find<UserController>(); |
|
|
final userController = Get.find<UserController>(); |
|
|
@ -2506,7 +2561,7 @@ Future<double> getValeurTotaleStock() async { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Dans AppDatabase |
|
|
// Dans AppDatabase |
|
|
Future<int> createDemandeTransfert({ |
|
|
Future<int> createDemandeTransfert({ |
|
|
required int produitId, |
|
|
required int produitId, |
|
|
required int pointDeVenteSourceId, |
|
|
required int pointDeVenteSourceId, |
|
|
@ -2689,9 +2744,9 @@ Future<double> getValeurTotaleStock() async { |
|
|
rethrow; |
|
|
rethrow; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
// Ajoutez ces méthodes dans votre classe AppDatabase |
|
|
// Ajoutez ces méthodes dans votre classe AppDatabase |
|
|
|
|
|
|
|
|
// 1. Méthode pour récupérer les demandes de transfert validées |
|
|
// 1. Méthode pour récupérer les demandes de transfert validées |
|
|
Future<List<Map<String, dynamic>>> getDemandesTransfertValidees() async { |
|
|
Future<List<Map<String, dynamic>>> getDemandesTransfertValidees() async { |
|
|
final db = await database; |
|
|
final db = await database; |
|
|
try { |
|
|
try { |
|
|
@ -2722,7 +2777,7 @@ Future<double> getValeurTotaleStock() async { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 2. Méthode pour récupérer toutes les demandes de transfert |
|
|
// 2. Méthode pour récupérer toutes les demandes de transfert |
|
|
Future<List<Map<String, dynamic>>> getToutesDemandesTransfert() async { |
|
|
Future<List<Map<String, dynamic>>> getToutesDemandesTransfert() async { |
|
|
final db = await database; |
|
|
final db = await database; |
|
|
try { |
|
|
try { |
|
|
@ -2758,7 +2813,7 @@ Future<double> getValeurTotaleStock() async { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 3. Méthode pour rejeter une demande de transfert |
|
|
// 3. Méthode pour rejeter une demande de transfert |
|
|
Future<int> rejeterTransfert( |
|
|
Future<int> rejeterTransfert( |
|
|
int demandeId, int validateurId, String motif) async { |
|
|
int demandeId, int validateurId, String motif) async { |
|
|
final db = await database; |
|
|
final db = await database; |
|
|
@ -2809,7 +2864,7 @@ Future<double> getValeurTotaleStock() async { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 4. Méthode supplémentaire : récupérer les demandes de transfert refusées |
|
|
// 4. Méthode supplémentaire : récupérer les demandes de transfert refusées |
|
|
Future<List<Map<String, dynamic>>> getDemandesTransfertRefusees() async { |
|
|
Future<List<Map<String, dynamic>>> getDemandesTransfertRefusees() async { |
|
|
final db = await database; |
|
|
final db = await database; |
|
|
try { |
|
|
try { |
|
|
@ -2840,7 +2895,7 @@ Future<double> getValeurTotaleStock() async { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 5. Méthode pour récupérer les demandes par statut spécifique |
|
|
// 5. Méthode pour récupérer les demandes par statut spécifique |
|
|
Future<List<Map<String, dynamic>>> getDemandesTransfertParStatut( |
|
|
Future<List<Map<String, dynamic>>> getDemandesTransfertParStatut( |
|
|
String statut) async { |
|
|
String statut) async { |
|
|
final db = await database; |
|
|
final db = await database; |
|
|
@ -2876,7 +2931,7 @@ Future<double> getValeurTotaleStock() async { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 6. Méthode pour récupérer les statistiques des transferts |
|
|
// 6. Méthode pour récupérer les statistiques des transferts |
|
|
Future<Map<String, dynamic>> getStatistiquesTransferts() async { |
|
|
Future<Map<String, dynamic>> getStatistiquesTransferts() async { |
|
|
final db = await database; |
|
|
final db = await database; |
|
|
|
|
|
|
|
|
@ -2944,7 +2999,7 @@ Future<double> getValeurTotaleStock() async { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 7. Méthode pour récupérer l'historique des transferts d'un produit |
|
|
// 7. Méthode pour récupérer l'historique des transferts d'un produit |
|
|
Future<List<Map<String, dynamic>>> getHistoriqueTransfertsProduit( |
|
|
Future<List<Map<String, dynamic>>> getHistoriqueTransfertsProduit( |
|
|
int produitId) async { |
|
|
int produitId) async { |
|
|
final db = await database; |
|
|
final db = await database; |
|
|
@ -2971,7 +3026,7 @@ Future<double> getValeurTotaleStock() async { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 8. Méthode pour annuler une demande de transfert (si en attente) |
|
|
// 8. Méthode pour annuler une demande de transfert (si en attente) |
|
|
Future<int> annulerDemandeTransfert(int demandeId, int utilisateurId) async { |
|
|
Future<int> annulerDemandeTransfert(int demandeId, int utilisateurId) async { |
|
|
final db = await database; |
|
|
final db = await database; |
|
|
|
|
|
|
|
|
@ -2998,7 +3053,7 @@ Future<double> getValeurTotaleStock() async { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// --- MÉTHODES POUR SORTIES STOCK PERSONNELLES --- |
|
|
// --- MÉTHODES POUR SORTIES STOCK PERSONNELLES --- |
|
|
|
|
|
|
|
|
Future<int> createSortieStockPersonnelle({ |
|
|
Future<int> createSortieStockPersonnelle({ |
|
|
required int produitId, |
|
|
required int produitId, |
|
|
@ -3157,12 +3212,12 @@ Future<double> getValeurTotaleStock() async { |
|
|
return []; |
|
|
return []; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
Future<List<Map<String, dynamic>>> getHistoriqueSortiesPersonnelles({ |
|
|
Future<List<Map<String, dynamic>>> getHistoriqueSortiesPersonnelles({ |
|
|
int? adminId, |
|
|
int? adminId, |
|
|
String? statut, |
|
|
String? statut, |
|
|
int? pointDeVenteId, |
|
|
int? pointDeVenteId, |
|
|
int limit = 50, |
|
|
int limit = 50, |
|
|
}) async { |
|
|
}) async { |
|
|
final db = await database; |
|
|
final db = await database; |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
@ -3210,7 +3265,7 @@ Future<List<Map<String, dynamic>>> getHistoriqueSortiesPersonnelles({ |
|
|
print('Erreur récupération historique sorties: $e'); |
|
|
print('Erreur récupération historique sorties: $e'); |
|
|
return []; |
|
|
return []; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Future<Map<String, dynamic>> getStatistiquesSortiesPersonnelles() async { |
|
|
Future<Map<String, dynamic>> getStatistiquesSortiesPersonnelles() async { |
|
|
final db = await database; |
|
|
final db = await database; |
|
|
@ -3269,4 +3324,7 @@ Future<List<Map<String, dynamic>>> getHistoriqueSortiesPersonnelles({ |
|
|
}; |
|
|
}; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
class _formatDate { |
|
|
} |
|
|
} |
|
|
|