verifyRole('viewOrder'); $data['page_title'] = $this->pageTitle; return $this->render_template('orders/index', $data); } public function fetchOrdersData() { helper(['url', 'form']); $Orders = new Orders(); $result = ['data' => []]; $data = $Orders->getOrdersData(); $session = session(); $users = $session->get('user'); if ($users['group_name'] == "Caissière") { foreach ($data as $key => $value) { $date_time = date('d-m-Y h:i a', strtotime($value['date_time'])); $buttons = ''; // Bouton imprimer (sauf pour SECURITE) if (in_array('viewOrder', $this->permission) && $users['group_name'] != "SECURITE" && $users['group_name'] != "COMMERCIALE") { $buttons .= ''; } // Bouton voir if (in_array('viewOrder', $this->permission)) { $buttons .= ' '; } // Bouton modifier if (in_array('updateOrder', $this->permission) && $users["store_id"] == $value['store_id']) { $buttons .= ' '; } // Statut de paiement if ($value['paid_status'] == 1) { $paid_status = 'Validé'; } elseif ($value['paid_status'] == 2) { $paid_status = 'En Attente'; } elseif ($value['paid_status'] == 3) { $paid_status = 'Validé et Livré'; } else { $paid_status = 'Refusé'; } // Calcul délai (SANS notification ici) $date1 = new DateTime($date_time); $date2 = new DateTime(); $interval = $date1->diff($date2); $daysPassed = $interval->days; $statuDate = ''; if ($value['paid_status'] == 2) { if ($daysPassed < 8) { $statuDate = ' depuis ' . $daysPassed . ' Jours'; } elseif ($daysPassed >= 8 && $daysPassed < 15) { $statuDate = ' depuis ' . $daysPassed . ' Jours'; } else { $statuDate = ' depuis ' . $daysPassed . ' Jours'; } } // $Orders_items = new OrderItems(); // $sum_order_item = $Orders_items->getSumOrdersItemData($value['id']); $result['data'][$key] = [ $value['product_names'], $value['user_name'], $date_time . "
" . $statuDate, number_format((int) $value['discount'], 0, ',', ' '), number_format((int) $value['gross_amount'], 0, ',', ' '), $paid_status, $buttons ]; } return $this->response->setJSON($result); } elseif($users['group_name'] == "Direction" || $users['group_name'] == "DAF"){ foreach ($data as $key => $value) { $date_time = date('d-m-Y h:i a', strtotime($value['date_time'])); $buttons = ''; // Bouton imprimer (sauf pour SECURITE) if (in_array('viewOrder', $this->permission) && $users['group_name'] != "SECURITE" && $users['group_name'] != "COMMERCIALE") { $buttons .= ''; } if (in_array('updateOrder', $this->permission)) { $buttons .= ' '; } if (in_array('deleteOrder', $this->permission)) { $buttons .= ' '; } // Statut de paiement if ($value['paid_status'] == 1) { $paid_status = 'Validé'; } elseif ($value['paid_status'] == 2) { $paid_status = 'En Attente'; } elseif ($value['paid_status'] == 3) { $paid_status = 'Validé et Livré'; } else { $paid_status = 'Refusé'; } // Calcul délai (SANS notification) $date1 = new DateTime($date_time); $date2 = new DateTime(); $interval = $date1->diff($date2); $daysPassed = $interval->days; $statuDate = ''; if ($value['paid_status'] == 2) { if ($daysPassed < 8) { $statuDate = ' depuis ' . $daysPassed . ' Jours'; } elseif ($daysPassed >= 8 && $daysPassed < 15) { $statuDate = ' depuis ' . $daysPassed . ' Jours'; } else { $statuDate = ' depuis ' . $daysPassed . ' Jours'; } } // $Orders_items= new OrderItems(); // $sum_order_item = $Orders_items->getSumOrdersItemData($value['id']); $result['data'][$key] = [ $value['bill_no'], $value['customer_name'], $value['customer_phone'], $date_time . "
" . $statuDate, number_format((int) $value['discount'], 0, ',', ' '), number_format((int) $value['gross_amount'], 0, ',', ' '), $paid_status, $buttons ]; } return $this->response->setJSON($result); } else { foreach ($data as $key => $value) { $date_time = date('d-m-Y h:i a', strtotime($value['date_time'])); $buttons = ''; // Bouton imprimer (sauf pour SECURITE) if (in_array('viewOrder', $this->permission) && $users['group_name'] != "SECURITE" && $users['group_name'] != "COMMERCIALE") { $buttons .= ''; } if (in_array('updateOrder', $this->permission) && $users["id"] == $value['user_id']) { $buttons .= ' '; } if (in_array('viewOrder', $this->permission)) { $buttons .= ' '; } if (in_array('deleteOrder', $this->permission) && $users["id"] == $value['user_id']) { $buttons .= ' '; } // Statut de paiement if ($value['paid_status'] == 1) { $paid_status = 'Validé'; } elseif ($value['paid_status'] == 2) { $paid_status = 'En Attente'; } elseif ($value['paid_status'] == 3) { $paid_status = 'Validé et Livré'; } else { $paid_status = 'Refusé'; } // Calcul délai (SANS notification) $date1 = new DateTime($date_time); $date2 = new DateTime(); $interval = $date1->diff($date2); $daysPassed = $interval->days; $statuDate = ''; if ($value['paid_status'] == 2) { if ($daysPassed < 8) { $statuDate = ' depuis ' . $daysPassed . ' Jours'; } elseif ($daysPassed >= 8 && $daysPassed < 15) { $statuDate = ' depuis ' . $daysPassed . ' Jours'; } else { $statuDate = ' depuis ' . $daysPassed . ' Jours'; } } // $Orders_items= new OrderItems(); // $sum_order_item = $Orders_items->getSumOrdersItemData($value['id']); $result['data'][$key] = [ $value['product_names'], $value['user_name'], $date_time . "
" . $statuDate, number_format((int) $value['discount'], 0, ',', ' '), number_format((int) $value['gross_amount'], 0, ',', ' '), $paid_status, $buttons ]; } return $this->response->setJSON($result); } } /** * Affiche le formulaire create avec les données d'une commande existante * Pour le rôle COMMERCIALE */ /** * function who check if the product is null * and create notification about it * @param array $product_id id of the product * @param int $store_id id of the store * @return void */ private function checkProductisNull(array $product_id, $store_id) { $notification = new NotificationController(); $product = new Products(); for ($i = 0; $i < count($product_id); $i++) { $singleProduct = $product->getProductData($product_id[$i]); if ($singleProduct['product_sold'] == true) { $notification->createNotification("Produit en rupture de stock", "Direction", $store_id, "products"); } } } private function calculGross($request) { $amount = $request; $montant = 0; for ($i = 0; $i < \count($amount); $i++) { $montant += $amount[$i]; } return $montant; } 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' ]); $validationData = [ 'product[]' => $this->request->getPost('product[]') ]; $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 = 'BILPR-' . strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, 4)); // Récupération des produits $posts = $this->request->getPost('product[]'); $rates = $this->request->getPost('rate_value[]'); $amounts = $this->request->getPost('amount_value[]'); $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; // Récupérer données produit + prix minimal $productData = $Products->getProductData($productId); $fourchette = $FourchettePrix->getFourchettePrixByProductId($productId); if ($fourchette) { $prixMinimal = (float)$fourchette['prix_minimal']; // ✅ Le rabais devient le prix de vente 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 inférieur au prix minimal autorisé de {$prixMinimalFormatted} Ar." ]); } } } } // ✅ NOUVELLE LOGIQUE : Calculer le montant à payer et net_amount $montant_a_payer = ($discount > 0) ? $discount : $gross_amount; // Récupérer les tranches $tranche_1 = (float)$this->request->getPost('tranche_1') ?? 0; $tranche_2 = (float)$this->request->getPost('tranche_2') ?? 0; // Calculer net_amount selon les tranches if ($tranche_1 > 0 && $tranche_2 > 0) { // Paiement en 2 tranches $net_amount = $tranche_1 + $tranche_2; } else { // Paiement en 1 tranche ou pas de tranches $net_amount = $montant_a_payer; } // ✅ Création de la commande avec la nouvelle logique $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'), 'date_time' => date('Y-m-d H:i:s'), 'service_charge_rate' => 0, 'vat_charge_rate' => 0, 'vat_charge' => 0, 'net_amount' => $net_amount, // ✅ Net amount = tranches OU montant_a_payer 'discount' => $discount, 'paid_status' => 2, // Toujours En Attente au départ 'user_id' => $user_id, 'amount_value' => $amounts, 'gross_amount' => $gross_amount, 'rate_value' => $rates, '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(); // ✅ WORKFLOW SELON LA REMISE if ($discount > 0) { // AVEC REMISE : Créer demande + Notifier Conseil $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 au CONSEIL $Notification->createNotification( "Nouvelle demande de remise à valider - Commande " . $bill_no, "Direction", (int)$users['store_id'], "remise/" ); } else { // SANS REMISE : Notifier directement la Caissière $Notification->createNotification( "Nouvelle commande à valider - " . $bill_no, "Caissière", (int)$users['store_id'], "orders" ); } // Redirection selon le rôle if ($users["group_name"] != "COMMERCIALE") { $this->checkProductisNull($posts, $users['store_id']); return redirect()->to('orders/update/' . $order_id); } else { return redirect()->to('orders/'); } } else { 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 */ public function markAsDelivered() { // Activer le retour JSON même en cas d'erreur ini_set('display_errors', 0); $order_id = $this->request->getPost('order_id'); $response = ['success' => false, 'messages' => '']; try { $session = session(); $users = $session->get('user'); // Vérifier que l'utilisateur est SECURITE if (!isset($users['group_name']) || $users['group_name'] !== 'SECURITE') { $response['messages'] = "Accès refusé : seule la sécurité peut marquer une commande comme livrée."; return $this->response->setJSON($response); } if (!$order_id) { $response['messages'] = "ID de commande manquant."; return $this->response->setJSON($response); } $Orders = new Orders(); // Récupérer la commande actuelle $current_order = $Orders->getOrdersData((int)$order_id); if (!$current_order) { $response['messages'] = "Commande introuvable."; return $this->response->setJSON($response); } // Vérifier que la commande est validée (paid_status = 1) if ($current_order['paid_status'] != 1) { $response['messages'] = "Cette commande doit être validée avant d'être marquée comme livrée."; return $this->response->setJSON($response); } // Mettre à jour UNIQUEMENT le statut à 3 (Livré) $updated = $Orders->update((int)$order_id, ['paid_status' => 3]); if ($updated) { // Créer une notification try { $Notification = new NotificationController(); $Notification->createNotification( "Commande " . $current_order['bill_no'] . " livrée avec succès", "Direction", (int)$current_order['store_id'], "orders" ); } catch (\Exception $e) { // Si la notification échoue, on continue quand même log_message('error', 'Erreur notification: ' . $e->getMessage()); } $response['success'] = true; $response['messages'] = "La commande a été marquée comme livrée avec succès."; } else { $response['messages'] = "Erreur lors de la mise à jour du statut."; } } catch (\Exception $e) { log_message('error', 'Erreur markAsDelivered: ' . $e->getMessage()); $response['messages'] = "Erreur serveur : " . $e->getMessage(); } return $this->response->setJSON($response); } public function getProductValueById() { $product_id = $this->request->getPost('product_id'); if ($product_id) { $Products = new \App\Models\Products(); $product_data = $Products->getProductData($product_id); $FourchettePrix = new \App\Models\FourchettePrix(); $fourchette = $FourchettePrix->where('product_id', $product_id)->first(); $response = [ 'id' => $product_data['id'], 'sku' => $product_data['sku'], 'name' => $product_data['name'], 'prix_vente' => $product_data['prix_vente'], 'prix_minimal' => $fourchette ? $fourchette['prix_minimal'] : 0, ]; return $this->response->setJSON($response); } } public function getTableProductRow() { $Products = new Products(); $session = session(); $users = $session->get('user'); $store_id = $users['store_id']; $product_data = $Products->getProductData2($store_id); die(var_dump($product_data)); return $this->response->setJSON($product_data); } public function update(int $id) { $this->verifyRole('updateOrder'); $data['page_title'] = $this->pageTitle; $validation = \Config\Services::validation(); // Règles de validation $validation->setRules([ 'product' => 'required' ]); $validationData = [ 'product' => $this->request->getPost('product') ]; $Orders = new Orders(); $Company = new Company(); $Products = new Products(); $OrderItems = new OrderItems(); $session = session(); $user = $session->get('user'); $role = $user['group_name'] ?? null; if ($this->request->getMethod() === 'post' && $validation->run($validationData)) { $current_order = $Orders->getOrdersData($id); $old_paid_status = $current_order['paid_status']; // ✅ Statut payé pour COMMERCIALE reste toujours "En attente" if ($role === 'COMMERCIALE') { $paid_status = 2; // ← mettre la valeur correspondant à "En attente" dans votre table } else { $paid_status = $this->request->getPost('paid_status'); } // Gestion remise $discount = $this->request->getPost('discount'); $original_discount = $this->request->getPost('original_discount'); if ($discount === '' || $discount === null) { $discount = $original_discount; } $dataUpdate = [ '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'), 'gross_amount' => $this->request->getPost('gross_amount_value'), 'service_charge_rate' => $this->request->getPost('service_charge_rate'), 'service_charge' => max(0, (float)$this->request->getPost('service_charge_value')), 'vat_charge_rate' => $this->request->getPost('vat_charge_rate'), 'vat_charge' => max(0, (float)$this->request->getPost('vat_charge_value')), 'net_amount' => $this->request->getPost('net_amount_value'), 'discount' => (float)$discount, 'paid_status' => $paid_status, 'product' => $this->request->getPost('product'), 'product_sold' => true, 'rate_value' => $this->request->getPost('rate_value'), 'amount_value' => $this->request->getPost('amount_value'), 'tranche_1' => $role !== 'COMMERCIALE' ? $this->request->getPost('tranche_1') : null, 'tranche_2' => $role !== 'COMMERCIALE' ? $this->request->getPost('tranche_2') : null, 'order_payment_mode' => $role !== 'COMMERCIALE' ? $this->request->getPost('order_payment_mode_1') : null, 'order_payment_mode_1' => $role !== 'COMMERCIALE' ? $this->request->getPost('order_payment_mode_2') : null ]; if ($Orders->updates($id, $dataUpdate)) { $order_item_data = $OrderItems->getOrdersItemData($id); $product_ids = array_column($order_item_data, 'product_id'); $Notification = new NotificationController(); // Notification pour la sécurité si commande validée if ($old_paid_status == 2 && $paid_status == 1) { $customer_name = $this->request->getPost('customer_name'); $bill_no = $current_order['bill_no']; $Notification->createNotification( "Commande validée: {$bill_no} - Client: {$customer_name}", "SECURITE", (int)$user['store_id'], 'orders' ); } // Gestion demande de remise if ((float)$discount > 0) { $productData = new Products(); $product_data_results = []; foreach ($product_ids as $product_id) { $product_data_results[] = $productData->getProductData((int) $product_id); } $product_lines = []; foreach ($product_data_results as $product) { if (isset($product['sku'], $product['price'])) { $product_lines[] = "{$product['sku']}:{$product['price']}"; } } $product_output = implode("\n", $product_lines); $data1 = [ 'date_demande' => date('Y-m-d H:i:s'), 'montant_demande' => $this->request->getPost('discount'), 'total_price' => $this->request->getPost('amount_value'), 'id_store' => $user['store_id'], 'id_order' => $id, 'product' => $product_output, 'demande_status' => 'En attente' ]; $Remise = new Remise(); $Remise->updateRemise1($id, $data1); $Notification->createNotification( "Une nouvelle demande de remise a été ajoutée", "Direction", (int)$user['store_id'] ?? null, "remise/" ); } session()->setFlashData('success', 'Commande mise à jour avec succès.'); return redirect()->to('orders/update/' . $id); } else { session()->setFlashData('errors', 'Une erreur est survenue lors de la mise à jour.'); return redirect()->to('orders/update/' . $id); } } // Si GET ou validation échoue $company = $Company->getCompanyData(1); $data['company_data'] = $company; $data['is_vat_enabled'] = ($company['vat_charge_value'] > 0); $data['is_service_enabled'] = ($company['service_charge_value'] > 0); $orders_data = $Orders->getOrdersData($id); // Montant tranches $orders_data['montant_tranches'] = (!empty($orders_data['discount']) && $orders_data['discount'] > 0) ? $orders_data['discount'] : $orders_data['gross_amount']; $result = ['order' => $orders_data]; $orders_item = $OrderItems->getOrdersItemData($orders_data['id']); foreach ($orders_item as $item) { $result['order_item'][] = $item; } $data['order_data'] = $result; $data['products'] = $Products->getActiveProductData(); $data['validation'] = $validation; return $this->render_template('orders/edit', $data); } public function lookOrder(int $id) { $this->verifyRole('viewOrder'); $data['page_title'] = $this->pageTitle; $Orders = new Orders(); $Company = new Company(); $Products = new Products(); $OrderItems = new OrderItems(); $Brands = new Brands(); // En cas d’échec de la validation ou si GET $company = $Company->getCompanyData(1); $data['company_data'] = $company; $data['is_vat_enabled'] = ($company['vat_charge_value'] > 0); $data['is_service_enabled'] = ($company['service_charge_value'] > 0); $orders_data = $Orders->getOrdersData($id); // $sum_order_item = $OrderItems->getSumOrdersItemData($orders_data['id']); $result = [ 'order' => $orders_data, // 'sum_order_data' => $sum_order_item ]; $orders_item = $OrderItems->getOrdersItemData($orders_data['id']); foreach ($orders_item as $item) { $result['order_item'][] = $item; } $data['order_data'] = $result; $data['products'] = $Products->getActiveProductData(); $data['brands'] = $Brands->findAll(); return $this->response->setJSON($data); } /** * return storename * @param int $id * @return string */ private function returnStore($id) { $Stores = new Stores(); $store = $Stores->getActiveStore(); $name = ""; foreach ($store as $key => $value) { if ($value['id'] == $id) { $name = $value['name']; } } return $name; } public function print2(int $id) { $this->verifyRole('viewOrder'); if ($id) { $Orders = new Orders(); $Company = new Company(); $Products = new Products(); $OrderItems = new OrderItems(); // Récupération des données $order_data = $Orders->getOrdersData($id); $orders_items = $OrderItems->getOrdersItemData($id); $company_info = $Company->getCompanyData(1); // die(\var_dump($orders_items)); $html = ''; // Vérifier si l'utilisateur a payé if ($order_data['paid_status'] == 1) { $paid_status = "Validé"; } elseif ($order_data['paid_status'] == 2) { $paid_status = "En Attente"; } else { $paid_status = "Refusé"; } // Génération du HTML $html .= '
' . esc($company_info['company_name']) . '

