diff --git a/app/Controllers/AvanceController.php b/app/Controllers/AvanceController.php index fe00e709..f09b1181 100644 --- a/app/Controllers/AvanceController.php +++ b/app/Controllers/AvanceController.php @@ -31,7 +31,7 @@ class AvanceController extends AdminController private function isAdmin($user) { - return in_array($user['group_name'], ['Conseil', 'Direction']); + return in_array($user['group_name'], ['SuperAdmin','DAF','Direction']); } private function isCommerciale($user) @@ -50,7 +50,7 @@ private function buildActionButtons($value, $isAdmin, $isOwner, $isCaissier = fa { $session = session(); $users = $session->get('user'); - $isDirection = in_array($users['group_name'], ['Direction', 'Conseil']); + $isDirection = in_array($users['group_name'], ['Direction', 'SuperAdmin','DAF']); $buttons = ''; @@ -468,15 +468,49 @@ public function fetchExpiredAvance() $Products->update($data['product_id'], ['product_sold' => 1]); } - // ✅ NOUVELLE FONCTIONNALITÉ : Envoyer notification au Conseil - $Notification->createNotification( - 'Une nouvelle avance a été créée', - "DAF", - (int)$users['store_id'], - 'avances' - ); + // ✅ MODIFICATION PRINCIPALE : Envoyer notifications à TOUS les stores + $db = \Config\Database::connect(); + + // Récupérer tous les stores + $storesQuery = $db->table('stores')->select('id')->get(); + $allStores = $storesQuery->getResultArray(); + + $customerName = $this->request->getPost('customer_name_avance'); + $avanceAmount = number_format((float)$this->request->getPost('avance_amount'), 0, ',', ' '); + $typeAvanceLabel = $type_avance === 'terre' ? 'SUR TERRE' : 'SUR MER'; + + $notificationMessage = "Nouvelle avance {$typeAvanceLabel} créée par {$users['firstname']} {$users['lastname']} - Client: {$customerName} - Montant: {$avanceAmount} Ar"; + + // ✅ Envoyer notification à DAF, Direction et SuperAdmin de TOUS les stores + foreach ($allStores as $store) { + $storeId = (int)$store['id']; + + // Notification pour DAF + $Notification->createNotification( + $notificationMessage, + "DAF", + $storeId, + 'avances' + ); + + // Notification pour Direction + $Notification->createNotification( + $notificationMessage, + "Direction", + $storeId, + 'avances' + ); + + // Notification pour SuperAdmin + $Notification->createNotification( + $notificationMessage, + "SuperAdmin", + $storeId, + 'avances' + ); + } - // ✅ NOUVELLE FONCTIONNALITÉ : Envoyer notification à la Caissière si l'utilisateur est COMMERCIALE + // ✅ Notification à la Caissière UNIQUEMENT du store concerné (si l'utilisateur est COMMERCIALE) if ($this->isCommerciale($users)) { $Notification->createNotification( 'Une nouvelle avance a été créée par un commercial', @@ -486,6 +520,8 @@ public function fetchExpiredAvance() ); } + log_message('info', "✅ Avance {$avance_id} créée - Notifications envoyées à DAF/Direction/SuperAdmin de tous les stores"); + return $this->response->setJSON([ 'success' => true, 'messages' => 'Avance créée avec succès !', @@ -505,7 +541,6 @@ public function fetchExpiredAvance() ]); } } - public function updateAvance() { @@ -1139,7 +1174,7 @@ public function getInvoicePreview($avance_id) $users = $session->get('user'); $isCaissier = $this->isCaissier($users); - $isDirection = in_array($users['group_name'], ['Direction', 'Conseil']); + $isDirection = in_array($users['group_name'], ['Direction', 'SuperAdmin','DAF']); if (!$isCaissier && !$isDirection) { return $this->response->setJSON([ @@ -1500,6 +1535,13 @@ public function notifyPrintInvoice() (int)$users['store_id'], 'avances' ); + + $Notification->createNotification( + "Il y a une avance N°{$avanceNumber} pour le client {$customerName}", + "SuperAdmin", + (int)$users['store_id'], + 'avances' + ); return $this->response->setJSON([ 'success' => true, diff --git a/app/Controllers/Dashboard.php b/app/Controllers/Dashboard.php index f499c8dd..42d37f73 100644 --- a/app/Controllers/Dashboard.php +++ b/app/Controllers/Dashboard.php @@ -136,7 +136,7 @@ class Dashboard extends AdminController $data['total_products'] = $productModel->countProductsByUserStore(); // === ✅ Récupérer le nom du store pour l'affichage === - $isAdmin = in_array($user_id['group_name'], ['DAF', 'Direction']); + $isAdmin = in_array($user_id['group_name'], ['DAF', 'Direction','SuperAdmin']); if (!$isAdmin && !empty($user_id['store_id']) && $user_id['store_id'] != 0) { $store = $storeModel->getStoresData($user_id['store_id']); @@ -219,7 +219,7 @@ class Dashboard extends AdminController $data['isMecanicien'] = false; $data['isSecurite'] = false; - if ($user_id['group_name'] == "Direction" || $user_id['group_name'] == "DAF") { + if ($user_id['group_name'] == "Direction" || $user_id['group_name'] == "DAF" || $user_id['group_name'] == "SuperAdmin") { $data['is_admin'] = true; } diff --git a/app/Controllers/MecanicienController.php b/app/Controllers/MecanicienController.php index 49d3c154..bf3aeecd 100644 --- a/app/Controllers/MecanicienController.php +++ b/app/Controllers/MecanicienController.php @@ -319,7 +319,7 @@ class MecanicienController extends AdminController // Iterate through the data - if($users['group_name'] == "Conseil" || $users['group_name'] == "Direction"){ + if($users['group_name'] == "SuperAdmin" || $users['group_name'] == "Direction"){ foreach ($reparation as $key => $repa) { $image = '' . $repa['name'] . ''; $produit = esc($repa['name']); diff --git a/app/Controllers/OrderController.php b/app/Controllers/OrderController.php index 07218c0b..8015e0d1 100644 --- a/app/Controllers/OrderController.php +++ b/app/Controllers/OrderController.php @@ -107,11 +107,11 @@ class OrderController extends AdminController // Statut de paiement if ($value['paid_status'] == 1) { - $paid_status = 'Validé'; + $paid_status = 'payé'; } elseif ($value['paid_status'] == 2) { $paid_status = 'En Attente'; } elseif ($value['paid_status'] == 3) { - $paid_status = 'Validé et Livré'; + $paid_status = 'payé et Livré'; } else { $paid_status = 'Refusé'; } @@ -149,7 +149,7 @@ class OrderController extends AdminController // ======================================== // 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) { $date_time = date('d-m-Y h:i a', strtotime($value['date_time'])); @@ -172,11 +172,11 @@ class OrderController extends AdminController // Statut de paiement if ($value['paid_status'] == 1) { - $paid_status = 'Validé'; + $paid_status = 'payé'; } elseif ($value['paid_status'] == 2) { $paid_status = 'En Attente'; } elseif ($value['paid_status'] == 3) { - $paid_status = 'Validé et Livré'; + $paid_status = 'Payé et Livré'; } else { $paid_status = 'Refusé'; } @@ -255,11 +255,11 @@ class OrderController extends AdminController // Statut de paiement if ($value['paid_status'] == 1) { - $paid_status = 'Validé'; + $paid_status = 'Payé'; } elseif ($value['paid_status'] == 2) { $paid_status = 'En Attente'; } elseif ($value['paid_status'] == 3) { - $paid_status = 'Validé et Livré'; + $paid_status = 'Payé et Livré'; } else { $paid_status = 'Refusé'; } @@ -331,211 +331,281 @@ class OrderController extends AdminController - public function create() - { - $this->verifyRole('createOrder'); - $data['page_title'] = $this->pageTitle; - - $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.']); +/** + * ✅ AMÉLIORATION : Notifications centralisées pour Direction/DAF/SuperAdmin (tous stores) + */ + +public function create() +{ + $this->verifyRole('createOrder'); + $data['page_title'] = $this->pageTitle; + + $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 - $validation->setRules([ - 'product[]' => 'required', - 'customer_type' => 'required', - 'source' => 'required' - ]); - - // ✅ AJOUT DES DONNÉES DE VALIDATION - $validationData = [ - 'product[]' => $this->request->getPost('product[]'), - 'customer_type' => $this->request->getPost('customer_type'), - 'source' => $this->request->getPost('source') + + $montant_a_payer = ($discount > 0) ? $discount : $gross_amount; + + $tranche_1 = (float)$this->request->getPost('tranche_1') ?? 0; + $tranche_2 = (float)$this->request->getPost('tranche_2') ?? 0; + + if ($tranche_1 > 0 && $tranche_2 > 0) { + $net_amount = $tranche_1 + $tranche_2; + } else { + $net_amount = $montant_a_payer; + } + + $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(); - $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']); - - // 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 + + $order_id = $Orders->create($data, $posts); + + if ($order_id) { + session()->setFlashdata('success', 'Créé avec succès'); + + $Notification = new NotificationController(); + $Stores = new Stores(); + 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é." - ]); - } - } + // ✅ DEMANDE DE REMISE : NOTIFIER TOUS LES STORES + $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); } - } - - // Calculer le montant à payer et net_amount - $montant_a_payer = ($discount > 0) ? $discount : $gross_amount; - - $tranche_1 = (float)$this->request->getPost('tranche_1') ?? 0; - $tranche_2 = (float)$this->request->getPost('tranche_2') ?? 0; - - 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_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") { - $this->checkProductisNull($posts, $users['store_id']); + + $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); + + // ✅ RÉCUPÉRER TOUS LES STORES + $allStores = $Stores->getActiveStore(); + + $montantFormatted = number_format($discount, 0, ',', ' '); + $message = "💰 Nouvelle demande de remise : {$montantFormatted} Ar
" . + "Commande : {$bill_no}
" . + "Store : " . $this->returnStore($users['store_id']) . "
" . + "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 . "
Pour information", + "Direction", + (int)$store['id'], + 'remise/' + ); + + // DAF (consultation) + $Notification->createNotification( + $message . "
Pour information", + "DAF", + (int)$store['id'], + 'remise/' + ); + } } - return redirect()->to('orders/'); } else { - session()->setFlashdata('errors', 'Error occurred!!'); - return redirect()->to('orders/create/'); + // ✅ COMMANDE SANS REMISE : NOTIFIER CAISSIÈRE DU STORE + TOUS LES CENTRAUX + + // Caissière du store concerné + $Notification->createNotification( + "📦 Nouvelle commande à valider : {$bill_no}
" . + "Client : {$data['customer_name']}
" . + "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}
" . + "Store : " . $this->returnStore($users['store_id']) . "
" . + "Client : {$data['customer_name']}
" . + "Montant : " . number_format($gross_amount, 0, ',', ' ') . " Ar
" . + "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 { - // 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); + session()->setFlashdata('errors', 'Error occurred!!'); + return redirect()->to('orders/create/'); } + + } 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 * Accessible uniquement par le rôle SECURITE @@ -583,15 +653,42 @@ public function markAsDelivered() $updated = $Orders->update((int)$order_id, ['paid_status' => 3]); if ($updated) { - // Créer une notification + // ✅ Créer une notification centralisée pour tous les stores try { $Notification = new NotificationController(); - $Notification->createNotification( - "Commande " . $current_order['bill_no'] . " livrée avec succès", - "Direction", - (int)$current_order['store_id'], - "orders" - ); + $Stores = new Stores(); + $allStores = $Stores->getActiveStore(); + + $messageGlobal = "📦 Commande livrée : {$current_order['bill_no']}
" . + "Store : " . $this->returnStore($current_order['store_id']) . "
" . + "Client : {$current_order['customer_name']}
" . + "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) { // Si la notification échoue, on continue quand même log_message('error', 'Erreur notification: ' . $e->getMessage()); @@ -611,7 +708,6 @@ public function markAsDelivered() return $this->response->setJSON($response); } - public function getProductValueById() { $product_id = $this->request->getPost('product_id'); @@ -793,10 +889,12 @@ public function update(int $id) $Notification = new NotificationController(); + // ✅ NOTIFICATION CENTRALISÉE POUR VALIDATION if ($old_paid_status == 2 && $paid_status == 1) { $customer_name = $this->request->getPost('customer_name'); $bill_no = $current_order['bill_no']; + // ✅ Notification SECURITE du store concerné $Notification->createNotification( "Commande validée: {$bill_no} - Client: {$customer_name}", "SECURITE", @@ -804,13 +902,39 @@ public function update(int $id) 'orders' ); - if ($role === 'Caissière') { - $Notification->createNotification( - "Commande validée par la caisse: {$bill_no}", - "Direction", - (int)$user['store_id'], - 'orders' - ); + // ✅ RÉCUPÉRER TOUS LES STORES + $Stores = new Stores(); + $allStores = $Stores->getActiveStore(); + + $messageGlobal = "✅ Commande validée : {$bill_no}
" . + "Store : " . $this->returnStore($user['store_id']) . "
" . + "Client : {$customer_name}
" . + "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 = ''; // Vérifier si l'utilisateur a payé if ($order_data['paid_status'] == 1) { - $paid_status = "Validé"; + $paid_status = "Payé"; } elseif ($order_data['paid_status'] == 2) { $paid_status = "En Attente"; } else { @@ -1460,7 +1584,7 @@ public function update(int $id) $company_info = $Company->getCompanyData(1); $paid_status = $order_data['paid_status'] == 1 - ? "Validé" + ? "Payé" : "Refusé"; // STYLE COMMUN @@ -2484,7 +2608,7 @@ public function print31(int $id) } $paid_status = $order_data['paid_status'] === 1 - ? "Validé" + ? "Payé" : "Refusé"; // Calculs globaux @@ -2773,4 +2897,4 @@ public function print31(int $id) echo ''; } -} +} \ No newline at end of file diff --git a/app/Controllers/RecouvrementController.php b/app/Controllers/RecouvrementController.php index 30467509..85dccd97 100644 --- a/app/Controllers/RecouvrementController.php +++ b/app/Controllers/RecouvrementController.php @@ -7,6 +7,7 @@ use App\Models\Orders; use App\Models\Recouvrement; use App\Models\SortieCaisse; use App\Models\Avance; +use App\Models\Stores; class RecouvrementController extends AdminController { @@ -197,14 +198,61 @@ class RecouvrementController extends AdminController $this->verifyRole('deleteRecouvrement'); $recouvrement_id = $this->request->getPost('recouvrement_id'); - $response = []; if ($recouvrement_id) { $Recouvrement = new Recouvrement(); + + // ✅ Récupérer les infos du recouvrement avant suppression + $recouvrementData = $Recouvrement->getRecouvrementSingle($recouvrement_id); + if ($Recouvrement->deleteRecouvrement($recouvrement_id)) { + // ✅ Notification pour TOUS les Direction, DAF et SuperAdmin de TOUS les stores + try { + if (class_exists('App\Controllers\NotificationController') && $recouvrementData) { + $Notification = new NotificationController(); + $Stores = new Stores(); + $allStores = $Stores->getActiveStore(); + + $session = session(); + $users = $session->get('user'); + + $message = "🗑️ Recouvrement supprimé
" . + "Montant: " . number_format($recouvrementData['recouvrement_montant'], 0, ',', ' ') . " Ar
" . + "Par: " . $users['firstname'] . ' ' . $users['lastname']; + + // ✅ Notifier Direction, DAF et SuperAdmin de TOUS les stores + if (is_array($allStores) && count($allStores) > 0) { + foreach ($allStores as $store) { + $Notification->createNotification( + $message, + "Direction", + (int)$store['id'], + 'recouvrement' + ); + + $Notification->createNotification( + $message, + "DAF", + (int)$store['id'], + 'recouvrement' + ); + + $Notification->createNotification( + $message, + "SuperAdmin", + (int)$store['id'], + 'recouvrement' + ); + } + } + } + } catch (\Exception $e) { + log_message('error', 'Erreur notification removeRecouvrement: ' . $e->getMessage()); + } + $response['success'] = true; - $response['messages'] = "Recouvrement supprimé avec succès !"; + $response['messages'] = "Recouvrement supprimé avec succès !
Notification envoyée à tous les Direction, DAF et SuperAdmin"; } else { $response['success'] = false; $response['messages'] = "Erreur lors de la suppression du recouvrement."; @@ -216,6 +264,7 @@ class RecouvrementController extends AdminController return $this->response->setJSON($response); } + public function createRecouvrement() { $this->verifyRole('createRecouvrement'); @@ -272,9 +321,57 @@ class RecouvrementController extends AdminController ]; if ($Recouvrement->addRecouvrement($data)) { - $Notification->createNotification("Un nouveau recouvrement a été crée", "Direction", (int)$users["store_id"], 'recouvrement'); + // ✅ Notification pour TOUS les Direction, DAF et SuperAdmin de TOUS les stores + try { + if (class_exists('App\Controllers\NotificationController')) { + $Stores = new Stores(); + $allStores = $Stores->getActiveStore(); + + $message = "💱 Nouveau recouvrement créé
" . + "Montant: " . number_format($amount, 0, ',', ' ') . " Ar
" . + "De: " . $send_mode . " → Vers: " . $get_mode . "
" . + "Store: " . $this->returnStoreName($users['store_id']) . "
" . + "Par: " . $fullname; + + // ✅ Notifier Direction, DAF et SuperAdmin de TOUS les stores + if (is_array($allStores) && count($allStores) > 0) { + foreach ($allStores as $store) { + // Notifier Direction + $Notification->createNotification( + $message, + "Direction", + (int)$store['id'], + 'recouvrement' + ); + + // Notifier DAF + $Notification->createNotification( + $message, + "DAF", + (int)$store['id'], + 'recouvrement' + ); + + // Notifier SuperAdmin + $Notification->createNotification( + $message, + "SuperAdmin", + (int)$store['id'], + 'recouvrement' + ); + } + } + } + } catch (\Exception $e) { + log_message('error', 'Erreur notification createRecouvrement: ' . $e->getMessage()); + // Continue même si la notification échoue + } + $response['success'] = true; - $response['messages'] = 'Recouvrement créé avec succès'; + $response['messages'] = 'Recouvrement créé avec succès
' . + 'Montant: ' . number_format($amount, 0, ',', ' ') . ' Ar
' . + $send_mode . ' → ' . $get_mode . '
' . + 'Notification envoyée à tous les Direction, DAF et SuperAdmin'; } else { $response['success'] = false; $response['messages'] = 'Erreur lors de la création du recouvrement.'; @@ -288,7 +385,6 @@ class RecouvrementController extends AdminController return $this->response->setJSON($response); } - public function updateRecouvrement($recouvrement_id) { $this->verifyRole('updateRecouvrement'); @@ -308,18 +404,61 @@ class RecouvrementController extends AdminController ]; $Recouvrement = new Recouvrement(); - // $recouvrement_id = (int) $this->request->getPost('recouvrement_id'); + if ($this->request->getMethod() === 'post') { $data = [ 'recouvrement_montant' => (int) $this->request->getPost('recouvrement_montant_edit'), 'recouvrement_date' => $this->request->getPost('recouvrement_date_edit') - ]; + if ($Recouvrement->updateRecouvrement($recouvrement_id, $data)) { - // $Notification->createNotification("Un nouveau recouvrement crée", "Conseil", $users['store_id'], 'recouvrement'); + // ✅ Notification pour TOUS les Direction, DAF et SuperAdmin de TOUS les stores + try { + if (class_exists('App\Controllers\NotificationController')) { + $Notification = new NotificationController(); + $Stores = new Stores(); + $allStores = $Stores->getActiveStore(); + + $session = session(); + $users = $session->get('user'); + + $message = "✏️ Recouvrement modifié
" . + "Nouveau montant: " . number_format($data['recouvrement_montant'], 0, ',', ' ') . " Ar
" . + "Par: " . $users['firstname'] . ' ' . $users['lastname']; + + // ✅ Notifier Direction, DAF et SuperAdmin de TOUS les stores + if (is_array($allStores) && count($allStores) > 0) { + foreach ($allStores as $store) { + $Notification->createNotification( + $message, + "Direction", + (int)$store['id'], + 'recouvrement' + ); + + $Notification->createNotification( + $message, + "DAF", + (int)$store['id'], + 'recouvrement' + ); + + $Notification->createNotification( + $message, + "SuperAdmin", + (int)$store['id'], + 'recouvrement' + ); + } + } + } + } catch (\Exception $e) { + log_message('error', 'Erreur notification updateRecouvrement: ' . $e->getMessage()); + } + return $this->response->setJSON([ 'success' => true, - 'messages' => 'Recouvrement modifié avec succès !' + 'messages' => 'Recouvrement modifié avec succès !
Notification envoyée à tous les Direction, DAF et SuperAdmin' ]); } else { return $this->response->setJSON([ @@ -340,6 +479,20 @@ class RecouvrementController extends AdminController echo json_encode($data); } } + + private function returnStoreName(int $id): string + { + $Stores = new Stores(); + $stor = $Stores->getActiveStore(); + $Storename = ""; + foreach ($stor as $key => $value) { + if ($value['id'] == $id) { + $Storename = $value['name']; + } + } + return $Storename; + } + private function canMakeRecouvrement($send_mode, $get_mode, $amount): bool { $orders = new Orders(); diff --git a/app/Controllers/RemiseController.php b/app/Controllers/RemiseController.php index 2c799caf..1de8c00c 100644 --- a/app/Controllers/RemiseController.php +++ b/app/Controllers/RemiseController.php @@ -6,6 +6,7 @@ use App\Controllers\AdminController; use App\Models\Notification; use App\Models\Orders; use App\Models\Remise; +use App\Models\Stores; class RemiseController extends AdminController { @@ -25,7 +26,6 @@ class RemiseController extends AdminController $this->render_template('demande/index', $data); } - public function fetchTotal(){ $data = [ 'user_permission' => $this->permission, @@ -34,7 +34,6 @@ class RemiseController extends AdminController return json_encode($data); } - public function fetchRemiseData() { helper(['url', 'form']); @@ -50,21 +49,31 @@ class RemiseController extends AdminController "recordsFiltered" => $totalRecords, "data" => [] ]; + + // ✅ RÉCUPÉRER LE RÔLE DE L'UTILISATEUR + $session = session(); + $user = $session->get('user'); + $role = $user['group_name'] ?? ''; + foreach ($data as $key => $value) { $buttons = ''; - if (in_array('validateRemise', $this->permission) && $value['demande_status'] == 'En attente') { + // ✅ SEUL LE SUPERADMIN PEUT VALIDER/REFUSER + if ($role === 'SuperAdmin' && $value['demande_status'] == 'En attente') { $buttons .= ''; - } - - if (in_array('refusedRemise', $this->permission) && $value['demande_status'] == 'En attente') { + $buttons .= ' '; } + // ✅ DIRECTION ET DAF VOIENT SEULEMENT (pas de boutons d'action) + if (in_array($role, ['Direction', 'DAF'])) { + $buttons = 'Consultation uniquement'; + } + $result['data'][$key] = [ $value['id_demande'], $value['product'], @@ -78,9 +87,23 @@ class RemiseController extends AdminController return $this->response->setJSON($result); } - + /** + * ✅ AMÉLIORATION : Notifications centralisées lors de la validation/refus des remises + */ public function updateRemise($id_demande) { + // ✅ VÉRIFIER QUE SEUL LE SUPERADMIN PEUT VALIDER + $session = session(); + $user = $session->get('user'); + $role = $user['group_name'] ?? ''; + + if ($role !== 'SuperAdmin') { + return $this->response->setJSON([ + 'success' => false, + 'messages' => 'Seul le SuperAdmin peut valider ou refuser les demandes de remise.' + ]); + } + $this->verifyRole('validateRemise'); $validation = \Config\Services::validation(); @@ -108,44 +131,104 @@ class RemiseController extends AdminController if ($Remise->updateRemise($id_demande, $data)) { $remise_product = $Remise->getProductByDemandeId($id_demande); $Notification = new NotificationController(); - $session = session(); - $users = $session->get('user'); $ordersModel = new Orders(); $order_id = $Remise->getOrderIdByDemandeId($id_demande); - // Logique de notification selon le statut + // ✅ Récupérer les infos de la commande + $order_info = $ordersModel->getOrdersData($order_id); + $bill_no = $order_info['bill_no'] ?? ''; + $store_id = $order_info['store_id'] ?? 0; + + // ✅ RÉCUPÉRER TOUS LES STORES + $Stores = new Stores(); + $allStores = $Stores->getActiveStore(); + + // ✅ SI REFUSÉ PAR LE SUPERADMIN if ($demande_status == 'Refusé') { - // Mettre à jour le paid_status de la commande à 0 (Refusé) if ($order_id) { $ordersModel->update($order_id, ['paid_status' => 0]); } - // Si refusé par le Conseil : notification retourne au Commercial + // Message de refus + $messageRefus = "❌ Demande de remise refusée : {$bill_no}
" . + "Produit : {$remise_product}
" . + "Décision : SuperAdmin"; + + // Notifier le commercial du store concerné $Notification->createNotification( - "Votre demande de remise a été refusée pour le produit: " . $remise_product . ". Veuillez modifier la commande.", + $messageRefus . "
Veuillez modifier la commande.", "COMMERCIALE", - (int)$users['store_id'], - "orders" // Retour à l'ajout de commande chez le commercial + (int)$store_id, + "orders" ); - $message = 'La demande de remise a été refusée. Une notification a été envoyée au commercial.'; + // ✅ NOTIFIER DIRECTION ET DAF DE TOUS LES STORES (POUR INFORMATION) + if (is_array($allStores) && count($allStores) > 0) { + foreach ($allStores as $store) { + $Notification->createNotification( + $messageRefus . "
Pour information", + "Direction", + (int)$store['id'], + 'remise/' + ); + + $Notification->createNotification( + $messageRefus . "
Pour information", + "DAF", + (int)$store['id'], + 'remise/' + ); + } + } + + $message = 'La demande de remise a été refusée. Le commercial et les responsables ont été notifiés.'; } elseif ($demande_status == 'Accepté' || $demande_status == 'Validé') { - // Si accepté par le Conseil : la commande reste "En Attente" (paid_status = 2) - // La caissière devra la valider manuellement + // ✅ SI ACCEPTÉ PAR LE SUPERADMIN if ($order_id) { - $ordersModel->update($order_id, ['paid_status' => 2]); // 2 = En Attente + $ordersModel->update($order_id, ['paid_status' => 2]); } - // Notification à la Caissière pour qu'elle valide la commande + $messageAcceptation = "✅ Demande de remise acceptée : {$bill_no}
" . + "Produit : {$remise_product}
" . + "Décision : SuperAdmin"; + + // Notifier la Caissière du store concerné $Notification->createNotification( - "Une commande avec remise acceptée est prête pour validation. Produit: " . $remise_product, + $messageAcceptation . "
Commande prête à être traitée", "Caissière", - (int)$users['store_id'], - "orders" // Va chez la caissière pour validation finale + (int)$store_id, + "orders" ); - $message = 'La demande de remise a été acceptée. La commande a été envoyée à la caissière pour validation.'; + // Notifier le commercial du store concerné + $Notification->createNotification( + $messageAcceptation, + "COMMERCIALE", + (int)$store_id, + "orders" + ); + + // ✅ NOTIFIER DIRECTION ET DAF DE TOUS LES STORES (POUR INFORMATION) + if (is_array($allStores) && count($allStores) > 0) { + foreach ($allStores as $store) { + $Notification->createNotification( + $messageAcceptation . "
Pour information", + "Direction", + (int)$store['id'], + 'remise/' + ); + + $Notification->createNotification( + $messageAcceptation . "
Pour information", + "DAF", + (int)$store['id'], + 'remise/' + ); + } + } + + $message = 'La demande de remise a été acceptée. La caissière, le commercial et les responsables ont été notifiés.'; } return $this->response->setJSON([ diff --git a/app/Controllers/ReportController.php b/app/Controllers/ReportController.php index f8540bae..9f890473 100644 --- a/app/Controllers/ReportController.php +++ b/app/Controllers/ReportController.php @@ -262,7 +262,7 @@ class ReportController extends AdminController $users = $session->get('user'); // Pour Direction et Conseil : afficher TOUTES les performances - if ($users['group_name'] === "DAF" || $users['group_name'] === "Direction") { + if ($users['group_name'] === "DAF" || $users['group_name'] === "Direction" ||$users['group_name'] === "SuperAdmin" ) { $orderPaid = $Orders->getPerformanceByOrders(); foreach ($orderPaid as $key => $value) { // Déterminer le prix de vente réel diff --git a/app/Controllers/SortieCaisseController.php b/app/Controllers/SortieCaisseController.php index 218979bf..99a91c63 100644 --- a/app/Controllers/SortieCaisseController.php +++ b/app/Controllers/SortieCaisseController.php @@ -22,6 +22,87 @@ class SortieCaisseController extends AdminController } private $mapping = [ + // superadmin + "Achat de matériel informatique" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Achat équipement de sécurité" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Achat mobilier de bureau" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Paiement salaire des collaborateurs" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Cotisation sociales" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Remboursement d'avance moto" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Payement prime ou endemnité" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Paiement sous-traitant" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Frais de formation" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Paiement loyer" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Frais de formation externe" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Abonnement internet" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Entretien locaux" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Paiement fournisseur" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Remboursement de frais" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Paiement assurance" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Réparation immobilisation" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "DVD" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Déclaration fiscale - Déclaration d'impôts" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], + "Enregistrement des contrats de bail au centre fiscal" => [ + 'source_fond' => 'Budget Directionnel', + 'initiateur_demande' => 'SuperAdmin' + ], // ----- Raisons Admin ----- "Achat de matériel informatique" => [ 'source_fond' => 'Budget Directionnel', @@ -243,7 +324,7 @@ class SortieCaisseController extends AdminController $users = $session->get('user'); // ✅ Vérifier si l'utilisateur est DAF ou Direction UNIQUEMENT - $canManage = in_array($users['group_name'], ['Direction', 'DAF']); + $canManage = in_array($users['group_name'], ['Direction', 'DAF','SuperAdmin']); $isCaissiere = $users['group_name'] === 'Caissière'; $result = [ @@ -289,7 +370,7 @@ class SortieCaisseController extends AdminController $buttons // Les caissières ne verront PAS les boutons (car $canManage = false) ]; } - elseif ($users["group_name"] === "Direction" || $users["group_name"] === "DAF") { + elseif ($users["group_name"] === "Direction" || $users["group_name"] === "DAF" ||$users["group_name"] === "SuperAdmin" ) { $result['data'][$key] = [ $value['id_sortie'], number_format($value['montant_retire'], 0, '.', ' '), @@ -328,50 +409,55 @@ class SortieCaisseController extends AdminController * ✅ NOUVELLE MÉTHODE : Marquer un décaissement comme payé * Accessible uniquement par les caissières */ - public function markAsPaid($id_sortie) - { - // Vérifier que l'utilisateur est une caissière - $session = session(); - $users = $session->get('user'); +/** + * ✅ CORRECTION COMPLÈTE : Marquer un décaissement comme payé + * Accessible uniquement par les caissières + */ +public function markAsPaid($id_sortie) +{ + // Vérifier que l'utilisateur est une caissière + $session = session(); + $users = $session->get('user'); + + if ($users['group_name'] !== 'Caissière') { + return $this->response->setJSON([ + 'success' => false, + 'messages' => 'Accès refusé. Seules les caissières peuvent marquer un décaissement comme payé.' + ]); + } + + try { + $SortieCaisse = new SortieCaisse(); + + // Récupérer le décaissement + $decaissement = $SortieCaisse->getSortieCaisseSingle($id_sortie); - if ($users['group_name'] !== 'Caissière') { + if (!$decaissement) { return $this->response->setJSON([ 'success' => false, - 'messages' => 'Accès refusé. Seules les caissières peuvent marquer un décaissement comme payé.' + 'messages' => 'Décaissement introuvable.' ]); } - - try { - $SortieCaisse = new SortieCaisse(); - - // Récupérer le décaissement - $decaissement = $SortieCaisse->getSortieCaisseSingle($id_sortie); - - if (!$decaissement) { - return $this->response->setJSON([ - 'success' => false, - 'messages' => 'Décaissement introuvable.' - ]); - } - - // Vérifier que le statut est "Valider" - if ($decaissement['statut'] !== 'Valider') { - return $this->response->setJSON([ - 'success' => false, - 'messages' => 'Ce décaissement ne peut pas être marqué comme payé.
Statut actuel : ' . $decaissement['statut'] - ]); - } - - // Mettre à jour le statut - $data = [ - 'statut' => 'Payé', - 'date_paiement_effectif' => date('Y-m-d H:i:s') - ]; - - $result = $SortieCaisse->updateSortieCaisse($id_sortie, $data); - - if ($result) { - // Créer une notification pour DAF et Direction DU MÊME STORE + + // Vérifier que le statut est "Valider" + if ($decaissement['statut'] !== 'Valider') { + return $this->response->setJSON([ + 'success' => false, + 'messages' => 'Ce décaissement ne peut pas être marqué comme payé.
Statut actuel : ' . $decaissement['statut'] + ]); + } + + // Mettre à jour le statut + $data = [ + 'statut' => 'Payé', + 'date_paiement_effectif' => date('Y-m-d H:i:s') + ]; + + $result = $SortieCaisse->updateSortieCaisse($id_sortie, $data); + + if ($result) { + // ✅ Créer une notification pour TOUS les DAF, Direction et SuperAdmin + try { if (class_exists('App\Controllers\NotificationController')) { $Notification = new NotificationController(); @@ -379,48 +465,68 @@ class SortieCaisseController extends AdminController $message = "💰 Décaissement payé - " . $montant . " Ar
" . "Motif: " . $decaissement['motif'] . "
" . "Caissière: " . $users['firstname'] . ' ' . $users['lastname'] . "
" . - "Store: " . $this->returnStoreName($users['store_id']); + "Store: " . $this->returnStoreName($decaissement['store_id']); - // ✅ Notifier la Direction DU MÊME STORE - $Notification->createNotification( - $message, - "Direction", - (int)$users['store_id'], // ✅ Store ID de la caissière - 'sortieCaisse' - ); + // ✅ Récupérer TOUS les stores + $Stores = new Stores(); + $allStores = $Stores->getActiveStore(); - // ✅ Notifier le DAF DU MÊME STORE - $Notification->createNotification( - $message, - "DAF", - (int)$users['store_id'], // ✅ Store ID de la caissière - 'sortieCaisse' - ); + // ✅ Notifier Direction, DAF et SuperAdmin de TOUS les stores + if (is_array($allStores) && count($allStores) > 0) { + foreach ($allStores as $store) { + // Notifier Direction + $Notification->createNotification( + $message, + "Direction", + (int)$store['id'], + 'sortieCaisse' + ); + + // Notifier DAF + $Notification->createNotification( + $message, + "DAF", + (int)$store['id'], + 'sortieCaisse' + ); + + // Notifier SuperAdmin + $Notification->createNotification( + $message, + "SuperAdmin", + (int)$store['id'], + 'sortieCaisse' + ); + } + } } - - return $this->response->setJSON([ - 'success' => true, - 'messages' => '✅ Décaissement marqué comme PAYÉ
' . - 'Direction et DAF de ' . $this->returnStoreName($users['store_id']) . ' ont été notifiés.
' . - 'Montant: ' . number_format($decaissement['montant_retire'], 0, ',', ' ') . ' Ar' - ]); - - } else { - return $this->response->setJSON([ - 'success' => false, - 'messages' => 'Erreur lors de la mise à jour du statut.' - ]); + } catch (\Exception $e) { + // Logger l'erreur mais continuer + log_message('error', 'Erreur notification markAsPaid: ' . $e->getMessage()); } - } catch (\Exception $e) { - log_message('error', 'Erreur markAsPaid: ' . $e->getMessage()); + return $this->response->setJSON([ + 'success' => true, + 'messages' => '✅ Décaissement marqué comme PAYÉ
' . + 'Tous les Direction, DAF et SuperAdmin ont été notifiés.
' . + 'Montant: ' . number_format($decaissement['montant_retire'], 0, ',', ' ') . ' Ar' + ]); + + } else { return $this->response->setJSON([ 'success' => false, - 'messages' => 'Erreur serveur: ' . $e->getMessage() + 'messages' => 'Erreur lors de la mise à jour du statut.' ]); } + + } catch (\Exception $e) { + log_message('error', 'Erreur markAsPaid: ' . $e->getMessage() . ' | Ligne: ' . $e->getLine()); + return $this->response->setJSON([ + 'success' => false, + 'messages' => 'Erreur serveur: ' . $e->getMessage() + ]); } - +} public function fetchSortieCaisseData1() { helper(['url', 'form']); @@ -436,7 +542,7 @@ class SortieCaisseController extends AdminController $users = $session->get('user'); // ✅ Vérifier si l'utilisateur est DAF ou Direction UNIQUEMENT - $canManage = in_array($users['group_name'], ['Direction', 'DAF']); + $canManage = in_array($users['group_name'], ['Direction', 'DAF','SuperAdmin']); $isCaissiere = $users['group_name'] === 'Caissière'; $result = [ @@ -481,7 +587,7 @@ class SortieCaisseController extends AdminController $buttons // Les caissières ne verront PAS les boutons ]; } - elseif ($users["group_name"] === "Direction" || $users["group_name"] === "DAF") { + elseif ($users["group_name"] === "Direction" || $users["group_name"] === "DAF" || $users["group_name"] === "SuperAdmin") { $result['data'][$key] = [ $value['id_sortie'], number_format($value['montant_retire'], 0, '.', ' '), @@ -591,10 +697,10 @@ class SortieCaisseController extends AdminController } // Recouvrements - $total_recouvrement_me = 0; // Mvola -> Espèce - $total_recouvrement_be = 0; // Banque -> Espèce - $total_recouvrement_bm = 0; // Banque -> Mvola - $total_recouvrement_mb = 0; // Mvola -> Banque + $total_recouvrement_me = 0; + $total_recouvrement_be = 0; + $total_recouvrement_bm = 0; + $total_recouvrement_mb = 0; if (is_object($totalRecouvrement)) { $total_recouvrement_me = isset($totalRecouvrement->me) ? (float) $totalRecouvrement->me : 0; @@ -621,14 +727,12 @@ class SortieCaisseController extends AdminController } // CALCUL DES SOLDES DISPONIBLES PAR MODE DE PAIEMENT - // Espèce: Orders + Recouvrements entrants - Sorties en espèce $total_espece_disponible = $total_espece1 + $total_espece2 + $total_recouvrement_me + $total_recouvrement_be - $total_sortie_espece; - // MVOLA: Orders - Recouvrements sortants + Recouvrements entrants - Sorties MVOLA $total_mvola_disponible = $total_mvola1 + $total_mvola2 - $total_recouvrement_me - @@ -636,7 +740,6 @@ class SortieCaisseController extends AdminController $total_recouvrement_bm - $total_sortie_mvola; - // Virement: Orders - Recouvrements sortants + Recouvrements entrants - Sorties virement $total_virement_disponible = $total_virement1 + $total_virement2 - $total_recouvrement_be - @@ -742,8 +845,8 @@ class SortieCaisseController extends AdminController $data['date_visa_chef_service'] = $this->request->getPost('date_visa_chef_service') ?? null; $data['visa_direction'] = $this->request->getPost('visa_direction') ?? ''; $data['date_visa_direction'] = $this->request->getPost('date_visa_direction') ?? null; - $data['visa_conseil'] = $this->request->getPost('visa_conseil') ?? ''; - $data['date_visa_conseil'] = $this->request->getPost('date_visa_conseil') ?? null; + $data['visa_superAdmin'] = $this->request->getPost('visa_superAdmin') ?? ''; + $data['date_visa_superAdmin'] = $this->request->getPost('date_visa_superAdmin') ?? null; $data['observations'] = $this->request->getPost('observations') ?? ''; } @@ -767,25 +870,49 @@ class SortieCaisseController extends AdminController $result = $model->addSortieCaisse($data); if ($result) { - // Notification UNIQUEMENT pour la Direction du même store - if (class_exists('App\Controllers\NotificationController')) { - $Notification = new NotificationController(); - - // ✅ Notifier UNIQUEMENT la Direction du store concerné - $Notification->createNotification( - "Nouvelle demande de décaissement de " . number_format($montant_retire, 0, ',', ' ') . " Ar (" . $mode_paiement . ")", - "Direction", - (int)$user['store_id'], // ✅ Store ID du créateur - 'sortieCaisse' - ); - - // ✅ Notifier aussi le DAF du même store (si vous avez des DAF par store) - $Notification->createNotification( - "Nouvelle demande de décaissement de " . number_format($montant_retire, 0, ',', ' ') . " Ar (" . $mode_paiement . ")", - "DAF", - (int)$user['store_id'], // ✅ Store ID du créateur - 'sortieCaisse' - ); + // ✅ Notification pour TOUS les Direction, DAF et SuperAdmin + try { + if (class_exists('App\Controllers\NotificationController')) { + $Notification = new NotificationController(); + + $message = "Nouvelle demande de décaissement de " . + number_format($montant_retire, 0, ',', ' ') . " Ar (" . $mode_paiement . ")
" . + "Store: " . $this->returnStoreName($user['store_id']) . "
" . + "Demandeur: " . $user['firstname'] . ' ' . $user['lastname']; + + // ✅ Récupérer TOUS les stores + $Stores = new Stores(); + $allStores = $Stores->getActiveStore(); + + // ✅ Notifier Direction, DAF et SuperAdmin de TOUS les stores + if (is_array($allStores) && count($allStores) > 0) { + foreach ($allStores as $store) { + $Notification->createNotification( + $message, + "Direction", + (int)$store['id'], + 'sortieCaisse' + ); + + $Notification->createNotification( + $message, + "DAF", + (int)$store['id'], + 'sortieCaisse' + ); + + $Notification->createNotification( + $message, + "SuperAdmin", + (int)$store['id'], + 'sortieCaisse' + ); + } + } + } + } catch (\Exception $e) { + log_message('error', 'Erreur notification createSortieCaisse: ' . $e->getMessage()); + // Continue même si la notification échoue } return $this->response->setJSON([ @@ -793,7 +920,7 @@ class SortieCaisseController extends AdminController 'messages' => 'Décaissement de ' . number_format($montant_retire, 0, ',', ' ') . ' Ar créé avec succès
' . 'Mode de paiement: ' . $mode_paiement . '
' . 'Nouveau solde ' . $mode_paiement_label . ': ' . number_format($fonds_disponible - $montant_retire, 0, ',', ' ') . ' Ar
' . - 'Notification envoyée à la Direction de ' . $this->returnStoreName($user['store_id']) . '' + 'Notification envoyée à tous les Direction, DAF et SuperAdmin' ]); } else { @@ -1096,15 +1223,15 @@ class SortieCaisseController extends AdminController switch ($statut) { case "Valider": - $message = "✅ Votre décaissement a été validé par la Direction de " . $this->returnStoreName($store_id); + $message = "✅ Votre décaissement a été validé par la Direction
Store: " . $this->returnStoreName($store_id); $Notification->createNotification($message, "Caissière", (int)$store_id, 'sortieCaisse'); break; case "Refuser": - $message = "❌ Votre décaissement a été refusé par la Direction de " . $this->returnStoreName($store_id) . "
Raison: " . $this->request->getPost('admin_raison'); + $message = "❌ Votre décaissement a été refusé par la Direction
Store: " . $this->returnStoreName($store_id) . "
Raison: " . $this->request->getPost('admin_raison'); $Notification->createNotification($message, "Caissière", (int)$store_id, 'sortieCaisse'); break; case "En attente": - $message = "⏳ Votre décaissement a été mis en attente par la Direction de " . $this->returnStoreName($store_id); + $message = "⏳ Votre décaissement a été mis en attente par la Direction
Store: " . $this->returnStoreName($store_id); $Notification->createNotification($message, "Caissière", (int)$store_id, 'sortieCaisse'); break; } diff --git a/app/Controllers/StatistiqueController.php b/app/Controllers/StatistiqueController.php index dc9ebc5b..a68035f5 100644 --- a/app/Controllers/StatistiqueController.php +++ b/app/Controllers/StatistiqueController.php @@ -78,7 +78,7 @@ class StatistiqueController extends AdminController // echo ''; $data['is_admin'] = false; - if ($user_id['group_name'] == "Direction" || $user_id['group_name'] == "Conseil") { + if ($user_id['group_name'] == "Direction" || $user_id['group_name'] == "SuperAdmin") { $data['is_admin'] = true; } diff --git a/app/Models/Avance.php b/app/Models/Avance.php index fc848d54..e3ca0b3b 100644 --- a/app/Models/Avance.php +++ b/app/Models/Avance.php @@ -58,7 +58,7 @@ class Avance extends Model { public function getAllAvanceData(int $id=null) { $session = session(); $users = $session->get('user'); - $isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']); + $isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction','DAF']); if($isAdmin) { if($id){ try { @@ -125,7 +125,7 @@ class Avance extends Model { public function getTotalAvance() { $session = session(); $users = $session->get('user'); - $isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']); + $isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction','DAF']); try { $builder = $this->select('SUM(avance_amount) AS ta') @@ -148,7 +148,7 @@ class Avance extends Model { { $session = session(); $users = $session->get('user'); - $isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']); + $isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction','DAF']); try { $builder = $this->db->table('avances') @@ -194,7 +194,7 @@ class Avance extends Model { public function getAllAvanceData1(int $id=null) { $session = session(); $users = $session->get('user'); - $isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']); + $isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction','DAF']); if($isAdmin) { if($id){ try { @@ -249,7 +249,7 @@ class Avance extends Model { public function getAllAvanceData2(int $id=null) { $session = session(); $users = $session->get('user'); - $isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']); + $isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction', 'DAF']); if($isAdmin) { if($id){ try { @@ -336,7 +336,7 @@ class Avance extends Model { { $session = session(); $users = $session->get('user'); - $isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']); + $isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction', 'DAF']); $builder = $this->where('is_order', 0) ->where('active', 1) @@ -357,7 +357,7 @@ class Avance extends Model { { $session = session(); $users = $session->get('user'); - $isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']); + $isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction', 'DAF']); $builder = $this->where('is_order', 0) ->where('active', 1) @@ -451,7 +451,7 @@ public function convertToOrder(int $avance_id) return false; } - // ✅ MODIFICATION PRINCIPALE : Vérifier que c'est bien une avance sur TERRE + // ✅ Vérifier que c'est bien une avance sur TERRE if ($avance['type_avance'] !== 'terre') { log_message('info', "Avance {$avance_id} de type '{$avance['type_avance']}' - Conversion ignorée (seules les avances TERRE sont converties)"); return false; @@ -528,9 +528,6 @@ public function convertToOrder(int $avance_id) ]); log_message('info', "Item ajouté : produit {$avance['product_id']} (TERRE)"); - - // ✅ Le produit reste marqué comme vendu (product_sold = 1) - // Il sera géré dans la commande maintenant } else { log_message('warning', "Produit {$avance['product_id']} introuvable pour avance TERRE {$avance_id}"); } @@ -538,7 +535,7 @@ public function convertToOrder(int $avance_id) // ✅ 3. Marquer l'avance comme convertie $this->update($avance_id, [ 'is_order' => 1, - 'active' => 0, // Désactiver l'avance (elle devient commande) + 'active' => 0, ]); $db->transComplete(); @@ -548,7 +545,10 @@ public function convertToOrder(int $avance_id) return false; } - // ✅ 4. Notification à la caissière + // ✅ 4. NOUVEAU : Envoyer notifications à TOUS les stores + $this->sendConversionNotifications($avance, $order_id, $bill_no); + + // ✅ 5. Notification à la caissière du store concerné $notificationController = new \App\Controllers\NotificationController(); $notificationController->createNotification( "Nouvelle commande issue d'une avance TERRE complète - {$bill_no}", @@ -567,6 +567,70 @@ public function convertToOrder(int $avance_id) } } +private function sendConversionNotifications($avance, $order_id, $bill_no) +{ + try { + $Notification = new \App\Controllers\NotificationController(); + $db = \Config\Database::connect(); + + // Récupérer tous les stores + $storesQuery = $db->table('stores')->select('id')->get(); + $allStores = $storesQuery->getResultArray(); + + // Récupérer les infos de l'utilisateur + $userQuery = $db->table('users') + ->select('firstname, lastname') + ->where('id', $avance['user_id']) + ->get(); + $user = $userQuery->getRowArray(); + + $userName = $user ? "{$user['firstname']} {$user['lastname']}" : 'Utilisateur inconnu'; + + // Préparer le message + $customerName = $avance['customer_name']; + $avanceNumber = str_pad($avance['avance_id'], 5, '0', STR_PAD_LEFT); + $avanceAmount = number_format((float)$avance['gross_amount'], 0, ',', ' '); + $typeAvance = strtoupper($avance['type_avance']); + + $notificationMessage = "🎉 Avance {$typeAvance} N°{$avanceNumber} convertie en COMMANDE {$bill_no} - Client: {$customerName} - Montant: {$avanceAmount} Ar - Par: {$userName}"; + + // ✅ Envoyer notification à DAF, Direction et SuperAdmin de TOUS les stores + foreach ($allStores as $store) { + $storeId = (int)$store['id']; + + // Notification pour DAF + $Notification->createNotification( + $notificationMessage, + "DAF", + $storeId, + 'orders' + ); + + // Notification pour Direction + $Notification->createNotification( + $notificationMessage, + "Direction", + $storeId, + 'orders' + ); + + // Notification pour SuperAdmin + $Notification->createNotification( + $notificationMessage, + "SuperAdmin", + $storeId, + 'orders' + ); + } + + log_message('info', "✅ Notifications conversion envoyées pour avance {$avance['avance_id']} → commande {$order_id} à tous les stores"); + + } catch (\Exception $e) { + log_message('error', "Erreur envoi notifications conversion: " . $e->getMessage()); + } +} + + /** * ✅ Hook appelé automatiquement lors du paiement d'une avance * Intégrer ceci dans votre fonction de paiement existante @@ -630,6 +694,7 @@ public function afterPayment(int $avance_id) ->where('type_avance', 'terre') // ✅ Uniquement TERRE à convertir ->findAll(); } + /** * ✅ NOUVELLE MÉTHODE : Récupérer les avances MER complètes (pour statistiques) @@ -638,7 +703,7 @@ public function afterPayment(int $avance_id) { $session = session(); $users = $session->get('user'); - $isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']); + $isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction', 'DAF']); $builder = $this->where('amount_due', 0) ->where('active', 1) @@ -650,5 +715,7 @@ public function afterPayment(int $avance_id) return $builder->orderBy('avance_date', 'DESC')->findAll(); } + + } \ No newline at end of file diff --git a/app/Models/Mecanicien.php b/app/Models/Mecanicien.php index b33f2bc3..e5889440 100644 --- a/app/Models/Mecanicien.php +++ b/app/Models/Mecanicien.php @@ -24,7 +24,7 @@ class Mecanicien extends Model { $session = session(); $user = $session->get('user'); - if ($user['group_name'] == "Conseil" || $user['group_name'] == "Direction") { + if ($user['group_name'] == "SuperAdmin" || $user['group_name'] == "Direction") { $reparation = $this->select('reparations.reparation_id as reparationsID, reparations.user_id, reparations.reparation_statut, reparations.produit_id, reparations.reparation_observation, reparations.reparation_debut, reparations.reparation_fin, users.*, products.*') ->join('users', 'reparations.user_id = users.id') ->join('products', 'reparations.produit_id = products.id') diff --git a/app/Models/Orders.php b/app/Models/Orders.php index 383ab52b..7944b119 100644 --- a/app/Models/Orders.php +++ b/app/Models/Orders.php @@ -130,7 +130,7 @@ class Orders extends Model $groupName = $group['group_name'] ?? ''; // Selon le rôle - if (in_array($groupName, ['Direction', 'Conseil'], true)) { + if (in_array($groupName, ['Direction', 'SuperAdmin', 'DAF'], true)) { return $builder ->orderBy('orders.id', 'DESC') ->get() @@ -163,7 +163,7 @@ class Orders extends Model $group = $this->getUserGroupNameByUserId($users['id']); $groupName = $group['group_name'] ?? ''; // Évite une erreur si 'group_name' est null - if ($groupName === "Direction" || $groupName === "Conseil") { + if ($groupName === "Direction" || $groupName === "SuperAdmin" || $groupName === "DAF") { return $builder->orderBy('orders.id', 'DESC')->get()->getResultArray(); } else { return $builder->where('orders.store_id', $users['store_id']) @@ -369,7 +369,7 @@ class Orders extends Model { $session = session(); $users = $session->get('user'); - $isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']); + $isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction', 'DAF']); if($isAdmin) { return $this->whereIn('paid_status', [1, 3]) // ← Ajoutez 3 ici @@ -396,7 +396,7 @@ class Orders extends Model { $session = session(); $users = $session->get('user'); - $isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']); + $isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction', 'DAF']); $baseQuery = $this->db->table('orders') ->select(' diff --git a/app/Models/Products.php b/app/Models/Products.php index 0e1f3380..2e247c5b 100644 --- a/app/Models/Products.php +++ b/app/Models/Products.php @@ -21,7 +21,7 @@ class Products extends Model $user = $session->get('user'); // Vérifier si l'utilisateur est admin (Conseil ou Direction) - $isAdmin = in_array($user['group_name'], ['Conseil', 'Direction']); + $isAdmin = in_array($user['group_name'], ['SuperAdmin', 'Direction', 'DAF']); $builder = $this->where('is_piece', 0) ->where('product_sold', 0); @@ -206,7 +206,7 @@ public function countProductsByUserStore() $user = $session->get('user'); // Vérifier si l'utilisateur est admin - $isAdmin = in_array($user['group_name'], ['DAF', 'Direction']); + $isAdmin = in_array($user['group_name'], ['DAF', 'Direction', 'SuperAdmin']); $db = \Config\Database::connect(); diff --git a/app/Models/Recouvrement.php b/app/Models/Recouvrement.php index b4a80d9c..a6a4895d 100644 --- a/app/Models/Recouvrement.php +++ b/app/Models/Recouvrement.php @@ -73,7 +73,7 @@ class Recouvrement extends Model{ public function getTotalRecouvrements(int $id = null, $start_date = null, $end_date = null) { $session = session(); $users = $session->get('user'); - $isAdmin = in_array($users['group_name'], ['DAF', 'Direction']); + $isAdmin = in_array($users['group_name'], ['DAF', 'Direction', 'SuperAdmin']); if($isAdmin){ if ($id) { return $this->db->table('recouvrement') @@ -190,7 +190,7 @@ class Recouvrement extends Model{ { $session = session(); $users = $session->get('user'); - $isAdmin = in_array($users['group_name'], ['DAF', 'Direction']); + $isAdmin = in_array($users['group_name'], ['DAF', 'Direction', 'SuperAdmin']); $builder = $this->db->table('recouvrement'); diff --git a/app/Models/Remise.php b/app/Models/Remise.php index c742e84d..2e8f4e6a 100644 --- a/app/Models/Remise.php +++ b/app/Models/Remise.php @@ -6,10 +6,6 @@ use DateTime; class Remise extends Model { - /** - * table name - * @var string - */ protected $table = 'demande_remise'; protected $primaryKey = 'id_demande'; protected $allowedFields = ['id_order', 'montant_demande', 'date_demande','product','id_store','demande_status','total_price']; @@ -20,26 +16,26 @@ class Remise extends Model $session = session(); $users = $session->get('user'); - // Si le rôle est CONSEIL → voir toutes les demandes "En attente" - if ($users["group_name"] === "Conseil") { + // ✅ SUPERADMIN VOIT TOUTES LES DEMANDES "EN ATTENTE" (POUR VALIDATION) + if ($users["group_name"] === "SuperAdmin") { return $this->where('demande_status', 'En attente') ->orderBy('date_demande', 'DESC') ->findAll(); } - // Si le rôle est DIRECTION → voir toutes les demandes aussi (pas filtrées par magasin) - if ($users["group_name"] === "Direction") { + // ✅ DIRECTION ET DAF VOIENT TOUTES LES DEMANDES (TOUS STATUTS) POUR CONSULTATION + if ($users["group_name"] === "Direction" || $users["group_name"] === "DAF") { return $this->orderBy('date_demande', 'DESC') ->findAll(); } - // Autres rôles (Caissière, etc.) → voir uniquement celles de son magasin + // ✅ AUTRES RÔLES : VOIR UNIQUEMENT CELLES DE LEUR MAGASIN return $this->where('id_store', $users['store_id']) ->orderBy('date_demande', 'DESC') ->findAll(); } catch (\Exception $e) { - log_message('error', 'Erreur lors de la récupération des demandes du jour : ' . $e->getMessage()); + log_message('error', 'Erreur lors de la récupération des demandes : ' . $e->getMessage()); return []; } } @@ -61,11 +57,6 @@ class Remise extends Model ->first(); } - /** - * Récupère l'ID de la commande associée à une demande de remise - * @param int $id_demande - * @return int|null - */ public function getOrderIdByDemandeId(int $id_demande): ?int { $result = $this->select('id_order') @@ -83,10 +74,7 @@ class Remise extends Model } try { - // Mettre à jour uniquement les données de la demande de remise - // On ne touche PAS aux montants de la commande ici $updateResult = $this->update($id, $data); - return $updateResult; } catch (\Exception $e) { @@ -109,13 +97,11 @@ class Remise extends Model $existing = $this->where('id_order', $id)->first(); if ($existing) { - // Mise à jour $this->update($existing['id_demande'], $data); return "Remise mise à jour avec succès."; } else { - // Création $this->insert($data); return "Nouvelle remise créée avec succès."; } } -} +} \ No newline at end of file diff --git a/app/Models/Securite.php b/app/Models/Securite.php index 0126f171..4cacc93b 100644 --- a/app/Models/Securite.php +++ b/app/Models/Securite.php @@ -35,7 +35,7 @@ class Securite extends Model { $session = session(); $users = $session->get('user'); - if ($users["group_name"] == "Direction") { + if ($users["group_name"] == "Direction" || $users["group_name"] == "SuperAdmin" || $users["group_name"] == "DAF") { return $this->where('active', true) ->findAll(); } diff --git a/app/Models/SortieCaisse.php b/app/Models/SortieCaisse.php index 0a6006b3..1d59cda3 100644 --- a/app/Models/SortieCaisse.php +++ b/app/Models/SortieCaisse.php @@ -5,173 +5,133 @@ use CodeIgniter\Model; class SortieCaisse extends Model { - /** - * table name - * @var string - */ protected $table = 'sortie_caisse'; - protected $primaryKey = 'id_sortie'; // Primary key column - // Dans le fichier App/Models/SortieCaisse.php -// Mettre à jour le tableau $allowedFields + protected $primaryKey = 'id_sortie'; -protected $allowedFields = [ - 'montant_retire', - 'date_retrait', - 'motif', - 'commentaire', - 'fournisseur', - 'nif_cin', - 'statistique', - 'telephone', - 'code_postal', - 'preuve_achat', - 'sortie_personnel', - 'source_fond', - 'initiateur_demande', - 'statut', - 'user_id', - 'store_id', - 'mime_type', - 'admin_raison', - // Champs pour le formulaire IM1 - 'nom_demandeur', - 'fonction_demandeur', - 'mode_paiement', - 'montant_lettre', - 'date_demande', - 'reference', - // ✅ NOUVEAU CHAMP - 'date_paiement_effectif', // Date à laquelle la caissière a effectué le paiement - // Champs pour le formulaire IM2/IM3 - 'numero_fiche', - 'date_fiche', - 'service_demandeur', - 'objet_depense', - 'nature_depense', - 'montant_estime', - 'mode_reglement', - 'date_paiement_prevue', - 'justificatifs', - 'visa_demandeur', - 'date_visa_demandeur', - 'visa_chef_service', - 'date_visa_chef_service', - 'visa_direction', - 'date_visa_direction', - 'visa_conseil', - 'date_visa_conseil', - 'observations' -]; -public function getAllSortieCaisse() -{ - try { - $session = session(); - $users = $session->get('user'); - - // ✅ DIRECTION : Voir uniquement les décaissements de SON store - if ($users['group_name'] === 'Direction') { - return $this - ->select('*') - ->where('store_id', $users['store_id']) // ✅ FILTRE PAR STORE - ->orderBy('date_retrait', 'DESC') - ->findAll(); - } - - // ✅ DAF : Voir uniquement les décaissements de SON store - if ($users['group_name'] === 'DAF') { - return $this - ->select('*') - ->where('store_id', $users['store_id']) // ✅ FILTRE PAR STORE - ->orderBy('date_retrait', 'DESC') - ->findAll(); - } - - // ✅ CONSEIL : Voir TOUS les décaissements (multi-stores) - // if ($users['group_name'] === 'Conseil') { - // return $this - // ->select('*') - // ->orderBy('date_retrait', 'DESC') - // ->findAll(); - // } - - // ✅ CAISSIÈRE : Voir uniquement SES décaissements - if($users["group_name"]==="Caissière"){ + protected $allowedFields = [ + 'montant_retire', + 'date_retrait', + 'motif', + 'commentaire', + 'fournisseur', + 'nif_cin', + 'statistique', + 'telephone', + 'code_postal', + 'preuve_achat', + 'sortie_personnel', + 'source_fond', + 'initiateur_demande', + 'statut', + 'user_id', + 'store_id', + 'mime_type', + 'admin_raison', + 'nom_demandeur', + 'fonction_demandeur', + 'mode_paiement', + 'montant_lettre', + 'date_demande', + 'reference', + 'date_paiement_effectif', + 'numero_fiche', + 'date_fiche', + 'service_demandeur', + 'objet_depense', + 'nature_depense', + 'montant_estime', + 'mode_reglement', + 'date_paiement_prevue', + 'justificatifs', + 'visa_demandeur', + 'date_visa_demandeur', + 'visa_chef_service', + 'date_visa_chef_service', + 'visa_direction', + 'date_visa_direction', + 'visa_conseil', + 'date_visa_conseil', + 'observations' + ]; + + /** + * ✅ MODIFICATION : DAF, Direction, SuperAdmin voient TOUS les stores + * Caissière voit uniquement SES décaissements + */ + public function getAllSortieCaisse() + { + try { + $session = session(); + $users = $session->get('user'); + + // ✅ DAF, Direction, SuperAdmin : Voir TOUS les stores + if (in_array($users['group_name'], ['Direction', 'DAF', 'SuperAdmin'])) { + return $this + ->select('*') + ->orderBy('date_retrait', 'DESC') + ->findAll(); + } + + // ✅ CAISSIÈRE : Voir uniquement SES décaissements + if($users["group_name"] === "Caissière"){ + return $this + ->select('*') + ->where('user_id', $users['id']) + ->orderBy('date_retrait', 'DESC') + ->findAll(); + } + + // ✅ AUTRES : Par défaut, voir uniquement leurs décaissements return $this ->select('*') ->where('user_id', $users['id']) ->orderBy('date_retrait', 'DESC') ->findAll(); + } catch (\Exception $e) { + log_message('error', 'Erreur lors de la récupération des sorties caisse : ' . $e->getMessage()); + return []; } - - // ✅ AUTRES : Par défaut, voir uniquement leurs décaissements - return $this - ->select('*') - ->where('user_id', $users['id']) - ->orderBy('date_retrait', 'DESC') - ->findAll(); - } catch (\Exception $e) { - log_message('error', 'Erreur lors de la récupération des sorties caisse : ' . $e->getMessage()); - return []; } -} -public function getAllSortieCaisse1() -{ - try { - $session = session(); - $users = $session->get('user'); - - // ✅ DIRECTION : Voir uniquement les décaissements de SON store - if ($users['group_name'] === 'Direction') { - return $this - ->select('*') - ->join('user_group', 'user_group.user_id = sortie_caisse.user_id') - ->where('user_group.group_id', 7) - ->where('sortie_caisse.store_id', $users['store_id']) // ✅ FILTRE PAR STORE - ->orderBy('date_retrait', 'DESC') - ->findAll(); - } - - // ✅ DAF : Voir uniquement les décaissements de SON store - if ($users['group_name'] === 'DAF') { - return $this - ->select('*') - ->join('user_group', 'user_group.user_id = sortie_caisse.user_id') - ->where('user_group.group_id', 7) - ->where('sortie_caisse.store_id', $users['store_id']) // ✅ FILTRE PAR STORE - ->orderBy('date_retrait', 'DESC') - ->findAll(); - } - - // ✅ CONSEIL : Voir TOUS les stores - // if ($users['group_name'] === 'Conseil') { - // return $this - // ->select('*') - // ->join('user_group', 'user_group.user_id = sortie_caisse.user_id') - // ->where('user_group.group_id', 6) - // ->orderBy('date_retrait', 'DESC') - // ->findAll(); - // } - - // ✅ CAISSIÈRE : Voir uniquement SES décaissements - if($users["group_name"]==="Caissière"){ + /** + * ✅ MODIFICATION : Même logique pour les décaissements filtrés + */ + public function getAllSortieCaisse1() + { + try { + $session = session(); + $users = $session->get('user'); + + // ✅ DAF, Direction, SuperAdmin : Voir TOUS les stores + if (in_array($users['group_name'], ['Direction', 'DAF', 'SuperAdmin'])) { + return $this + ->select('*') + ->join('user_group', 'user_group.user_id = sortie_caisse.user_id') + ->where('user_group.group_id', 7) + ->orderBy('date_retrait', 'DESC') + ->findAll(); + } + + // ✅ CAISSIÈRE : Voir uniquement SES décaissements + if($users["group_name"] === "Caissière"){ + return $this + ->select('*') + ->where('user_id', $users['id']) + ->orderBy('date_retrait', 'DESC') + ->findAll(); + } + return $this ->select('*') ->where('user_id', $users['id']) ->orderBy('date_retrait', 'DESC') ->findAll(); + } catch (\Exception $e) { + log_message('error', 'Erreur lors de la récupération des sorties caisse : ' . $e->getMessage()); + return []; } - - return $this - ->select('*') - ->where('user_id', $users['id']) - ->orderBy('date_retrait', 'DESC') - ->findAll(); - } catch (\Exception $e) { - log_message('error', 'Erreur lors de la récupération des sorties caisse : ' . $e->getMessage()); - return []; } -} + public function addSortieCaisse(array $data) { try { return $this->insert($data); @@ -203,15 +163,15 @@ public function getAllSortieCaisse1() return $reparation; } + /** + * ✅ MODIFICATION : DAF, Direction, SuperAdmin voient TOUS les totaux + */ public function getTotalSortieCaisse() { $session = session(); $users = $session->get('user'); - // ✅ DIRECTION et DAF : Voir uniquement leur store - $isAdmin = in_array($users['group_name'], ['Direction', 'DAF']); - - // ✅ CONSEIL : Voir TOUS les stores - $isConseil = $users['group_name'] === 'Conseil'; + // ✅ DAF, Direction, SuperAdmin : Voir TOUS les stores + $isAdmin = in_array($users['group_name'], ['Direction', 'DAF', 'SuperAdmin']); if ($isAdmin) { try { @@ -221,7 +181,7 @@ public function getAllSortieCaisse1() SUM(CASE WHEN mode_paiement = "Virement Bancaire" THEN montant_retire ELSE 0 END) AS total_virement, SUM(montant_retire) AS mr ') - ->where('store_id', $users['store_id']) // ✅ FILTRE PAR STORE + // ✅ SUPPRESSION DU FILTRE PAR STORE ->whereIn('statut', ['Valider', 'Payé']) ->get() ->getRowObject(); @@ -234,27 +194,6 @@ public function getAllSortieCaisse1() 'mr' => 0 ]; } - } elseif ($isConseil) { - // ✅ CONSEIL voit TOUS les stores - try { - return $this->select(' - SUM(CASE WHEN mode_paiement = "En espèce" THEN montant_retire ELSE 0 END) AS total_espece, - SUM(CASE WHEN mode_paiement = "MVOLA" THEN montant_retire ELSE 0 END) AS total_mvola, - SUM(CASE WHEN mode_paiement = "Virement Bancaire" THEN montant_retire ELSE 0 END) AS total_virement, - SUM(montant_retire) AS mr - ') - ->whereIn('statut', ['Valider', 'Payé']) - ->get() - ->getRowObject(); - } catch (\Exception $e) { - log_message('error', 'Erreur getTotalSortieCaisse (Conseil) : ' . $e->getMessage()); - return (object)[ - 'total_espece' => 0, - 'total_mvola' => 0, - 'total_virement' => 0, - 'mr' => 0 - ]; - } } else { // ✅ CAISSIÈRE : Uniquement son store try { diff --git a/app/Views/avances/avance.php b/app/Views/avances/avance.php index 4120a9f5..f5e412d5 100644 --- a/app/Views/avances/avance.php +++ b/app/Views/avances/avance.php @@ -44,13 +44,13 @@ get('user'); -$isAdmin = isset($users['group_name']) && in_array($users['group_name'], ['Conseil', 'Direction']); +$isAdmin = isset($users['group_name']) && in_array($users['group_name'], ['SuperAdmin', 'Direction', 'DAF']); $isCommerciale = isset($users['group_name']) && in_array($users['group_name'], ['COMMERCIALE']); $isCaissier = isset($users['group_name']) && in_array($users['group_name'], ['Caissière']); ?> - +
get('user'); - if ($users["group_name"] === "Direction") : + if ($users["group_name"] === "Direction" || $users["group_name"] === "SuperAdmin" || $users["group_name"] === "DAF" ) : ?>
diff --git a/app/Views/login.php b/app/Views/login.php index 26c258e2..60ef9f24 100644 --- a/app/Views/login.php +++ b/app/Views/login.php @@ -12,7 +12,7 @@ - + + +
+
+
🏍️
+ +
+
Démarrage en cours...
+
+
+ -
+
@@ -197,5 +300,25 @@ + + - + \ No newline at end of file diff --git a/app/Views/orders/avance.php b/app/Views/orders/avance.php index ae3cf068..9f215b5d 100644 --- a/app/Views/orders/avance.php +++ b/app/Views/orders/avance.php @@ -26,7 +26,7 @@ get('user'); - $isAdmin = in_array($users['group_name'], ['Direction', 'Conseil']); + $isAdmin = in_array($users['group_name'], ['Direction', 'SuperAdmin']); $isCommerciale = in_array($users['group_name'], ['COMMERCIALE']); $isCaissier = in_array($users['group_name'], ['Caissier']); if ($isAdmin): ?> @@ -46,7 +46,7 @@ get('user'); - $isAdmin = in_array($users['group_name'], ['Direction', 'Conseil']); + $isAdmin = in_array($users['group_name'], ['Direction', 'SuperAdmin']); $isCommerciale = in_array($users['group_name'], ['COMMERCIALE']); $isCaissier = in_array($users['group_name'], ['Caissier']); if ($isCommerciale || $isCaissier): ?> diff --git a/app/Views/orders/edit.php b/app/Views/orders/edit.php index b8b28153..c93d2f32 100644 --- a/app/Views/orders/edit.php +++ b/app/Views/orders/edit.php @@ -306,7 +306,7 @@
diff --git a/app/Views/orders/index.php b/app/Views/orders/index.php index 42e8f5ce..7dfb2b4f 100644 --- a/app/Views/orders/index.php +++ b/app/Views/orders/index.php @@ -50,7 +50,7 @@ get('user'); - if ($users['group_name'] === 'Conseil' || $users['group_name'] === "Direction") { + if ($users['group_name'] === 'SuperAdmin' || $users['group_name'] === "Direction" || $users['group_name'] === "DAF" ) { ?> Facture n° Nom du client @@ -58,7 +58,7 @@ Date et Heure Prix demandé Prix de vente - Validation + Status Date et Heure Prix demandé Prix de vente - Validation + Status + - -

Produits

+ +

Informations de la commande

- + + + + + + + + +
MarqueDesignationNuméro de SériePrix Unitaire
MarqueDésignationNuméro de SérieN° de MoteurChâssisN° FactureStatut
- - - - - -
Montant brutRabaisStatut
' ); - // Mettre à jour le statut dans la modal - $('#paid_status').html('Validé et Livré'); + // Mettre à jour le statut dans toutes les lignes du tableau + $('#view_products_table tbody tr').each(function() { + $(this).find('td:last').html('Payé et Livré'); + }); // Cacher le bouton "Livré" $('#btn-mark-delivered').hide(); @@ -364,6 +369,7 @@ } } + // ✅ FONCTION MODIFIÉE POUR AFFICHER LES NOUVELLES COLONNES $(document).on('click', '.btn-view', function(e) { e.preventDefault(); var orderId = $(this).data('order-id'); @@ -384,7 +390,25 @@ $('#customer_phone').text(d.customer_phone); $('#customer_cin').text(d.customer_cin); - // Produits + // Déterminer le statut une seule fois + var statutHtml = ''; + if (d.paid_status == 1) { + statutHtml = 'Payé'; + + $('#btn-mark-delivered').show(); + + } else if (d.paid_status == 2) { + statutHtml = 'En Attente'; + $('#btn-mark-delivered').hide(); + } else if (d.paid_status == 3) { + statutHtml = 'Payé et Livré'; + $('#btn-mark-delivered').hide(); + } else { + statutHtml = 'Refusé'; + $('#btn-mark-delivered').hide(); + } + + // Produits avec les nouvelles colonnes var $tb = $('#view_products_table tbody'); $tb.empty(); $.each(response.order_data.order_item, function(_, item) { @@ -405,41 +429,21 @@ } }); + // ✅ AJOUT DES NOUVELLES COLONNES : N° Moteur, Châssis, N° Facture, Statut $tb.append( '' + '' + (brandName || 'Aucune marque') + '' + '' + (product.name || '') + '' + '' + (product.sku || '') + '' + - '' + parseInt(item.amount).toLocaleString('fr-MG', { minimumFractionDigits: 0, maximumFractionDigits: 0 }) + ' Ar' + + '' + (product.numero_de_moteur || 'N/A') + '' + + '' + (product.chasis || 'N/A') + '' + + '' + (d.bill_no || 'N/A') + '' + + '' + statutHtml + '' + '' ); } }); - // Totaux - $('#gross_amount').text(parseInt(d.gross_amount).toLocaleString('fr-MG', { minimumFractionDigits: 0, maximumFractionDigits: 0 }) + ' Ar'); - $('#discount').text(parseInt(d.discount).toLocaleString('fr-MG', { minimumFractionDigits: 0, maximumFractionDigits: 0 }) + ' Ar'); - - // Statut de paiement avec gestion du statut "Livré" - var statutHtml = ''; - if (d.paid_status == 1) { - statutHtml = 'Validé'; - // Afficher le bouton "Livré" pour la sécurité si statut = Validé - - $('#btn-mark-delivered').show(); - - } else if (d.paid_status == 2) { - statutHtml = 'En Attente'; - $('#btn-mark-delivered').hide(); - } else if (d.paid_status == 3) { - statutHtml = 'Validé et Livré'; - $('#btn-mark-delivered').hide(); - } else { - statutHtml = 'Refusé'; - $('#btn-mark-delivered').hide(); - } - $('#paid_status').html(statutHtml); - // Afficher la modal $('#viewOrderModal').modal('show'); }); diff --git a/app/Views/reports/index.php b/app/Views/reports/index.php index 29aed344..c64c024e 100644 --- a/app/Views/reports/index.php +++ b/app/Views/reports/index.php @@ -303,4 +303,146 @@ } } }); - --> \ No newline at end of file + + diff --git a/app/Views/sortieCaisse/index.php b/app/Views/sortieCaisse/index.php index 5a4e1c3a..67a2a563 100644 --- a/app/Views/sortieCaisse/index.php +++ b/app/Views/sortieCaisse/index.php @@ -125,7 +125,7 @@ input[readonly], select[disabled], textarea[readonly] {
get('user'); - $isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "Conseil"; + $isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "SuperAdmin" || $users['group_name'] == "DAF"; $isCaissier = $users['group_name'] == "Caissière"; if($isAdmin): ?> @@ -159,7 +159,7 @@ input[readonly], select[disabled], textarea[readonly] { Action # Montant @@ -296,7 +296,7 @@ input[readonly], select[disabled], textarea[readonly] { get('user'); - $isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "Conseil"; + $isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "SuperAdmin" || $users['group_name'] == "DAF"; $isCaissier = $users['group_name'] == "Caissière"; $options = $isAdmin ? $admin_options : $caissier_options; @@ -522,9 +522,9 @@ input[readonly], select[disabled], textarea[readonly] { - Conseil d'Administration - - + SuperAdmin + + @@ -605,7 +605,7 @@ input[readonly], select[disabled], textarea[readonly] { get('user'); - $isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "Conseil"; + $isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "SuperAdmin" || $users['group_name'] == "DAF"; $options = $isAdmin ? $admin_options : $caissier_options; echo "\n"; @@ -1038,7 +1038,7 @@ $(document).ready(function() { get('user'); - $isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "Conseil"; + $isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "SuperAdmin" || $users['group_name'] == "DAF"; ?> diff --git a/app/Views/statistic/index.php b/app/Views/statistic/index.php index ccd75f84..7fab8588 100644 --- a/app/Views/statistic/index.php +++ b/app/Views/statistic/index.php @@ -1,61 +1,190 @@ + +
- -
-

- Tableau de bord - Statistiques des utilisateurs -

- -
- -
-
- - -
- - -
-
+
+

+ Tableau de bord + Statistiques des utilisateurs +

+ +
+ +
+
+ +
+ +
+
+ \ No newline at end of file + renderUsers(allUsers); + diff --git a/app/Views/templates/header.php b/app/Views/templates/header.php index 1367d4b0..a3b40ea8 100644 --- a/app/Views/templates/header.php +++ b/app/Views/templates/header.php @@ -908,5 +908,6 @@ } + \ No newline at end of file