@ -107,11 +107,11 @@ class OrderController extends AdminController
// Statut de paiement
// Statut de paiement
if ($value['paid_status'] == 1) {
if ($value['paid_status'] == 1) {
$paid_status = '< span class = "label label-success" > Valid é< / span > ';
$paid_status = '< span class = "label label-success" > pay é< / span > ';
} elseif ($value['paid_status'] == 2) {
} elseif ($value['paid_status'] == 2) {
$paid_status = '< span class = "label label-warning" > En Attente< / span > ';
$paid_status = '< span class = "label label-warning" > En Attente< / span > ';
} elseif ($value['paid_status'] == 3) {
} elseif ($value['paid_status'] == 3) {
$paid_status = '< span class = "label label-info" > Valid é et Livré< / span > ';
$paid_status = '< span class = "label label-info" > pay é et Livré< / span > ';
} else {
} else {
$paid_status = '< span class = "label label-danger" > Refusé< / span > ';
$paid_status = '< span class = "label label-danger" > Refusé< / span > ';
}
}
@ -149,7 +149,7 @@ class OrderController extends AdminController
// ========================================
// ========================================
// POUR DIRECTION OU DAF
// POUR DIRECTION OU DAF
// ========================================
// ========================================
elseif($users['group_name'] == "Direction" || $users['group_name'] == "DAF"){
elseif($users['group_name'] == "Direction" || $users['group_name'] == "DAF" || $users['group_name'] == "SuperAdmin" ){
foreach ($data as $key => $value) {
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']));
@ -172,11 +172,11 @@ class OrderController extends AdminController
// Statut de paiement
// Statut de paiement
if ($value['paid_status'] == 1) {
if ($value['paid_status'] == 1) {
$paid_status = '< span class = "label label-success" > Valid é< / span > ';
$paid_status = '< span class = "label label-success" > pay é< / span > ';
} elseif ($value['paid_status'] == 2) {
} elseif ($value['paid_status'] == 2) {
$paid_status = '< span class = "label label-warning" > En Attente< / span > ';
$paid_status = '< span class = "label label-warning" > En Attente< / span > ';
} elseif ($value['paid_status'] == 3) {
} elseif ($value['paid_status'] == 3) {
$paid_status = '< span class = "label label-info" > Valid é et Livré< / span > ';
$paid_status = '< span class = "label label-info" > Pay é et Livré< / span > ';
} else {
} else {
$paid_status = '< span class = "label label-danger" > Refusé< / span > ';
$paid_status = '< span class = "label label-danger" > Refusé< / span > ';
}
}
@ -255,11 +255,11 @@ class OrderController extends AdminController
// Statut de paiement
// Statut de paiement
if ($value['paid_status'] == 1) {
if ($value['paid_status'] == 1) {
$paid_status = '< span class = "label label-success" > Valid é< / span > ';
$paid_status = '< span class = "label label-success" > Pay é< / span > ';
} elseif ($value['paid_status'] == 2) {
} elseif ($value['paid_status'] == 2) {
$paid_status = '< span class = "label label-warning" > En Attente< / span > ';
$paid_status = '< span class = "label label-warning" > En Attente< / span > ';
} elseif ($value['paid_status'] == 3) {
} elseif ($value['paid_status'] == 3) {
$paid_status = '< span class = "label label-info" > Valid é et Livré< / span > ';
$paid_status = '< span class = "label label-info" > Pay é et Livré< / span > ';
} else {
} else {
$paid_status = '< span class = "label label-danger" > Refusé< / span > ';
$paid_status = '< span class = "label label-danger" > Refusé< / span > ';
}
}
@ -331,211 +331,281 @@ class OrderController extends AdminController
public function create()
/**
{
* ✅ AMÉLIORATION : Notifications centralisées pour Direction/DAF/SuperAdmin (tous stores)
$this->verifyRole('createOrder');
*/
$data['page_title'] = $this->pageTitle;
public function create()
$validation = \Config\Services::validation();
{
$products = $this->request->getPost('product[]');
$this->verifyRole('createOrder');
$data['page_title'] = $this->pageTitle;
if ($products !== null & & (count($products) !== count(array_unique($products)))) {
return redirect()->back()->withInput()->with('errors', ['product' => 'Chaque produit sélectionné doit être unique.']);
$validation = \Config\Services::validation();
$products = $this->request->getPost('product[]');
if ($products !== null & & (count($products) !== count(array_unique($products)))) {
return redirect()->back()->withInput()->with('errors', ['product' => 'Chaque produit sélectionné doit être unique.']);
}
$validation->setRules([
'product[]' => 'required',
'customer_type' => 'required',
'source' => 'required'
]);
$validationData = [
'product[]' => $this->request->getPost('product[]'),
'customer_type' => $this->request->getPost('customer_type'),
'source' => $this->request->getPost('source')
];
$Orders = new Orders();
$Company = new Company();
$Products = new Products();
if ($this->request->getMethod() === 'post' & & $validation->run($validationData)) {
$session = session();
$users = $session->get('user');
$user_id = $users['id'];
$bill_no = $this->generateBillNo($users['store_id']);
$posts = $this->request->getPost('product[]');
$rates = $this->request->getPost('rate_value[]');
$amounts = $this->request->getPost('amount_value[]');
$puissances = $this->request->getPost('puissance[]');
$discount = (float)$this->request->getPost('discount') ?? 0;
$gross_amount = $this->calculGross($amounts);
// Vérification prix minimal SI rabais existe
if ($discount > 0) {
$FourchettePrix = new \App\Models\FourchettePrix();
foreach ($posts as $index => $productId) {
$productId = (int)$productId;
$productData = $Products->getProductData($productId);
$fourchette = $FourchettePrix->getFourchettePrixByProductId($productId);
if ($fourchette) {
$prixMinimal = (float)$fourchette['prix_minimal'];
if ($discount < $prixMinimal) {
$prixMinimalFormatted = number_format($prixMinimal, 0, ',', ' ');
$discountFormatted = number_format($discount, 0, ',', ' ');
return redirect()->back()
->withInput()
->with('errors', [
"⚠️ Commande bloquée : Le rabais de {$discountFormatted} Ar pour « {$productData['name']} » est trop élevé."
]);
}
}
}
}
}
// ✅ AJOUT DES RÈGLES DE VALIDATION
$montant_a_payer = ($discount > 0) ? $discount : $gross_amount;
$validation->setRules([
'product[]' => 'required',
$tranche_1 = (float)$this->request->getPost('tranche_1') ?? 0;
'customer_type' => 'required',
$tranche_2 = (float)$this->request->getPost('tranche_2') ?? 0;
'source' => 'required'
]);
if ($tranche_1 > 0 & & $tranche_2 > 0) {
$net_amount = $tranche_1 + $tranche_2;
// ✅ AJOUT DES DONNÉES DE VALIDATION
} else {
$validationData = [
$net_amount = $montant_a_payer;
'product[]' => $this->request->getPost('product[]'),
}
'customer_type' => $this->request->getPost('customer_type'),
'source' => $this->request->getPost('source')
$data = [
'bill_no' => $bill_no,
'customer_name' => $this->request->getPost('customer_name'),
'customer_address' => $this->request->getPost('customer_address'),
'customer_phone' => $this->request->getPost('customer_phone'),
'customer_cin' => $this->request->getPost('customer_cin'),
'customer_type' => $this->request->getPost('customer_type'),
'source' => $this->request->getPost('source'),
'date_time' => date('Y-m-d H:i:s'),
'service_charge_rate' => 0,
'vat_charge_rate' => 0,
'vat_charge' => 0,
'net_amount' => $net_amount,
'discount' => $discount,
'paid_status' => 2,
'user_id' => $user_id,
'amount_value' => $amounts,
'gross_amount' => $gross_amount,
'rate_value' => $rates,
'puissance' => $puissances,
'store_id' => $users['store_id'],
'tranche_1' => $tranche_1,
'tranche_2' => $tranche_2,
'order_payment_mode' => $this->request->getPost('order_payment_mode_1'),
'order_payment_mode_1' => $this->request->getPost('order_payment_mode_2')
];
];
$Orders = new Orders();
$order_id = $Orders->create($data, $posts);
$Company = new Company();
$Products = new Products();
if ($order_id) {
session()->setFlashdata('success', 'Créé avec succès');
if ($this->request->getMethod() === 'post' & & $validation->run($validationData)) {
$Notification = new NotificationController();
$session = session();
$Stores = new Stores();
$users = $session->get('user');
$user_id = $users['id'];
$bill_no = $this->generateBillNo($users['store_id']);
// Récupération des produits
$posts = $this->request->getPost('product[]');
$rates = $this->request->getPost('rate_value[]');
$amounts = $this->request->getPost('amount_value[]');
$puissances = $this->request->getPost('puissance[]');
$discount = (float)$this->request->getPost('discount') ?? 0;
$gross_amount = $this->calculGross($amounts);
// Vérification prix minimal SI rabais existe
if ($discount > 0) {
if ($discount > 0) {
$FourchettePrix = new \App\Models\FourchettePrix();
// ✅ DEMANDE DE REMISE : NOTIFIER TOUS LES STORES
$Order_item1 = new OrderItems();
foreach ($posts as $index => $productId) {
$order_item_data = $Order_item1->getOrdersItemData($order_id);
$productId = (int)$productId;
$product_ids = array_column($order_item_data, 'product_id');
$productData = $Products->getProductData($productId);
$productData = new Products();
$fourchette = $FourchettePrix->getFourchettePrixByProductId($productId);
$product_data_results = [];
if ($fourchette) {
foreach ($product_ids as $prod_id) {
$prixMinimal = (float)$fourchette['prix_minimal'];
$id = (int) $prod_id;
$product_data_results[] = $productData->getProductData($id);
if ($discount < $prixMinimal) {
$prixMinimalFormatted = number_format($prixMinimal, 0, ',', ' ');
$discountFormatted = number_format($discount, 0, ',', ' ');
return redirect()->back()
->withInput()
->with('errors', [
"⚠️ Commande bloquée : Le rabais de {$discountFormatted} Ar pour « {$productData['name']} » est trop élevé."
]);
}
}
}
}
}
$product_lines = [];
// Calculer le montant à payer et net_amount
foreach ($product_data_results as $product) {
$montant_a_payer = ($discount > 0) ? $discount : $gross_amount;
if (isset($product['sku'], $product['price'])) {
$sku = $product['sku'];
$tranche_1 = (float)$this->request->getPost('tranche_1') ?? 0;
$price = $product['price'];
$tranche_2 = (float)$this->request->getPost('tranche_2') ?? 0;
$product_lines[] = "{$sku}:{$price}";
if ($tranche_1 > 0 & & $tranche_2 > 0) {
$net_amount = $tranche_1 + $tranche_2;
} else {
$net_amount = $montant_a_payer;
}
// ✅ AJOUT DES NOUVEAUX CHAMPS ICI
$data = [
'bill_no' => $bill_no,
'customer_name' => $this->request->getPost('customer_name'),
'customer_address' => $this->request->getPost('customer_address'),
'customer_phone' => $this->request->getPost('customer_phone'),
'customer_cin' => $this->request->getPost('customer_cin'),
'customer_type' => $this->request->getPost('customer_type'), // ✅ NOUVEAU
'source' => $this->request->getPost('source'), // ✅ NOUVEAU
'date_time' => date('Y-m-d H:i:s'),
'service_charge_rate' => 0,
'vat_charge_rate' => 0,
'vat_charge' => 0,
'net_amount' => $net_amount,
'discount' => $discount,
'paid_status' => 2,
'user_id' => $user_id,
'amount_value' => $amounts,
'gross_amount' => $gross_amount,
'rate_value' => $rates,
'puissance' => $puissances,
'store_id' => $users['store_id'],
'tranche_1' => $tranche_1,
'tranche_2' => $tranche_2,
'order_payment_mode' => $this->request->getPost('order_payment_mode_1'),
'order_payment_mode_1' => $this->request->getPost('order_payment_mode_2')
];
$order_id = $Orders->create($data, $posts);
if ($order_id) {
session()->setFlashdata('success', 'Créé avec succès');
$Notification = new NotificationController();
if ($discount > 0) {
// Logique demande de remise...
$Order_item1 = new OrderItems();
$order_item_data = $Order_item1->getOrdersItemData($order_id);
$product_ids = array_column($order_item_data, 'product_id');
$productData = new Products();
$product_data_results = [];
foreach ($product_ids as $prod_id) {
$id = (int) $prod_id;
$product_data_results[] = $productData->getProductData($id);
}
$product_lines = [];
foreach ($product_data_results as $product) {
if (isset($product['sku'], $product['price'])) {
$sku = $product['sku'];
$price = $product['price'];
$product_lines[] = "{$sku}:{$price}";
}
}
}
$product_output = implode("\n", $product_lines);
$data1 = [
'date_demande' => date('Y-m-d H:i:s'),
'montant_demande' => $discount,
'total_price' => $amounts,
'id_store' => $users['store_id'],
'id_order' => $order_id,
'product' => $product_output,
'demande_status' => 'En attente'
];
$Remise = new Remise();
$id_remise = $Remise->addDemande($data1);
$Notification->createNotification(
"Nouvelle demande de remise à valider - Commande " . $bill_no,
"Direction",
(int)$users['store_id'],
"remise/"
);
} else {
$Notification->createNotification(
"Nouvelle commande à valider - " . $bill_no,
"Caissière",
(int)$users['store_id'],
"orders"
);
}
}
if ($users["group_name"] != "COMMERCIALE") {
$product_output = implode("\n", $product_lines);
$this->checkProductisNull($posts, $users['store_id']);
$data1 = [
'date_demande' => date('Y-m-d H:i:s'),
'montant_demande' => $discount,
'total_price' => $amounts,
'id_store' => $users['store_id'],
'id_order' => $order_id,
'product' => $product_output,
'demande_status' => 'En attente'
];
$Remise = new Remise();
$id_remise = $Remise->addDemande($data1);
// ✅ RÉCUPÉRER TOUS LES STORES
$allStores = $Stores->getActiveStore();
$montantFormatted = number_format($discount, 0, ',', ' ');
$message = "💰 Nouvelle demande de remise : {$montantFormatted} Ar< br > " .
"Commande : {$bill_no}< br > " .
"Store : " . $this->returnStore($users['store_id']) . "< br > " .
"Demandeur : {$users['firstname']} {$users['lastname']}";
// ✅ NOTIFIER SUPERADMIN, DIRECTION, DAF DE TOUS LES STORES
if (is_array($allStores) & & count($allStores) > 0) {
foreach ($allStores as $store) {
// SuperAdmin (validation)
$Notification->createNotification(
$message,
"SuperAdmin",
(int)$store['id'],
'remise/'
);
// Direction (consultation)
$Notification->createNotification(
$message . "< br > < em > Pour information< / em > ",
"Direction",
(int)$store['id'],
'remise/'
);
// DAF (consultation)
$Notification->createNotification(
$message . "< br > < em > Pour information< / em > ",
"DAF",
(int)$store['id'],
'remise/'
);
}
}
}
return redirect()->to('orders/');
} else {
} else {
session()->setFlashdata('errors', 'Error occurred!!');
// ✅ COMMANDE SANS REMISE : NOTIFIER CAISSIÈRE DU STORE + TOUS LES CENTRAUX
return redirect()->to('orders/create/');
// Caissière du store concerné
$Notification->createNotification(
"📦 Nouvelle commande à valider : {$bill_no}< br > " .
"Client : {$data['customer_name']}< br > " .
"Montant : " . number_format($gross_amount, 0, ',', ' ') . " Ar",
"Caissière",
(int)$users['store_id'],
"orders"
);
// ✅ RÉCUPÉRER TOUS LES STORES
$allStores = $Stores->getActiveStore();
$messageGlobal = "📋 Nouvelle commande créée : {$bill_no}< br > " .
"Store : " . $this->returnStore($users['store_id']) . "< br > " .
"Client : {$data['customer_name']}< br > " .
"Montant : " . number_format($gross_amount, 0, ',', ' ') . " Ar< br > " .
"Créée par : {$users['firstname']} {$users['lastname']}";
// ✅ NOTIFIER DIRECTION, DAF, SUPERADMIN DE TOUS LES STORES
if (is_array($allStores) & & count($allStores) > 0) {
foreach ($allStores as $store) {
$Notification->createNotification(
$messageGlobal,
"Direction",
(int)$store['id'],
'orders'
);
$Notification->createNotification(
$messageGlobal,
"DAF",
(int)$store['id'],
'orders'
);
$Notification->createNotification(
$messageGlobal,
"SuperAdmin",
(int)$store['id'],
'orders'
);
}
}
}
}
if ($users["group_name"] != "COMMERCIALE") {
$this->checkProductisNull($posts, $users['store_id']);
}
return redirect()->to('orders/');
} else {
} else {
// Affichage du formulaire
session()->setFlashdata('errors', 'Error occurred!!');
$company = $Company->getCompanyData(1);
return redirect()->to('orders/create/');
$session = session();
$users = $session->get('user');
$store_id = $users['store_id'];
$data = [
'paid_status' => 2,
'company_data' => $company,
'is_vat_enabled' => ($company['vat_charge_value'] > 0),
'is_service_enabled' => ($company['service_charge_value'] > 0),
'products' => $Products->getProductData2($store_id),
'validation' => $validation,
'page_title' => $this->pageTitle,
];
return $this->render_template('orders/create', $data);
}
}
} else {
// Affichage du formulaire
$company = $Company->getCompanyData(1);
$session = session();
$users = $session->get('user');
$store_id = $users['store_id'];
$data = [
'paid_status' => 2,
'company_data' => $company,
'is_vat_enabled' => ($company['vat_charge_value'] > 0),
'is_service_enabled' => ($company['service_charge_value'] > 0),
'products' => $Products->getProductData2($store_id),
'validation' => $validation,
'page_title' => $this->pageTitle,
];
return $this->render_template('orders/create', $data);
}
}
}
/**
/**
* Marquer une commande comme livrée
* Marquer une commande comme livrée
* Accessible uniquement par le rôle SECURITE
* Accessible uniquement par le rôle SECURITE
@ -583,15 +653,42 @@ public function markAsDelivered()
$updated = $Orders->update((int)$order_id, ['paid_status' => 3]);
$updated = $Orders->update((int)$order_id, ['paid_status' => 3]);
if ($updated) {
if ($updated) {
// Créer une notification
// ✅ Créer une notification centralisée pour tous les stores
try {
try {
$Notification = new NotificationController();
$Notification = new NotificationController();
$Notification->createNotification(
$Stores = new Stores();
"Commande " . $current_order['bill_no'] . " livrée avec succès",
$allStores = $Stores->getActiveStore();
"Direction",
(int)$current_order['store_id'],
$messageGlobal = "📦 Commande livrée : {$current_order['bill_no']}< br > " .
"orders"
"Store : " . $this->returnStore($current_order['store_id']) . "< br > " .
);
"Client : {$current_order['customer_name']}< br > " .
"Livrée par : {$users['firstname']} {$users['lastname']}";
// ✅ NOTIFIER DIRECTION, DAF, SUPERADMIN DE TOUS LES STORES
if (is_array($allStores) & & count($allStores) > 0) {
foreach ($allStores as $store) {
$Notification->createNotification(
$messageGlobal,
"Direction",
(int)$store['id'],
'orders'
);
$Notification->createNotification(
$messageGlobal,
"DAF",
(int)$store['id'],
'orders'
);
$Notification->createNotification(
$messageGlobal,
"SuperAdmin",
(int)$store['id'],
'orders'
);
}
}
} catch (\Exception $e) {
} catch (\Exception $e) {
// Si la notification échoue, on continue quand même
// Si la notification échoue, on continue quand même
log_message('error', 'Erreur notification: ' . $e->getMessage());
log_message('error', 'Erreur notification: ' . $e->getMessage());
@ -611,7 +708,6 @@ public function markAsDelivered()
return $this->response->setJSON($response);
return $this->response->setJSON($response);
}
}
public function getProductValueById()
public function getProductValueById()
{
{
$product_id = $this->request->getPost('product_id');
$product_id = $this->request->getPost('product_id');
@ -793,10 +889,12 @@ public function update(int $id)
$Notification = new NotificationController();
$Notification = new NotificationController();
// ✅ NOTIFICATION CENTRALISÉE POUR VALIDATION
if ($old_paid_status == 2 & & $paid_status == 1) {
if ($old_paid_status == 2 & & $paid_status == 1) {
$customer_name = $this->request->getPost('customer_name');
$customer_name = $this->request->getPost('customer_name');
$bill_no = $current_order['bill_no'];
$bill_no = $current_order['bill_no'];
// ✅ Notification SECURITE du store concerné
$Notification->createNotification(
$Notification->createNotification(
"Commande validée: {$bill_no} - Client: {$customer_name}",
"Commande validée: {$bill_no} - Client: {$customer_name}",
"SECURITE",
"SECURITE",
@ -804,13 +902,39 @@ public function update(int $id)
'orders'
'orders'
);
);
if ($role === 'Caissière') {
// ✅ RÉCUPÉRER TOUS LES STORES
$Notification->createNotification(
$Stores = new Stores();
"Commande validée par la caisse: {$bill_no}",
$allStores = $Stores->getActiveStore();
"Direction",
(int)$user['store_id'],
$messageGlobal = "✅ Commande validée : {$bill_no}< br > " .
'orders'
"Store : " . $this->returnStore($user['store_id']) . "< br > " .
);
"Client : {$customer_name}< br > " .
"Validée par : {$user['firstname']} {$user['lastname']}";
// ✅ NOTIFIER DIRECTION, DAF, SUPERADMIN DE TOUS LES STORES
if (is_array($allStores) & & count($allStores) > 0) {
foreach ($allStores as $store) {
$Notification->createNotification(
$messageGlobal,
"Direction",
(int)$store['id'],
'orders'
);
$Notification->createNotification(
$messageGlobal,
"DAF",
(int)$store['id'],
'orders'
);
$Notification->createNotification(
$messageGlobal,
"SuperAdmin",
(int)$store['id'],
'orders'
);
}
}
}
}
}
@ -973,7 +1097,7 @@ public function update(int $id)
$html = '';
$html = '';
// Vérifier si l'utilisateur a payé
// Vérifier si l'utilisateur a payé
if ($order_data['paid_status'] == 1) {
if ($order_data['paid_status'] == 1) {
$paid_status = "< span style = 'color: green; font-weight: bold;' > Valid é< / span > ";
$paid_status = "< span style = 'color: green; font-weight: bold;' > Pay é< / span > ";
} elseif ($order_data['paid_status'] == 2) {
} elseif ($order_data['paid_status'] == 2) {
$paid_status = "< span style = 'color: orange; font-weight: bold;' > En Attente< / span > ";
$paid_status = "< span style = 'color: orange; font-weight: bold;' > En Attente< / span > ";
} else {
} else {
@ -1460,7 +1584,7 @@ public function update(int $id)
$company_info = $Company->getCompanyData(1);
$company_info = $Company->getCompanyData(1);
$paid_status = $order_data['paid_status'] == 1
$paid_status = $order_data['paid_status'] == 1
? "< span style = 'color: green; font-weight: bold;' > Valid é< / span > "
? "< span style = 'color: green; font-weight: bold;' > Pay é< / span > "
: "< span style = 'color: red; font-weight: bold;' > Refusé< / span > ";
: "< span style = 'color: red; font-weight: bold;' > Refusé< / span > ";
// STYLE COMMUN
// STYLE COMMUN
@ -2484,7 +2608,7 @@ public function print31(int $id)
}
}
$paid_status = $order_data['paid_status'] === 1
$paid_status = $order_data['paid_status'] === 1
? "< span style = 'color: green; font-weight: bold;' > Valid é< / span > "
? "< span style = 'color: green; font-weight: bold;' > Pay é< / span > "
: "< span style = 'color: red; font-weight: bold;' > Refusé< / span > ";
: "< span style = 'color: red; font-weight: bold;' > Refusé< / span > ";
// Calculs globaux
// Calculs globaux
@ -2773,4 +2897,4 @@ public function print31(int $id)
echo '< / body > < / html > ';
echo '< / body > < / html > ';
}
}
}
}