Facture ID : ' . esc($order_data['bill_no']) . '

NIF : ' . esc($company_info['NIF']) . '

STAT : ' . esc($company_info['STAT']) . '

Contact : ' . esc($company_info['phone']) . ' ' . esc($company_info['phone2']) . '

Magasin : ' . esc($this->returnStore($order_data['store_id'])) . '

Nom: ' . esc($order_data['customer_name']) . '

Adresse: ' . esc($order_data['customer_address']) . '

Téléphone: ' . esc($order_data['customer_phone']) . '

CIN: ' . esc($order_data['customer_cin']) . '



Antananarivo le ' . esc(date('d/m/Y')) . '

'; foreach ($orders_items as $item) { $product_data = $Products->getProductData($item['product_id']); $html .= ''; } $html .= '
Marque Moteur Puissance Prix
' . esc($product_data['sku']) . ' ' . esc($product_data['numero_de_moteur']) . ' ' . number_format((float) $item['amount'], 2, '.', ' ') . '
'; $html .= ''; // Vérification et ajout des informations de paiement if (!empty($order_data['order_payment_mode'])) { $html .= ''; } if (!empty($order_data['tranche_1'])) { $html .= ''; } if (!empty($order_data['tranche_2'])) { $html .= ''; } $html .= '
Total: ' . number_format(((float) $order_data['gross_amount'] - ((float) $order_data['gross_amount'] * 0.2)), 2, '.', ' ') . '
TVA: ' . number_format((((float) $order_data['gross_amount'] * 0.2)), 2, '.', ' ') . '
Réduction: ' . number_format((float) $order_data['discount'], 2, '.', ' ') . '
Total à payer: ' . number_format((float) ($order_data['net_amount']), 2, '.', ' ') . '
Statut: ' . $paid_status . '
Mode de paiement: ' . esc($order_data['order_payment_mode']) . '
Tranche 1: ' . number_format((float) $order_data['tranche_1'], 2, '.', ' ') . '
Tranche 2: ' . number_format((float) $order_data['tranche_2'], 2, '.', ' ') . '

