feat: modifications et corrections du 03-04-2026

- Bouton impression conditionnel : 2 boutons (Facture + BL) si 1 produit, 1 bouton (BL) si plusieurs produits
- Ajout filtres (date, point de vente, utilisateur) sur la page Rapports principale
- Ajout filtres (date, point de vente) sur la page Rapports/Stock pour les 3 tableaux
- Remplacement affichage "UGS" par "N° SERIE" dans toutes les pages
- Mise en page facture avec remise : titre FACTURE repositionné, tableau plus compact
- Correction remise commandes multi-produits : total_price recevait un tableau au lieu d'un nombre
- SuperAdmin voit toutes les remises (tous statuts) au lieu de seulement "En attente"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
andrymodeste 2026-04-04 08:49:40 +02:00
parent fe80b9c4f8
commit 38d37a0987
10 changed files with 402 additions and 264 deletions

View File

@ -96,14 +96,23 @@ class OrderController extends AdminController
// POUR CAISSIÈRE
// ========================================
if ($users['group_name'] == "Caissière") {
$Remise = new Remise();
$Remise = new Remise();
foreach ($data as $key => $value) {
$date_time = date('d-m-Y h:i a', strtotime($value['date_time']));
$date_time = date('d-m-Y h:i a', strtotime($value['date_time']));
$buttons = '';
$discount = (float)$value['discount'];
$itemCount = (int)$value['item_count'];
// Génération des boutons d'impression
if ($itemCount > 1) {
$printButtons = '<a target="_blank" href="' . site_url('orders/printDivBL/' . $value['id']) . '" class="btn btn-default" title="Bon de livraison"><i class="fa fa-print"></i></a>';
} else {
$printButtons = '<a target="_blank" href="' . site_url('orders/printDiv/' . $value['id']) . '" class="btn btn-default" title="Facture"><i class="fa fa-print"></i></a>';
$printButtons .= ' <a target="_blank" href="' . site_url('orders/printDivBL/' . $value['id']) . '" class="btn btn-info" title="Bon de livraison"><i class="fa fa-file-text-o"></i></a>';
}
// ✅ VÉRIFICATION : Si la commande est refusée (paid_status = 0), aucun bouton
if ($value['paid_status'] == 0) {
$buttons = '<span class="label label-danger"><i class="fa fa-ban"></i> Accès bloqué</span>';
@ -112,15 +121,15 @@ class OrderController extends AdminController
if (in_array('viewOrder', $this->permission)) {
// CAS 1 : Commande payée (1) ou livrée (3) → Toujours afficher imprimer
if (in_array($value['paid_status'], [1, 3])) {
$buttons .= '<a target="_blank" href="' . site_url('orders/printDiv/' . $value['id']) . '" class="btn btn-default"><i class="fa fa-print"></i></a>';
$buttons .= $printButtons;
}
// CAS 2 : Commande en attente (2) SANS remise → Afficher imprimer
elseif ($value['paid_status'] == 2 && $discount == 0) {
$buttons .= '<a target="_blank" href="' . site_url('orders/printDiv/' . $value['id']) . '" class="btn btn-default"><i class="fa fa-print"></i></a>';
}
$buttons .= $printButtons;
}
// CAS 3 : Commande en attente (2) AVEC remise validée → Afficher imprimer
elseif ($value['paid_status'] == 2 && $Remise->hasRemiseValidatedForOrder($value['id'])) {
$buttons .= '<a target="_blank" href="' . site_url('orders/printDiv/' . $value['id']) . '" class="btn btn-default"><i class="fa fa-print"></i></a>';
$buttons .= $printButtons;
}
// CAS 4 : Commande en attente (2) AVEC remise en attente → Indicateur
elseif ($value['paid_status'] == 2 && $Remise->hasRemisePendingForOrder($value['id'])) {
@ -221,15 +230,21 @@ class OrderController extends AdminController
// ========================================
elseif(in_array($users['group_name'], ["Direction", "DAF", "SuperAdmin", "Administrator"])){
foreach ($data as $key => $value) {
$date_time = date('d-m-Y h:i a', strtotime($value['date_time']));
$date_time = date('d-m-Y h:i a', strtotime($value['date_time']));
$buttons = '';
$itemCount = (int)$value['item_count'];
// Bouton imprimer
if (in_array('viewOrder', $this->permission) && $users['group_name'] != "SECURITE" && $users['group_name'] != "COMMERCIALE") {
$buttons .= '<a target="_blank" href="' . site_url('orders/printDiv/' . $value['id']) . '" class="btn btn-default"><i class="fa fa-print"></i></a>';
if ($itemCount > 1) {
$buttons .= '<a target="_blank" href="' . site_url('orders/printDivBL/' . $value['id']) . '" class="btn btn-default" title="Bon de livraison"><i class="fa fa-print"></i></a>';
} else {
$buttons .= '<a target="_blank" href="' . site_url('orders/printDiv/' . $value['id']) . '" class="btn btn-default" title="Facture"><i class="fa fa-print"></i></a>';
$buttons .= ' <a target="_blank" href="' . site_url('orders/printDivBL/' . $value['id']) . '" class="btn btn-info" title="Bon de livraison"><i class="fa fa-file-text-o"></i></a>';
}
}
// ✅ Bouton modifier pour statuts 0 (Refusé) et 2 (En Attente)
if (in_array('updateOrder', $this->permission) && in_array($value['paid_status'], [0, 2])) {
$buttons .= ' <a href="' . site_url('orders/update/' . $value['id']) . '" class="btn btn-default"><i class="fa fa-pencil"></i></a>';
@ -287,15 +302,21 @@ class OrderController extends AdminController
// ========================================
else {
foreach ($data as $key => $value) {
$date_time = date('d-m-Y h:i a', strtotime($value['date_time']));
$date_time = date('d-m-Y h:i a', strtotime($value['date_time']));
$buttons = '';
$itemCount = (int)$value['item_count'];
// Bouton imprimer
if (in_array('viewOrder', $this->permission) && $users['group_name'] != "SECURITE" && $users['group_name'] != "COMMERCIALE") {
$buttons .= '<a target="_blank" href="' . site_url('orders/printDiv/' . $value['id']) . '" class="btn btn-default"><i class="fa fa-print"></i></a>';
if ($itemCount > 1) {
$buttons .= '<a target="_blank" href="' . site_url('orders/printDivBL/' . $value['id']) . '" class="btn btn-default" title="Bon de livraison"><i class="fa fa-print"></i></a>';
} else {
$buttons .= '<a target="_blank" href="' . site_url('orders/printDiv/' . $value['id']) . '" class="btn btn-default" title="Facture"><i class="fa fa-print"></i></a>';
$buttons .= ' <a target="_blank" href="' . site_url('orders/printDivBL/' . $value['id']) . '" class="btn btn-info" title="Bon de livraison"><i class="fa fa-file-text-o"></i></a>';
}
}
// ✅ Bouton modifier pour statuts 0 et 2, ET si c'est l'utilisateur créateur
if (in_array('updateOrder', $this->permission)
&& $users["id"] == $value['user_id']
@ -642,7 +663,7 @@ class OrderController extends AdminController
$data1 = [
'date_demande' => date('Y-m-d H:i:s'),
'montant_demande' => $discount,
'total_price' => $amounts,
'total_price' => $gross_amount,
'id_store' => $users['store_id'],
'id_order' => $order_id,
'product' => $product_output,
@ -1112,7 +1133,7 @@ public function update(int $id)
$data1 = [
'date_demande' => date('Y-m-d H:i:s'),
'montant_demande' => $this->request->getPost('discount'),
'total_price' => $amounts,
'total_price' => $gross_amount,
'id_store' => $user['store_id'],
'id_order' => $id,
'product' => $product_output,
@ -2080,6 +2101,7 @@ public function print5(int $id)
display: flex;
flex-direction: column;
border-bottom: 2px dashed #aaa;
overflow: hidden;
}
.facture-box:last-child {
@ -2091,7 +2113,6 @@ public function print5(int $id)
font-size: 24px;
font-weight: bold;
text-decoration: underline;
margin-bottom: 12px;
}
.f-company {
@ -2120,13 +2141,13 @@ public function print5(int $id)
.f-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 10px;
margin-bottom: 6px;
}
.f-table th, .f-table td {
border-left: 2px solid #000;
border-right: 2px solid #000;
padding: 8px 10px;
padding: 3px 8px;
text-align: center;
font-size: 12px;
}
@ -2137,7 +2158,7 @@ public function print5(int $id)
border-bottom: 2px solid #000;
}
.f-table td { height: 30px; }
.f-table td { height: 20px; }
.f-table tbody tr:last-child td {
border-bottom: 2px solid #000;
@ -2147,7 +2168,7 @@ public function print5(int $id)
.f-words {
font-size: 12px;
line-height: 1.3;
margin-bottom: 12px;
margin-bottom: 8px;
}
/* Signatures */
@ -2268,8 +2289,6 @@ public function print5(int $id)
$qrId = 'qr_recto_'.$i;
$html .= '
<div class="facture-box">
<div class="f-title" style="text-align:center;">FACTURE</div>
<div style="display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:8px;">
<div class="f-company" style="margin-bottom:0;">
<strong>'.$companyName.'</strong><br>
@ -2278,6 +2297,9 @@ public function print5(int $id)
Contact : '.$companyPhone.' / '.$companyPhone2.'<br>
'.$companyAddress.'
</div>
<div style="text-align:center; flex:1;">
<div class="f-title">FACTURE</div>
</div>
<div style="text-align:right; font-size:12px;">
<div>DATE : '.$today.'</div>
<div> : '.$billNo.'</div>

View File

@ -25,102 +25,125 @@ class ReportController extends AdminController
{
$this->verifyRole('viewReports');
$data['page_title'] = $this->pageTitle;
// Get the current year or the selected year from the form
$today_year = date('Y');
if ($this->request->getPost('select_year')) {
$today_year = $this->request->getPost('select_year');
}
// Récupérer les filtres
$startDate = $this->request->getPost('start_date') ?: null;
$endDate = $this->request->getPost('end_date') ?: null;
$storeId = $this->request->getPost('store_id') ?: null;
$userId = $this->request->getPost('user_id') ?: null;
// Fetch order data and years
$Reports = new Reports();
$Orders = new Orders();
$Store = new Stores();
$parking_data = $Reports->getOrderData($today_year);
$parking_data = $Reports->getOrderData($today_year, $startDate, $endDate, $storeId, $userId);
$data['report_years'] = $Reports->getOrderYear();
// Process the parking data and calculate total amounts
$final_parking_data = [];
foreach ($parking_data as $month => $orders) {
$total_amount_earned = 0;
if (!empty($orders)) {
foreach ($orders as $order) {
// Utiliser le montant selon la logique : discount si existe, sinon gross_amount
if (!empty($order['discount']) && $order['discount'] > 0) {
$total_amount_earned += (float) $order['discount'];
} else {
$total_amount_earned += (float) $order['gross_amount'];
}
// Charger les stores et users pour les filtres
$data['stores'] = $Store->getActiveStore();
$db = \Config\Database::connect();
$data['users_list'] = $db->table('users u')
->select('u.id, u.firstname, u.lastname, g.group_name')
->join('user_group ug', 'u.id = ug.user_id')
->join('groups g', 'ug.group_id = g.id')
->whereIn('g.group_name', ['COMMERCIALE', 'Caissière', "Cheffe d'Agence"])
->orderBy('u.firstname', 'ASC')
->get()->getResultArray();
// Conserver les filtres sélectionnés
$data['selected_start_date'] = $startDate;
$data['selected_end_date'] = $endDate;
$data['selected_store_id'] = $storeId;
$data['selected_user_id'] = $userId;
// Process the parking data and calculate total amounts
$final_parking_data = [];
foreach ($parking_data as $month => $orders) {
$total_amount_earned = 0;
if (!empty($orders)) {
foreach ($orders as $order) {
if (!empty($order['discount']) && $order['discount'] > 0) {
$total_amount_earned += (float) $order['discount'];
} else {
$total_amount_earned += (float) $order['gross_amount'];
}
}
$final_parking_data[$month] = $total_amount_earned;
}
$final_parking_data[$month] = $total_amount_earned;
}
// Data for the camembert (pie chart)
$paymentModes = $Orders->getPaymentModes();
$total_mvola1 = $paymentModes->total_mvola1;
$total_mvola2 = $paymentModes->total_mvola2;
$total_espece1 = $paymentModes->total_espece1;
$total_espece2 = $paymentModes->total_espece2;
$total_banque1 = $paymentModes->total_virement_bancaire1;
$total_banque2 = $paymentModes->total_virement_bancaire2;
$paymentModes = $Orders->getPaymentModes($startDate, $endDate, $storeId, $userId);
$total_mvola1 = $paymentModes->total_mvola1 ?? 0;
$total_mvola2 = $paymentModes->total_mvola2 ?? 0;
$total_espece1 = $paymentModes->total_espece1 ?? 0;
$total_espece2 = $paymentModes->total_espece2 ?? 0;
$total_banque1 = $paymentModes->total_virement_bancaire1 ?? 0;
$total_banque2 = $paymentModes->total_virement_bancaire2 ?? 0;
$total_mvola = $total_mvola1 + $total_mvola2;
$total_banque = $total_banque1 + $total_banque2;
$total_espece = $total_espece1 + $total_espece2;
$totalOrders = $Orders->getTotalOrders();
$totalOrders = $Orders->getTotalOrders($startDate, $endDate, $storeId, $userId);
$totalAmountPerPaymentModes = ["MVOLA" => $total_mvola, "Espece" => $total_espece, "Virement Bancaire" => $total_banque];
$totalOrdersCount = (int) $totalOrders->total_orders;
$labels = [];
$totals = [];
if ($totalOrdersCount > 0) {
foreach ($totalAmountPerPaymentModes as $mode => $total) {
$labels[] = $mode;
$totals[] = $total;
}
}
$data['labels'] = json_encode($labels);
$data['totals'] = json_encode($totals);
// Prepare data for product chart
$OrderItem = new OrderItems();
$productTable = $OrderItem->getAllSoldProductToday();
$product_sold = (int) $productTable->total_product_sold;
$unsold_product = (int) $productTable->total_unsold_product;
$productTable = $OrderItem->getAllSoldProductToday($startDate, $endDate, $storeId, $userId);
$product_sold = (int) ($productTable->total_product_sold ?? 0);
$unsold_product = (int) ($productTable->total_unsold_product ?? 0);
$labels1 = ["Produits vendus", "Produits non vendus"];
$totals2 = [$product_sold, $unsold_product];
$data['labels_product'] = json_encode($labels1);
$data['totals_product'] = json_encode($totals2);
// Prepare data for the view
$data['selected_year'] = $today_year;
$data['company_currency'] = $this->companycurrency();
$data['results'] = $final_parking_data;
// Data for the camembert in dashboard
$totalStoreOrder = $Orders->getTotalOrderPerStore();
$totalOrders = $Orders->getTotalOrders();
$totalStoreOrder = $Orders->getTotalOrderPerStore($startDate, $endDate, $storeId, $userId);
$totalOrders = $Orders->getTotalOrders($startDate, $endDate, $storeId, $userId);
$totalOrdersCount = (int) $totalOrders->total_orders;
// Initialisation des variables pour éviter l'erreur "Undefined variable"
$labelStore = [];
$totalPerStore = [];
foreach ($totalStoreOrder as $totalOrdersInStore) {
$storeList = $Store->getStoreById($totalOrdersInStore->store_id);
$labelStore[] = $storeList->name ?? 'Inconnu';
$totalPerStore[] = ((int) $totalOrdersInStore->total / $totalOrdersCount) * 100;
$totalPerStore[] = ($totalOrdersCount > 0) ? ((int) $totalOrdersInStore->total / $totalOrdersCount) * 100 : 0;
}
$data['labelStore'] = json_encode($labelStore);
$data['totalPerStore'] = json_encode($totalPerStore);
// Load the view
return $this->render_template('reports/index', $data);
}
@ -169,13 +192,13 @@ class ReportController extends AdminController
{
$Orders = new Orders();
$productVente = $Orders->getTotalProductvente2($id);
$startDate = $this->request->getGet('startDate');
$endDate = $this->request->getGet('endDate');
$productVente = $Orders->getTotalProductvente2($id, $startDate, $endDate);
$result = ['data' => []];
foreach ($productVente as $key => $value) {
// die(var_dump($value)); // Debugging: Check what $value contains
// Add the row data
$result['data'][$key] = [
$value->sku,
$value->date_time,
@ -183,7 +206,6 @@ class ReportController extends AdminController
];
}
// Return data in JSON format
return $this->response->setJSON($result);
}
@ -223,15 +245,13 @@ class ReportController extends AdminController
{
$Products = new Orders();
$produitStock = $Products->getOrderVendue();
$startDate = $this->request->getGet('startDate');
$endDate = $this->request->getGet('endDate');
$produitStock = $Products->getOrderVendue($id, $startDate, $endDate);
$result = ['data' => []];
// echo '<pre>';
// die(var_dump($produitStock));
foreach ($produitStock as $key => $value) {
// die(var_dump($value)); // Debugging: Check what $value contains
// Add the row data
$result['data'][$key] = [
$value['sku'],
$value['qty'],
@ -241,7 +261,6 @@ class ReportController extends AdminController
];
}
// Return data in JSON format
return $this->response->setJSON($result);
}
@ -526,7 +545,7 @@ class ReportController extends AdminController
$imageUrl, // 0 - Image
$order['bill_no'] ?? 'N/A', // 1 - N° Facture
$product['name'], // 2 - Désignation
$product['sku'], // 3 - UGS
$product['sku'], // 3 - N° SERIE
$brandName, // 4 - Marque
$order['customer_name'], // 5 - Client
$agentName, // 6 - Agent Sécurité

View File

@ -61,7 +61,7 @@ class SecuriteController extends AdminController
$result['data'][] = [
'image' => $img,
'ugs' => esc($product['sku']),
'num_serie' => esc($product['sku']),
'designation' => esc($product['name']),
'statut' => $statut,
'action' => $buttons
@ -88,7 +88,7 @@ class SecuriteController extends AdminController
$response = [
'image' => base_url('assets/images/product_image/' . $product['image']),
'nom' => $product['name'],
'ugs' => $product['sku'],
'num_serie' => $product['sku'],
'bill_no' => $data['bill_no'],
'customer_name' => $order_data['customer_name'],
'customer_address' => $order_data['customer_address'],

View File

@ -24,15 +24,32 @@ class OrderItems extends Model
return $this->where('order_id', $order_id)->findAll();
}
public function getAllSoldProductToday() {
return $this->select('
COUNT(orders_item.id) as total_product_sold,
public function getAllSoldProductToday($startDate = null, $endDate = null, $storeId = null, $userId = null) {
$builder = $this->select('
COUNT(orders_item.id) as total_product_sold,
(SELECT SUM(products.qty) FROM products) as total_unsold_product
')
->join('orders', 'orders_item.order_id = orders.id')
->where('DATE(orders.date_time)', date('Y-m-d'))
->get()
->getRow();
->join('orders', 'orders_item.order_id = orders.id');
if (!empty($startDate) || !empty($endDate) || !empty($storeId) || !empty($userId)) {
if (!empty($startDate)) {
$builder->where('DATE(orders.date_time) >=', $startDate);
}
if (!empty($endDate)) {
$builder->where('DATE(orders.date_time) <=', $endDate);
}
} else {
$builder->where('DATE(orders.date_time)', date('Y-m-d'));
}
if (!empty($storeId)) {
$builder->where('orders.store_id', $storeId);
}
if (!empty($userId)) {
$builder->where('orders.user_id', $userId);
}
return $builder->get()->getRow();
}
public function getSumOrdersItemData($order_id = null)

View File

@ -124,6 +124,7 @@ class Orders extends Model
->join('orders_item', 'orders_item.order_id = orders.id', 'left')
->join('products', 'products.id = orders_item.product_id', 'left')
->select("IFNULL(GROUP_CONCAT(DISTINCT products.name SEPARATOR '\\n'), '') AS product_names", false)
->select("COUNT(DISTINCT orders_item.id) AS item_count", false)
->groupBy('orders.id');
// Récupération du groupe de l'utilisateur
@ -387,7 +388,7 @@ class Orders extends Model
->findAll();
}
public function getPaymentModes($startDate = null, $endDate = null)
public function getPaymentModes($startDate = null, $endDate = null, $storeId = null, $userId = null)
{
$session = session();
$users = $session->get('user');
@ -395,79 +396,85 @@ class Orders extends Model
$baseQuery = $this->db->table('orders')
->select('
SUM(CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
SUM(CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN orders.discount
ELSE orders.net_amount
ELSE orders.net_amount
END) AS total,
SUM(CASE
WHEN orders.order_payment_mode = "MVOLA" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
SUM(CASE
WHEN orders.order_payment_mode = "MVOLA" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN (orders.tranche_1 * orders.discount / orders.net_amount)
ELSE orders.tranche_1
ELSE orders.tranche_1
END
ELSE 0
ELSE 0
END) AS total_mvola1,
SUM(CASE
WHEN orders.order_payment_mode_1 = "MVOLA" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
SUM(CASE
WHEN orders.order_payment_mode_1 = "MVOLA" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN (orders.tranche_2 * orders.discount / orders.net_amount)
ELSE orders.tranche_2
ELSE orders.tranche_2
END
ELSE 0
ELSE 0
END) AS total_mvola2,
SUM(CASE
WHEN orders.order_payment_mode = "En espèce" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
SUM(CASE
WHEN orders.order_payment_mode = "En espèce" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN (orders.tranche_1 * orders.discount / orders.net_amount)
ELSE orders.tranche_1
ELSE orders.tranche_1
END
ELSE 0
ELSE 0
END) AS total_espece1,
SUM(CASE
WHEN orders.order_payment_mode_1 = "En espèce" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
SUM(CASE
WHEN orders.order_payment_mode_1 = "En espèce" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN (orders.tranche_2 * orders.discount / orders.net_amount)
ELSE orders.tranche_2
ELSE orders.tranche_2
END
ELSE 0
ELSE 0
END) AS total_espece2,
SUM(CASE
WHEN orders.order_payment_mode = "Virement bancaire" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
SUM(CASE
WHEN orders.order_payment_mode = "Virement bancaire" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN (orders.tranche_1 * orders.discount / orders.net_amount)
ELSE orders.tranche_1
ELSE orders.tranche_1
END
ELSE 0
ELSE 0
END) AS total_virement_bancaire1,
SUM(CASE
WHEN orders.order_payment_mode_1 = "Virement bancaire" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
SUM(CASE
WHEN orders.order_payment_mode_1 = "Virement bancaire" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN (orders.tranche_2 * orders.discount / orders.net_amount)
ELSE orders.tranche_2
ELSE orders.tranche_2
END
ELSE 0
ELSE 0
END) AS total_virement_bancaire2
')
->whereIn('orders.paid_status', [1, 3]);
if (!$isAdmin) {
if (!empty($storeId)) {
$baseQuery->where('orders.store_id', $storeId);
} elseif (!$isAdmin) {
$baseQuery->where('orders.store_id', $users['store_id']);
}
if (!empty($userId)) {
$baseQuery->where('orders.user_id', $userId);
}
if ($startDate) {
$baseQuery->where('DATE(orders.date_time) >=', $startDate);
}
@ -478,21 +485,47 @@ class Orders extends Model
return $baseQuery->get()->getRowObject();
}
public function getTotalOrders()
public function getTotalOrders($startDate = null, $endDate = null, $storeId = null, $userId = null)
{
return $this->db->table('orders')
->select(' COUNT(*) as total_orders')
->get()
->getRow();
$builder = $this->db->table('orders')
->select('COUNT(*) as total_orders');
if (!empty($storeId)) {
$builder->where('store_id', $storeId);
}
if (!empty($userId)) {
$builder->where('user_id', $userId);
}
if (!empty($startDate)) {
$builder->where('DATE(date_time) >=', $startDate);
}
if (!empty($endDate)) {
$builder->where('DATE(date_time) <=', $endDate);
}
return $builder->get()->getRow();
}
public function getTotalOrderPerStore()
public function getTotalOrderPerStore($startDate = null, $endDate = null, $storeId = null, $userId = null)
{
return $this->db->table('orders')
$builder = $this->db->table('orders')
->select('store_id, COUNT(*) as total')
->groupBy('store_id')
->get()
->getResult();
->groupBy('store_id');
if (!empty($storeId)) {
$builder->where('store_id', $storeId);
}
if (!empty($userId)) {
$builder->where('user_id', $userId);
}
if (!empty($startDate)) {
$builder->where('DATE(date_time) >=', $startDate);
}
if (!empty($endDate)) {
$builder->where('DATE(date_time) <=', $endDate);
}
return $builder->get()->getResult();
}
public function getPaymentModesPercentage()
@ -556,53 +589,57 @@ class Orders extends Model
return $order;
}
public function getTotalProductvente2(?int $id)
public function getTotalProductvente2(?int $id, $startDate = null, $endDate = null)
{
$builder = $this->db->table('orders')
->select('orders.id, orders.paid_status, orders.store_id, orders.date_time, brands.name, products.name as Pname, products.sku')
->join('orders_item', 'orders.id = orders_item.order_id')
->join('products', 'orders_item.product_id = products.id')
->join('brands', 'brands.id = products.marque')
->whereIn('orders.paid_status', [1, 3]);
if ($id != 0) {
$order = $this->db->table('orders')
->select('orders.id, orders.paid_status, orders.store_id, orders.date_time, brands.name, products.name as Pname, products.sku')
->join('orders_item', 'orders.id = orders_item.order_id')
->join('products', 'orders_item.product_id = products.id')
->join('brands', 'brands.id = products.marque')
->whereIn('orders.paid_status', [1, 3]) // ← CHANGÉ ICI
->where('orders.store_id', $id)
->get()
->getResult();
} else {
$order = $this->db->table('orders')
->select('orders.id, orders.paid_status, orders.store_id, orders.date_time, brands.name, products.name as Pname, products.sku')
->join('orders_item', 'orders.id = orders_item.order_id')
->join('products', 'orders_item.product_id = products.id')
->join('brands', 'brands.id = products.marque')
->whereIn('orders.paid_status', [1, 3]) // ← CHANGÉ ICI
->get()
->getResult();
$builder->where('orders.store_id', $id);
}
return $order;
if (!empty($startDate)) {
$builder->where('DATE(orders.date_time) >=', $startDate);
}
if (!empty($endDate)) {
$builder->where('DATE(orders.date_time) <=', $endDate);
}
return $builder->get()->getResult();
}
public function getOrderVendue()
public function getOrderVendue($storeId = null, $startDate = null, $endDate = null)
{
$order = $this->db->table('products')
$builder = $this->db->table('products')
->select('
products.*,
products.name as Pname,
products.sku,
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN orders.discount
ELSE orders.gross_amount
products.*,
products.name as Pname,
products.sku,
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN orders.discount
ELSE orders.gross_amount
END as totalNet,
orders.date_time as DateTime
', false) // ← MODIFIÉ ICI
', false)
->join('orders_item', 'products.id = orders_item.product_id')
->join('orders', 'orders_item.order_id = orders.id')
->whereIn('orders.paid_status', [1, 3]) // ← ET ICI
->get()
->getResultArray();
return $order;
->whereIn('orders.paid_status', [1, 3]);
if (!empty($storeId) && $storeId != 0) {
$builder->where('orders.store_id', $storeId);
}
if (!empty($startDate)) {
$builder->where('DATE(orders.date_time) >=', $startDate);
}
if (!empty($endDate)) {
$builder->where('DATE(orders.date_time) <=', $endDate);
}
return $builder->get()->getResultArray();
}
public function getPerformanceByOrders($startDate = null, $endDate = null, $pvente = null, $commercialId = null)

View File

@ -16,10 +16,9 @@ class Remise extends Model
$session = session();
$users = $session->get('user');
// ✅ SUPERADMIN VOIT TOUTES LES DEMANDES "EN ATTENTE" (POUR VALIDATION)
// ✅ SUPERADMIN VOIT TOUTES LES DEMANDES (TOUS STATUTS)
if ($users["group_name"] === "SuperAdmin") {
return $this->where('demande_status', 'En attente')
->orderBy('date_demande', 'DESC')
return $this->orderBy('date_demande', 'DESC')
->findAll();
}

View File

@ -39,37 +39,51 @@ class Reports extends Model
* @param mixed $year
* @return array<array>
*/
public function getOrderData($year)
{
public function getOrderData($year, $startDate = null, $endDate = null, $storeId = null, $userId = null)
{
if ($year) {
$months = $this->months();
// Fetch orders with paid_status = 1 or 3
$result = $this->whereIn('paid_status', [1, 3])->findAll();
$builder = $this->whereIn('paid_status', [1, 3]);
if (!empty($storeId)) {
$builder->where('store_id', $storeId);
}
if (!empty($userId)) {
$builder->where('user_id', $userId);
}
if (!empty($startDate)) {
$builder->where('DATE(date_time) >=', $startDate);
}
if (!empty($endDate)) {
$builder->where('DATE(date_time) <=', $endDate);
}
$result = $builder->findAll();
$final_data = [];
foreach ($months as $month) {
$get_mon_year = $year . '-' . $month;
$get_mon_year = $year . '-' . $month;
$final_data[$get_mon_year] = [];
foreach ($result as $v) {
$month_year = date('Y-m', strtotime($v['date_time']));
$month_year = date('Y-m', strtotime($v['date_time']));
if ($get_mon_year == $month_year) {
// Modifier le montant selon votre logique
if (!empty($v['discount']) && $v['discount'] > 0) {
$v['amount_to_display'] = $v['discount']; // Utiliser le rabais
$v['amount_to_display'] = $v['discount'];
} else {
$v['amount_to_display'] = $v['gross_amount']; // Utiliser gross_amount
$v['amount_to_display'] = $v['gross_amount'];
}
$final_data[$get_mon_year][] = $v;
}
}
}
return $final_data;
}
return [];
}
}

View File

@ -13,20 +13,59 @@
<section class="content">
<div class="row">
<div class="col-md-12 col-xs-12">
<form class="form-inline" action="<?php echo base_url('reports/'); ?>" method="POST">
<div class="form-group">
<label for="select_year">Année</label>
<select class="form-control" name="select_year" id="select_year">
<?php foreach ($report_years as $value): ?>
<option value="<?php echo $value; ?>" <?php echo ($value == $selected_year) ? 'selected' : ''; ?>>
<?php echo $value; ?>
</option>
<?php endforeach; ?>
</select>
<form action="<?php echo base_url('reports/'); ?>" method="POST">
<div class="row" style="margin-bottom: 15px;">
<div class="col-md-2">
<label for="select_year">Année</label>
<select class="form-control" name="select_year" id="select_year">
<?php foreach ($report_years as $value): ?>
<option value="<?php echo $value; ?>" <?php echo ($value == $selected_year) ? 'selected' : ''; ?>>
<?php echo $value; ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-2">
<label for="start_date">Date début</label>
<input type="date" class="form-control" name="start_date" id="start_date" value="<?= $selected_start_date ?? '' ?>">
</div>
<div class="col-md-2">
<label for="end_date">Date fin</label>
<input type="date" class="form-control" name="end_date" id="end_date" value="<?= $selected_end_date ?? '' ?>">
</div>
<div class="col-md-2">
<label for="store_id">Point de vente</label>
<select class="form-control" name="store_id" id="store_id">
<option value="">TOUS</option>
<?php foreach ($stores as $store): ?>
<option value="<?= $store['id'] ?>" <?= (isset($selected_store_id) && $selected_store_id == $store['id']) ? 'selected' : '' ?>>
<?= $store['name'] ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-2">
<label for="user_id">Utilisateur</label>
<select class="form-control" name="user_id" id="user_id">
<option value="">TOUS</option>
<?php foreach ($users_list as $u): ?>
<option value="<?= $u['id'] ?>" <?= (isset($selected_user_id) && $selected_user_id == $u['id']) ? 'selected' : '' ?>>
<?= $u['firstname'] . ' ' . $u['lastname'] ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-2" style="padding-top: 25px;">
<button type="submit" class="btn btn-primary"><i class="fa fa-filter"></i> Filtrer</button>
<a href="<?= base_url('reports/') ?>" class="btn btn-default" title="Réinitialiser"><i class="fa fa-refresh"></i></a>
</div>
</div>
<div class="row" style="margin-bottom: 10px;">
<div class="col-md-12">
<a href="<?= base_url('reports/detail/stock') ?>" class="btn btn-sm btn-success">Details Stock</a>
<a href="<?= base_url('reports/detail/performance') ?>" class="btn btn-sm btn-primary">Performances</a>
</div>
</div>
<button type="submit" class="btn btn-default">Envoyer</button>
<a href="<?= base_url('reports/detail/stock') ?>" class="btn btn-sm btn-success">Details Stock</a>
<a href="<?= base_url('reports/detail/performance') ?>" class="btn btn-sm btn-primary">Performances</a>
</form>
</div>

View File

@ -136,20 +136,27 @@
</div>
<div class="card-body">
<div class="row g-3 align-items-center mb-4" style="margin: 5px 0 5px 5px;">
<div class="col-md-4">
<div class="col-md-3">
<label for="startDate" class="form-label">Date de début</label>
<input type="date" id="startDate" class="form-control">
</div>
<div class="col-md-4">
<div class="col-md-3">
<label for="endDate" class="form-label">Date de fin</label>
<input type="date" id="endDate" class="form-control">
</div>
<div class="col-md-4 d-flex align-items-end">
<div class="col-md-3">
<label for="exportStoreFilter" class="form-label">Point de vente</label>
<select id="exportStoreFilter" class="form-control">
<option value="TOUS">TOUS</option>
<?php foreach ($stores as $value) { ?>
<option value="<?= $value['id'] ?>"><?= $value['name'] ?></option>
<?php } ?>
</select>
</div>
<div class="col-md-3 d-flex align-items-end">
<br>
<button id="filteredB1" class="btn btn-primary w-100">Filtrer
🔍</button>
<button id="ExportBTN1" class="btn btn-success w-100">Exporter
📤</button>
<button id="filteredB1" class="btn btn-primary w-100">Filtrer</button>
<button id="ExportBTN1" class="btn btn-success w-100">Exporter</button>
</div>
</div>
@ -228,14 +235,16 @@
]
});
const filterBtn = document.getElementById('storeFilter');
const storeSelect = document.getElementById('storeFilter');
filterBtn.addEventListener('change', function () {
let filterValue = filterBtn.value === "TOUS" ? "0" : filterBtn.value;
storeSelect.addEventListener('change', function () {
let filterValue = storeSelect.value === "TOUS" ? "0" : storeSelect.value;
let startDate = $('#startDateStock').val();
let endDate = $('#endDateStock').val();
let params = '?startDate=' + startDate + '&endDate=' + endDate;
// Update the DataTable dynamically without reinitialization
manageTable.ajax.url('fetchData/' + filterValue).load();
manageTable2.ajax.url('fetchDataStock/' + filterValue).load();
manageTable.ajax.url('fetchData/' + filterValue + params).load();
manageTable2.ajax.url('fetchDataStock/' + filterValue + params).load();
});
let productsSold = <?= $ventes ?>;
@ -272,32 +281,14 @@
applyFilter("TOUS");
});
$.fn.dataTable.ext.search.push(function (settings, data, dataIndex) {
if (settings.nTable.id !== 'export1') return true; // Apply only to your table
const startDate = $('#startDate').val();
const endDate = $('#endDate').val();
const saleDate = data[3]; // assuming column 4 is "Date de vente"
// If no start date, show everything (default)
if (!startDate) {
return true;
}
const sale = new Date(saleDate);
const start = new Date(startDate);
const end = endDate ? new Date(endDate) : null;
if (end) {
return sale >= start && sale <= end;
} else {
return sale >= start;
}
});
$('#filteredB1').on('click', function () {
manageTable3.draw(); // re-filter table
let storeId = $('#exportStoreFilter').val();
let filterValue = storeId === "TOUS" ? "0" : storeId;
let startDate = $('#startDate').val();
let endDate = $('#endDate').val();
let params = '?startDate=' + startDate + '&endDate=' + endDate;
manageTable3.ajax.url('fetchDataStock2/' + filterValue + params).load();
});

View File

@ -308,7 +308,7 @@
</div>
<div class="col-md-8">
<p><strong>Produit :</strong> <span id="editNom"></span></p>
<p><strong>UGS :</strong> <span id="editUgs"></span></p>
<p><strong>SERIE :</strong> <span id="editNumSerie"></span></p>
<p><strong> Facture :</strong> <span id="editBillNo"></span></p>
<p><strong>Client :</strong> <span id="editClient"></span></p>
<p><strong>Adresse :</strong> <span id="editAddress"></span></p>
@ -353,8 +353,8 @@
<div class="col-xs-6"><span id="detailDesignation"></span></div>
</div>
<div class="row" style="margin-bottom: 15px;">
<div class="col-xs-6"><strong>UGS:</strong></div>
<div class="col-xs-6"><span id="detailUGS"></span></div>
<div class="col-xs-6"><strong>SERIE:</strong></div>
<div class="col-xs-6"><span id="detailNumSerie"></span></div>
</div>
<div class="row" style="margin-bottom: 15px;">
<div class="col-xs-6"><strong>Marque:</strong></div>
@ -430,7 +430,7 @@ $(function() {
},
columns: [
{ data: 'image', orderable: false },
{ data: 'ugs' },
{ data: 'num_serie' },
{ data: 'designation' },
{ data: 'statut' },
{ data: 'action', orderable: false }
@ -462,7 +462,7 @@ $(function() {
success: function(response) {
$('#editImage').attr('src', response.image);
$('#editNom').text(response.nom);
$('#editUgs').text(response.ugs);
$('#editNumSerie').text(response.num_serie);
$('#editBillNo').text(response.bill_no);
$('#editClient').text(response.customer_name);
$('#editAddress').text(response.customer_address);
@ -767,7 +767,7 @@ $(function() {
data.push([
'N° Facture',
'Désignation',
'UGS',
'N° SERIE',
'Marque',
'Client',
'Magasin',
@ -818,7 +818,7 @@ function viewDetails(id) {
$('#detailImage').attr('src', data[0]);
$('#detailBillNo').text(data[1]);
$('#detailDesignation').text(data[2]);
$('#detailUGS').text(data[3]);
$('#detailNumSerie').text(data[3]);
$('#detailMarque').text(data[4]);
$('#detailSerie').text(data[3]);
$('#detailStore').text(data[7]);