06112025
This commit is contained in:
parent
6f2b1d3661
commit
10f3dae939
@ -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();
|
||||
|
||||
// ✅ NOUVELLE FONCTIONNALITÉ : Envoyer notification à la Caissière si l'utilisateur est COMMERCIALE
|
||||
// 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'
|
||||
);
|
||||
}
|
||||
|
||||
// ✅ 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,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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 = '<img src="' . base_url('assets/images/product_image/' . $repa['image']) . '" alt="' . $repa['name'] . '" class="img-circle" width="50" height="50" />';
|
||||
$produit = esc($repa['name']);
|
||||
|
||||
@ -107,11 +107,11 @@ class OrderController extends AdminController
|
||||
|
||||
// Statut de paiement
|
||||
if ($value['paid_status'] == 1) {
|
||||
$paid_status = '<span class="label label-success">Validé</span>';
|
||||
$paid_status = '<span class="label label-success">payé</span>';
|
||||
} elseif ($value['paid_status'] == 2) {
|
||||
$paid_status = '<span class="label label-warning">En Attente</span>';
|
||||
} elseif ($value['paid_status'] == 3) {
|
||||
$paid_status = '<span class="label label-info">Validé et Livré</span>';
|
||||
$paid_status = '<span class="label label-info">payé et Livré</span>';
|
||||
} else {
|
||||
$paid_status = '<span class="label label-danger">Refusé</span>';
|
||||
}
|
||||
@ -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 = '<span class="label label-success">Validé</span>';
|
||||
$paid_status = '<span class="label label-success">payé</span>';
|
||||
} elseif ($value['paid_status'] == 2) {
|
||||
$paid_status = '<span class="label label-warning">En Attente</span>';
|
||||
} elseif ($value['paid_status'] == 3) {
|
||||
$paid_status = '<span class="label label-info">Validé et Livré</span>';
|
||||
$paid_status = '<span class="label label-info">Payé et Livré</span>';
|
||||
} else {
|
||||
$paid_status = '<span class="label label-danger">Refusé</span>';
|
||||
}
|
||||
@ -255,11 +255,11 @@ class OrderController extends AdminController
|
||||
|
||||
// Statut de paiement
|
||||
if ($value['paid_status'] == 1) {
|
||||
$paid_status = '<span class="label label-success">Validé</span>';
|
||||
$paid_status = '<span class="label label-success">Payé</span>';
|
||||
} elseif ($value['paid_status'] == 2) {
|
||||
$paid_status = '<span class="label label-warning">En Attente</span>';
|
||||
} elseif ($value['paid_status'] == 3) {
|
||||
$paid_status = '<span class="label label-info">Validé et Livré</span>';
|
||||
$paid_status = '<span class="label label-info">Payé et Livré</span>';
|
||||
} else {
|
||||
$paid_status = '<span class="label label-danger">Refusé</span>';
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
$product_lines = [];
|
||||
foreach ($product_data_results as $product) {
|
||||
if (isset($product['sku'], $product['price'])) {
|
||||
$sku = $product['sku'];
|
||||
$price = $product['price'];
|
||||
$product_lines[] = "{$sku}:{$price}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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_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<br>" .
|
||||
"Commande : {$bill_no}<br>" .
|
||||
"Store : " . $this->returnStore($users['store_id']) . "<br>" .
|
||||
"Demandeur : {$users['firstname']} {$users['lastname']}";
|
||||
|
||||
// ✅ NOTIFIER SUPERADMIN, DIRECTION, DAF DE TOUS LES STORES
|
||||
if (is_array($allStores) && count($allStores) > 0) {
|
||||
foreach ($allStores as $store) {
|
||||
// SuperAdmin (validation)
|
||||
$Notification->createNotification(
|
||||
$message,
|
||||
"SuperAdmin",
|
||||
(int)$store['id'],
|
||||
'remise/'
|
||||
);
|
||||
|
||||
// Direction (consultation)
|
||||
$Notification->createNotification(
|
||||
$message . "<br><em>Pour information</em>",
|
||||
"Direction",
|
||||
(int)$store['id'],
|
||||
'remise/'
|
||||
);
|
||||
|
||||
// DAF (consultation)
|
||||
$Notification->createNotification(
|
||||
$message . "<br><em>Pour information</em>",
|
||||
"DAF",
|
||||
(int)$store['id'],
|
||||
'remise/'
|
||||
);
|
||||
}
|
||||
|
||||
$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']);
|
||||
}
|
||||
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}<br>" .
|
||||
"Client : {$data['customer_name']}<br>" .
|
||||
"Montant : " . number_format($gross_amount, 0, ',', ' ') . " Ar",
|
||||
"Caissière",
|
||||
(int)$users['store_id'],
|
||||
"orders"
|
||||
);
|
||||
|
||||
// ✅ RÉCUPÉRER TOUS LES STORES
|
||||
$allStores = $Stores->getActiveStore();
|
||||
|
||||
$messageGlobal = "📋 Nouvelle commande créée : {$bill_no}<br>" .
|
||||
"Store : " . $this->returnStore($users['store_id']) . "<br>" .
|
||||
"Client : {$data['customer_name']}<br>" .
|
||||
"Montant : " . number_format($gross_amount, 0, ',', ' ') . " Ar<br>" .
|
||||
"Créée par : {$users['firstname']} {$users['lastname']}";
|
||||
|
||||
// ✅ NOTIFIER DIRECTION, DAF, SUPERADMIN DE TOUS LES STORES
|
||||
if (is_array($allStores) && count($allStores) > 0) {
|
||||
foreach ($allStores as $store) {
|
||||
$Notification->createNotification(
|
||||
$messageGlobal,
|
||||
"Direction",
|
||||
(int)$store['id'],
|
||||
'orders'
|
||||
);
|
||||
|
||||
$Notification->createNotification(
|
||||
$messageGlobal,
|
||||
"DAF",
|
||||
(int)$store['id'],
|
||||
'orders'
|
||||
);
|
||||
|
||||
$Notification->createNotification(
|
||||
$messageGlobal,
|
||||
"SuperAdmin",
|
||||
(int)$store['id'],
|
||||
'orders'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($users["group_name"] != "COMMERCIALE") {
|
||||
$this->checkProductisNull($posts, $users['store_id']);
|
||||
}
|
||||
return redirect()->to('orders/');
|
||||
|
||||
} else {
|
||||
// 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']}<br>" .
|
||||
"Store : " . $this->returnStore($current_order['store_id']) . "<br>" .
|
||||
"Client : {$current_order['customer_name']}<br>" .
|
||||
"Livrée par : {$users['firstname']} {$users['lastname']}";
|
||||
|
||||
// ✅ NOTIFIER DIRECTION, DAF, SUPERADMIN DE TOUS LES STORES
|
||||
if (is_array($allStores) && count($allStores) > 0) {
|
||||
foreach ($allStores as $store) {
|
||||
$Notification->createNotification(
|
||||
$messageGlobal,
|
||||
"Direction",
|
||||
(int)$store['id'],
|
||||
'orders'
|
||||
);
|
||||
|
||||
$Notification->createNotification(
|
||||
$messageGlobal,
|
||||
"DAF",
|
||||
(int)$store['id'],
|
||||
'orders'
|
||||
);
|
||||
|
||||
$Notification->createNotification(
|
||||
$messageGlobal,
|
||||
"SuperAdmin",
|
||||
(int)$store['id'],
|
||||
'orders'
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// 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}<br>" .
|
||||
"Store : " . $this->returnStore($user['store_id']) . "<br>" .
|
||||
"Client : {$customer_name}<br>" .
|
||||
"Validée par : {$user['firstname']} {$user['lastname']}";
|
||||
|
||||
// ✅ NOTIFIER DIRECTION, DAF, SUPERADMIN DE TOUS LES STORES
|
||||
if (is_array($allStores) && count($allStores) > 0) {
|
||||
foreach ($allStores as $store) {
|
||||
$Notification->createNotification(
|
||||
$messageGlobal,
|
||||
"Direction",
|
||||
(int)$store['id'],
|
||||
'orders'
|
||||
);
|
||||
|
||||
$Notification->createNotification(
|
||||
$messageGlobal,
|
||||
"DAF",
|
||||
(int)$store['id'],
|
||||
'orders'
|
||||
);
|
||||
|
||||
$Notification->createNotification(
|
||||
$messageGlobal,
|
||||
"SuperAdmin",
|
||||
(int)$store['id'],
|
||||
'orders'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -973,7 +1097,7 @@ public function update(int $id)
|
||||
$html = '';
|
||||
// Vérifier si l'utilisateur a payé
|
||||
if ($order_data['paid_status'] == 1) {
|
||||
$paid_status = "<span style='color: green; font-weight: bold;'>Validé</span>";
|
||||
$paid_status = "<span style='color: green; font-weight: bold;'>Payé</span>";
|
||||
} elseif ($order_data['paid_status'] == 2) {
|
||||
$paid_status = "<span style='color: orange; font-weight: bold;'>En Attente</span>";
|
||||
} else {
|
||||
@ -1460,7 +1584,7 @@ public function update(int $id)
|
||||
$company_info = $Company->getCompanyData(1);
|
||||
|
||||
$paid_status = $order_data['paid_status'] == 1
|
||||
? "<span style='color: green; font-weight: bold;'>Validé</span>"
|
||||
? "<span style='color: green; font-weight: bold;'>Payé</span>"
|
||||
: "<span style='color: red; font-weight: bold;'>Refusé</span>";
|
||||
|
||||
// STYLE COMMUN
|
||||
@ -2484,7 +2608,7 @@ public function print31(int $id)
|
||||
}
|
||||
|
||||
$paid_status = $order_data['paid_status'] === 1
|
||||
? "<span style='color: green; font-weight: bold;'>Validé</span>"
|
||||
? "<span style='color: green; font-weight: bold;'>Payé</span>"
|
||||
: "<span style='color: red; font-weight: bold;'>Refusé</span>";
|
||||
|
||||
// Calculs globaux
|
||||
@ -2773,4 +2897,4 @@ public function print31(int $id)
|
||||
echo '</body></html>';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -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é<br>" .
|
||||
"Montant: " . number_format($recouvrementData['recouvrement_montant'], 0, ',', ' ') . " Ar<br>" .
|
||||
"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 !<br><em>Notification envoyée à tous les Direction, DAF et SuperAdmin</em>";
|
||||
} 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éé<br>" .
|
||||
"Montant: " . number_format($amount, 0, ',', ' ') . " Ar<br>" .
|
||||
"De: " . $send_mode . " → Vers: " . $get_mode . "<br>" .
|
||||
"Store: " . $this->returnStoreName($users['store_id']) . "<br>" .
|
||||
"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<br>' .
|
||||
'Montant: ' . number_format($amount, 0, ',', ' ') . ' Ar<br>' .
|
||||
$send_mode . ' → ' . $get_mode . '<br>' .
|
||||
'<em>Notification envoyée à tous les Direction, DAF et SuperAdmin</em>';
|
||||
} 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é<br>" .
|
||||
"Nouveau montant: " . number_format($data['recouvrement_montant'], 0, ',', ' ') . " Ar<br>" .
|
||||
"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 !<br><em>Notification envoyée à tous les Direction, DAF et SuperAdmin</em>'
|
||||
]);
|
||||
} 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();
|
||||
|
||||
@ -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 .= '<button type="submit" class="btn btn-success" onclick="valideFunc(' . $value['id_demande'] . ')">';
|
||||
$buttons .= '<i class="fa fa-check-circle"></i>';
|
||||
$buttons .= '</button>';
|
||||
}
|
||||
|
||||
if (in_array('refusedRemise', $this->permission) && $value['demande_status'] == 'En attente') {
|
||||
|
||||
$buttons .= ' <button type="button" class="btn btn-danger" onclick="refuseFunc(' . $value['id_demande'] . ')">';
|
||||
$buttons .= '<i class="fa fa-times-circle"></i>';
|
||||
$buttons .= '</button>';
|
||||
}
|
||||
|
||||
// ✅ DIRECTION ET DAF VOIENT SEULEMENT (pas de boutons d'action)
|
||||
if (in_array($role, ['Direction', 'DAF'])) {
|
||||
$buttons = '<span class="label label-info">Consultation uniquement</span>';
|
||||
}
|
||||
|
||||
$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}<br>" .
|
||||
"Produit : {$remise_product}<br>" .
|
||||
"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 . "<br><em>Veuillez modifier la commande.</em>",
|
||||
"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.';
|
||||
|
||||
} 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
|
||||
if ($order_id) {
|
||||
$ordersModel->update($order_id, ['paid_status' => 2]); // 2 = En Attente
|
||||
// ✅ NOTIFIER DIRECTION ET DAF DE TOUS LES STORES (POUR INFORMATION)
|
||||
if (is_array($allStores) && count($allStores) > 0) {
|
||||
foreach ($allStores as $store) {
|
||||
$Notification->createNotification(
|
||||
$messageRefus . "<br><em>Pour information</em>",
|
||||
"Direction",
|
||||
(int)$store['id'],
|
||||
'remise/'
|
||||
);
|
||||
|
||||
$Notification->createNotification(
|
||||
$messageRefus . "<br><em>Pour information</em>",
|
||||
"DAF",
|
||||
(int)$store['id'],
|
||||
'remise/'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Notification à la Caissière pour qu'elle valide la commande
|
||||
$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 SUPERADMIN
|
||||
if ($order_id) {
|
||||
$ordersModel->update($order_id, ['paid_status' => 2]);
|
||||
}
|
||||
|
||||
$messageAcceptation = "✅ Demande de remise acceptée : {$bill_no}<br>" .
|
||||
"Produit : {$remise_product}<br>" .
|
||||
"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 . "<br><em>Commande prête à être traitée</em>",
|
||||
"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 . "<br><em>Pour information</em>",
|
||||
"Direction",
|
||||
(int)$store['id'],
|
||||
'remise/'
|
||||
);
|
||||
|
||||
$Notification->createNotification(
|
||||
$messageAcceptation . "<br><em>Pour information</em>",
|
||||
"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([
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
if ($users['group_name'] !== 'Caissière') {
|
||||
// Récupérer le décaissement
|
||||
$decaissement = $SortieCaisse->getSortieCaisseSingle($id_sortie);
|
||||
|
||||
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é.<br>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é.<br>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<br>" .
|
||||
"Motif: " . $decaissement['motif'] . "<br>" .
|
||||
"Caissière: " . $users['firstname'] . ' ' . $users['lastname'] . "<br>" .
|
||||
"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 <strong>PAYÉ</strong><br>' .
|
||||
'Direction et DAF de ' . $this->returnStoreName($users['store_id']) . ' ont été notifiés.<br>' .
|
||||
'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 <strong>PAYÉ</strong><br>' .
|
||||
'Tous les Direction, DAF et SuperAdmin ont été notifiés.<br>' .
|
||||
'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 . ")<br>" .
|
||||
"Store: " . $this->returnStoreName($user['store_id']) . "<br>" .
|
||||
"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<br>' .
|
||||
'Mode de paiement: ' . $mode_paiement . '<br>' .
|
||||
'Nouveau solde ' . $mode_paiement_label . ': ' . number_format($fonds_disponible - $montant_retire, 0, ',', ' ') . ' Ar<br>' .
|
||||
'<em>Notification envoyée à la Direction de ' . $this->returnStoreName($user['store_id']) . '</em>'
|
||||
'<em>Notification envoyée à tous les Direction, DAF et SuperAdmin</em>'
|
||||
]);
|
||||
|
||||
} 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<br>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) . "<br>Raison: " . $this->request->getPost('admin_raison');
|
||||
$message = "❌ Votre décaissement a été refusé par la Direction<br>Store: " . $this->returnStoreName($store_id) . "<br>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<br>Store: " . $this->returnStoreName($store_id);
|
||||
$Notification->createNotification($message, "Caissière", (int)$store_id, 'sortieCaisse');
|
||||
break;
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ class StatistiqueController extends AdminController
|
||||
// echo '</pre>';
|
||||
$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;
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -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')
|
||||
|
||||
@ -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('
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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');
|
||||
|
||||
|
||||
@ -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.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -44,13 +44,13 @@
|
||||
<?php
|
||||
$session = session();
|
||||
$users = $session->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']);
|
||||
?>
|
||||
|
||||
<!-- Bouton de vérification des avances expirées -->
|
||||
<?php if (isset($users['group_name']) && in_array($users['group_name'], ['Conseil', 'Direction', 'DAF'])): ?>
|
||||
<?php if (isset($users['group_name']) && in_array($users['group_name'], ['SuperAdmin', 'Direction', 'DAF'])): ?>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-12 text-right">
|
||||
<button
|
||||
@ -70,7 +70,7 @@ $isCaissier = isset($users['group_name']) && in_array($users['group_name'], ['Ca
|
||||
<thead>
|
||||
<?php $session = session();
|
||||
$users = $session->get('user');
|
||||
$isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']);
|
||||
$isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction','DAF']);
|
||||
$isCommerciale = in_array($users['group_name'], ['COMMERCIALE']);
|
||||
$isCaissier = in_array($users['group_name'], ['Caissière']);
|
||||
if ($isAdmin): ?>
|
||||
@ -90,7 +90,7 @@ $isCaissier = isset($users['group_name']) && in_array($users['group_name'], ['Ca
|
||||
<?php endif;?>
|
||||
<?php $session = session();
|
||||
$users = $session->get('user');
|
||||
$isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']);
|
||||
$isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction', 'DAF']);
|
||||
$isCommerciale = in_array($users['group_name'], ['COMMERCIALE']);
|
||||
$isCaissier = in_array($users['group_name'], ['Caissière']);
|
||||
if ($isCommerciale || $isCaissier): ?>
|
||||
|
||||
@ -325,7 +325,7 @@
|
||||
</div>
|
||||
<?php $session = session();
|
||||
$users = $session->get('user');
|
||||
if ($users["group_name"] === "Direction") :
|
||||
if ($users["group_name"] === "Direction" || $users["group_name"] === "SuperAdmin" || $users["group_name"] === "DAF" ) :
|
||||
|
||||
?>
|
||||
<div class="col-md-3">
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
<link rel="stylesheet" href="<?php echo base_url('assets/dist/css/AdminLTE.min.css') ?>">
|
||||
|
||||
<!-- Google Font -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
body {
|
||||
@ -22,6 +22,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
@ -39,10 +40,6 @@
|
||||
.login-image {
|
||||
flex: 1;
|
||||
background: url('https://lh3.googleusercontent.com/p/AF1QipN4iewRbD9iIfbsvyPTD2SGUkxyi952uG30pHD9=s1360-w1360-h1020') center/cover no-repeat;
|
||||
/* Alternative possible :
|
||||
https://images.unsplash.com/photo-1520975661595-6453be3f7070?auto=format&fit=crop&w=1000&q=80
|
||||
(casque de moto)
|
||||
*/
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@ -138,6 +135,96 @@
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
/* Animation de chargement */
|
||||
.loading-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(135deg, #007bff, #0056b3);
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
animation: overlayFadeIn 0.5s ease;
|
||||
}
|
||||
|
||||
.loading-overlay.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.loading-content {
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.loading-logo {
|
||||
font-size: 3.5em;
|
||||
font-weight: 700;
|
||||
color: #ffcc00;
|
||||
margin-bottom: 30px;
|
||||
animation: logoReveal 1.2s ease-in-out;
|
||||
letter-spacing: 3px;
|
||||
}
|
||||
|
||||
.motorcycle-icon {
|
||||
font-size: 4em;
|
||||
margin-bottom: 20px;
|
||||
animation: bikeRide 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 1.2em;
|
||||
margin-top: 20px;
|
||||
opacity: 0;
|
||||
animation: textFadeIn 0.8s ease 0.5s forwards;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 4px solid rgba(255, 255, 255, 0.3);
|
||||
border-top: 4px solid #ffcc00;
|
||||
border-radius: 50%;
|
||||
margin: 30px auto;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes overlayFadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes logoReveal {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.5) rotateY(-90deg);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.1) rotateY(0deg);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1) rotateY(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bikeRide {
|
||||
0%, 100% { transform: translateX(-20px) rotate(-2deg); }
|
||||
50% { transform: translateX(20px) rotate(2deg); }
|
||||
}
|
||||
|
||||
@keyframes textFadeIn {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.login-card {
|
||||
flex-direction: column;
|
||||
@ -149,11 +236,27 @@
|
||||
.login-form {
|
||||
padding: 25px;
|
||||
}
|
||||
.loading-logo {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
.motorcycle-icon {
|
||||
font-size: 3em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Overlay de chargement -->
|
||||
<div class="loading-overlay" id="loadingOverlay">
|
||||
<div class="loading-content">
|
||||
<div class="motorcycle-icon">🏍️</div>
|
||||
<div class="loading-logo">MOTORBIKE</div>
|
||||
<div class="loading-spinner"></div>
|
||||
<div class="loading-text">Démarrage en cours...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="login-card">
|
||||
|
||||
<!-- Image + message -->
|
||||
@ -174,7 +277,7 @@
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form action="<?= base_url('login') ?>" method="post">
|
||||
<form action="<?= base_url('login') ?>" method="post" id="loginForm">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-envelope"></i></span>
|
||||
<input type="email" class="form-control" name="email" placeholder="Email" required>
|
||||
@ -197,5 +300,25 @@
|
||||
|
||||
<script src="<?php echo base_url('assets/bower_components/jquery/dist/jquery.min.js') ?>"></script>
|
||||
<script src="<?php echo base_url('assets/bower_components/bootstrap/dist/js/bootstrap.min.js') ?>"></script>
|
||||
|
||||
<script>
|
||||
document.getElementById('loginForm').addEventListener('submit', function(e) {
|
||||
// Afficher l'animation de chargement
|
||||
document.getElementById('loadingOverlay').classList.add('active');
|
||||
|
||||
// Le formulaire se soumettra normalement
|
||||
// L'animation reste visible pendant le traitement côté serveur
|
||||
});
|
||||
|
||||
// Si vous voulez tester l'animation en local sans backend
|
||||
// décommentez cette fonction et appelez testAnimation()
|
||||
function testAnimation() {
|
||||
document.getElementById('loadingOverlay').classList.add('active');
|
||||
setTimeout(function() {
|
||||
alert('Animation terminée ! En production, vous seriez redirigé vers le dashboard.');
|
||||
document.getElementById('loadingOverlay').classList.remove('active');
|
||||
}, 2500);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@ -26,7 +26,7 @@
|
||||
<thead>
|
||||
<?php $session = session();
|
||||
$users = $session->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 @@
|
||||
<?php endif;?>
|
||||
<?php $session = session();
|
||||
$users = $session->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): ?>
|
||||
|
||||
@ -306,7 +306,7 @@
|
||||
<label for="paid_status" class="col-sm-5 control-label">Statut payant</label>
|
||||
<div class="col-sm-7">
|
||||
<select type="text" class="form-control" id="paid_status" name="paid_status">
|
||||
<option value="1">Validé</option>
|
||||
<option value="1">Payé</option>
|
||||
<option value="2">Refusé</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
<?php
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
if ($users['group_name'] === 'Conseil' || $users['group_name'] === "Direction") {
|
||||
if ($users['group_name'] === 'SuperAdmin' || $users['group_name'] === "Direction" || $users['group_name'] === "DAF" ) {
|
||||
?>
|
||||
<th>Facture n°</th>
|
||||
<th>Nom du client</th>
|
||||
@ -58,7 +58,7 @@
|
||||
<th>Date et Heure</th>
|
||||
<th>Prix demandé</th>
|
||||
<th>Prix de vente</th>
|
||||
<th>Validation</th>
|
||||
<th>Status</th>
|
||||
|
||||
<?php if (
|
||||
in_array('updateOrder', $user_permission)
|
||||
@ -79,7 +79,7 @@
|
||||
<th>Date et Heure</th>
|
||||
<th>Prix demandé</th>
|
||||
<th>Prix de vente</th>
|
||||
<th>Validation</th>
|
||||
<th>Status</th>
|
||||
<?php if (
|
||||
in_array('viewOrder', $user_permission)
|
||||
|| in_array('updateOrder', $user_permission)
|
||||
@ -135,6 +135,7 @@
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
<!-- Modal -->
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="viewOrderModal" tabindex="-1" role="dialog" aria-labelledby="viewOrderModalLabel">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
@ -181,20 +182,22 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tableau produits -->
|
||||
<h4>Produits</h4>
|
||||
<!-- Tableau produits avec toutes les infos sur une ligne -->
|
||||
<h4>Informations de la commande</h4>
|
||||
<table class="table table-bordered table-striped" id="view_products_table">
|
||||
<thead>
|
||||
<tr><th>Marque</th><th>Designation</th><th>Numéro de Série</th><th>Prix Unitaire</th></tr>
|
||||
<tr>
|
||||
<th>Marque</th>
|
||||
<th>Désignation</th>
|
||||
<th>Numéro de Série</th>
|
||||
<th>N° de Moteur</th>
|
||||
<th>Châssis</th>
|
||||
<th>N° Facture</th>
|
||||
<th>Statut</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<!-- Totaux -->
|
||||
<table class="table table-bordered table-striped" id="view_totals">
|
||||
<tr><th>Montant brut</th><th>Rabais</th><th>Statut</th></tr>
|
||||
<tr><td id="gross_amount"></td><td id="discount"></td><td id="paid_status"></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
@ -284,8 +287,10 @@
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Mettre à jour le statut dans la modal
|
||||
$('#paid_status').html('<span class="label label-info">Validé et Livré</span>');
|
||||
// Mettre à jour le statut dans toutes les lignes du tableau
|
||||
$('#view_products_table tbody tr').each(function() {
|
||||
$(this).find('td:last').html('<span class="label label-info">Payé et Livré</span>');
|
||||
});
|
||||
|
||||
// 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 = '<span class="label label-success">Payé</span>';
|
||||
<?php if ($users['group_name'] === 'SECURITE'): ?>
|
||||
$('#btn-mark-delivered').show();
|
||||
<?php endif; ?>
|
||||
} else if (d.paid_status == 2) {
|
||||
statutHtml = '<span class="label label-warning">En Attente</span>';
|
||||
$('#btn-mark-delivered').hide();
|
||||
} else if (d.paid_status == 3) {
|
||||
statutHtml = '<span class="label label-info">Payé et Livré</span>';
|
||||
$('#btn-mark-delivered').hide();
|
||||
} else {
|
||||
statutHtml = '<span class="label label-danger">Refusé</span>';
|
||||
$('#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(
|
||||
'<tr>' +
|
||||
'<td>' + (brandName || 'Aucune marque') + '</td>' +
|
||||
'<td>' + (product.name || '') + '</td>' +
|
||||
'<td>' + (product.sku || '') + '</td>' +
|
||||
'<td>' + parseInt(item.amount).toLocaleString('fr-MG', { minimumFractionDigits: 0, maximumFractionDigits: 0 }) + ' Ar</td>' +
|
||||
'<td>' + (product.numero_de_moteur || 'N/A') + '</td>' +
|
||||
'<td>' + (product.chasis || 'N/A') + '</td>' +
|
||||
'<td>' + (d.bill_no || 'N/A') + '</td>' +
|
||||
'<td>' + statutHtml + '</td>' +
|
||||
'</tr>'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// 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 = '<span class="label label-success">Validé</span>';
|
||||
// Afficher le bouton "Livré" pour la sécurité si statut = Validé
|
||||
<?php if ($users['group_name'] === 'SECURITE'): ?>
|
||||
$('#btn-mark-delivered').show();
|
||||
<?php endif; ?>
|
||||
} else if (d.paid_status == 2) {
|
||||
statutHtml = '<span class="label label-warning">En Attente</span>';
|
||||
$('#btn-mark-delivered').hide();
|
||||
} else if (d.paid_status == 3) {
|
||||
statutHtml = '<span class="label label-info">Validé et Livré</span>';
|
||||
$('#btn-mark-delivered').hide();
|
||||
} else {
|
||||
statutHtml = '<span class="label label-danger">Refusé</span>';
|
||||
$('#btn-mark-delivered').hide();
|
||||
}
|
||||
$('#paid_status').html(statutHtml);
|
||||
|
||||
// Afficher la modal
|
||||
$('#viewOrderModal').modal('show');
|
||||
});
|
||||
|
||||
@ -303,4 +303,146 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
</script> -->
|
||||
</script>
|
||||
<style>
|
||||
/* --- Style global --- */
|
||||
body {
|
||||
background: #f4f6f9;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
}
|
||||
|
||||
h1, h3 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
/* --- En-tête --- */
|
||||
.content-header {
|
||||
background: linear-gradient(135deg, #3498db, #2ecc71);
|
||||
color: white;
|
||||
padding: 25px;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 30px;
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.content-header h1 {
|
||||
margin: 0;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
background: transparent;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.breadcrumb li a {
|
||||
color: #ecf0f1;
|
||||
}
|
||||
|
||||
/* --- Formulaire --- */
|
||||
.form-inline {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.form-inline .form-control,
|
||||
.form-inline button,
|
||||
.form-inline a {
|
||||
border-radius: 8px !important;
|
||||
}
|
||||
|
||||
.btn-default {
|
||||
background-color: #2980b9;
|
||||
color: white;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-default:hover {
|
||||
background-color: #1f618d;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-success:hover {
|
||||
background-color: #27ae60;
|
||||
}
|
||||
|
||||
/* --- Boîtes de statistiques --- */
|
||||
.box {
|
||||
background: white;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 6px 15px rgba(0,0,0,0.08);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.box:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 12px 25px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.box-header {
|
||||
border-bottom: 2px solid #f1f1f1;
|
||||
padding: 15px 20px;
|
||||
background: #fafafa;
|
||||
border-radius: 15px 15px 0 0;
|
||||
}
|
||||
|
||||
.box-title {
|
||||
font-size: 18px;
|
||||
color: #34495e;
|
||||
}
|
||||
|
||||
.box-body {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* --- Table --- */
|
||||
table {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #3498db;
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
td {
|
||||
text-align: center;
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
/* --- Alertes --- */
|
||||
.alert {
|
||||
border-radius: 10px;
|
||||
animation: fadeIn 0.6s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {opacity: 0; transform: translateY(-10px);}
|
||||
to {opacity: 1; transform: translateY(0);}
|
||||
}
|
||||
|
||||
/* --- Charts --- */
|
||||
canvas {
|
||||
width: 100% !important;
|
||||
height: 300px !important;
|
||||
}
|
||||
|
||||
/* --- Responsive --- */
|
||||
@media (max-width: 768px) {
|
||||
.box {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -125,7 +125,7 @@ input[readonly], select[disabled], textarea[readonly] {
|
||||
<br>
|
||||
<?php $session = session();
|
||||
$users = $session->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): ?>
|
||||
<button id="validate_filtered" class="btn btn-primary w-100">A valider</button>
|
||||
@ -159,7 +159,7 @@ input[readonly], select[disabled], textarea[readonly] {
|
||||
<th>Action</th>
|
||||
<?php } ?>
|
||||
<?php
|
||||
} elseif ($users['group_name'] === 'Direction' || $users['group_name'] === 'DAF') {
|
||||
} elseif ($users['group_name'] === 'Direction' || $users['group_name'] === 'DAF' || $users['group_name'] === 'SuperAdmin') {
|
||||
?>
|
||||
<th>#</th>
|
||||
<th>Montant</th>
|
||||
@ -296,7 +296,7 @@ input[readonly], select[disabled], textarea[readonly] {
|
||||
<?php
|
||||
$session = session();
|
||||
$users = $session->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] {
|
||||
<td><input type="date" class="form-control" name="date_visa_direction"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Conseil d'Administration</td>
|
||||
<td><input type="text" class="form-control" name="visa_conseil" placeholder="Nom et signature"></td>
|
||||
<td><input type="date" class="form-control" name="date_visa_conseil"></td>
|
||||
<td>SuperAdmin</td>
|
||||
<td><input type="text" class="form-control" name="visa_superAdmin" placeholder="Nom et signature"></td>
|
||||
<td><input type="date" class="form-control" name="date_superAdmin"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -605,7 +605,7 @@ input[readonly], select[disabled], textarea[readonly] {
|
||||
<?php
|
||||
$session = session();
|
||||
$users = $session->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 "<option value=''>Veuillez sélectionner une raison</option>\n";
|
||||
@ -1038,7 +1038,7 @@ $(document).ready(function() {
|
||||
<?php
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
$isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "Conseil";
|
||||
$isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "SuperAdmin" || $users['group_name'] == "DAF";
|
||||
?>
|
||||
|
||||
<?php if($isAdmin): ?>
|
||||
|
||||
@ -1,61 +1,190 @@
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
Tableau de bord
|
||||
<small>Statistiques des utilisateurs</small>
|
||||
</h1>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="#"><i class="fa fa-dashboard"></i> Accueil</a></li>
|
||||
<li class="active"><a href="../">Tableau de bord</a></li>
|
||||
</ol>
|
||||
</section>
|
||||
<style>
|
||||
/* --- Style général --- */
|
||||
body {
|
||||
background: #f4f6f9;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
}
|
||||
|
||||
<section class="content">
|
||||
<div class="box" style="padding-top: 5px; padding-left: 5px; padding-right: 5px">
|
||||
<?php if ($is_admin == true): ?>
|
||||
h1 {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
<div class="row" id="dataToMap"></div>
|
||||
<!-- /.row -->
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$("#dashboardMainMenu").addClass('active');
|
||||
});
|
||||
small {
|
||||
color: #7f8c8d;
|
||||
}
|
||||
|
||||
// Convert PHP array to JavaScript array
|
||||
/* --- En-tête --- */
|
||||
.content-header {
|
||||
background: linear-gradient(135deg, #3498db, #2ecc71);
|
||||
color: white;
|
||||
padding: 25px;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 25px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
const allUsers = <?php echo json_encode($allUsers); ?>;
|
||||
console.log(allUsers);
|
||||
// Function to render users
|
||||
function renderUsers(users) {
|
||||
const container = document.getElementById('dataToMap');
|
||||
container.innerHTML = ''; // Clear existing content
|
||||
.breadcrumb {
|
||||
background: transparent;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
users.forEach(user => {
|
||||
const userHtml = `
|
||||
<div class="col-lg-3 col-xs-6">
|
||||
<div class="small-box" style="background-color: rgba(54, 162, 235, 0.5);">
|
||||
<div class="inner">
|
||||
<h3>${user.username}</h3>
|
||||
<p>Produits vendues <b style="font-size: 20px;">${user.totalVente}</b></p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-stats-bars"></i>
|
||||
</div>
|
||||
<a href="<?php echo base_url('statistic/') ?>${user.id}" class="small-box-footer">
|
||||
Plus d'information <i class="fa fa-arrow-circle-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
container.innerHTML += userHtml; // Append the user HTML to the container
|
||||
});
|
||||
.breadcrumb a {
|
||||
color: #ecf0f1;
|
||||
}
|
||||
|
||||
/* --- Boîte principale --- */
|
||||
.box {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 6px 15px rgba(0,0,0,0.08);
|
||||
padding: 20px;
|
||||
animation: fadeIn 0.6s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {opacity: 0; transform: translateY(15px);}
|
||||
to {opacity: 1; transform: translateY(0);}
|
||||
}
|
||||
|
||||
/* --- Cartes utilisateurs --- */
|
||||
.small-box {
|
||||
position: relative;
|
||||
background: linear-gradient(135deg, #3498db, #2980b9);
|
||||
color: white;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 8px 18px rgba(0,0,0,0.15);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.small-box:hover {
|
||||
transform: translateY(-6px);
|
||||
box-shadow: 0 12px 24px rgba(0,0,0,0.25);
|
||||
}
|
||||
|
||||
.small-box .inner {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.small-box h3 {
|
||||
font-size: 22px;
|
||||
margin-bottom: 10px;
|
||||
font-weight: 600;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.small-box p {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.small-box b {
|
||||
color: #f1c40f;
|
||||
}
|
||||
|
||||
.small-box .icon {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 15px;
|
||||
font-size: 60px;
|
||||
opacity: 0.15;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.small-box:hover .icon {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.small-box-footer {
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
color: #ecf0f1;
|
||||
background: rgba(0,0,0,0.15);
|
||||
border-radius: 0 0 15px 15px;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
.small-box-footer:hover {
|
||||
background: rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
/* --- Couleurs aléatoires dynamiques pour chaque carte --- */
|
||||
.small-box:nth-child(4n+1) {
|
||||
background: linear-gradient(135deg, #3498db, #2980b9);
|
||||
}
|
||||
.small-box:nth-child(4n+2) {
|
||||
background: linear-gradient(135deg, #2ecc71, #27ae60);
|
||||
}
|
||||
.small-box:nth-child(4n+3) {
|
||||
background: linear-gradient(135deg, #e67e22, #d35400);
|
||||
}
|
||||
.small-box:nth-child(4n+4) {
|
||||
background: linear-gradient(135deg, #9b59b6, #8e44ad);
|
||||
}
|
||||
|
||||
/* --- Responsive --- */
|
||||
@media (max-width: 768px) {
|
||||
.small-box {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
// Render all users initially
|
||||
renderUsers(allUsers);
|
||||
</script>
|
||||
<div class="content-wrapper">
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
Tableau de bord
|
||||
<small>Statistiques des utilisateurs</small>
|
||||
</h1>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="#"><i class="fa fa-dashboard"></i> Accueil</a></li>
|
||||
<li class="active"><a href="../">Tableau de bord</a></li>
|
||||
</ol>
|
||||
</section>
|
||||
|
||||
<section class="content">
|
||||
<div class="box">
|
||||
<?php if ($is_admin == true): ?>
|
||||
<div class="row" id="dataToMap"></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$("#dashboardMainMenu").addClass('active');
|
||||
});
|
||||
|
||||
const allUsers = <?php echo json_encode($allUsers); ?>;
|
||||
|
||||
function renderUsers(users) {
|
||||
const container = document.getElementById('dataToMap');
|
||||
container.innerHTML = '';
|
||||
|
||||
users.forEach(user => {
|
||||
const userHtml = `
|
||||
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
|
||||
<div class="small-box">
|
||||
<div class="inner">
|
||||
<h3>${user.username}</h3>
|
||||
<p>Produits vendus : <b>${user.totalVente}</b></p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-stats-bars"></i>
|
||||
</div>
|
||||
<a href="<?php echo base_url('statistic/') ?>${user.id}" class="small-box-footer">
|
||||
Plus d'informations <i class="fa fa-arrow-circle-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>`;
|
||||
container.innerHTML += userHtml;
|
||||
});
|
||||
}
|
||||
|
||||
renderUsers(allUsers);
|
||||
</script>
|
||||
|
||||
@ -908,5 +908,6 @@
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
Loading…
Reference in New Issue
Block a user