L\'acheteur

Le vendeur

'; return $this->response->setBody($html); } } public function print(int $id) { $this->verifyRole('viewOrder'); if ($id) { $Orders = new Orders(); $Company = new Company(); $Products = new Products(); $OrderItems = new OrderItems(); $order_data = $Orders->getOrdersData($id); $orders_items = $OrderItems->getOrdersItemData($id); $company_info = $Company->getCompanyData(1); $paid_status = ($order_data['paid_status'] == 1) ? "Payé" : "Non payé"; foreach ($orders_items as $index => $item) { $product_data = $Products->getProductData($item['product_id']); echo '
' . esc($company_info['company_name']) . '

Facture ID : ' . esc($order_data['bill_no']) . '

NIF : ' . esc($company_info['NIF']) . '

STAT : ' . esc($company_info['STAT']) . '

Contact : ' . esc($company_info['phone']) . ' ' . esc($company_info['phone2']) . '

Magasin : ' . esc($this->returnStore($order_data['store_id'])) . '

Nom: ' . esc($order_data['customer_name']) . '

Adresse: ' . esc($order_data['customer_address']) . '

Téléphone: ' . esc($order_data['customer_phone']) . '

CIN: ' . esc($order_data['customer_cin']) . '



Antananarivo le ' . esc(date('d/m/Y')) . '

