client
This commit is contained in:
parent
99d570bd3a
commit
13296529c3
@ -806,24 +806,12 @@ class AppDatabase {
|
|||||||
|
|
||||||
Future<List<Commande>> getCommandes() async {
|
Future<List<Commande>> getCommandes() async {
|
||||||
final db = await database;
|
final db = await database;
|
||||||
|
|
||||||
final result = await db.query('''
|
final result = await db.query('''
|
||||||
SELECT
|
SELECT c.*, cl.nom as clientNom, cl.prenom as clientPrenom, cl.email as clientEmail
|
||||||
c.*,
|
|
||||||
cl.nom as clientNom,
|
|
||||||
cl.prenom as clientPrenom,
|
|
||||||
cl.email as clientEmail,
|
|
||||||
u.nom as commandeurNom,
|
|
||||||
u.prenom as commandeurPrenom,
|
|
||||||
pdv.nom as pointDeVenteNom,
|
|
||||||
pdv.id as pointDeVenteId
|
|
||||||
FROM commandes c
|
FROM commandes c
|
||||||
LEFT JOIN clients cl ON c.clientId = cl.id
|
LEFT JOIN clients cl ON c.clientId = cl.id
|
||||||
LEFT JOIN users u ON c.commandeurId = u.id
|
|
||||||
LEFT JOIN points_de_vente pdv ON u.point_de_vente_id = pdv.id
|
|
||||||
ORDER BY c.dateCommande DESC
|
ORDER BY c.dateCommande DESC
|
||||||
''');
|
''');
|
||||||
|
|
||||||
return result.map((row) => Commande.fromMap(row.fields)).toList();
|
return result.map((row) => Commande.fromMap(row.fields)).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,19 +1,20 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:youmazgestion/Components/app_bar.dart';
|
import 'package:youmazgestion/Components/app_bar.dart';
|
||||||
import 'package:youmazgestion/Components/appDrawer.dart';
|
import 'package:youmazgestion/Components/appDrawer.dart';
|
||||||
import 'package:youmazgestion/Models/client.dart';
|
import 'package:youmazgestion/Models/client.dart';
|
||||||
import 'package:youmazgestion/Services/stock_managementDatabase.dart';
|
import 'package:youmazgestion/Services/stock_managementDatabase.dart';
|
||||||
import 'package:youmazgestion/controller/userController.dart';
|
import 'package:youmazgestion/controller/userController.dart';
|
||||||
class HistoriquePage extends StatefulWidget {
|
|
||||||
|
class HistoriquePage extends StatefulWidget {
|
||||||
const HistoriquePage({super.key});
|
const HistoriquePage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_HistoriquePageState createState() => _HistoriquePageState();
|
_HistoriquePageState createState() => _HistoriquePageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _HistoriquePageState extends State<HistoriquePage> {
|
class _HistoriquePageState extends State<HistoriquePage> {
|
||||||
final AppDatabase _appDatabase = AppDatabase.instance;
|
final AppDatabase _appDatabase = AppDatabase.instance;
|
||||||
|
|
||||||
// Listes pour les commandes
|
// Listes pour les commandes
|
||||||
@ -30,7 +31,8 @@
|
|||||||
// Contrôleurs pour les filtres
|
// Contrôleurs pour les filtres
|
||||||
final TextEditingController _searchController = TextEditingController();
|
final TextEditingController _searchController = TextEditingController();
|
||||||
final TextEditingController _searchClientController = TextEditingController();
|
final TextEditingController _searchClientController = TextEditingController();
|
||||||
final TextEditingController _searchCommandeIdController = TextEditingController();
|
final TextEditingController _searchCommandeIdController =
|
||||||
|
TextEditingController();
|
||||||
|
|
||||||
// Variables de filtre
|
// Variables de filtre
|
||||||
StatutCommande? _selectedStatut;
|
StatutCommande? _selectedStatut;
|
||||||
@ -50,8 +52,7 @@
|
|||||||
_searchCommandeIdController.addListener(_filterCommandes);
|
_searchCommandeIdController.addListener(_filterCommandes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _loadPointsDeVenteWithDefault() async {
|
||||||
Future<void> _loadPointsDeVenteWithDefault() async {
|
|
||||||
try {
|
try {
|
||||||
print(_userController.userId);
|
print(_userController.userId);
|
||||||
final points = await _appDatabase.getPointsDeVente();
|
final points = await _appDatabase.getPointsDeVente();
|
||||||
@ -79,7 +80,7 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
Get.snackbar('Erreur', 'Impossible de charger les points de vente: $e');
|
Get.snackbar('Erreur', 'Impossible de charger les points de vente: $e');
|
||||||
print('❌ Erreur chargement points de vente: $e');
|
print('❌ Erreur chargement points de vente: $e');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadCommandes() async {
|
Future<void> _loadCommandes() async {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -115,7 +116,8 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
context: context,
|
context: context,
|
||||||
firstDate: DateTime(2020),
|
firstDate: DateTime(2020),
|
||||||
lastDate: DateTime.now().add(const Duration(days: 365)),
|
lastDate: DateTime.now().add(const Duration(days: 365)),
|
||||||
initialDateRange: _dateRange ?? DateTimeRange(
|
initialDateRange: _dateRange ??
|
||||||
|
DateTimeRange(
|
||||||
start: DateTime.now().subtract(const Duration(days: 30)),
|
start: DateTime.now().subtract(const Duration(days: 30)),
|
||||||
end: DateTime.now(),
|
end: DateTime.now(),
|
||||||
),
|
),
|
||||||
@ -151,8 +153,8 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
bool matchesCommandeId = commandeIdQuery.isEmpty ||
|
bool matchesCommandeId = commandeIdQuery.isEmpty ||
|
||||||
commande.id.toString().contains(commandeIdQuery);
|
commande.id.toString().contains(commandeIdQuery);
|
||||||
|
|
||||||
bool matchesStatut = _selectedStatut == null ||
|
bool matchesStatut =
|
||||||
commande.statut == _selectedStatut;
|
_selectedStatut == null || commande.statut == _selectedStatut;
|
||||||
|
|
||||||
bool matchesDate = true;
|
bool matchesDate = true;
|
||||||
if (_dateRange != null) {
|
if (_dateRange != null) {
|
||||||
@ -161,8 +163,7 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
date.isBefore(_dateRange!.end.add(const Duration(days: 1)));
|
date.isBefore(_dateRange!.end.add(const Duration(days: 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool matchesToday = !_showOnlyToday ||
|
bool matchesToday = !_showOnlyToday || _isToday(commande.dateCommande);
|
||||||
_isToday(commande.dateCommande);
|
|
||||||
|
|
||||||
bool matchesAmount = true;
|
bool matchesAmount = true;
|
||||||
if (_minAmount != null && commande.montantTotal < _minAmount!) {
|
if (_minAmount != null && commande.montantTotal < _minAmount!) {
|
||||||
@ -172,8 +173,13 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
matchesAmount = false;
|
matchesAmount = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matchesSearch && matchesClient && matchesCommandeId &&
|
if (matchesSearch &&
|
||||||
matchesStatut && matchesDate && matchesToday && matchesAmount) {
|
matchesClient &&
|
||||||
|
matchesCommandeId &&
|
||||||
|
matchesStatut &&
|
||||||
|
matchesDate &&
|
||||||
|
matchesToday &&
|
||||||
|
matchesAmount) {
|
||||||
_filteredCommandes.add(commande);
|
_filteredCommandes.add(commande);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,7 +247,8 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
TextButton.icon(
|
TextButton.icon(
|
||||||
onPressed: _clearFilters,
|
onPressed: _clearFilters,
|
||||||
icon: const Icon(Icons.clear, size: 18),
|
icon: const Icon(Icons.clear, size: 18),
|
||||||
label: isMobile ? const SizedBox() : const Text('Réinitialiser'),
|
label:
|
||||||
|
isMobile ? const SizedBox() : const Text('Réinitialiser'),
|
||||||
style: TextButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
foregroundColor: Colors.grey.shade600,
|
foregroundColor: Colors.grey.shade600,
|
||||||
),
|
),
|
||||||
@ -281,7 +288,8 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
filled: true,
|
filled: true,
|
||||||
fillColor: Colors.grey.shade50,
|
fillColor: Colors.grey.shade50,
|
||||||
),
|
),
|
||||||
),),
|
),
|
||||||
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
@ -376,34 +384,38 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
label: Text(_showOnlyToday
|
label: Text(_showOnlyToday
|
||||||
? isMobile ? 'Toutes dates' : 'Toutes les dates'
|
? isMobile
|
||||||
: isMobile ? 'Aujourd\'hui' : 'Aujourd\'hui seulement'),
|
? 'Toutes dates'
|
||||||
|
: 'Toutes les dates'
|
||||||
|
: isMobile
|
||||||
|
? 'Aujourd\'hui'
|
||||||
|
: 'Aujourd\'hui seulement'),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: _showOnlyToday
|
backgroundColor: _showOnlyToday
|
||||||
? Colors.green.shade600
|
? Colors.green.shade600
|
||||||
: Colors.blue.shade600,
|
: Colors.blue.shade600,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
horizontal: isMobile ? 12 : 16,
|
horizontal: isMobile ? 12 : 16, vertical: 8),
|
||||||
vertical: 8
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
onPressed: () => _selectDateRange(context),
|
onPressed: () => _selectDateRange(context),
|
||||||
icon: const Icon(Icons.date_range, size: 20),
|
icon: const Icon(Icons.date_range, size: 20),
|
||||||
label: Text(_dateRange != null
|
label: Text(_dateRange != null
|
||||||
? isMobile ? 'Période' : 'Période sélectionnée'
|
? isMobile
|
||||||
: isMobile ? 'Période' : 'Choisir période'),
|
? 'Période'
|
||||||
|
: 'Période sélectionnée'
|
||||||
|
: isMobile
|
||||||
|
? 'Période'
|
||||||
|
: 'Choisir période'),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: _dateRange != null
|
backgroundColor: _dateRange != null
|
||||||
? Colors.orange.shade600
|
? Colors.orange.shade600
|
||||||
: Colors.grey.shade600,
|
: Colors.grey.shade600,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
horizontal: isMobile ? 12 : 16,
|
horizontal: isMobile ? 12 : 16, vertical: 8),
|
||||||
vertical: 8
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -422,8 +434,7 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.date_range,
|
Icon(Icons.date_range,
|
||||||
size: 16,
|
size: 16, color: Colors.orange.shade700),
|
||||||
color: Colors.orange.shade700),
|
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Text(
|
Text(
|
||||||
'${DateFormat('dd/MM/yyyy').format(_dateRange!.start)} - ${DateFormat('dd/MM/yyyy').format(_dateRange!.end)}',
|
'${DateFormat('dd/MM/yyyy').format(_dateRange!.start)} - ${DateFormat('dd/MM/yyyy').format(_dateRange!.end)}',
|
||||||
@ -442,8 +453,7 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
_filterCommandes();
|
_filterCommandes();
|
||||||
},
|
},
|
||||||
child: Icon(Icons.close,
|
child: Icon(Icons.close,
|
||||||
size: 16,
|
size: 16, color: Colors.orange.shade700),
|
||||||
color: Colors.orange.shade700),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -454,10 +464,7 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
|
|
||||||
// Compteur de résultats
|
// Compteur de résultats
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||||
horizontal: 12,
|
|
||||||
vertical: 8
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.blue.shade50,
|
color: Colors.blue.shade50,
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
@ -484,7 +491,8 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
Get.bottomSheet(
|
Get.bottomSheet(
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
height: MediaQuery.of(context).size.height * 0.85, // Plus grand sur mobile
|
height:
|
||||||
|
MediaQuery.of(context).size.height * 0.85, // Plus grand sur mobile
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
||||||
@ -503,7 +511,8 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
color: Colors.blue.shade100,
|
color: Colors.blue.shade100,
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: Icon(Icons.receipt_long, color: Colors.blue.shade700),
|
child:
|
||||||
|
Icon(Icons.receipt_long, color: Colors.blue.shade700),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Text(
|
Text(
|
||||||
@ -533,18 +542,28 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_buildDetailRow('Client', '${client?.nom} ${client?.prenom}', Icons.person),
|
_buildDetailRow('Client', '${client?.nom} ${client?.prenom}',
|
||||||
_buildDetailRow('Date', DateFormat('dd/MM/yyyy à HH:mm').format(commande.dateCommande), Icons.calendar_today),
|
Icons.person),
|
||||||
_buildDetailRow('Client', '${_selectedPointDeVente} ', Icons.person),
|
_buildDetailRow(
|
||||||
|
'Date',
|
||||||
|
DateFormat('dd/MM/yyyy à HH:mm')
|
||||||
|
.format(commande.dateCommande),
|
||||||
|
Icons.calendar_today),
|
||||||
|
_buildDetailRow(
|
||||||
|
'PV', '${_selectedPointDeVente} ', Icons.person),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.assignment, size: 16, color: Colors.grey.shade600),
|
Icon(Icons.assignment,
|
||||||
|
size: 16, color: Colors.grey.shade600),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
const Text('Statut: ', style: TextStyle(fontWeight: FontWeight.w500)),
|
const Text('Statut: ',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.w500)),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8, vertical: 4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: _getStatutColor(commande.statut).withOpacity(0.2),
|
color:
|
||||||
|
_getStatutColor(commande.statut).withOpacity(0.2),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -618,7 +637,8 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
detail.produitNom ?? 'Produit inconnu',
|
detail.produitNom ?? 'Produit inconnu',
|
||||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
style:
|
||||||
|
const TextStyle(fontWeight: FontWeight.w500),
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
'${detail.quantite} x ${detail.prixUnitaire.toStringAsFixed(2)} MGA',
|
'${detail.quantite} x ${detail.prixUnitaire.toStringAsFixed(2)} MGA',
|
||||||
@ -643,7 +663,8 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.blue.shade800,
|
backgroundColor: Colors.blue.shade800,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 14), // Plus compact
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 14), // Plus compact
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
@ -817,7 +838,7 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'${_selectedPointDeVente}',
|
'PV: ${_selectedPointDeVente}',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
@ -846,7 +867,8 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
padding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: _getStatutColor(commande.statut).withOpacity(0.2),
|
color: _getStatutColor(commande.statut).withOpacity(0.2),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
@ -892,7 +914,8 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
// Sur mobile, on ajoute un bouton pour afficher les filtres dans un modal
|
// Sur mobile, on ajoute un bouton pour afficher les filtres dans un modal
|
||||||
if (isMobile) ...[
|
if (isMobile) ...[
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
padding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||||
child: ElevatedButton.icon(
|
child: ElevatedButton.icon(
|
||||||
icon: const Icon(Icons.filter_alt),
|
icon: const Icon(Icons.filter_alt),
|
||||||
label: const Text('Filtres'),
|
label: const Text('Filtres'),
|
||||||
@ -921,7 +944,8 @@ Future<void> _loadPointsDeVenteWithDefault() async {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
padding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.blue.shade50,
|
color: Colors.blue.shade50,
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
|||||||
@ -11,7 +11,7 @@ class DatabaseConfig {
|
|||||||
static const String localDatabase = 'guycom';
|
static const String localDatabase = 'guycom';
|
||||||
|
|
||||||
// Production (public) MySQL settings
|
// Production (public) MySQL settings
|
||||||
static const String prodHost = '185.70.105.157';
|
static const String prodHost = '102.17.52.31';
|
||||||
static const String prodUsername = 'guycom';
|
static const String prodUsername = 'guycom';
|
||||||
static const String prodPassword = '3iV59wjRdbuXAPR';
|
static const String prodPassword = '3iV59wjRdbuXAPR';
|
||||||
static const String prodDatabase = 'guycom';
|
static const String prodDatabase = 'guycom';
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user