Marque Moteur Puissance Prix
' . esc($product_data['sku']) . ' ' . esc($product_data['numero_de_moteur']) . ' ' . number_format((float)$item['amount'], 2, '.', ' ') . '
'; if (!empty($order_data['order_payment_mode'])) { echo ''; } if (!empty($order_data['tranche_1'])) { echo ''; } if (!empty($order_data['tranche_2'])) { echo ''; } echo '
Total: ' . number_format($item['amount'] - ($item['amount'] * 0.2), 2, '.', ' ') . '
TVA: ' . number_format($item['amount'] * 0.2, 2, '.', ' ') . '
Réduction: ' . number_format($order_data['discount'], 2, '.', ' ') . '
Total à payer: ' . number_format($item['amount'] - $order_data['discount'], 2, '.', ' ') . '
Statut: ' . $paid_status . '
Mode de paiement:' . esc($order_data['order_payment_mode']) . '
Tranche 1:' . number_format((float)$order_data['tranche_1'], 2, '.', ' ') . '
Tranche 2:' . number_format((float)$order_data['tranche_2'], 2, '.', ' ') . '

L\'acheteur

Le vendeur

'; } } } public function remove() { $this->verifyRole('deleteOrder'); $order_id = $this->request->getPost('order_id'); $response = []; if ($order_id) { $Orders = new Orders(); if ($Orders->remove($order_id)) { $response['success'] = true; $response['messages'] = "Successfully removed"; } else { $response['success'] = false; $response['messages'] = "Error in the database while removing the product information"; } } else { $response['success'] = false; $response['messages'] = "Refersh the page again!!"; } return $this->response->setJSON($response); } public function createById(int $id) { $this->verifyRole('createOrder'); $data['page_title'] = $this->pageTitle; $Company = new Company(); $Products = new Products(); // If validation fails $company = $Company->getCompanyData(1); // Prepare data for the view $data = [ 'company_data' => $company, 'is_vat_enabled' => ($company['vat_charge_value'] > 0), 'is_service_enabled' => ($company['service_charge_value'] > 0), 'products' => $Products->getProductData($id), // 'discount' => $Products->getProductData($id)['discount'], 'pu' => $Products->getProductData($id)['prix_vente'], 'page_title' => $this->pageTitle, ]; return $this->render_template('orders/createbyid', $data); } // update caisse public function update_caisse($data) { $p1 = 0; $p2 = 0; $op = ""; $p3 = 0; $dest = ""; if ($data['tranche2']) { if ($data['order']) { # code... } } } public function print3(int $id) { // Vérification du rôle $this->verifyRole('viewOrder'); if (!$id) { return $this->response->setStatusCode(400, 'ID manquant'); } // Instanciation des modèles $Orders = new Orders(); $Company = new Company(); $OrderItems = new OrderItems(); $Products = new Products(); // Récupération des données $order_data = $Orders->getOrdersData($id); $items = $OrderItems->getOrdersItemData($id); $company_info = $Company->getCompanyData(1); // Statut de paiement $paid_status = $order_data['paid_status'] == 1 ? "Payé" : "Non payé"; // STYLE COMMUN $style = ' '; // --- FACTURES : Une par produit --- foreach ($items as $item) { $product_data = $Products->getProductData($item['product_id']); $unitPrice = (float)$item['amount']; $quantity = isset($item['qty']) ? (int)$item['qty'] : 1; $subtotal = $unitPrice * $quantity; $vatAmount = $subtotal * 0.2; $discount = (float)$order_data['discount']; $totalNet = $subtotal + $vatAmount - $discount; echo ' ' . $style . '
FACTURE

Facture ID : ' . esc($order_data['bill_no']) . '

NIF : ' . esc($company_info['NIF']) . '

STAT : ' . esc($company_info['STAT']) . '

Contact : ' . esc($company_info['phone']) . ' / ' . esc($company_info['phone2']) . '

Magasin : ' . esc($this->returnStore($order_data['store_id'])) . '

Nom: ' . esc($order_data['customer_name']) . '

Adresse: ' . esc($order_data['customer_address']) . '

Téléphone: ' . esc($order_data['customer_phone']) . '

CIN: ' . esc($order_data['customer_cin']) . '

MarqueMoteurPuissancePrix unitaire
' . esc($product_data['sku']) . ' ' . esc($product_data['numero_de_moteur']) . ' ' . esc($product_data['puissance']) . ' ' . number_format($unitPrice, 2, '.', ' ') . '
'; if (!empty($order_data['order_payment_mode'])) { echo ''; } if (!empty($order_data['tranche_1'])) { echo ''; } if (!empty($order_data['tranche_2'])) { echo ''; } echo '
Total:
TVA (20%):
Réduction:
Total à payer:
Statut:
Mode de paiement:
Tranche 1:
Tranche 2:

L\'acheteur

Le vendeur

'; } // --- BON DE COMMANDE : une seule fois après la boucle --- echo ' ' . $style . '
BON DE COMMANDE

Commande ID : ' . esc($order_data['order_no'] ?? $order_data['bill_no']) . '

Magasin : ' . esc($this->returnStore($order_data['store_id'])) . '

Nom: ' . esc($order_data['customer_name']) . '

Adresse: ' . esc($order_data['customer_address']) . '

Téléphone: ' . esc($order_data['customer_phone']) . '

CIN: ' . esc($order_data['customer_cin']) . '

'; $total_ht = 0; foreach ($items as $item) { $product_data = $Products->getProductData($item['product_id']); $total_ht += (float)$item['amount']; echo ''; } $tva = $total_ht * 0.2; $total_ttc = $total_ht + $tva - $order_data['discount']; echo ''; echo '
Marque Moteur Puissance Prix
' . esc($product_data['sku']) . ' ' . esc($product_data['numero_de_moteur']) . ' ' . number_format((float)$item['amount'], 2, '.', ' ') . '
Total:' . number_format($total_ht, 2, '.', ' ') . '
TVA:' . number_format($tva, 2, '.', ' ') . '
Réduction:' . number_format($order_data['discount'], 2, '.', ' ') . '
Total à payer:' . number_format($total_ttc, 2, '.', ' ') . '
'; echo '

L\'acheteur

Le vendeur

'; echo''; echo '
'; echo ''; echo''; } // PRINT5 - Facture détaillée avec conditions générales // ==================================== public function print5(int $id) { $this->verifyRole('viewOrder'); if (! $id) { throw new \CodeIgniter\Exceptions\PageNotFoundException(); } // Modèles $Orders = new Orders(); $Company = new Company(); $Products = new Products(); $OrderItems = new OrderItems(); $Brand = new Brands(); $Category = new Category(); // Récupération des données $order = $Orders->getOrdersData($id); $items = $OrderItems->getOrdersItemData($id); $company = $Company->getCompanyData(1); $today = date('d/m/Y'); // ✅ LOGIQUE DE REMISE: Si discount existe, il devient le prix de vente $discount = (float) $order['discount']; $grossAmount = (float) $order['gross_amount']; // Si remise existe, elle devient le montant TTC, sinon on prend gross_amount $totalTTC = ($discount > 0) ? $discount : $grossAmount; $totalHT = $totalTTC / 1.20; $tva = $totalTTC - $totalHT; $inWords = $this->numberToWords((int) round($totalTTC)); // Statut paiement $paidLabel = $order['paid_status'] == 1 ? 'Payé' : 'Non payé'; // Début du HTML $html = ' Facture '.$order['bill_no'].'

'.esc($company['company_name']).'

NIF : '.esc($company['NIF']).'

STAT : '.esc($company['STAT']).'

Contact : '.esc($company['phone']).' | '.esc($company['phone2']).'

Logo

Facture N° '.esc($order['bill_no']).'

DOIT Nom : '.esc($order['customer_name']).'

Adresse : '.esc($order['customer_address']).'

CIN : '.esc($order['customer_cin']).'

Téléphone : '.esc($order['customer_phone'] ?? '').'

Antananarivo, le '.$today.'

'; foreach ($items as $it) { $p = $Products->getProductData($it['product_id']); // ✅ Récupérer le nom de la marque correctement $brandName = 'Non définie'; if (!empty($p['marque'])) { $brandData = $Brand->find($p['marque']); if ($brandData && isset($brandData['name'])) { $brandName = $brandData['name']; } } // ✅ LOGIQUE: Si discount existe pour la commande, on l'affiche comme prix $prixAffiche = ($discount > 0) ? $discount : $p['prix_vente']; $html .= ' '; } $html .= '
Désignation MARQUE N° Moteur N° Châssis Puissance (CC) PRIX (Ar)
'.esc($p['name']).' '.esc($brandName).' '.esc($p['numero_de_moteur']).' '.esc($p['chasis'] ?? '').' '.esc($p['puissance']).' '.number_format($prixAffiche, 0, '', ' ').'
Prix (HT) : '.number_format($totalHT, 0, '', ' ').' Ar
TVA (20%) : '.number_format($tva, 0, '', ' ').' Ar
Total (TTC) : '.number_format($totalTTC, 0, '', ' ').' Ar
Arrêté à la somme de :
'.$inWords.'
L\'Acheteur

__________________
Le Vendeur

__________________

Conditions Générales

Logo
L\'Acheteur
'; return $this->response->setBody($html); } /** * Convertit un nombre entier en texte (français, sans décimales). * Usage basique, pour Ariary. */ private function numberToWords(int $num): string { // Cas zéro if ($num === 0) { return 'zéro ariary'; } // Tableaux de base $units = [ '', 'un', 'deux', 'trois', 'quatre', 'cinq', 'six', 'sept', 'huit', 'neuf', 'dix', 'onze', 'douze', 'treize', 'quatorze', 'quinze', 'seize', 'dix-sept', 'dix-huit', 'dix-neuf' ]; $tens = [ 2 => 'vingt', 3 => 'trente', 4 => 'quarante', 5 => 'cinquante', 6 => 'soixante', 7 => 'soixante-dix', 8 => 'quatre-vingt', 9 => 'quatre-vingt-dix' ]; // Fonction récursive interne (sans la monnaie) $convert = function(int $n) use (&$convert, $units, $tens): string { if ($n < 20) { return $units[$n]; } if ($n < 100) { $d = intdiv($n, 10); $r = $n % 10; // 70–79 et 90–99 if ($d === 7 || $d === 9) { $base = $d === 7 ? 60 : 80; return $tens[$d] . ($r ? '-' . $units[$n - $base] : ''); } // 20–69 ou 80–89 return $tens[$d] . ($r ? '-' . $units[$r] : ''); } if ($n < 1000) { $h = intdiv($n, 100); $rest = $n % 100; $hundredText = $h > 1 ? $units[$h] . ' cent' : 'cent'; // « deux cents » prend un « s » si pas de reste if ($h > 1 && $rest === 0) { $hundredText .= 's'; } return $hundredText . ($rest ? ' ' . $convert($rest) : ''); } if ($n < 1000000) { $k = intdiv($n, 1000); $rest = $n % 1000; $thousandText = $k > 1 ? $convert($k) . ' mille' : 'mille'; return $thousandText . ($rest ? ' ' . $convert($rest) : ''); } // millions et plus $m = intdiv($n, 1000000); $rest = $n % 1000000; $millionText = $m > 1 ? $convert($m) . ' million' : 'million'; // pas de 's' à million en francais return $millionText . ($rest ? ' ' . $convert($rest) : ''); }; // Construit le texte sans la monnaie, puis ajoute 'ariary' à la fin $words = $convert($num); return trim($words) . ' ariary'; } // ==================================== // PRINT7 - Bon de commande // ==================================== public function print7(int $id) { $this->verifyRole('viewOrder'); if (! $id) { throw new \CodeIgniter\Exceptions\PageNotFoundException(); } // Modèles $Orders = new Orders(); $Company = new Company(); $Products = new Products(); $OrderItems = new OrderItems(); $Brand = new Brands(); $Category = new Category(); // Récupération des données $order = $Orders->getOrdersData($id); $items = $OrderItems->getOrdersItemData($id); $company = $Company->getCompanyData(1); $today = date('d/m/Y'); // Calculs totaux $totalTTC = (float) $order['net_amount']; $totalHT = $totalTTC / 1.20; $tva = $totalTTC - $totalHT; $paidLabel = $order['paid_status'] == 1 ? 'Payé' : 'Non payé'; // Démarrage du HTML $html = ' Bon de commande '.$order['bill_no'].'

'.esc($company['company_name']).'

NIF : '.esc($company['NIF']).'

STAT : '.esc($company['STAT']).'

Contact : '.esc($company['phone']).' | '.esc($company['phone2']).'

Logo

Bon de commande N° '.esc($order['bill_no']).'

Client : '.esc($order['customer_name']).'

Adresse : '.esc($order['customer_address']).'

Téléphone : '.esc($order['customer_phone']).'

CIN : '.esc($order['customer_cin']).'

Antananarivo, le '.$today.'

'; foreach ($items as $item) { $p = $Products->getProductData($item['product_id']); // ✅ Récupérer le nom de la marque correctement $brandName = 'Non définie'; if (!empty($p['marque'])) { $brandData = $Brand->find($p['marque']); if ($brandData && isset($brandData['name'])) { $brandName = $brandData['name']; } } // ✅ Récupérer le nom de la catégorie $categoryName = 'Non définie'; if (!empty($p['categorie_id'])) { $categoryData = $Category->find($p['categorie_id']); if ($categoryData && isset($categoryData['name'])) { $categoryName = $categoryData['name']; } } $html .= ''; } $html .= '
Nom Marque Catégorie N° Moteur Châssis Puissance (CC) Prix Unitaire (Ar)
'.esc($p['name']).' '.esc($brandName).' '.esc($categoryName).' '.esc($p['numero_de_moteur']).' '.esc($p['chasis'] ?? '').' '.esc($p['puissance']).' '.number_format($p['prix_vente'], 0, '', ' ').'
'; if (! empty($order['order_payment_mode'])) { $html .= ''; } $html .= '
Total HT : '.number_format($totalHT, 0, '', ' ').' Ar
TVA (20%) : '.number_format($tva, 0, '', ' ').' Ar
Total TTC : '.number_format($totalTTC, 0, '', ' ').' Ar
Statut : '.$paidLabel.'
Mode de paiement : '.esc($order['order_payment_mode']).'
L\'acheteur

__________________
Le vendeur

__________________

Conditions Générales

Logo
L\'Acheteur
'; echo $html; } // ==================================== // PRINT31 - Facture + Bon de commande (pages séparées) // ==================================== public function print31(int $id) { $this->verifyRole('viewOrder'); if (! $id) { return $this->response->setStatusCode(400, 'ID manquant'); } $Orders = new Orders(); $Company = new Company(); $OrderItems = new OrderItems(); $Products = new Products(); $Brand = new Brands(); $Category = new Category(); $order_data = $Orders->getOrdersData($id); $items = $OrderItems->getOrdersItemData($id); $company_info = $Company->getCompanyData(1); $paid_status = $order_data['paid_status'] === 1 ? "Validé" : "Refusé"; // --- FACTURES : Une par produit --- foreach ($items as $item) { $p = $Products->getProductData($item['product_id']); $unitPrice = (float) $item['amount']; $quantity = isset($item['qty']) ? (int) $item['qty'] : 1; $subtotal = $unitPrice * $quantity; $vatAmount = $subtotal * 0.2; $discount = (float) $order_data['discount']; $totalNet = $subtotal + $vatAmount - $discount; $inWords = $this->numberToWords((int) round($subtotal)); // ✅ Récupérer le nom de la marque $brandName = 'Non définie'; if (!empty($p['marque'])) { $brandData = $Brand->find($p['marque']); if ($brandData && isset($brandData['name'])) { $brandName = $brandData['name']; } } // ✅ Récupérer le nom de la catégorie $categoryName = 'Non définie'; if (!empty($p['categorie_id'])) { $categoryData = $Category->find($p['categorie_id']); if ($categoryData && isset($categoryData['name'])) { $categoryName = $categoryData['name']; } } echo ''; echo ''; echo ''; echo ''; echo ""; echo ''; echo '
'; echo '
'; echo '
'; echo '

' . esc($company_info['company_name']) . '

'; echo '

NIF : ' . esc($company_info['NIF']) . '

'; echo '

STAT : ' . esc($company_info['STAT']) . '

'; echo '

Contact : ' . esc($company_info['phone']) . ' | ' . esc($company_info['phone2']) . '

'; echo '

Magasin : ' . esc($this->returnStore($order_data['store_id'])) . '

'; echo '
'; echo '
'; echo 'Logo'; echo '

Facture N° ' . esc($order_data['bill_no']) . '

'; echo '

Antananarivo, le ' . date('d/m/Y') . '

'; echo '
'; echo '
'; echo '
'; echo '

Client : ' . esc($order_data['customer_name']) . '

'; echo '

Adresse : ' . esc($order_data['customer_address']) . '

'; echo '

Téléphone : ' . esc($order_data['customer_phone']) . '

'; echo '

CIN : ' . esc($order_data['customer_cin']) . '

'; echo '
'; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; } $tva = $total_ht * 0.2; $total_ttc = $total_ht + $tva - (float) $order_data['discount']; echo '
NomMarqueCatégorieN° MoteurChâssisPuissance (CC)Prix Unit. (Ar)
' . esc($p['name']) . '' . esc($brandName) . '' . esc($categoryName) . '' . esc($p['numero_de_moteur']) . '' . esc($p['chasis'] ?? '') . '' . esc($p['puissance']) . '' . number_format($amount, 0, '', ' ') . '
'; echo ''; echo ''; echo ''; echo ''; echo ''; echo '
Total HT :' . number_format($total_ht, 0, '', ' ') . ' Ar
TVA :' . number_format($tva, 0, '', ' ') . ' Ar
Réduction :' . number_format($order_data['discount'], 0, '', ' ') . ' Ar
Total TTC :' . number_format($total_ttc, 0, '', ' ') . ' Ar
'; echo '
'; echo '
L\'Acheteur

__________________
'; echo '
Le Vendeur

__________________
'; echo '
'; // --- CONDITIONS GÉNÉRALES --- echo '
'; echo '
'; echo '

Conditions Générales

'; echo 'Logo'; echo '
'; echo ''; echo '
L\'Acheteur
'; echo '
'; echo '
'; echo ''; } }