13102025
This commit is contained in:
parent
e9ed02267c
commit
1c92093b90
@ -184,6 +184,7 @@ $routes->group('', ['filter' => 'auth'], function ($routes) {
|
||||
$routes->group('/orders', function ($routes) {
|
||||
$routes->get('/', [OrderController::class, 'index']);
|
||||
$routes->get('fetchOrdersData', [OrderController::class, 'fetchOrdersData']);
|
||||
$routes->get('editAsNew/(:num)', 'OrderController::editAsNew/$1');
|
||||
$routes->get('create', [OrderController::class, 'create']);
|
||||
$routes->post('create', [OrderController::class, 'create']);
|
||||
$routes->post('getProductValueById', [OrderController::class, 'getProductValueById']);
|
||||
@ -194,11 +195,12 @@ $routes->group('', ['filter' => 'auth'], function ($routes) {
|
||||
$routes->get('printDivBL/(:num)', [OrderController::class, 'print7']);
|
||||
$routes->get('printDivBLF/(:num)', [OrderController::class, 'print31']);
|
||||
$routes->post('remove', [OrderController::class, 'remove']);
|
||||
$routes->post('markAsDelivered', [OrderController::class, 'markAsDelivered']); // ← AJOUTEZ CETTE LIGNE ICI
|
||||
$routes->get('lookOrder/(:num)', [OrderController::class, 'lookOrder']);
|
||||
$routes->get('createFromEspace/(:num)', [OrderController::class, 'createById']);
|
||||
$routes->get('resrevation', [ReservationController::class, 'index']);
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* route for the reports
|
||||
*/
|
||||
@ -261,19 +263,25 @@ $routes->group('', ['filter' => 'auth'], function ($routes) {
|
||||
$routes->post('markAsRead/(:num)', [NotificationController::class, 'markAsRead']);
|
||||
});
|
||||
// routes for sortie caisse
|
||||
$routes->group('/sortieCaisse', function ($routes) {
|
||||
$routes->get('/', [SortieCaisseController::class, 'index']);
|
||||
$routes->get('fetchSortieCaisseData', [SortieCaisseController::class, 'fetchSortieCaisseData']);
|
||||
$routes->get('fetchSortieCaisseData1', [SortieCaisseController::class, 'fetchSortieCaisseData1']);
|
||||
$routes->post('fetchSortieCaisseSingle/(:num)', [SortieCaisseController::class, 'fetchSortieCaisseSingle']);
|
||||
$routes->post('createSortieCaisse', [SortieCaisseController::class, 'createSortieCaisse']);
|
||||
// $routes->post('delete', [RecouvrementController::class, 'removeRecouvrement']);
|
||||
$routes->post('updateSortieCaisse/(:num)', [SortieCaisseController::class, 'updateSortieCaisse']);
|
||||
$routes->post('validateSortieCaisse/(:num)', [SortieCaisseController::class, 'validateSortieCaisse']);
|
||||
});
|
||||
$routes->group('/sortieCaisse', function ($routes) {
|
||||
$routes->get('/', [SortieCaisseController::class, 'index']);
|
||||
$routes->get('fetchSortieCaisseData', [SortieCaisseController::class, 'fetchSortieCaisseData']);
|
||||
$routes->get('fetchSortieCaisseData1', [SortieCaisseController::class, 'fetchSortieCaisseData1']);
|
||||
$routes->post('fetchSortieCaisseSingle/(:num)', [SortieCaisseController::class, 'fetchSortieCaisseSingle']);
|
||||
$routes->post('createSortieCaisse', [SortieCaisseController::class, 'createSortieCaisse']);
|
||||
$routes->post('markAsPaid/(:num)', 'SortieCaisseController::markAsPaid/$1');
|
||||
$routes->post('updateSortieCaisse/(:num)', [SortieCaisseController::class, 'updateSortieCaisse']);
|
||||
$routes->post('validateSortieCaisse/(:num)', [SortieCaisseController::class, 'validateSortieCaisse']);
|
||||
|
||||
// ✅ Routes d'exportation
|
||||
$routes->get('exportExcel', [SortieCaisseController::class, 'exportExcel']);
|
||||
$routes->get('exportCsv', [SortieCaisseController::class, 'exportCsv']);
|
||||
$routes->get('exportWithFilters', [SortieCaisseController::class, 'exportWithFilters']);
|
||||
});
|
||||
|
||||
// remise
|
||||
$routes->group('/remise', function ($routes) {
|
||||
$routes->get('', [RemiseController::class, 'index']);
|
||||
$routes->get('/', [RemiseController::class, 'index']);
|
||||
$routes->get('fetchRemiseData', [RemiseController::class, 'fetchRemiseData']);
|
||||
// $routes->post('delete', [RecouvrementController::class, 'removeRecouvrement']);
|
||||
|
||||
@ -63,19 +63,25 @@ class AvanceController extends AdminController
|
||||
. '<i class="fa fa-eye"></i></a>';
|
||||
}
|
||||
|
||||
|
||||
return $buttons;
|
||||
}
|
||||
|
||||
private function buildDataRow($value, $product, $isAdmin, $isCommerciale, $isCaissier, $buttons)
|
||||
{
|
||||
$date_time = date('d-m-Y h:i a', strtotime($value['avance_date']));
|
||||
|
||||
// ✅ Afficher product_name si disponible, sinon récupérer depuis la BDD
|
||||
$productName = !empty($value['product_name'])
|
||||
? $value['product_name']
|
||||
: $product->getProductNameById($value['product_id']);
|
||||
|
||||
if ($isAdmin) {
|
||||
return [
|
||||
$value['customer_name'],
|
||||
$value['customer_phone'],
|
||||
$value['customer_address'],
|
||||
$product->getProductNameById($value['product_id']),
|
||||
$productName, // ✅ Utiliser la variable
|
||||
number_format((int)$value['gross_amount'], 0, ',', ' '),
|
||||
number_format((int)$value['avance_amount'], 0, ',', ' '),
|
||||
number_format((int)$value['amount_due'], 0, ',', ' '),
|
||||
@ -85,7 +91,7 @@ class AvanceController extends AdminController
|
||||
} elseif ($isCommerciale || $isCaissier) {
|
||||
return [
|
||||
$value['avance_id'],
|
||||
$product->getProductNameById($value['product_id']),
|
||||
$productName, // ✅ Utiliser la variable
|
||||
number_format((int)$value['avance_amount'], 0, ',', ' '),
|
||||
number_format((int)$value['amount_due'], 0, ',', ' '),
|
||||
$date_time,
|
||||
@ -354,14 +360,14 @@ class AvanceController extends AdminController
|
||||
public function createAvance()
|
||||
{
|
||||
$this->verifyRole('createAvance');
|
||||
|
||||
|
||||
if ($this->request->getMethod() !== 'post') {
|
||||
return $this->response->setJSON([
|
||||
'success' => false,
|
||||
'messages' => 'Méthode non autorisée'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
@ -369,37 +375,51 @@ class AvanceController extends AdminController
|
||||
$Avance = new Avance();
|
||||
$Products = new Products();
|
||||
$Notification = new NotificationController();
|
||||
|
||||
|
||||
// ✅ Récupérer le type AVANT la validation
|
||||
$type_avance = $this->request->getPost('type_avance');
|
||||
|
||||
// ✅ Validation conditionnelle
|
||||
$validation = \Config\Services::validation();
|
||||
$validation->setRules([
|
||||
|
||||
$baseRules = [
|
||||
'customer_name_avance' => 'required|min_length[2]',
|
||||
'customer_phone_avance' => 'required',
|
||||
'customer_address_avance' => 'required',
|
||||
'customer_cin_avance' => 'required',
|
||||
'id_product' => 'required|numeric',
|
||||
'gross_amount' => 'required|numeric|greater_than[0]',
|
||||
'avance_amount' => 'required|numeric|greater_than[0]',
|
||||
'type_avance' => 'required|in_list[terre,mere]'
|
||||
]);
|
||||
|
||||
'type_avance' => 'required|in_list[terre,mere]',
|
||||
'type_payment' => 'required'
|
||||
];
|
||||
|
||||
if ($type_avance === 'mere') {
|
||||
$baseRules['product_name_text'] = 'required|min_length[2]';
|
||||
} else {
|
||||
$baseRules['id_product'] = 'required|numeric';
|
||||
}
|
||||
|
||||
$validation->setRules($baseRules);
|
||||
|
||||
if (!$validation->withRequest($this->request)->run()) {
|
||||
return $this->response->setJSON([
|
||||
'success' => false,
|
||||
'messages' => 'Données invalides: ' . implode(', ', $validation->getErrors())
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$avance_date = date('Y-m-d H:i:s');
|
||||
|
||||
// Calcul automatique de la deadline selon le type d'avance
|
||||
$type_avance = $this->request->getPost('type_avance');
|
||||
|
||||
// Calcul de la deadline
|
||||
if ($type_avance === 'terre') {
|
||||
$deadline = date('Y-m-d', strtotime($avance_date . ' +15 days'));
|
||||
} elseif ($type_avance === 'mere') {
|
||||
$deadline = date('Y-m-d', strtotime($avance_date . ' +2 months'));
|
||||
} else {
|
||||
$deadline = null; // fallback si jamais
|
||||
$deadline = null;
|
||||
}
|
||||
|
||||
|
||||
// Préparer les données communes
|
||||
$data = [
|
||||
'type_avance' => $type_avance,
|
||||
'type_payment' => $this->request->getPost('type_payment'),
|
||||
@ -411,16 +431,30 @@ class AvanceController extends AdminController
|
||||
'deadline' => $deadline,
|
||||
'user_id' => $users['id'],
|
||||
'store_id' => $users['store_id'],
|
||||
'product_id' => (int)$this->request->getPost('id_product'),
|
||||
'gross_amount' => (float)$this->request->getPost('gross_amount'),
|
||||
'avance_amount' => (float)$this->request->getPost('avance_amount'),
|
||||
'amount_due' => (float)$this->request->getPost('amount_due'),
|
||||
'amount_due' => (float)$this->request->getPost('gross_amount') - (float)$this->request->getPost('avance_amount'),
|
||||
'is_order' => 0,
|
||||
'active' => 1,
|
||||
];
|
||||
|
||||
|
||||
// ✅ Ajouter le produit selon le type
|
||||
if ($type_avance === 'mere') {
|
||||
$data['product_name'] = $this->request->getPost('product_name_text');
|
||||
// $data['product_id'] = null;
|
||||
$data['commentaire'] = $this->request->getPost('commentaire');
|
||||
} else {
|
||||
$data['product_id'] = (int)$this->request->getPost('id_product');
|
||||
$data['product_name'] = null;
|
||||
$data['commentaire'] = null;
|
||||
}
|
||||
|
||||
if ($avance_id = $Avance->createAvance($data)) {
|
||||
$Products->update($data['product_id'], ['product_sold' => 1]);
|
||||
|
||||
// ✅ Marquer le produit comme vendu UNIQUEMENT pour "terre"
|
||||
if ($type_avance === 'terre' && !empty($data['product_id'])) {
|
||||
$Products->update($data['product_id'], ['product_sold' => 1]);
|
||||
}
|
||||
|
||||
$Notification->createNotification(
|
||||
'Une nouvelle avance a été créée',
|
||||
@ -444,10 +478,11 @@ class AvanceController extends AdminController
|
||||
log_message('error', "Erreur création avance: " . $e->getMessage());
|
||||
return $this->response->setJSON([
|
||||
'success' => false,
|
||||
'messages' => 'Une erreur interne est survenue'
|
||||
'messages' => 'Une erreur interne est survenue: ' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateAvance()
|
||||
{
|
||||
$this->verifyRole('updateAvance');
|
||||
@ -467,18 +502,31 @@ class AvanceController extends AdminController
|
||||
$Products = new Products();
|
||||
$Notification = new NotificationController();
|
||||
|
||||
// Validation des données (avec les vrais noms des champs du formulaire)
|
||||
// ✅ Récupérer le type AVANT la validation
|
||||
$type_avance = $this->request->getPost('type_avance_edit');
|
||||
|
||||
// ✅ Validation conditionnelle selon le type
|
||||
$validation = \Config\Services::validation();
|
||||
$validation->setRules([
|
||||
|
||||
$baseRules = [
|
||||
'id' => 'required|numeric',
|
||||
'customer_name_avance_edit' => 'required|min_length[2]',
|
||||
'customer_phone_avance_edit' => 'required',
|
||||
'customer_address_avance_edit' => 'required',
|
||||
'customer_cin_avance_edit' => 'required',
|
||||
'id_product_edit' => 'required|numeric',
|
||||
'gross_amount_edit' => 'required|numeric|greater_than[0]',
|
||||
'avance_amount_edit' => 'required|numeric|greater_than[0]',
|
||||
'type_avance_edit' => 'required|in_list[terre,mere]'
|
||||
]);
|
||||
'type_avance_edit' => 'required|in_list[terre,mere]',
|
||||
'type_payment_edit' => 'required'
|
||||
];
|
||||
|
||||
if ($type_avance === 'mere') {
|
||||
$baseRules['product_name_text_edit'] = 'required|min_length[2]';
|
||||
} else {
|
||||
$baseRules['id_product_edit'] = 'required|numeric';
|
||||
}
|
||||
|
||||
$validation->setRules($baseRules);
|
||||
|
||||
if (!$validation->withRequest($this->request)->run()) {
|
||||
return $this->response->setJSON([
|
||||
@ -487,7 +535,7 @@ class AvanceController extends AdminController
|
||||
]);
|
||||
}
|
||||
|
||||
$avance_id = $this->request->getPost('id'); // Changement ici
|
||||
$avance_id = $this->request->getPost('id');
|
||||
|
||||
// Vérifier si l'avance existe
|
||||
$existingAvance = $Avance->fetchSingleAvance($avance_id);
|
||||
@ -510,10 +558,8 @@ class AvanceController extends AdminController
|
||||
}
|
||||
|
||||
// Recalculer la deadline si le type d'avance a changé
|
||||
$type_avance = $this->request->getPost('type_avance_edit'); // Changement ici
|
||||
$current_deadline = $existingAvance['deadline'];
|
||||
|
||||
// Si le type a changé, recalculer la deadline
|
||||
if ($type_avance !== $existingAvance['type_avance']) {
|
||||
if ($type_avance === 'terre') {
|
||||
$current_deadline = date('Y-m-d', strtotime($existingAvance['avance_date'] . ' +15 days'));
|
||||
@ -523,34 +569,54 @@ class AvanceController extends AdminController
|
||||
}
|
||||
|
||||
$old_product_id = $existingAvance['product_id'];
|
||||
$new_product_id = (int)$this->request->getPost('id_product_edit'); // Changement ici
|
||||
|
||||
// Préparer les données communes
|
||||
$data = [
|
||||
'type_avance' => $type_avance,
|
||||
'type_payment' => $this->request->getPost('type_payment_edit'), // Changement ici
|
||||
'customer_name' => $this->request->getPost('customer_name_avance_edit'), // Changement ici
|
||||
'customer_address' => $this->request->getPost('customer_address_avance_edit'), // Changement ici
|
||||
'customer_phone' => $this->request->getPost('customer_phone_avance_edit'), // Changement ici
|
||||
'customer_cin' => $this->request->getPost('customer_cin_avance_edit'), // Changement ici
|
||||
'type_payment' => $this->request->getPost('type_payment_edit'),
|
||||
'customer_name' => $this->request->getPost('customer_name_avance_edit'),
|
||||
'customer_address' => $this->request->getPost('customer_address_avance_edit'),
|
||||
'customer_phone' => $this->request->getPost('customer_phone_avance_edit'),
|
||||
'customer_cin' => $this->request->getPost('customer_cin_avance_edit'),
|
||||
'deadline' => $current_deadline,
|
||||
'product_id' => $new_product_id,
|
||||
'gross_amount' => (float)$this->request->getPost('gross_amount_edit'), // Changement ici
|
||||
'avance_amount' => (float)$this->request->getPost('avance_amount_edit'), // Changement ici
|
||||
'amount_due' => (float)$this->request->getPost('amount_due_edit'), // Changement ici
|
||||
'gross_amount' => (float)$this->request->getPost('gross_amount_edit'),
|
||||
'avance_amount' => (float)$this->request->getPost('avance_amount_edit'),
|
||||
'amount_due' => (float)$this->request->getPost('amount_due_edit'),
|
||||
];
|
||||
|
||||
// ✅ Gérer le produit selon le type
|
||||
if ($type_avance === 'mere') {
|
||||
$data['product_name'] = $this->request->getPost('product_name_text_edit');
|
||||
$data['product_id'] = null; // ⚠️ Sera NULL si la colonne l'accepte
|
||||
$data['commentaire'] = $this->request->getPost('commentaire_edit');
|
||||
$new_product_id = null;
|
||||
} else {
|
||||
$new_product_id = (int)$this->request->getPost('id_product_edit');
|
||||
$data['product_id'] = $new_product_id;
|
||||
$data['product_name'] = null;
|
||||
$data['commentaire'] = null;
|
||||
}
|
||||
|
||||
// Mettre à jour l'avance
|
||||
if ($Avance->updateAvance($avance_id, $data)) {
|
||||
|
||||
// Gérer le changement de produit si nécessaire
|
||||
if ($old_product_id !== $new_product_id) {
|
||||
// Libérer l'ancien produit
|
||||
$Products->update($old_product_id, ['product_sold' => 0]);
|
||||
// Marquer le nouveau produit comme vendu
|
||||
$Products->update($new_product_id, ['product_sold' => 1]);
|
||||
// ✅ Gérer le changement de produit UNIQUEMENT pour "terre"
|
||||
if ($type_avance === 'terre') {
|
||||
if ($old_product_id && $old_product_id !== $new_product_id) {
|
||||
// Libérer l'ancien produit
|
||||
$Products->update($old_product_id, ['product_sold' => 0]);
|
||||
}
|
||||
if ($new_product_id) {
|
||||
// Marquer le nouveau produit comme vendu
|
||||
$Products->update($new_product_id, ['product_sold' => 1]);
|
||||
}
|
||||
} else {
|
||||
// Si on passe de "terre" à "mere", libérer l'ancien produit
|
||||
if ($old_product_id && $existingAvance['type_avance'] === 'terre') {
|
||||
$Products->update($old_product_id, ['product_sold' => 0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Créer une notification
|
||||
$Notification->createNotification(
|
||||
'Une avance a été modifiée',
|
||||
"Conseil",
|
||||
@ -574,11 +640,12 @@ class AvanceController extends AdminController
|
||||
log_message('error', "Erreur modification avance: " . $e->getMessage());
|
||||
return $this->response->setJSON([
|
||||
'success' => false,
|
||||
'messages' => 'Une erreur interne est survenue'
|
||||
'messages' => 'Une erreur interne est survenue: ' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function removeAvance()
|
||||
{
|
||||
$this->verifyRole('deleteAvance');
|
||||
|
||||
@ -10,6 +10,7 @@ use App\Models\Stores;
|
||||
use App\Models\Users;
|
||||
use App\Models\Recouvrement;
|
||||
use App\Models\SortieCaisse;
|
||||
|
||||
class Dashboard extends AdminController
|
||||
{
|
||||
|
||||
@ -32,71 +33,78 @@ class Dashboard extends AdminController
|
||||
$totalRecouvrement = $Recouvrement->getTotalRecouvrements();
|
||||
$sortieCaisse = new SortieCaisse();
|
||||
$total_sortie_caisse = $sortieCaisse->getTotalSortieCaisse();
|
||||
$total_sortie_caisse1= $total_sortie_caisse->mr;
|
||||
|
||||
// Recouvrements
|
||||
$total_recouvrement_me = $totalRecouvrement->me;
|
||||
$total_recouvrement_bm = $totalRecouvrement->bm;
|
||||
$total_recouvrement_be = $totalRecouvrement->be;
|
||||
$total_recouvrement_mb = $totalRecouvrement->mb;
|
||||
// === EXTRACTION DES SORTIES PAR MODE DE PAIEMENT ===
|
||||
$total_sortie_espece = isset($total_sortie_caisse->total_espece) ? (float) $total_sortie_caisse->total_espece : 0;
|
||||
$total_sortie_mvola = isset($total_sortie_caisse->total_mvola) ? (float) $total_sortie_caisse->total_mvola : 0;
|
||||
$total_sortie_virement = isset($total_sortie_caisse->total_virement) ? (float) $total_sortie_caisse->total_virement : 0;
|
||||
|
||||
// === TOTAUX RECOUVREMENT ===
|
||||
$me = isset($totalRecouvrement->me) ? (float) $totalRecouvrement->me : 0;
|
||||
$bm = isset($totalRecouvrement->bm) ? (float) $totalRecouvrement->bm : 0;
|
||||
$be = isset($totalRecouvrement->be) ? (float) $totalRecouvrement->be : 0;
|
||||
$mb = isset($totalRecouvrement->mb) ? (float) $totalRecouvrement->mb : 0;
|
||||
|
||||
// Avances
|
||||
$Avance = new Avance();
|
||||
$totalAvance = $Avance->getTotalAvance();
|
||||
$paymentDataAvance = $Avance->getPaymentModesAvance();
|
||||
|
||||
// Initialisation des totaux Orders (en utilisant les bonnes propriétés)
|
||||
$total_orders = isset($paymentData->total) ? $paymentData->total : 0;
|
||||
$total_mvola1_orders = isset($paymentData->total_mvola1) ? $paymentData->total_mvola1 : 0;
|
||||
$total_mvola2_orders = isset($paymentData->total_mvola2) ? $paymentData->total_mvola2 : 0;
|
||||
$total_espece1_orders = isset($paymentData->total_espece1) ? $paymentData->total_espece1 : 0;
|
||||
$total_espece2_orders = isset($paymentData->total_espece2) ? $paymentData->total_espece2 : 0;
|
||||
$total_virement_bancaire1_orders = isset($paymentData->total_virement_bancaire1) ? $paymentData->total_virement_bancaire1 : 0;
|
||||
$total_virement_bancaire2_orders = isset($paymentData->total_virement_bancaire2) ? $paymentData->total_virement_bancaire2 : 0;
|
||||
// === TOTAUX PAIEMENTS ORDERS ===
|
||||
$total_orders = isset($paymentData->total) ? (float) $paymentData->total : 0;
|
||||
$mv1_orders = isset($paymentData->total_mvola1) ? (float) $paymentData->total_mvola1 : 0;
|
||||
$mv2_orders = isset($paymentData->total_mvola2) ? (float) $paymentData->total_mvola2 : 0;
|
||||
$es1_orders = isset($paymentData->total_espece1) ? (float) $paymentData->total_espece1 : 0;
|
||||
$es2_orders = isset($paymentData->total_espece2) ? (float) $paymentData->total_espece2 : 0;
|
||||
$vb1_orders = isset($paymentData->total_virement_bancaire1) ? (float) $paymentData->total_virement_bancaire1 : 0;
|
||||
$vb2_orders = isset($paymentData->total_virement_bancaire2) ? (float) $paymentData->total_virement_bancaire2 : 0;
|
||||
|
||||
// Initialisation des totaux Avances (utiliser les bonnes propriétés de getPaymentModesAvance)
|
||||
$total_avances = isset($paymentDataAvance->total) ? $paymentDataAvance->total : 0;
|
||||
$total_mvola_avances = isset($paymentDataAvance->total_mvola) ? $paymentDataAvance->total_mvola : 0;
|
||||
$total_espece_avances = isset($paymentDataAvance->total_espece) ? $paymentDataAvance->total_espece : 0;
|
||||
$total_virement_bancaire_avances = isset($paymentDataAvance->total_virement_bancaire) ? $paymentDataAvance->total_virement_bancaire : 0;
|
||||
// === TOTAUX PAIEMENTS AVANCES ===
|
||||
$total_avances = isset($paymentDataAvance->total) ? (float) $paymentDataAvance->total : 0;
|
||||
$mv_avances = isset($paymentDataAvance->total_mvola) ? (float) $paymentDataAvance->total_mvola : 0;
|
||||
$es_avances = isset($paymentDataAvance->total_espece) ? (float) $paymentDataAvance->total_espece : 0;
|
||||
$vb_avances = isset($paymentDataAvance->total_virement_bancaire) ? (float) $paymentDataAvance->total_virement_bancaire : 0;
|
||||
|
||||
// Addition Orders + Avances
|
||||
// === COMBINAISON ORDERS + AVANCES ===
|
||||
$total_mvola = $mv1_orders + $mv2_orders + $mv_avances;
|
||||
$total_espece = $es1_orders + $es2_orders + $es_avances;
|
||||
$total_vb = $vb1_orders + $vb2_orders + $vb_avances;
|
||||
$total = $total_orders + $total_avances;
|
||||
|
||||
// Combiner les totaux par type de paiement
|
||||
$total_mvola1 = $total_mvola1_orders;
|
||||
$total_mvola2 = $total_mvola2_orders;
|
||||
$total_espece1 = $total_espece1_orders;
|
||||
$total_espece2 = $total_espece2_orders;
|
||||
$total_virement_bancaire1 = $total_virement_bancaire1_orders;
|
||||
$total_virement_bancaire2 = $total_virement_bancaire2_orders;
|
||||
// === AJUSTEMENTS AVEC RECOUVREMENTS ET SORTIES (PAR MODE DE PAIEMENT) ===
|
||||
$total_mvola_final = $total_mvola -
|
||||
$me -
|
||||
$mb +
|
||||
$bm -
|
||||
$total_sortie_mvola;
|
||||
|
||||
// Totaux combinés Orders
|
||||
$total_mvola_orders_combined = $total_mvola1 + $total_mvola2;
|
||||
$total_espece_orders_combined = $total_espece1 + $total_espece2;
|
||||
$total_virement_bancaire_orders_combined = $total_virement_bancaire1 + $total_virement_bancaire2;
|
||||
$total_espece_final = $total_espece +
|
||||
$me +
|
||||
$be -
|
||||
$total_sortie_espece;
|
||||
|
||||
// Totaux finaux (Orders + Avances)
|
||||
$total_mvola = $total_mvola_orders_combined + $total_mvola_avances;
|
||||
$total_espece = $total_espece_orders_combined + $total_espece_avances;
|
||||
$total_virement_bancaire = $total_virement_bancaire_orders_combined + $total_virement_bancaire_avances;
|
||||
|
||||
// Ajustements avec les recouvrements et sorties caisse
|
||||
$total_mvola_final = $total_mvola - $total_recouvrement_me - $total_recouvrement_mb + $total_recouvrement_bm;
|
||||
$total_espece_final = $total_espece + $total_recouvrement_me + $total_recouvrement_be - $total_sortie_caisse1;
|
||||
$total_virement_bancaire_final = $total_virement_bancaire - $total_recouvrement_be - $total_recouvrement_bm + $total_recouvrement_mb;
|
||||
$total_virement_bancaire_final = $total_vb -
|
||||
$be -
|
||||
$bm +
|
||||
$mb -
|
||||
$total_sortie_virement;
|
||||
|
||||
// === CALCUL DU TOTAL GÉNÉRAL ===
|
||||
// ✅ CORRECTION: Ne PAS additionner les recouvrements au total
|
||||
// Les recouvrements sont des transferts internes, pas des entrées d'argent
|
||||
$total_sortie_global = $total_sortie_espece + $total_sortie_mvola + $total_sortie_virement;
|
||||
$total_final = $total - $total_sortie_global;
|
||||
|
||||
// check avance expired
|
||||
$avance = new Avance();
|
||||
$avance->checkExpiredAvance();
|
||||
|
||||
|
||||
$data = [
|
||||
'total' => $total,
|
||||
'total' => $total_final,
|
||||
'total_mvola' => $total_mvola_final,
|
||||
'total_espece' => $total_espece_final,
|
||||
'total_virement_bancaire' => $total_virement_bancaire_final,
|
||||
'user_permission' => $this->permission,
|
||||
|
||||
];
|
||||
|
||||
$data['total_products'] = $productModel->countTotalProducts();
|
||||
@ -144,10 +152,10 @@ class Dashboard extends AdminController
|
||||
|
||||
// filter to keep non empty array
|
||||
$filteredArray = array_filter($newData, function($item) {
|
||||
return !empty($item); // Keep only non-empty arrays
|
||||
return !empty($item);
|
||||
});
|
||||
|
||||
// Re-index the array (optional, if you want sequential keys)
|
||||
// Re-index the array
|
||||
$userWhoSoldProducts = array_values($filteredArray);
|
||||
|
||||
// Count occurrences of each userId
|
||||
@ -166,6 +174,7 @@ class Dashboard extends AdminController
|
||||
}
|
||||
|
||||
$data['count_id'] = $countId;
|
||||
|
||||
// Check if the user is an Conseil
|
||||
$session = session();
|
||||
$user_id = $session->get('user');
|
||||
@ -174,6 +183,7 @@ class Dashboard extends AdminController
|
||||
$data['isChef'] = false;
|
||||
$data['isCaissier'] = false;
|
||||
$data['isMecanicien'] = false;
|
||||
|
||||
if ($user_id['group_name'] == "Direction" || $user_id['group_name'] == "Conseil") {
|
||||
$data['is_admin'] = true;
|
||||
}
|
||||
@ -186,16 +196,18 @@ class Dashboard extends AdminController
|
||||
}
|
||||
if ($user_id['group_name'] == "Cheffe d'Agence") {
|
||||
$data['isChef'] = true;
|
||||
}
|
||||
}
|
||||
if ($user_id['group_name'] == "Caissière") {
|
||||
$data['isCaissier'] = true;
|
||||
}
|
||||
if ($user_id['group_name'] == "MECANICIEN") {
|
||||
$data['isMecanicien'] = true;
|
||||
}
|
||||
|
||||
$data['page_title'] = 'Dashboard';
|
||||
$data['marques_total'] = json_encode($orderModel->getTotalProductvente());
|
||||
$data['marques'] = json_encode($Brancds->getName());
|
||||
|
||||
$Orders = new Orders();
|
||||
$Products = new Products();
|
||||
$Stores = new Stores();
|
||||
|
||||
@ -11,30 +11,30 @@ class NotificationController extends AdminController
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
// Récupérer toutes les notifications selon les règles définies dans le modèle
|
||||
public function getNotification()
|
||||
{
|
||||
$Notification = new Notification();
|
||||
|
||||
$notifications = $Notification->getNotifications();
|
||||
|
||||
return $this->response->setJSON($notifications);
|
||||
}
|
||||
|
||||
// Marquer une notification comme lue
|
||||
public function markAsRead(int $id)
|
||||
{
|
||||
$Notification = new Notification();
|
||||
$Notification->markAsRead($id);
|
||||
|
||||
return $this->response->setJSON(['status' => 'success']);
|
||||
}
|
||||
|
||||
// Créer une nouvelle notification
|
||||
public function createNotification(string $message, string $group, ?int $store_id, ?string $link)
|
||||
{
|
||||
$Notification = new Notification();
|
||||
|
||||
$data = [
|
||||
'message' => $message,
|
||||
'is_read' => 0,
|
||||
'is_read' => 0,
|
||||
'forgroup' => $group,
|
||||
'store_id' => $store_id,
|
||||
'link' => $link,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -159,27 +159,36 @@ class ProductCOntroller extends AdminController
|
||||
$Category = new Category();
|
||||
$Stores = new Stores();
|
||||
$Notification = new NotificationController();
|
||||
$Fourchette = new \App\Models\FourchettePrix();
|
||||
$this->verifyRole('createProduct');
|
||||
$data['page_title'] = $this->pageTitle;
|
||||
|
||||
|
||||
$validation = \Config\Services::validation();
|
||||
$validation->setRules([
|
||||
'nom_de_produit' => 'required',
|
||||
'marque' => 'required',
|
||||
'type' => 'required',
|
||||
'numero_de_moteur' => 'required',
|
||||
'prix' => 'required|numeric',
|
||||
'price_vente' => 'required|numeric',
|
||||
'puissance' => 'required',
|
||||
'store' => 'required',
|
||||
'availability' => 'required',
|
||||
'price_min' => 'required|numeric',
|
||||
'nom_de_produit' => 'required',
|
||||
'marque' => 'required',
|
||||
'type' => 'required',
|
||||
'numero_de_moteur' => 'required',
|
||||
'prix' => 'required|numeric',
|
||||
'price_vente' => 'required|numeric',
|
||||
'puissance' => 'required',
|
||||
'store' => 'required',
|
||||
'availability' => 'required',
|
||||
'price_min' => 'required|numeric',
|
||||
]);
|
||||
|
||||
if ($this->request->getMethod() === 'post' && $validation->withRequest($this->request)->run()) {
|
||||
|
||||
|
||||
$prix_min = (float)$this->request->getPost('price_min');
|
||||
$prix_vente = (float)$this->request->getPost('price_vente');
|
||||
|
||||
// --- Vérification côté serveur ---
|
||||
if ($prix_min > $prix_vente) {
|
||||
session()->setFlashdata('errors', 'Le prix de vente ne peut pas être inférieur au prix minimal.');
|
||||
return redirect()->to('/products/create')->withInput();
|
||||
}
|
||||
|
||||
$upload_image = '';
|
||||
|
||||
$file = $this->request->getFile('product_image');
|
||||
if ($file && $file->isValid() && !$file->hasMoved()) {
|
||||
$uploadResult = $this->uploadImage();
|
||||
@ -188,65 +197,69 @@ class ProductCOntroller extends AdminController
|
||||
}
|
||||
}
|
||||
|
||||
$product_sold = 0;
|
||||
$availabilityValue = (int)$this->request->getPost('availability');
|
||||
$availability = ($availabilityValue === 1) ? 1 : 0;
|
||||
|
||||
$data = [
|
||||
'name' => $this->request->getPost('nom_de_produit'),
|
||||
'sku' => $this->request->getPost('numero_de_serie'),
|
||||
'price' => $this->request->getPost('prix'),
|
||||
'qty' => 1,
|
||||
'image' => $upload_image,
|
||||
'description' => $this->request->getPost('description'),
|
||||
'name' => $this->request->getPost('nom_de_produit'),
|
||||
'sku' => $this->request->getPost('numero_de_serie'),
|
||||
'price' => $this->request->getPost('prix'),
|
||||
'qty' => 1,
|
||||
'image' => $upload_image,
|
||||
'description' => $this->request->getPost('description'),
|
||||
'numero_de_moteur' => $this->request->getPost('numero_de_moteur'),
|
||||
'marque' => $this->request->getPost('marque'),
|
||||
'chasis' => $this->request->getPost('chasis'),
|
||||
'store_id' => (int)$this->request->getPost('store'),
|
||||
'availability' => $availability,
|
||||
'prix_vente' => $this->request->getPost('price_vente'),
|
||||
'date_arivage' => $this->request->getPost('datea'),
|
||||
'puissance' => $this->request->getPost('puissance'),
|
||||
'cler' => $this->request->getPost('cler'),
|
||||
'categorie_id' => json_encode($this->request->getPost('categorie[]')),
|
||||
'etats' => $this->request->getPost('etats'),
|
||||
'infoManquekit' => $this->request->getPost('infoManquekit'),
|
||||
'info' => $this->request->getPost('info'),
|
||||
'infoManque' => $this->request->getPost('infoManque'),
|
||||
'product_sold' => $product_sold,
|
||||
'type'=> $this->request->getPost('type')
|
||||
'marque' => $this->request->getPost('marque'),
|
||||
'chasis' => $this->request->getPost('chasis'),
|
||||
'store_id' => (int)$this->request->getPost('store'),
|
||||
'availability' => $availability,
|
||||
'prix_vente' => $prix_vente,
|
||||
'date_arivage' => $this->request->getPost('datea'),
|
||||
'puissance' => $this->request->getPost('puissance'),
|
||||
'cler' => $this->request->getPost('cler'),
|
||||
'categorie_id' => json_encode($this->request->getPost('categorie[]')),
|
||||
'etats' => $this->request->getPost('etats'),
|
||||
'infoManquekit' => $this->request->getPost('infoManquekit'),
|
||||
'info' => $this->request->getPost('info'),
|
||||
'infoManque' => $this->request->getPost('infoManque'),
|
||||
'product_sold' => 0,
|
||||
'type' => $this->request->getPost('type')
|
||||
];
|
||||
|
||||
|
||||
$store_id1 = (int)$this->request->getPost('store');
|
||||
|
||||
|
||||
$productId = $Products->insert($data);
|
||||
if ($productId) {
|
||||
$data_fourchette = [
|
||||
'product_id' => $productId,
|
||||
'prix_minimal' => $this->request->getPost('price_min'),
|
||||
];
|
||||
$Fourchette = new FourchettePrix();
|
||||
$Fourchette->createFourchettePrix([
|
||||
'product_id' => $productId,
|
||||
'prix_minimal' => $prix_min,
|
||||
]);
|
||||
|
||||
$Fourchette->createFourchettePrix($data_fourchette);
|
||||
session()->setFlashdata('success', 'Créé avec succès');
|
||||
$Notification->createNotification("Un nouveau Produit a été crée", "COMMERCIALE",$store_id1,'product/');
|
||||
$Notification->createNotification(
|
||||
"Un nouveau Produit a été créé",
|
||||
"COMMERCIALE",
|
||||
$store_id1,
|
||||
'product/'
|
||||
);
|
||||
|
||||
return redirect()->to('/products');
|
||||
} else {
|
||||
session()->setFlashdata('errors', 'Error occurred while creating the product');
|
||||
return redirect()->to('products/create');
|
||||
session()->setFlashdata('errors', 'Erreur lors de la création du produit');
|
||||
return redirect()->to('products/create')->withInput();
|
||||
}
|
||||
} else {
|
||||
$data = [
|
||||
'stores' => $Stores->getActiveStore(),
|
||||
'validation' => $validation,
|
||||
'page_title' => $this->pageTitle,
|
||||
'marque' => $Brands->getActiveBrands(),
|
||||
'categorie' => $Category->getActiveCategory(),
|
||||
'marque' => $Brands->getActiveBrands(),
|
||||
'categorie' => $Category->getActiveCategory(),
|
||||
];
|
||||
|
||||
return $this->render_template('products/create', $data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function uploadImage()
|
||||
{
|
||||
@ -282,71 +295,105 @@ class ProductCOntroller extends AdminController
|
||||
public function update(int $id)
|
||||
{
|
||||
$Products = new Products();
|
||||
$Stores = new Stores();
|
||||
$Stores = new Stores();
|
||||
$Category = new Category();
|
||||
$Brands = new Brands();
|
||||
$FourchettePrix = new \App\Models\FourchettePrix(); // Modèle FourchettePrix
|
||||
|
||||
$this->verifyRole('updateProduct');
|
||||
$data['page_title'] = $this->pageTitle;
|
||||
$Brands = new Brands();
|
||||
|
||||
|
||||
$validation = \Config\Services::validation();
|
||||
$validation->setRules([
|
||||
'nom_de_produit' => 'required',
|
||||
'marque' => 'required',
|
||||
'marque' => 'required',
|
||||
]);
|
||||
|
||||
|
||||
// Récupérer produit et prix minimal
|
||||
$product_data = $Products->getProductData($id);
|
||||
$prix_minimal_data = $FourchettePrix->where('product_id', $id)->first();
|
||||
$prix_minimal = $prix_minimal_data['prix_minimal'] ?? '';
|
||||
|
||||
if ($this->request->getMethod() === 'post' && $validation->withRequest($this->request)->run()) {
|
||||
|
||||
$availabilityValue = (int)$this->request->getPost('availability');
|
||||
$availability = ($availabilityValue === 1) ? 1 : 0;
|
||||
|
||||
|
||||
$data = [
|
||||
'name' => $this->request->getPost('nom_de_produit'),
|
||||
'sku' => $this->request->getPost('numero_de_serie'),
|
||||
'price' => $this->request->getPost('price'),
|
||||
'qty' => 1,
|
||||
'name' => $this->request->getPost('nom_de_produit'),
|
||||
'sku' => $this->request->getPost('numero_de_serie'),
|
||||
'price' => $this->request->getPost('price'),
|
||||
'qty' => 1,
|
||||
'description' => $this->request->getPost('description'),
|
||||
'numero_de_moteur' => $this->request->getPost('numero_de_moteur'),
|
||||
'marque' => $this->request->getPost('marque'),
|
||||
'chasis' => $this->request->getPost('chasis'),
|
||||
'store_id' => (int)$this->request->getPost('store'),
|
||||
'availability' => $availability,
|
||||
'prix_vente' => $this->request->getPost('price_vente'),
|
||||
'date_arivage' => $this->request->getPost('datea'),
|
||||
'puissance' => $this->request->getPost('puissance'),
|
||||
'cler' => $this->request->getPost('cler'),
|
||||
'categorie_id' => json_encode($this->request->getPost('categorie[]')),
|
||||
'etats' => $this->request->getPost('etats'),
|
||||
'infoManquekit' => $this->request->getPost('infoManquekit'),
|
||||
'info' => $this->request->getPost('info'),
|
||||
'infoManque' => $this->request->getPost('infoManque'),
|
||||
'type'=> $this->request->getPost('type'),
|
||||
'marque' => $this->request->getPost('marque'),
|
||||
'chasis' => $this->request->getPost('chasis'),
|
||||
'store_id' => (int)$this->request->getPost('store'),
|
||||
'availability'=> $availability,
|
||||
'prix_vente' => $this->request->getPost('price_vente'),
|
||||
'date_arivage'=> $this->request->getPost('datea'),
|
||||
'puissance' => $this->request->getPost('puissance'),
|
||||
'cler' => $this->request->getPost('cler'),
|
||||
'categorie_id'=> json_encode($this->request->getPost('categorie[]')),
|
||||
'etats' => $this->request->getPost('etats'),
|
||||
'infoManquekit'=> $this->request->getPost('infoManquekit'),
|
||||
'info' => $this->request->getPost('info'),
|
||||
'infoManque' => $this->request->getPost('infoManque'),
|
||||
'type' => $this->request->getPost('type'),
|
||||
];
|
||||
|
||||
|
||||
// ---- GESTION PRIX MINIMAL ----
|
||||
$prix_minimal_saisi = (float)$this->request->getPost('price_min');
|
||||
$prix_vente = (float)$this->request->getPost('price_vente');
|
||||
|
||||
// Vérification serveur : prix minimal <= prix de vente
|
||||
if ($prix_minimal_saisi > 0 && $prix_vente < $prix_minimal_saisi) {
|
||||
session()->setFlashdata('errors', 'Le prix de vente ne peut pas être inférieur au prix minimal.');
|
||||
return redirect()->to('/products/update/' . $id)->withInput();
|
||||
}
|
||||
|
||||
// Sauvegarde ou mise à jour du prix minimal
|
||||
if ($prix_minimal_data) {
|
||||
$FourchettePrix->update($prix_minimal_data['id'], [
|
||||
'prix_minimal' => $prix_minimal_saisi
|
||||
]);
|
||||
} else {
|
||||
$FourchettePrix->insert([
|
||||
'product_id' => $id,
|
||||
'prix_minimal' => $prix_minimal_saisi
|
||||
]);
|
||||
}
|
||||
|
||||
// Upload image si fournie
|
||||
if ($this->request->getFile('product_image')->isValid()) {
|
||||
$uploadImage = $this->uploadImage();
|
||||
$uploadData = ['image' => $uploadImage];
|
||||
$Products->update($id, $uploadData);
|
||||
$Products->update($id, ['image' => $uploadImage]);
|
||||
}
|
||||
|
||||
|
||||
// Mise à jour du produit
|
||||
if ($Products->updateProduct($data, $id)) {
|
||||
session()->setFlashdata('success', 'Successfully updated');
|
||||
session()->setFlashdata('success', 'Produit mis à jour avec succès.');
|
||||
return redirect()->to('/products');
|
||||
} else {
|
||||
session()->setFlashdata('errors', 'Error occurred!!');
|
||||
session()->setFlashdata('errors', 'Une erreur est survenue lors de la mise à jour.');
|
||||
return redirect()->to('/products/update/' . $id);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Affichage du formulaire
|
||||
$data = [
|
||||
'stores' => $Stores->getActiveStore(),
|
||||
'validation' => $validation,
|
||||
'page_title' => $this->pageTitle,
|
||||
'product_data' => $Products->getProductData($id),
|
||||
'categorie' => $Category->getActiveCategory(),
|
||||
'marque' => $Brands->getActiveBrands()
|
||||
'stores' => $Stores->getActiveStore(),
|
||||
'validation' => $validation,
|
||||
'page_title' => $this->pageTitle,
|
||||
'product_data' => $product_data,
|
||||
'categorie' => $Category->getActiveCategory(),
|
||||
'marque' => $Brands->getActiveBrands(),
|
||||
'prix_minimal' => $prix_minimal
|
||||
];
|
||||
|
||||
|
||||
return $this->render_template('products/editbackup', $data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function remove()
|
||||
{
|
||||
@ -418,6 +465,7 @@ class ProductCOntroller extends AdminController
|
||||
'prix d\'achat' => 'price',
|
||||
'prix ar' => 'prix_vente',
|
||||
'catégories' => 'categorie_id',
|
||||
'prix minimale' => 'prix_minimal',
|
||||
'magasin' => 'store_id',
|
||||
'disponibilité' => 'availability',
|
||||
'état' => 'etats',
|
||||
@ -565,4 +613,5 @@ class ProductCOntroller extends AdminController
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -49,46 +49,67 @@ class RecouvrementController extends AdminController
|
||||
$avance = new Avance();
|
||||
|
||||
// Récupère les données brutes
|
||||
$paymentDataOrders = $orders->getPaymentModes();
|
||||
$paymentDataAvance = $avance->getPaymentModesAvance();
|
||||
$total_sortie_caisse = $sortieCaisse->getTotalSortieCaisse()->mr ?? 0;
|
||||
$totalRecouvrement = $recouvrement->getTotalRecouvrements();
|
||||
$paymentDataOrders = $orders->getPaymentModes();
|
||||
$paymentDataAvance = $avance->getPaymentModesAvance();
|
||||
$totalRecouvrement = $recouvrement->getTotalRecouvrements();
|
||||
$total_sortie_caisse = $sortieCaisse->getTotalSortieCaisse();
|
||||
|
||||
// Totaux recouvrement
|
||||
$me = $totalRecouvrement->me ?? 0;
|
||||
$bm = $totalRecouvrement->bm ?? 0;
|
||||
$be = $totalRecouvrement->be ?? 0;
|
||||
$mb = $totalRecouvrement->mb ?? 0;
|
||||
// === EXTRACTION DES SORTIES PAR MODE DE PAIEMENT ===
|
||||
$total_sortie_espece = isset($total_sortie_caisse->total_espece) ? (float) $total_sortie_caisse->total_espece : 0;
|
||||
$total_sortie_mvola = isset($total_sortie_caisse->total_mvola) ? (float) $total_sortie_caisse->total_mvola : 0;
|
||||
$total_sortie_virement = isset($total_sortie_caisse->total_virement) ? (float) $total_sortie_caisse->total_virement : 0;
|
||||
|
||||
// Totaux paiements Orders
|
||||
$total_orders = $paymentDataOrders->total ?? 0;
|
||||
$mv1_orders = $paymentDataOrders->total_mvola1 ?? 0;
|
||||
$mv2_orders = $paymentDataOrders->total_mvola2 ?? 0;
|
||||
$es1_orders = $paymentDataOrders->total_espece1 ?? 0;
|
||||
$es2_orders = $paymentDataOrders->total_espece2 ?? 0;
|
||||
$vb1_orders = $paymentDataOrders->total_virement_bancaire1 ?? 0;
|
||||
$vb2_orders = $paymentDataOrders->total_virement_bancaire2 ?? 0;
|
||||
// === TOTAUX RECOUVREMENT ===
|
||||
$me = isset($totalRecouvrement->me) ? (float) $totalRecouvrement->me : 0;
|
||||
$bm = isset($totalRecouvrement->bm) ? (float) $totalRecouvrement->bm : 0;
|
||||
$be = isset($totalRecouvrement->be) ? (float) $totalRecouvrement->be : 0;
|
||||
$mb = isset($totalRecouvrement->mb) ? (float) $totalRecouvrement->mb : 0;
|
||||
|
||||
// Totaux paiements Avances
|
||||
$total_avances = $paymentDataAvance->total ?? 0;
|
||||
$mv_avances = $paymentDataAvance->total_mvola ?? 0;
|
||||
$es_avances = $paymentDataAvance->total_espece ?? 0;
|
||||
$vb_avances = $paymentDataAvance->total_virement_bancaire ?? 0;
|
||||
$ta = $avance->getTotalAvance()->ta ?? 0;
|
||||
// === TOTAUX PAIEMENTS ORDERS ===
|
||||
$total_orders = isset($paymentDataOrders->total) ? (float) $paymentDataOrders->total : 0;
|
||||
$mv1_orders = isset($paymentDataOrders->total_mvola1) ? (float) $paymentDataOrders->total_mvola1 : 0;
|
||||
$mv2_orders = isset($paymentDataOrders->total_mvola2) ? (float) $paymentDataOrders->total_mvola2 : 0;
|
||||
$es1_orders = isset($paymentDataOrders->total_espece1) ? (float) $paymentDataOrders->total_espece1 : 0;
|
||||
$es2_orders = isset($paymentDataOrders->total_espece2) ? (float) $paymentDataOrders->total_espece2 : 0;
|
||||
$vb1_orders = isset($paymentDataOrders->total_virement_bancaire1) ? (float) $paymentDataOrders->total_virement_bancaire1 : 0;
|
||||
$vb2_orders = isset($paymentDataOrders->total_virement_bancaire2) ? (float) $paymentDataOrders->total_virement_bancaire2 : 0;
|
||||
|
||||
// Combinaison Orders + Avances
|
||||
$total_mvola = $mv1_orders + $mv2_orders + $mv_avances;
|
||||
$total_espece = $es1_orders + $es2_orders + $es_avances;
|
||||
$total_vb = $vb1_orders + $vb2_orders + $vb_avances;
|
||||
$total = $total_orders + $total_avances;
|
||||
// === TOTAUX PAIEMENTS AVANCES ===
|
||||
$total_avances = isset($paymentDataAvance->total) ? (float) $paymentDataAvance->total : 0;
|
||||
$mv_avances = isset($paymentDataAvance->total_mvola) ? (float) $paymentDataAvance->total_mvola : 0;
|
||||
$es_avances = isset($paymentDataAvance->total_espece) ? (float) $paymentDataAvance->total_espece : 0;
|
||||
$vb_avances = isset($paymentDataAvance->total_virement_bancaire) ? (float) $paymentDataAvance->total_virement_bancaire : 0;
|
||||
|
||||
// Ajustements avec recouvrements et sorties caisse
|
||||
$total_mvola_final = $total_mvola - $me - $mb + $bm;
|
||||
$total_espece_final = $total_espece + $me + $be - $total_sortie_caisse;
|
||||
$total_virement_bancaire_final = $total_vb - $be - $bm + $mb;
|
||||
// === COMBINAISON ORDERS + AVANCES ===
|
||||
$total_mvola = $mv1_orders + $mv2_orders + $mv_avances;
|
||||
$total_espece = $es1_orders + $es2_orders + $es_avances;
|
||||
$total_vb = $vb1_orders + $vb2_orders + $vb_avances;
|
||||
$total = $total_orders + $total_avances;
|
||||
|
||||
// === AJUSTEMENTS AVEC RECOUVREMENTS ET SORTIES (PAR MODE DE PAIEMENT) ===
|
||||
$total_mvola_final = $total_mvola -
|
||||
$me -
|
||||
$mb +
|
||||
$bm -
|
||||
$total_sortie_mvola;
|
||||
|
||||
$total_espece_final = $total_espece +
|
||||
$me +
|
||||
$be -
|
||||
$total_sortie_espece;
|
||||
|
||||
$total_virement_bancaire_final = $total_vb -
|
||||
$be -
|
||||
$bm +
|
||||
$mb -
|
||||
$total_sortie_virement;
|
||||
|
||||
// === CALCUL DU TOTAL GÉNÉRAL ===
|
||||
$total_sortie_global = $total_sortie_espece + $total_sortie_mvola + $total_sortie_virement;
|
||||
$total_final = $total - $total_sortie_global;
|
||||
|
||||
return [
|
||||
'total' => $total,
|
||||
'total' => $total_final,
|
||||
'total_mvola' => $total_mvola_final,
|
||||
'total_espece' => $total_espece_final,
|
||||
'total_virement_bancaire' => $total_virement_bancaire_final,
|
||||
@ -96,7 +117,6 @@ class RecouvrementController extends AdminController
|
||||
'permission' => $this->permission
|
||||
];
|
||||
}
|
||||
|
||||
public function fetchRecouvrementData()
|
||||
{
|
||||
helper(['url', 'form']);
|
||||
|
||||
@ -36,55 +36,54 @@ class RemiseController extends AdminController
|
||||
|
||||
|
||||
public function fetchRemiseData()
|
||||
{
|
||||
helper(['url', 'form']);
|
||||
$Remise = new Remise(); // Assure-toi du bon namespace
|
||||
{
|
||||
helper(['url', 'form']);
|
||||
$Remise = new Remise();
|
||||
|
||||
$draw = intval($this->request->getVar('draw'));
|
||||
$data = $Remise->getAllDemandeRemiseToday();
|
||||
$totalRecords = count($data);
|
||||
|
||||
$result = [
|
||||
"draw" => $draw,
|
||||
"recordsTotal" => $totalRecords,
|
||||
"recordsFiltered" => $totalRecords,
|
||||
"data" => []
|
||||
];
|
||||
foreach ($data as $key => $value) {
|
||||
$buttons = '';
|
||||
|
||||
if (in_array('validateRemise', $this->permission) && $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>';
|
||||
}
|
||||
// die(var_dump($value));
|
||||
$result['data'][$key] = [
|
||||
$value['id_demande'],
|
||||
$value['product'],
|
||||
number_format($value['total_price'], 0, '.', ' '),
|
||||
number_format($value['montant_demande'], 0, '.', ' '),
|
||||
$value['demande_status'],
|
||||
$buttons
|
||||
$draw = intval($this->request->getVar('draw'));
|
||||
$data = $Remise->getAllDemandeRemiseToday();
|
||||
$totalRecords = count($data);
|
||||
|
||||
$result = [
|
||||
"draw" => $draw,
|
||||
"recordsTotal" => $totalRecords,
|
||||
"recordsFiltered" => $totalRecords,
|
||||
"data" => []
|
||||
];
|
||||
foreach ($data as $key => $value) {
|
||||
$buttons = '';
|
||||
|
||||
if (in_array('validateRemise', $this->permission) && $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>';
|
||||
}
|
||||
|
||||
$result['data'][$key] = [
|
||||
$value['id_demande'],
|
||||
$value['product'],
|
||||
number_format($value['total_price'], 0, '.', ' '),
|
||||
number_format($value['montant_demande'], 0, '.', ' '),
|
||||
$value['demande_status'],
|
||||
$buttons
|
||||
];
|
||||
}
|
||||
|
||||
return $this->response->setJSON($result);
|
||||
}
|
||||
|
||||
return $this->response->setJSON($result);
|
||||
}
|
||||
|
||||
|
||||
public function updateRemise($id_demande) {
|
||||
public function updateRemise($id_demande)
|
||||
{
|
||||
$this->verifyRole('validateRemise');
|
||||
|
||||
// Load validation service
|
||||
$validation = \Config\Services::validation();
|
||||
|
||||
$data['page_title'] = $this->pageTitle;
|
||||
|
||||
$validation->setRules([
|
||||
@ -94,15 +93,15 @@ class RemiseController extends AdminController
|
||||
$validationData = [
|
||||
'demande_status' => $this->request->getPost('demande_status')
|
||||
];
|
||||
$data = [
|
||||
'demande_status' => $this->request->getPost('demande_status')
|
||||
];
|
||||
|
||||
|
||||
$Remise = new Remise();
|
||||
if ($this->request->getMethod()=='post') {
|
||||
|
||||
if ($this->request->getMethod() == 'post') {
|
||||
$today = date('Y-m-d');
|
||||
$demande_status = $this->request->getPost('demande_status');
|
||||
|
||||
$data = [
|
||||
'demande_status' => $this->request->getPost('demande_status'),
|
||||
'demande_status' => $demande_status,
|
||||
'date_demande' => $today,
|
||||
];
|
||||
|
||||
@ -111,10 +110,47 @@ class RemiseController extends AdminController
|
||||
$Notification = new NotificationController();
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
$Notification->createNotification("Une demande de remise a été " . $this->request->getPost('demande_status')." Pour le produit: ".$remise_product,"Caissière",(int)$users['store_id'],'remise/');
|
||||
$ordersModel = new Orders();
|
||||
$order_id = $Remise->getOrderIdByDemandeId($id_demande);
|
||||
|
||||
// Logique de notification selon le statut
|
||||
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
|
||||
$Notification->createNotification(
|
||||
"Votre demande de remise a été refusée pour le produit: " . $remise_product . ". Veuillez modifier la commande.",
|
||||
"COMMERCIALE",
|
||||
(int)$users['store_id'],
|
||||
"orders" // Retour à l'ajout de commande chez le commercial
|
||||
);
|
||||
|
||||
$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
|
||||
}
|
||||
|
||||
// Notification à la Caissière pour qu'elle valide la commande
|
||||
$Notification->createNotification(
|
||||
"Une commande avec remise acceptée est prête pour validation. Produit: " . $remise_product,
|
||||
"Caissière",
|
||||
(int)$users['store_id'],
|
||||
"orders" // Va chez la caissière pour validation finale
|
||||
);
|
||||
|
||||
$message = 'La demande de remise a été acceptée. La commande a été envoyée à la caissière pour validation.';
|
||||
}
|
||||
|
||||
return $this->response->setJSON([
|
||||
'success' => true,
|
||||
'messages' => 'Vous avez '.$this->request->getPost('demande_status').' la remise'
|
||||
'messages' => $message
|
||||
]);
|
||||
} else {
|
||||
return $this->response->setJSON([
|
||||
@ -123,7 +159,5 @@ class RemiseController extends AdminController
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -36,20 +36,24 @@ class ReportController extends AdminController
|
||||
$parking_data = $Reports->getOrderData($today_year);
|
||||
$data['report_years'] = $Reports->getOrderYear();
|
||||
|
||||
// Process the parking data and calculate total amounts
|
||||
$final_parking_data = [];
|
||||
foreach ($parking_data as $month => $orders) {
|
||||
$total_amount_earned = 0; // Initialize the total amount for the month
|
||||
|
||||
if (!empty($orders)) {
|
||||
foreach ($orders as $order) {
|
||||
$total_amount_earned += (float) $order['net_amount'];
|
||||
// Process the parking data and calculate total amounts
|
||||
$final_parking_data = [];
|
||||
foreach ($parking_data as $month => $orders) {
|
||||
$total_amount_earned = 0;
|
||||
|
||||
if (!empty($orders)) {
|
||||
foreach ($orders as $order) {
|
||||
// Utiliser le montant selon la logique : discount si existe, sinon gross_amount
|
||||
if (!empty($order['discount']) && $order['discount'] > 0) {
|
||||
$total_amount_earned += (float) $order['discount'];
|
||||
} else {
|
||||
$total_amount_earned += (float) $order['gross_amount'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$final_parking_data[$month] = $total_amount_earned;
|
||||
}
|
||||
|
||||
$final_parking_data[$month] = $total_amount_earned;
|
||||
}
|
||||
|
||||
// Data for the camembert (pie chart)
|
||||
$paymentModes = $Orders->getPaymentModes();
|
||||
$total_mvola1 = $paymentModes->total_mvola1;
|
||||
@ -256,76 +260,73 @@ class ReportController extends AdminController
|
||||
$Orders = new Orders();
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
if ($users['group_name'] === "Conseil" || $users['group_name'] === "Direction" ) {
|
||||
|
||||
// Pour Direction et Conseil : afficher TOUTES les performances
|
||||
if ($users['group_name'] === "DAF" || $users['group_name'] === "Direction") {
|
||||
$orderPaid = $Orders->getPerformanceByOrders();
|
||||
foreach ($orderPaid as $key => $value) {
|
||||
$benefice =
|
||||
// Déterminer le prix de vente réel
|
||||
$prix_vente_reel = (!empty($value['discount']) && $value['discount'] > 0)
|
||||
? $value['discount']
|
||||
: $value['prix_vente'];
|
||||
|
||||
// Calculer le bénéfice
|
||||
$benefice = $prix_vente_reel - $value['price'];
|
||||
|
||||
$result['data'][$key] = [
|
||||
$value['firstname'] . ' ' . $value['lastname'],
|
||||
$value['email'],
|
||||
($value['sku'] == "" ? $value['motoname'] : $value['sku']),
|
||||
(new DateTime($value['datevente']))->format('Y-m-d'),
|
||||
number_format($value['price'],0,'.',' '),
|
||||
number_format($value['prix_vente'],0,'.',' '),
|
||||
number_format($value['price'], 0, '.', ' '),
|
||||
number_format($prix_vente_reel, 0, '.', ' '),
|
||||
$this->returnName($value['store_id']),
|
||||
number_format($value['prix_vente'] - $value['price'],0,'.',' '),
|
||||
number_format($benefice, 0, '.', ' '),
|
||||
];
|
||||
}
|
||||
|
||||
// Return data in JSON format
|
||||
return $this->response->setJSON($result);
|
||||
}
|
||||
if ($users['group_name'] === "Conseil" || $users['group_name'] === "Direction") {
|
||||
$orderPaid = $Orders->getPerformanceByOrders1();
|
||||
foreach ($orderPaid as $key => $value) {
|
||||
$benefice =
|
||||
$result['data'][$key] = [
|
||||
$value['firstname'] . ' ' . $value['lastname'],
|
||||
$value['email'],
|
||||
($value['sku'] == "" ? $value['motoname'] : $value['sku']),
|
||||
(new DateTime($value['datevente']))->format('Y-m-d'),
|
||||
number_format($value['price'],0,'.',' '),
|
||||
number_format($value['prix_vente'],0,'.',' '),
|
||||
$this->returnName($value['store_id']),
|
||||
number_format($value['prix_vente'] - $value['price'],0,'.',' '),
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
// Return data in JSON format
|
||||
return $this->response->setJSON($result);
|
||||
}
|
||||
if ($users['group_name'] === "COMMERCIALE") {
|
||||
$orderPaid = $Orders->getPerformanceByOrders2();
|
||||
foreach ($orderPaid as $key => $value) {
|
||||
$benefice =
|
||||
$result['data'][$key] = [
|
||||
$value['firstname'] . ' ' . $value['lastname'],
|
||||
($value['sku'] == "" ? $value['motoname'] : $value['sku']),
|
||||
(new DateTime($value['datevente']))->format('Y-m-d'),
|
||||
number_format($value['prix_vente'],0,'.',' '),
|
||||
];
|
||||
}
|
||||
|
||||
// Return data in JSON format
|
||||
return $this->response->setJSON($result);
|
||||
}
|
||||
|
||||
|
||||
// Pour Cheffe d'Agence : performances de son magasin
|
||||
if ($users['group_name'] === "Cheffe d'Agence") {
|
||||
$orderPaid = $Orders->getPerformanceByOrders1();
|
||||
foreach ($orderPaid as $key => $value) {
|
||||
$benefice =
|
||||
// Déterminer le prix de vente réel
|
||||
$prix_vente_reel = (!empty($value['discount']) && $value['discount'] > 0)
|
||||
? $value['discount']
|
||||
: $value['prix_vente'];
|
||||
|
||||
$result['data'][$key] = [
|
||||
$value['firstname'] . ' ' . $value['lastname'],
|
||||
($value['sku'] == "" ? $value['motoname'] : $value['sku']),
|
||||
(new DateTime($value['datevente']))->format('Y-m-d'),
|
||||
number_format($value['prix_vente'],0,'.',' '),
|
||||
number_format($prix_vente_reel, 0, '.', ' '),
|
||||
];
|
||||
}
|
||||
|
||||
// Return data in JSON format
|
||||
return $this->response->setJSON($result);
|
||||
}
|
||||
|
||||
// Pour COMMERCIALE : uniquement ses propres ventes
|
||||
if ($users['group_name'] === "COMMERCIALE") {
|
||||
$orderPaid = $Orders->getPerformanceByOrders2();
|
||||
foreach ($orderPaid as $key => $value) {
|
||||
// Déterminer le prix de vente réel
|
||||
$prix_vente_reel = (!empty($value['discount']) && $value['discount'] > 0)
|
||||
? $value['discount']
|
||||
: $value['prix_vente'];
|
||||
|
||||
$result['data'][$key] = [
|
||||
$value['firstname'] . ' ' . $value['lastname'],
|
||||
($value['sku'] == "" ? $value['motoname'] : $value['sku']),
|
||||
(new DateTime($value['datevente']))->format('Y-m-d'),
|
||||
number_format($prix_vente_reel, 0, '.', ' '),
|
||||
];
|
||||
}
|
||||
return $this->response->setJSON($result);
|
||||
}
|
||||
|
||||
// Retour par défaut si aucun rôle ne correspond
|
||||
return $this->response->setJSON($result);
|
||||
}
|
||||
|
||||
public function fetchmecperformance()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@ class Avance extends Model {
|
||||
'avance_amount', 'avance_date','user_id',
|
||||
'customer_name', 'customer_address', 'customer_phone', 'customer_cin',
|
||||
'gross_amount','amount_due','product_id','is_order','active','store_id',
|
||||
'type_avance','type_payment', 'deadline' // Ajout du champ type et deadline
|
||||
'type_avance','type_payment', 'deadline','commentaire','product_name' // Ajout du champ type et deadline
|
||||
];
|
||||
|
||||
public function createAvance(array $data) {
|
||||
|
||||
@ -15,12 +15,20 @@ class Notification extends Model
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
|
||||
$today = date('Y-m-d');
|
||||
|
||||
return $this->where('store_id', $users['store_id'])
|
||||
->groupStart()
|
||||
->where('forgroup', $users['group_name'])
|
||||
->orWhere('forgroup', strtolower('TOUS'))
|
||||
->groupEnd()
|
||||
->where('is_read', 0)
|
||||
->groupStart()
|
||||
->where('is_read', 0) // toutes les notifications non lues
|
||||
->orGroupStart()
|
||||
->where('is_read', 1) // notifications lues
|
||||
->where('DATE(created_at)', $today) // mais seulement celles d’aujourd’hui
|
||||
->groupEnd()
|
||||
->groupEnd()
|
||||
->orderBy('created_at', 'DESC')
|
||||
->findAll();
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ namespace App\Models;
|
||||
use CodeIgniter\Model;
|
||||
use App\Models\Products;
|
||||
use App\Models\OrderItems;
|
||||
use App\Models\FourchettePrix;
|
||||
|
||||
class Orders extends Model
|
||||
{
|
||||
@ -32,7 +33,9 @@ class Orders extends Model
|
||||
'tranche_1',
|
||||
'tranche_2',
|
||||
'order_payment_mode',
|
||||
'order_payment_mode_1'
|
||||
'order_payment_mode_1',
|
||||
'delivered_at',
|
||||
'delivered_by'
|
||||
];
|
||||
|
||||
|
||||
@ -75,66 +78,66 @@ class Orders extends Model
|
||||
|
||||
|
||||
public function getOrdersData(int $id = null)
|
||||
{
|
||||
// Récupération des infos de session
|
||||
$session = session();
|
||||
$user = $session->get('user');
|
||||
|
||||
// Construction de la requête avec jointures et agrégation des noms de produits
|
||||
$builder = $this->db->table('orders')
|
||||
->select([
|
||||
'orders.id',
|
||||
'orders.bill_no',
|
||||
'orders.store_id',
|
||||
'orders.customer_name',
|
||||
'orders.customer_phone',
|
||||
'orders.customer_cin',
|
||||
'orders.customer_address',
|
||||
'orders.discount',
|
||||
'orders.date_time',
|
||||
'orders.gross_amount',
|
||||
'orders.net_amount',
|
||||
'orders.paid_status',
|
||||
'orders.user_id',
|
||||
"CONCAT(users.firstname, ' ', users.lastname) AS user_name",
|
||||
])
|
||||
->join('users', 'orders.user_id = users.id', 'left')
|
||||
->join('orders_item', 'orders_item.order_id = orders.id', 'left')
|
||||
->join('products', 'products.id = orders_item.product_id', 'left')
|
||||
// Sépare chaque nom de produit par un saut de ligne '\n'
|
||||
->select("GROUP_CONCAT(products.name SEPARATOR '\\n') AS product_names", false)
|
||||
->groupBy('orders.id');
|
||||
|
||||
// Si on demande une commande précise
|
||||
if ($id !== null) {
|
||||
return $builder
|
||||
->where('orders.id', $id)
|
||||
->get()
|
||||
->getRowArray();
|
||||
}
|
||||
|
||||
// Récupération du groupe de l'utilisateur
|
||||
$group = $this->getUserGroupNameByUserId($user['id']);
|
||||
$groupName = $group['group_name'] ?? '';
|
||||
|
||||
// Selon le rôle, on affiche toutes les commandes ou seulement celles du magasin
|
||||
if (in_array($groupName, ['Direction', 'Conseil'], true)) {
|
||||
{
|
||||
$session = session();
|
||||
$user = $session->get('user');
|
||||
|
||||
// Si on demande UNE commande spécifique (pas de GROUP_CONCAT)
|
||||
if ($id !== null) {
|
||||
return $this->db->table('orders')
|
||||
->select([
|
||||
'orders.*',
|
||||
"CONCAT(users.firstname, ' ', users.lastname) AS user_name"
|
||||
])
|
||||
->join('users', 'orders.user_id = users.id', 'left')
|
||||
->where('orders.id', $id)
|
||||
->get()
|
||||
->getRowArray();
|
||||
}
|
||||
|
||||
// Pour la LISTE des commandes (avec GROUP_CONCAT)
|
||||
$builder = $this->db->table('orders')
|
||||
->select([
|
||||
'orders.id',
|
||||
'orders.bill_no',
|
||||
'orders.store_id',
|
||||
'orders.customer_name',
|
||||
'orders.customer_phone',
|
||||
'orders.customer_cin',
|
||||
'orders.customer_address',
|
||||
'orders.discount',
|
||||
'orders.date_time',
|
||||
'orders.gross_amount',
|
||||
'orders.net_amount',
|
||||
'orders.paid_status',
|
||||
'orders.user_id',
|
||||
"CONCAT(users.firstname, ' ', users.lastname) AS user_name"
|
||||
])
|
||||
->join('users', 'orders.user_id = users.id', 'left')
|
||||
->join('orders_item', 'orders_item.order_id = orders.id', 'left')
|
||||
->join('products', 'products.id = orders_item.product_id', 'left')
|
||||
->select("IFNULL(GROUP_CONCAT(DISTINCT products.name SEPARATOR '\\n'), '') AS product_names", false)
|
||||
->groupBy('orders.id');
|
||||
|
||||
// Récupération du groupe de l'utilisateur
|
||||
$group = $this->getUserGroupNameByUserId($user['id']);
|
||||
$groupName = $group['group_name'] ?? '';
|
||||
|
||||
// Selon le rôle
|
||||
if (in_array($groupName, ['Direction', 'Conseil'], true)) {
|
||||
return $builder
|
||||
->orderBy('orders.id', 'DESC')
|
||||
->get()
|
||||
->getResultArray();
|
||||
}
|
||||
|
||||
return $builder
|
||||
->where('orders.store_id', $user['store_id'])
|
||||
->orderBy('orders.id', 'DESC')
|
||||
->get()
|
||||
->getResultArray();
|
||||
}
|
||||
|
||||
// Autres utilisateurs : filtrage par magasin
|
||||
return $builder
|
||||
->where('orders.store_id', $user['store_id'])
|
||||
->orderBy('orders.id', 'DESC')
|
||||
->get()
|
||||
->getResultArray();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function getOrdersDataByBillNo(string $id = null)
|
||||
{
|
||||
$session = session();
|
||||
@ -356,24 +359,27 @@ class Orders extends Model
|
||||
*/
|
||||
public function countTotalPaidOrders()
|
||||
{
|
||||
return $this->where('paid_status', 1)->countAllResults();
|
||||
return $this->whereIn('paid_status', [1, 3])->countAllResults();
|
||||
}
|
||||
|
||||
public function getPaidOrderData()
|
||||
{
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
$users = $session->get('user');
|
||||
$isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']);
|
||||
if($isAdmin) {
|
||||
return $this->where('paid_status', 1)->orderBy('id', 'DESC')->findAll();
|
||||
}
|
||||
else{
|
||||
return $this->where('paid_status', 1)
|
||||
->where('store_id', $users['store_id'])
|
||||
->orderBy('id', 'DESC')->findAll();
|
||||
|
||||
if($isAdmin) {
|
||||
return $this->whereIn('paid_status', [1, 3]) // ← Ajoutez 3 ici
|
||||
->orderBy('id', 'DESC')
|
||||
->findAll();
|
||||
}
|
||||
}
|
||||
else {
|
||||
return $this->whereIn('paid_status', [1, 3]) // ← Ajoutez 3 ici
|
||||
->where('store_id', $users['store_id'])
|
||||
->orderBy('id', 'DESC')
|
||||
->findAll();
|
||||
}
|
||||
}
|
||||
|
||||
public function getSingleStat(int $id)
|
||||
{
|
||||
@ -386,46 +392,87 @@ class Orders extends Model
|
||||
public function getPaymentModes()
|
||||
{
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
$users = $session->get('user');
|
||||
$isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']);
|
||||
if($isAdmin){
|
||||
return $this->db->table('orders')
|
||||
|
||||
$baseQuery = $this->db->table('orders')
|
||||
->select('
|
||||
SUM(net_amount) AS total,
|
||||
SUM(CASE WHEN orders.order_payment_mode = "MVOLA" THEN tranche_1 ELSE 0 END) AS total_mvola1,
|
||||
SUM(CASE WHEN orders.order_payment_mode = "MVOLA" THEN tranche_2 ELSE 0 END) AS total_mvola2,
|
||||
SUM(CASE WHEN orders.order_payment_mode = "En espèce" THEN tranche_1 ELSE 0 END) AS total_espece1,
|
||||
SUM(CASE WHEN orders.order_payment_mode = "En espèce" THEN tranche_2 ELSE 0 END) AS total_espece2,
|
||||
SUM(CASE WHEN orders.order_payment_mode = "Virement bancaire" THEN tranche_1 ELSE 0 END) AS total_virement_bancaire1,
|
||||
SUM(CASE WHEN orders.order_payment_mode = "Virement bancaire" THEN tranche_2 ELSE 0 END) AS total_virement_bancaire2
|
||||
|
||||
SUM(CASE
|
||||
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
|
||||
THEN orders.discount
|
||||
ELSE orders.net_amount
|
||||
END) AS total,
|
||||
|
||||
|
||||
SUM(CASE
|
||||
WHEN orders.order_payment_mode = "MVOLA" THEN
|
||||
CASE
|
||||
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
|
||||
THEN (orders.tranche_1 * orders.discount / orders.net_amount)
|
||||
ELSE orders.tranche_1
|
||||
END
|
||||
ELSE 0
|
||||
END) AS total_mvola1,
|
||||
SUM(CASE
|
||||
WHEN orders.order_payment_mode_1 = "MVOLA" THEN
|
||||
CASE
|
||||
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
|
||||
THEN (orders.tranche_2 * orders.discount / orders.net_amount)
|
||||
ELSE orders.tranche_2
|
||||
END
|
||||
ELSE 0
|
||||
END) AS total_mvola2,
|
||||
|
||||
|
||||
SUM(CASE
|
||||
WHEN orders.order_payment_mode = "En espèce" THEN
|
||||
CASE
|
||||
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
|
||||
THEN (orders.tranche_1 * orders.discount / orders.net_amount)
|
||||
ELSE orders.tranche_1
|
||||
END
|
||||
ELSE 0
|
||||
END) AS total_espece1,
|
||||
SUM(CASE
|
||||
WHEN orders.order_payment_mode_1 = "En espèce" THEN
|
||||
CASE
|
||||
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
|
||||
THEN (orders.tranche_2 * orders.discount / orders.net_amount)
|
||||
ELSE orders.tranche_2
|
||||
END
|
||||
ELSE 0
|
||||
END) AS total_espece2,
|
||||
|
||||
|
||||
SUM(CASE
|
||||
WHEN orders.order_payment_mode = "Virement bancaire" THEN
|
||||
CASE
|
||||
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
|
||||
THEN (orders.tranche_1 * orders.discount / orders.net_amount)
|
||||
ELSE orders.tranche_1
|
||||
END
|
||||
ELSE 0
|
||||
END) AS total_virement_bancaire1,
|
||||
SUM(CASE
|
||||
WHEN orders.order_payment_mode_1 = "Virement bancaire" THEN
|
||||
CASE
|
||||
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
|
||||
THEN (orders.tranche_2 * orders.discount / orders.net_amount)
|
||||
ELSE orders.tranche_2
|
||||
END
|
||||
ELSE 0
|
||||
END) AS total_virement_bancaire2
|
||||
')
|
||||
->where('orders.paid_status', 1)
|
||||
->get()
|
||||
->getRowObject();
|
||||
}
|
||||
else{
|
||||
return $this->db->table('orders')
|
||||
->select('
|
||||
SUM(net_amount) AS total,
|
||||
SUM(CASE WHEN orders.order_payment_mode = "MVOLA" THEN tranche_1 ELSE 0 END) AS total_mvola1,
|
||||
SUM(CASE WHEN orders.order_payment_mode = "MVOLA" THEN tranche_2 ELSE 0 END) AS total_mvola2,
|
||||
SUM(CASE WHEN orders.order_payment_mode = "En espèce" THEN tranche_1 ELSE 0 END) AS total_espece1,
|
||||
SUM(CASE WHEN orders.order_payment_mode = "En espèce" THEN tranche_2 ELSE 0 END) AS total_espece2,
|
||||
SUM(CASE WHEN orders.order_payment_mode = "Virement bancaire" THEN tranche_1 ELSE 0 END) AS total_virement_bancaire1,
|
||||
SUM(CASE WHEN orders.order_payment_mode = "Virement bancaire" THEN tranche_2 ELSE 0 END) AS total_virement_bancaire2
|
||||
')
|
||||
->where('orders.paid_status', 1)
|
||||
->where('orders.store_id', $users['store_id'])
|
||||
->get()
|
||||
->getRowObject();
|
||||
->whereIn('orders.paid_status', [1, 3]); // ← CHANGEZ CETTE LIGNE
|
||||
|
||||
if (!$isAdmin) {
|
||||
$baseQuery->where('orders.store_id', $users['store_id']);
|
||||
}
|
||||
|
||||
return $baseQuery->get()->getRowObject();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public function getTotalOrders()
|
||||
{
|
||||
return $this->db->table('orders')
|
||||
@ -497,13 +544,13 @@ class Orders extends Model
|
||||
->join('orders_item', 'orders.id = orders_item.order_id')
|
||||
->join('products', 'orders_item.product_id = products.id')
|
||||
->join('brands', 'brands.id = products.marque')
|
||||
->where('orders.paid_status', 1)
|
||||
->whereIn('orders.paid_status', [1, 3]) // ← CHANGÉ ICI
|
||||
->get()
|
||||
->getResult(); // Return a single object
|
||||
|
||||
->getResult();
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
|
||||
public function getTotalProductvente2(?int $id)
|
||||
{
|
||||
if ($id != 0) {
|
||||
@ -512,35 +559,44 @@ class Orders extends Model
|
||||
->join('orders_item', 'orders.id = orders_item.order_id')
|
||||
->join('products', 'orders_item.product_id = products.id')
|
||||
->join('brands', 'brands.id = products.marque')
|
||||
->where('orders.paid_status', 1)
|
||||
->whereIn('orders.paid_status', [1, 3]) // ← CHANGÉ ICI
|
||||
->where('orders.store_id', $id)
|
||||
->get()
|
||||
->getResult(); // Return a single object
|
||||
->getResult();
|
||||
} else {
|
||||
$order = $this->db->table('orders')
|
||||
->select('orders.id, orders.paid_status, orders.store_id, orders.date_time, brands.name, products.name as Pname, products.sku')
|
||||
->join('orders_item', 'orders.id = orders_item.order_id')
|
||||
->join('products', 'orders_item.product_id = products.id')
|
||||
->join('brands', 'brands.id = products.marque')
|
||||
->where('orders.paid_status', 1)
|
||||
->whereIn('orders.paid_status', [1, 3]) // ← CHANGÉ ICI
|
||||
->get()
|
||||
->getResult(); // Return a single object
|
||||
->getResult();
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
public function getOrderVendue()
|
||||
{
|
||||
$order = $this->db->table('products')
|
||||
->select('products.*, products.name as Pname, products.sku, (orders_item.amount - orders.discount) as totalNet, orders.date_time as DateTime')
|
||||
->select('
|
||||
products.*,
|
||||
products.name as Pname,
|
||||
products.sku,
|
||||
CASE
|
||||
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
|
||||
THEN orders.discount
|
||||
ELSE orders.gross_amount
|
||||
END as totalNet,
|
||||
orders.date_time as DateTime
|
||||
', false) // ← MODIFIÉ ICI
|
||||
->join('orders_item', 'products.id = orders_item.product_id')
|
||||
->join('orders', 'orders_item.order_id = orders.id')
|
||||
->where('orders.paid_status', 1)
|
||||
->whereIn('orders.paid_status', [1, 3]) // ← ET ICI
|
||||
->get()
|
||||
->getResultArray(); // Return a single object
|
||||
|
||||
->getResultArray();
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
@ -552,31 +608,32 @@ class Orders extends Model
|
||||
->join('orders_item', 'orders.id = orders_item.order_id')
|
||||
->join('products', 'products.id = orders_item.product_id')
|
||||
->join('users', 'users.id = orders.user_id')
|
||||
->where('orders.paid_status', 1)
|
||||
->whereIn('orders.paid_status', [1, 3])
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
|
||||
return $Performance;
|
||||
}
|
||||
|
||||
// for Adminan cheffe d'agence
|
||||
public function getPerformanceByOrders1()
|
||||
{
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
$Performance = $this->db
|
||||
->table('orders')
|
||||
->select('orders.id as orderid, orders.net_amount, orders.date_time as datevente, orders.discount, products.price, products.sku, products.prix_vente, products.name as motoname, stores.id as store_id, users.firstname, users.lastname, users.email')
|
||||
->join('stores', 'orders.store_id = stores.id')
|
||||
->join('orders_item', 'orders.id = orders_item.order_id')
|
||||
->join('products', 'products.id = orders_item.product_id')
|
||||
->join('users', 'users.id = orders.user_id')
|
||||
->where('orders.paid_status', 1)
|
||||
->where('orders.store_id', $users["store_id"])
|
||||
->get()
|
||||
->getResultArray();
|
||||
public function getPerformanceByOrders1()
|
||||
{
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
$Performance = $this->db
|
||||
->table('orders')
|
||||
->select('orders.id as orderid, orders.net_amount, orders.date_time as datevente, orders.discount, products.price, products.sku, products.prix_vente, products.name as motoname, stores.id as store_id, users.firstname, users.lastname, users.email')
|
||||
->join('stores', 'orders.store_id = stores.id')
|
||||
->join('orders_item', 'orders.id = orders_item.order_id')
|
||||
->join('products', 'products.id = orders_item.product_id')
|
||||
->join('users', 'users.id = orders.user_id')
|
||||
->whereIn('orders.paid_status', [1, 3])
|
||||
->where('orders.store_id', $users["store_id"])
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
return $Performance;
|
||||
}
|
||||
return $Performance;
|
||||
}
|
||||
|
||||
// for commerciale
|
||||
public function getPerformanceByOrders2()
|
||||
@ -590,14 +647,13 @@ class Orders extends Model
|
||||
->join('orders_item', 'orders.id = orders_item.order_id')
|
||||
->join('products', 'products.id = orders_item.product_id')
|
||||
->join('users', 'users.id = orders.user_id')
|
||||
->where('orders.paid_status', 1)
|
||||
->whereIn('orders.paid_status', [1, 3])
|
||||
->where('orders.user_id', $users["id"])
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
|
||||
return $Performance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function update1(int $id, $data1,$data2)
|
||||
@ -614,9 +670,6 @@ class Orders extends Model
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public function getUserList()
|
||||
{
|
||||
$session = session();
|
||||
@ -640,103 +693,102 @@ class Orders extends Model
|
||||
|
||||
|
||||
public function getUserPerformanceToday(string $date)
|
||||
{
|
||||
$users = $this->getUserList();
|
||||
$results = [];
|
||||
|
||||
foreach ($users as $user) {
|
||||
// 1) Récupérer count et sum
|
||||
$summary = $this->db->table('orders')
|
||||
->select('COUNT(id) AS total_user_order, SUM(net_amount) AS total_prix_vente')
|
||||
->where('user_id', $user->user_id)
|
||||
->where('DATE(date_time)', $date)
|
||||
->where('paid_status', 1)
|
||||
->get()
|
||||
->getRow();
|
||||
|
||||
// 2) Récupérer la liste des order_id
|
||||
$ids = $this->db->table('orders')
|
||||
->select('id')
|
||||
->where('user_id', $user->user_id)
|
||||
->where('DATE(date_time)', $date)
|
||||
->where('paid_status', 1)
|
||||
->get()
|
||||
->getResult();
|
||||
|
||||
$orderIds = array_map(fn($o) => $o->id, $ids);
|
||||
|
||||
// 3) Composer le résultat pour cet utilisateur
|
||||
$results[] = [
|
||||
'user_id' => $user->user_id,
|
||||
'full_name' => $user->full_name,
|
||||
'total_user_order' => $summary->total_user_order,
|
||||
'total_prix_vente' => $summary->total_prix_vente,
|
||||
'order_ids' => $orderIds,
|
||||
];
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
|
||||
public function getUserPerformanceByWeek(string $date = null)
|
||||
{
|
||||
$users = $this->getUserList();
|
||||
$results = [];
|
||||
|
||||
// Si aucune date fournie, on prend aujourd'hui
|
||||
if ($date === null) {
|
||||
$date = date('Y-m-d');
|
||||
}
|
||||
|
||||
// Trouver le lundi et le dimanche de la semaine de $date
|
||||
$timestamp = strtotime($date);
|
||||
$startOfWeek = date('Y-m-d', strtotime('monday this week', $timestamp));
|
||||
$endOfWeek = date('Y-m-d', strtotime('sunday this week', $timestamp));
|
||||
|
||||
foreach ($users as $user) {
|
||||
// 1) Récupérer count et sum pour la semaine
|
||||
$summary = $this->db->table('orders')
|
||||
->select('COUNT(id) AS total_user_order, SUM(net_amount) AS total_prix_vente')
|
||||
->where('user_id', $user->user_id)
|
||||
->where('DATE(date_time) >=', $startOfWeek)
|
||||
->where('DATE(date_time) <=', $endOfWeek)
|
||||
->where('paid_status', 1)
|
||||
->get()
|
||||
->getRow();
|
||||
|
||||
// 2) Récupérer la liste des order_id de la semaine
|
||||
$ids = $this->db->table('orders')
|
||||
->select('id')
|
||||
->where('user_id', $user->user_id)
|
||||
->where('DATE(date_time) >=', $startOfWeek)
|
||||
->where('DATE(date_time) <=', $endOfWeek)
|
||||
->where('paid_status', 1)
|
||||
->get()
|
||||
->getResult();
|
||||
|
||||
$orderIds = array_map(fn($o) => $o->id, $ids);
|
||||
|
||||
// 3) Résultat pour l'utilisateur
|
||||
$results[] = [
|
||||
'user_id' => $user->user_id,
|
||||
'full_name' => $user->full_name,
|
||||
'total_user_order' => $summary->total_user_order ?? 0,
|
||||
'total_prix_vente' => $summary->total_prix_vente ?? 0,
|
||||
'order_ids' => $orderIds,
|
||||
];
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
{
|
||||
$users = $this->getUserList();
|
||||
$results = [];
|
||||
|
||||
foreach ($users as $user) {
|
||||
$summary = $this->db->table('orders')
|
||||
->select('COUNT(id) AS total_user_order, SUM(net_amount) AS total_prix_vente')
|
||||
->where('user_id', $user->user_id)
|
||||
->where('DATE(date_time)', $date)
|
||||
->whereIn('paid_status', [1, 3])
|
||||
->get()
|
||||
->getRow();
|
||||
|
||||
$ids = $this->db->table('orders')
|
||||
->select('id')
|
||||
->where('user_id', $user->user_id)
|
||||
->where('DATE(date_time)', $date)
|
||||
->whereIn('paid_status', [1, 3])
|
||||
->get()
|
||||
->getResult();
|
||||
|
||||
$orderIds = array_map(fn($o) => $o->id, $ids);
|
||||
|
||||
$results[] = [
|
||||
'user_id' => $user->user_id,
|
||||
'full_name' => $user->full_name,
|
||||
'total_user_order' => $summary->total_user_order,
|
||||
'total_prix_vente' => $summary->total_prix_vente,
|
||||
'order_ids' => $orderIds,
|
||||
];
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
public function getUserPerformanceByWeek(string $date = null)
|
||||
{
|
||||
$users = $this->getUserList();
|
||||
$results = [];
|
||||
|
||||
if ($date === null) {
|
||||
$date = date('Y-m-d');
|
||||
}
|
||||
|
||||
$timestamp = strtotime($date);
|
||||
$startOfWeek = date('Y-m-d', strtotime('monday this week', $timestamp));
|
||||
$endOfWeek = date('Y-m-d', strtotime('sunday this week', $timestamp));
|
||||
|
||||
foreach ($users as $user) {
|
||||
$summary = $this->db->table('orders')
|
||||
->select('COUNT(id) AS total_user_order, SUM(net_amount) AS total_prix_vente')
|
||||
->where('user_id', $user->user_id)
|
||||
->where('DATE(date_time) >=', $startOfWeek)
|
||||
->where('DATE(date_time) <=', $endOfWeek)
|
||||
->whereIn('paid_status', [1, 3])
|
||||
->get()
|
||||
->getRow();
|
||||
|
||||
$ids = $this->db->table('orders')
|
||||
->select('id')
|
||||
->where('user_id', $user->user_id)
|
||||
->where('DATE(date_time) >=', $startOfWeek)
|
||||
->where('DATE(date_time) <=', $endOfWeek)
|
||||
->whereIn('paid_status', [1, 3])
|
||||
->get()
|
||||
->getResult();
|
||||
|
||||
$orderIds = array_map(fn($o) => $o->id, $ids);
|
||||
|
||||
$results[] = [
|
||||
'user_id' => $user->user_id,
|
||||
'full_name' => $user->full_name,
|
||||
'total_user_order' => $summary->total_user_order ?? 0,
|
||||
'total_prix_vente' => $summary->total_prix_vente ?? 0,
|
||||
'order_ids' => $orderIds,
|
||||
];
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
public function checkMinimalPrice($product_id, $discount)
|
||||
{
|
||||
$fourchetteModel = new FourchettePrix(); // plus court car on a "use"
|
||||
$row = $fourchetteModel->where('product_id', $product_id)->first();
|
||||
|
||||
if ($row) {
|
||||
return ($discount >= $row['prix_minimal']);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function getUserPerformanceByMonth(string $month)
|
||||
{
|
||||
// Calcul du premier et dernier jour du mois donné
|
||||
$startOfMonth = date('Y-m-01', strtotime($month . '-01'));
|
||||
$endOfMonth = date('Y-m-t', strtotime($month . '-01'));
|
||||
|
||||
@ -744,29 +796,26 @@ public function getUserPerformanceByMonth(string $month)
|
||||
$results = [];
|
||||
|
||||
foreach ($users as $user) {
|
||||
// 1) Récupérer les stats du mois
|
||||
$orderData = $this->db->table('orders')
|
||||
->select('COUNT(id) as total_user_order, SUM(net_amount) as total_prix_vente')
|
||||
->where('user_id', $user->user_id)
|
||||
->where('DATE(date_time) >=', $startOfMonth)
|
||||
->where('DATE(date_time) <=', $endOfMonth)
|
||||
->where('paid_status', 1)
|
||||
->whereIn('paid_status', [1, 3])
|
||||
->get()
|
||||
->getRow();
|
||||
|
||||
// 2) Récupérer les IDs des commandes du mois
|
||||
$ids = $this->db->table('orders')
|
||||
->select('id')
|
||||
->where('user_id', $user->user_id)
|
||||
->where('DATE(date_time) >=', $startOfMonth)
|
||||
->where('DATE(date_time) <=', $endOfMonth)
|
||||
->where('paid_status', 1)
|
||||
->whereIn('paid_status', [1, 3])
|
||||
->get()
|
||||
->getResult();
|
||||
|
||||
$orderIds = array_map(fn($o) => $o->id, $ids);
|
||||
|
||||
// 3) Composer les résultats
|
||||
$results[] = [
|
||||
'user_id' => $user->user_id,
|
||||
'full_name' => $user->full_name,
|
||||
|
||||
@ -153,15 +153,32 @@ class Products extends Model
|
||||
return $this->delete($id) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* count all product
|
||||
*/
|
||||
public function countTotalProducts()
|
||||
{
|
||||
$db = \Config\Database::connect();
|
||||
|
||||
// Sous-requête pour obtenir les product_id dans avances actives
|
||||
$subQuery = $db->table('avances')
|
||||
->select('product_id')
|
||||
->where('active', 1)
|
||||
->where('is_order', 0)
|
||||
->getCompiledSelect();
|
||||
|
||||
// Compter les produits disponibles
|
||||
return $this->where('is_piece', 0)
|
||||
->where('product_sold', 0)
|
||||
->where("id NOT IN ($subQuery)", null, false)
|
||||
->countAllResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* count all products including sold and reserved (méthode originale si besoin)
|
||||
*/
|
||||
public function countAllProductsIncludingSold()
|
||||
{
|
||||
return $this->countAll();
|
||||
}
|
||||
|
||||
|
||||
public function getTotalProductPriceByIds(array $productIds)
|
||||
{
|
||||
try {
|
||||
|
||||
@ -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'], ['Conseil', 'Direction']);
|
||||
$isAdmin = in_array($users['group_name'], ['DAF', 'Direction']);
|
||||
if($isAdmin){
|
||||
if ($id) {
|
||||
return $this->db->table('recouvrement')
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<?php
|
||||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
use App\Models\Orders;
|
||||
use DateTime;
|
||||
@ -12,120 +11,111 @@ class Remise extends Model
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'demande_remise';
|
||||
protected $primaryKey = 'id_demande'; // Primary key column
|
||||
protected $primaryKey = 'id_demande';
|
||||
protected $allowedFields = ['id_order', 'montant_demande', 'date_demande','product','id_store','demande_status','total_price'];
|
||||
|
||||
|
||||
public function getAllDemandeRemiseToday()
|
||||
{
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
if ($users["group_name"] === "Conseil") {
|
||||
try {
|
||||
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
$users = session()->get('user_data');
|
||||
if($users['group_name'] === "Direction"){
|
||||
return $this ->where('demande_status', 'En attente')
|
||||
->orderBy('date_demande', 'DESC')
|
||||
->findAll();
|
||||
}
|
||||
return $this->where('demande_status', 'En attente')
|
||||
->orderBy('date_demande', 'DESC')
|
||||
->findAll();
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
log_message('error', 'Erreur lors de la récupération des demandes du jour : ' . $e->getMessage());
|
||||
return [];
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
|
||||
return $this
|
||||
->where('id_store',$users['store_id'])
|
||||
->orderBy('date_demande', 'DESC')
|
||||
->findAll();
|
||||
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
|
||||
// Si le rôle est CONSEIL → voir toutes les demandes "En attente"
|
||||
if ($users["group_name"] === "Conseil") {
|
||||
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") {
|
||||
return $this->orderBy('date_demande', 'DESC')
|
||||
->findAll();
|
||||
}
|
||||
|
||||
// Autres rôles (Caissière, etc.) → voir uniquement celles de son 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());
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function addDemande( array $data) {
|
||||
|
||||
public function addDemande(array $data)
|
||||
{
|
||||
try {
|
||||
return $this->insert($data);
|
||||
return $this->insert($data);
|
||||
} catch (\Exception $e) {
|
||||
log_message('error', 'Erreur lors de l\'ajout de la demande de remise : ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getRemiseData1(int $remise_id){
|
||||
return $this->select('montant_demande','id_order')
|
||||
->where('id_demande',$remise_id)
|
||||
->first();
|
||||
|
||||
public function getRemiseData1(int $remise_id)
|
||||
{
|
||||
return $this->select('montant_demande, id_order')
|
||||
->where('id_demande', $remise_id)
|
||||
->first();
|
||||
}
|
||||
|
||||
public function updateRemise( $id,$data) {
|
||||
|
||||
/**
|
||||
* 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')
|
||||
->where('id_demande', $id_demande)
|
||||
->first();
|
||||
|
||||
return $result['id_order'] ?? null;
|
||||
}
|
||||
|
||||
public function updateRemise($id, $data)
|
||||
{
|
||||
if ($id <= 0) {
|
||||
log_message('error', 'ID invalide pour la mise à jour du recouvrement : ' . $id);
|
||||
log_message('error', 'ID invalide pour la mise à jour de la demande : ' . $id);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
// Essayer de mettre à jour les données
|
||||
return $this->update($id, $data);
|
||||
if ($data['demande_status'] == 'accepte') {
|
||||
$Order = new Orders();
|
||||
$remise_data = $this->getRemiseData1($id);
|
||||
$montant_demande = $remise_data->montant_demande;
|
||||
$order_id = $remise_data->id_order;
|
||||
$data1 = [
|
||||
'net_amount' => $montant_demande,
|
||||
'gross_amount' => $montant_demande
|
||||
];
|
||||
$data2 = [
|
||||
'rate' => $montant_demande,
|
||||
'amount' => $montant_demande
|
||||
];
|
||||
$Order->update1($order_id, $data1,$data2);
|
||||
}
|
||||
// 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) {
|
||||
// En cas d'exception, loguer l'erreur
|
||||
log_message('error', 'Erreur lors de la mise à jour du recouvrement : ' . $e->getMessage());
|
||||
return false;
|
||||
log_message('error', 'Erreur lors de la mise à jour de la demande : ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getProductByDemandeId(int $id_demande): ?string
|
||||
{
|
||||
$row = $this
|
||||
->select('product')
|
||||
->where('id_order', $id_demande)
|
||||
->first();
|
||||
|
||||
$row = $this->select('product')
|
||||
->where('id_demande', $id_demande)
|
||||
->first();
|
||||
|
||||
return $row['product'] ?? null;
|
||||
}
|
||||
|
||||
public function updateRemise1(int $id,$data)
|
||||
{
|
||||
$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.";
|
||||
|
||||
public function updateRemise1(int $id, $data)
|
||||
{
|
||||
$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.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
|
||||
class Reports extends Model
|
||||
@ -11,7 +9,7 @@ class Reports extends Model
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'orders';
|
||||
|
||||
|
||||
/**
|
||||
* total month
|
||||
* @return array<int|string>
|
||||
@ -20,22 +18,22 @@ class Reports extends Model
|
||||
{
|
||||
return ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Getting the year of the orders (paid_status = 1)
|
||||
* Getting the year of the orders (paid_status = 1 or 3)
|
||||
* @return array
|
||||
*/
|
||||
public function getOrderYear()
|
||||
{
|
||||
$result = $this->where('paid_status', 1)->findAll();
|
||||
|
||||
$result = $this->whereIn('paid_status', [1, 3])->findAll(); // ← CHANGÉ ICI
|
||||
|
||||
$return_data = array_map(function($v) {
|
||||
return date('Y', strtotime($v['date_time']));
|
||||
}, $result);
|
||||
|
||||
|
||||
return array_values(array_unique($return_data));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Getting the order reports based on the year and months
|
||||
* @param mixed $year
|
||||
@ -45,28 +43,33 @@ class Reports extends Model
|
||||
{
|
||||
if ($year) {
|
||||
$months = $this->months();
|
||||
|
||||
// Fetch orders with paid_status = 1 or 3
|
||||
$result = $this->whereIn('paid_status', [1, 3])->findAll();
|
||||
|
||||
// Fetch orders with paid_status = 1
|
||||
$result = $this->where('paid_status', 1)->findAll();
|
||||
|
||||
$final_data = [];
|
||||
|
||||
|
||||
foreach ($months as $month) {
|
||||
$get_mon_year = $year . '-' . $month;
|
||||
$final_data[$get_mon_year] = [];
|
||||
|
||||
|
||||
foreach ($result as $v) {
|
||||
$month_year = date('Y-m', strtotime($v['date_time']));
|
||||
if ($get_mon_year == $month_year) {
|
||||
// Modifier le montant selon votre logique
|
||||
if (!empty($v['discount']) && $v['discount'] > 0) {
|
||||
$v['amount_to_display'] = $v['discount']; // Utiliser le rabais
|
||||
} else {
|
||||
$v['amount_to_display'] = $v['gross_amount']; // Utiliser gross_amount
|
||||
}
|
||||
$final_data[$get_mon_year][] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// die(var_dump($final_data));
|
||||
|
||||
return $final_data;
|
||||
}
|
||||
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@ -11,109 +11,138 @@ class SortieCaisse extends Model
|
||||
*/
|
||||
protected $table = 'sortie_caisse';
|
||||
protected $primaryKey = 'id_sortie'; // Primary key column
|
||||
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'
|
||||
];
|
||||
// Dans le fichier App/Models/SortieCaisse.php
|
||||
// Mettre à jour le tableau $allowedFields
|
||||
|
||||
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');
|
||||
if ($users['group_name'] === 'Direction') {
|
||||
return $this
|
||||
->select('*')
|
||||
->orderBy('date_retrait', 'DESC')
|
||||
->findAll();
|
||||
}
|
||||
|
||||
if ($users['group_name'] === 'Conseil') {
|
||||
return $this
|
||||
->select('*')
|
||||
->orderBy('date_retrait', 'DESC')
|
||||
->findAll();
|
||||
}
|
||||
|
||||
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 [];
|
||||
}
|
||||
}
|
||||
|
||||
public function getAllSortieCaisse1()
|
||||
{
|
||||
try {
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
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)
|
||||
->orderBy('date_retrait', 'DESC')
|
||||
->findAll();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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 [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function addSortieCaisse( array $data) {
|
||||
{
|
||||
try {
|
||||
return $this->insert($data);
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
if ($users['group_name'] === 'Direction') {
|
||||
return $this
|
||||
->select('*')
|
||||
->orderBy('date_retrait', 'DESC')
|
||||
->findAll();
|
||||
}
|
||||
|
||||
if ($users['group_name'] === 'Conseil') {
|
||||
return $this
|
||||
->select('*')
|
||||
->orderBy('date_retrait', 'DESC')
|
||||
->findAll();
|
||||
}
|
||||
|
||||
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 [];
|
||||
}
|
||||
}
|
||||
|
||||
public function getAllSortieCaisse1()
|
||||
{
|
||||
try {
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
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)
|
||||
->orderBy('date_retrait', 'DESC')
|
||||
->findAll();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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 [];
|
||||
}
|
||||
}
|
||||
|
||||
public function addSortieCaisse(array $data) {
|
||||
try {
|
||||
return $this->insert($data);
|
||||
} catch (\Exception $e) {
|
||||
log_message('error', 'Erreur lors de l\'ajout de la sortie : ' . $e->getMessage());
|
||||
return false;
|
||||
@ -121,17 +150,14 @@ public function getAllSortieCaisse1()
|
||||
}
|
||||
|
||||
public function updateSortieCaisse(int $id, array $data) {
|
||||
// Vérifier si l'ID est valide (par exemple, positif et non nul)
|
||||
if ($id <= 0) {
|
||||
log_message('error', 'ID invalide pour la mise à jour de la sortie caisse : ' . $id);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// Essayer de mettre à jour les données
|
||||
return $this->update($id, $data);
|
||||
} catch (\Exception $e) {
|
||||
// En cas d'exception, loguer l'erreur
|
||||
log_message('error', 'Erreur lors de la mise à jour du recouvrement : ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
@ -142,35 +168,55 @@ public function getAllSortieCaisse1()
|
||||
$reparation = $this->select('*')
|
||||
->where('id_sortie', $id)
|
||||
->first();
|
||||
// return $this->where('user_id', $id)->findAll();
|
||||
|
||||
return $reparation;
|
||||
}
|
||||
|
||||
public function getTotalSortieCaisse() {
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
$users = $session->get('user');
|
||||
$isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']);
|
||||
|
||||
if ($isAdmin) {
|
||||
try {
|
||||
return $this->select('
|
||||
SUM(montant_retire) AS mr,
|
||||
|
||||
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
|
||||
')
|
||||
->where('statut', "Valider")
|
||||
->whereIn('statut', ['Valider', 'Payé'])
|
||||
->get()
|
||||
->getRowObject();
|
||||
} catch (\Exception $e) {
|
||||
log_message('error', 'Erreur lors de la récupération des sorties caisse : ' . $e->getMessage());
|
||||
return false;
|
||||
log_message('error', 'Erreur getTotalSortieCaisse (Admin) : ' . $e->getMessage());
|
||||
return (object)[
|
||||
'total_espece' => 0,
|
||||
'total_mvola' => 0,
|
||||
'total_virement' => 0,
|
||||
'mr' => 0
|
||||
];
|
||||
}
|
||||
} else {
|
||||
return $this->select('SUM(montant_retire) AS mr')
|
||||
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
|
||||
')
|
||||
->where('store_id', $users['store_id'])
|
||||
->where('statut', "Valider")
|
||||
->whereIn('statut', ['Valider', 'Payé'])
|
||||
->get()
|
||||
->getRowObject();
|
||||
} catch (\Exception $e) {
|
||||
log_message('error', 'Erreur getTotalSortieCaisse (Store) : ' . $e->getMessage());
|
||||
return (object)[
|
||||
'total_espece' => 0,
|
||||
'total_mvola' => 0,
|
||||
'total_virement' => 0,
|
||||
'mr' => 0
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
<!-- Content Wrapper. Contains page content -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
@ -96,56 +98,51 @@
|
||||
<div class="modal-content">
|
||||
<form id="create_avance_form">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title"> Ajouter une avance </h4>
|
||||
<h4 class="modal-title">Ajouter une avance</h4>
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<!-- type d'avance -->
|
||||
<!-- <div class="form-group col-md-6">
|
||||
<label for="id_product" class="form-label">Type d'avance</label>
|
||||
<select name="id_product" id="id_product" class="form-control " required>
|
||||
<option value="" disabled selected>Sélectionnez un type d'avance </option>
|
||||
<option value="terre">Avance sur terre</option>
|
||||
<option value="mere">Avance sur mère</option>
|
||||
<!-- Type d'avance -->
|
||||
<div class="form-group col-md-6">
|
||||
<label for="type_avance" class="form-label">Type d'avance</label>
|
||||
<select name="type_avance" id="type_avance" class="form-control" required>
|
||||
<option value="" disabled selected>Sélectionnez un type d'avance</option>
|
||||
<option value="terre">Avance sur terre</option>
|
||||
<option value="mere">Avance sur mer</option>
|
||||
</select>
|
||||
</div> -->
|
||||
<div class="form-group col-md-6">
|
||||
<label for="type_avance" class="form-label">Type d'avance</label>
|
||||
<select name="type_avance" id="type_avance" class="form-control" required>
|
||||
<option value="" disabled selected>Sélectionnez un type d'avance</option>
|
||||
<option value="terre">Avance sur terre</option>
|
||||
<option value="mere">Avance sur mère</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="type_avance" class="form-label">Moyen de payment</label>
|
||||
<select class="form-control" id="type_payment" name="type_payment">
|
||||
<option value="" disabled selected>Sélectionnez un moyen de payement</option>
|
||||
<option value="MVOLA">MVOLA</option>
|
||||
<option value="Virement Bancaire">Virement Bancaire</option>
|
||||
<option value="En espèce">En espèce</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Moyen de paiement -->
|
||||
<div class="form-group col-md-6">
|
||||
<label for="type_payment" class="form-label">Moyen de paiement</label>
|
||||
<select class="form-control" id="type_payment" name="type_payment">
|
||||
<option value="" disabled selected>Sélectionnez un moyen de paiement</option>
|
||||
<option value="MVOLA">MVOLA</option>
|
||||
<option value="Virement Bancaire">Virement Bancaire</option>
|
||||
<option value="En espèce">En espèce</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Nom client -->
|
||||
<div class="form-group col-md-6">
|
||||
<label>Nom du client</label>
|
||||
<input type="text" name="customer_name_avance" id="customer_name_avance" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<!-- Téléphone client -->
|
||||
<div class="form-group col-md-6">
|
||||
<label>Téléphone du client</label>
|
||||
<input type="text" name="customer_phone_avance" id="customer_phone_avance" class="form-control" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- Adresse client -->
|
||||
<div class="form-group col-md-6">
|
||||
<label>Adresse du client</label>
|
||||
<input type="text" name="customer_address_avance" id="customer_address_avance" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<!-- CIN client -->
|
||||
<div class="form-group col-md-6">
|
||||
<label>CIN du client</label>
|
||||
@ -154,10 +151,10 @@
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- Produit -->
|
||||
<div class="form-group col-md-6">
|
||||
<!-- Produit avec sélection (pour "terre") -->
|
||||
<div class="form-group col-md-6" id="product_select_container">
|
||||
<label for="id_product" class="form-label">Produit</label>
|
||||
<select name="id_product" id="id_product" class="form-control" onchange="getProductDataCreate()" required>
|
||||
<select name="id_product" id="id_product" class="form-control" onchange="getProductDataCreate()">
|
||||
<option value="">Sélectionnez un produit</option>
|
||||
<?php foreach($products as $p): ?>
|
||||
<option value="<?= $p['id'] ?>" <?= $p['product_sold'] ? 'disabled' : '' ?>>
|
||||
@ -166,10 +163,17 @@
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<!-- Prix brut -->
|
||||
|
||||
<!-- Produit avec texte libre (pour "mère") -->
|
||||
<div class="form-group col-md-6" id="product_text_container" style="display:none;">
|
||||
<label>Produit (à compléter)</label>
|
||||
<input type="text" name="product_name_text" id="product_name_text" class="form-control" placeholder="Entrez le nom du produit">
|
||||
</div>
|
||||
|
||||
<!-- Prix du produit -->
|
||||
<div class="form-group col-md-6">
|
||||
<label>Prix du produit</label>
|
||||
<input type="text" name="gross_amount" id="gross_amount" class="form-control" readonly>
|
||||
<input type="number" name="gross_amount" id="gross_amount" class="form-control" placeholder="Entrez le prix">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -177,15 +181,25 @@
|
||||
<!-- Avance -->
|
||||
<div class="form-group col-md-6">
|
||||
<label>Avance</label>
|
||||
<input type="number" name="avance_amount" id="avance_amount" class="form-control" onkeyup="updateDueCreate()" required>
|
||||
<input type="number" name="avance_amount" id="avance_amount" class="form-control" placeholder="Entrez l'avance">
|
||||
</div>
|
||||
|
||||
<!-- Reste à payer -->
|
||||
<div class="form-group col-md-6">
|
||||
<label>Reste à payer</label>
|
||||
<input type="text" name="amount_due" id="amount_due" class="form-control" readonly>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Commentaire (affiché uniquement pour "mère") -->
|
||||
<div class="row">
|
||||
<div class="form-group col-md-12" id="commentaire_container" style="display:none;">
|
||||
<label>Commentaire</label>
|
||||
<textarea name="commentaire" id="commentaire" class="form-control" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">Enregistrer</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Annuler</button>
|
||||
@ -196,17 +210,19 @@
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Modal Modification CORRIGÉ -->
|
||||
<!-- Modal Modification -->
|
||||
<?php if (in_array('updateAvance', $user_permission)): ?>
|
||||
<div class="modal fade" id="updateModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form id="update_avance_form" method="post">
|
||||
<input type="hidden" name="id" id="avance_id_edit">
|
||||
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Modifier une avance</h4>
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<!-- Type d'avance -->
|
||||
@ -215,11 +231,11 @@
|
||||
<select name="type_avance_edit" id="type_avance_edit" class="form-control" required>
|
||||
<option value="" disabled>Sélectionnez un type d'avance</option>
|
||||
<option value="terre">Avance sur terre</option>
|
||||
<option value="mere">Avance sur mère</option>
|
||||
<option value="mere">Avance sur mer</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- CORRECTION: ID cohérent pour le type de paiement -->
|
||||
<!-- Moyen de paiement -->
|
||||
<div class="form-group col-md-6">
|
||||
<label for="type_payment_edit" class="form-label">Moyen de paiement</label>
|
||||
<select class="form-control" id="type_payment_edit" name="type_payment_edit">
|
||||
@ -253,11 +269,13 @@
|
||||
<label>CIN du client</label>
|
||||
<input type="text" name="customer_cin_avance_edit" id="customer_cin_avance_edit" class="form-control" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Produit -->
|
||||
<div class="form-group col-md-6">
|
||||
<div class="row">
|
||||
<!-- Produit avec sélection (pour "terre") -->
|
||||
<div class="form-group col-md-6" id="product_select_container_edit">
|
||||
<label class="form_label">Produit</label>
|
||||
<select name="id_product_edit" id="id_product_edit" class="form-control" onchange="getProductDataUpdate()" required>
|
||||
<select name="id_product_edit" id="id_product_edit" class="form-control" onchange="getProductDataUpdate()">
|
||||
<option value="">Sélectionnez un produit</option>
|
||||
<?php foreach($products as $p): ?>
|
||||
<option value="<?= $p['id'] ?>" <?= $p['product_sold'] ? 'disabled' : '' ?>>
|
||||
@ -268,17 +286,24 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Produit avec texte libre (pour "mère") -->
|
||||
<div class="form-group col-md-6" id="product_text_container_edit" style="display:none;">
|
||||
<label>Produit (à compléter)</label>
|
||||
<input type="text" name="product_name_text_edit" id="product_name_text_edit" class="form-control" placeholder="Entrez le nom du produit">
|
||||
</div>
|
||||
|
||||
<!-- Prix du produit -->
|
||||
<div class="form-group col-md-6">
|
||||
<label>Prix du produit</label>
|
||||
<input type="text" name="gross_amount_edit" id="gross_amount_edit" class="form-control" readonly>
|
||||
<input type="number" name="gross_amount_edit" id="gross_amount_edit" class="form-control" placeholder="Entrez le prix">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- Avance -->
|
||||
<div class="form-group col-md-6">
|
||||
<label>Avance</label>
|
||||
<input type="number" name="avance_amount_edit" id="avance_amount_edit" class="form-control" onkeyup="updateDueEdit()" required>
|
||||
<input type="number" name="avance_amount_edit" id="avance_amount_edit" class="form-control" placeholder="Entrez l'avance">
|
||||
</div>
|
||||
|
||||
<!-- Reste à payer -->
|
||||
@ -287,6 +312,14 @@
|
||||
<input type="text" name="amount_due_edit" id="amount_due_edit" class="form-control" readonly>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Commentaire (affiché uniquement pour "mère") -->
|
||||
<div class="row">
|
||||
<div class="form-group col-md-12" id="commentaire_container_edit" style="display:none;">
|
||||
<label>Commentaire</label>
|
||||
<textarea name="commentaire_edit" id="commentaire_edit" class="form-control" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
@ -367,10 +400,26 @@ $(document).ready(function() {
|
||||
// 🔄 FONCTION DE MISE À JOUR DYNAMIQUE DE LA DATATABLE
|
||||
function refreshDataTable() {
|
||||
if (typeof manageTable !== 'undefined' && manageTable) {
|
||||
manageTable.ajax.reload(null, false); // Recharger seulement les données de la table
|
||||
manageTable.ajax.reload(null, false);
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ INITIALISATION : Définir "terre" par défaut au chargement du modal création
|
||||
$('#createModal').on('show.bs.modal', function() {
|
||||
$('#create_avance_form')[0].reset();
|
||||
|
||||
// Par défaut : mode "terre"
|
||||
$('#product_select_container').show();
|
||||
$('#id_product').prop('required', true);
|
||||
$('#product_text_container').hide();
|
||||
$('#product_name_text').prop('required', false);
|
||||
$('#gross_amount').prop('readonly', true).prop('type', 'text');
|
||||
$('#commentaire_container').hide();
|
||||
|
||||
// Réattacher les événements
|
||||
$('#avance_amount').off('keyup').on('keyup', updateDueCreate);
|
||||
});
|
||||
|
||||
<?php if ($isAdmin): ?>
|
||||
var adminColumns = [
|
||||
{ title: "Client" },
|
||||
@ -386,18 +435,18 @@ $(document).ready(function() {
|
||||
<?php endif; ?>
|
||||
];
|
||||
|
||||
var manageTable = initAvanceTable('fetchAvanceData', adminColumns);
|
||||
var manageTable = initAvanceTable(base_url + 'avances/fetchAvanceData', adminColumns);
|
||||
|
||||
$('#avance_order').on('click', function () {
|
||||
manageTable = initAvanceTable('fetchAvanceBecameOrder', adminColumns);
|
||||
manageTable = initAvanceTable(base_url + 'avances/fetchAvanceBecameOrder', adminColumns);
|
||||
});
|
||||
|
||||
$('#avance_expired').on('click', function () {
|
||||
manageTable = initAvanceTable('fetchExpiredAvance', adminColumns);
|
||||
manageTable = initAvanceTable(base_url + 'avances/fetchExpiredAvance', adminColumns);
|
||||
});
|
||||
|
||||
$('#avance_no_order').on('click', function () {
|
||||
manageTable = initAvanceTable('fetchAvanceData', adminColumns);
|
||||
manageTable = initAvanceTable(base_url + 'avances/fetchAvanceData', adminColumns);
|
||||
});
|
||||
<?php endif; ?>
|
||||
|
||||
@ -424,70 +473,159 @@ $(document).ready(function() {
|
||||
});
|
||||
<?php endif; ?>
|
||||
|
||||
// =====================================================
|
||||
// 🔥 GESTION DU TYPE D'AVANCE - CRÉATION
|
||||
// =====================================================
|
||||
$('#type_avance').on('change', function() {
|
||||
var typeAvance = $(this).val();
|
||||
|
||||
if (typeAvance === 'mere') {
|
||||
// MASQUER le select de produit
|
||||
$('#product_select_container').hide();
|
||||
$('#id_product').prop('required', false).val('');
|
||||
|
||||
// AFFICHER le champ texte pour produit
|
||||
$('#product_text_container').show();
|
||||
$('#product_name_text').prop('required', true);
|
||||
|
||||
// RENDRE le prix modifiable ET changer en type="number"
|
||||
$('#gross_amount').prop('readonly', false).prop('type', 'number').val('').prop('required', true);
|
||||
|
||||
// AFFICHER le commentaire
|
||||
$('#commentaire_container').show();
|
||||
|
||||
// Calcul simple : Prix - Avance
|
||||
$('#avance_amount, #gross_amount').off('keyup').on('keyup', function() {
|
||||
var prix = parseFloat($('#gross_amount').val()) || 0;
|
||||
var avance = parseFloat($('#avance_amount').val()) || 0;
|
||||
var reste = prix - avance;
|
||||
$('#amount_due').val(reste >= 0 ? reste.toFixed(0) : 0);
|
||||
});
|
||||
|
||||
} else if (typeAvance === 'terre') {
|
||||
// AFFICHER le select de produit
|
||||
$('#product_select_container').show();
|
||||
$('#id_product').prop('required', true);
|
||||
|
||||
// MASQUER le champ texte
|
||||
$('#product_text_container').hide();
|
||||
$('#product_name_text').prop('required', false).val('');
|
||||
|
||||
// RENDRE le prix readonly ET en type="text"
|
||||
$('#gross_amount').prop('readonly', true).prop('type', 'text').prop('required', false);
|
||||
|
||||
// MASQUER le commentaire
|
||||
$('#commentaire_container').hide();
|
||||
$('#commentaire').val('');
|
||||
|
||||
// Restaurer le comportement normal avec validation 25%
|
||||
$('#avance_amount').off('keyup').on('keyup', updateDueCreate);
|
||||
$('#gross_amount').off('keyup');
|
||||
}
|
||||
|
||||
// Réinitialiser les champs
|
||||
$('#gross_amount').val('');
|
||||
$('#avance_amount').val('');
|
||||
$('#amount_due').val('');
|
||||
});
|
||||
|
||||
// =====================================================
|
||||
// 🔥 GESTION DU TYPE D'AVANCE - ÉDITION
|
||||
// =====================================================
|
||||
$('#type_avance_edit').on('change', function() {
|
||||
var typeAvance = $(this).val();
|
||||
|
||||
if (typeAvance === 'mere') {
|
||||
$('#product_select_container_edit').hide();
|
||||
$('#id_product_edit').prop('required', false).val('');
|
||||
|
||||
$('#product_text_container_edit').show();
|
||||
$('#product_name_text_edit').prop('required', true);
|
||||
|
||||
$('#gross_amount_edit').prop('readonly', false).prop('type', 'number').prop('required', true);
|
||||
$('#commentaire_container_edit').show();
|
||||
|
||||
$('#avance_amount_edit, #gross_amount_edit').off('keyup').on('keyup', function() {
|
||||
var prix = parseFloat($('#gross_amount_edit').val()) || 0;
|
||||
var avance = parseFloat($('#avance_amount_edit').val()) || 0;
|
||||
var reste = prix - avance;
|
||||
$('#amount_due_edit').val(reste >= 0 ? reste.toFixed(0) : 0);
|
||||
});
|
||||
|
||||
} else if (typeAvance === 'terre') {
|
||||
$('#product_select_container_edit').show();
|
||||
$('#id_product_edit').prop('required', true);
|
||||
|
||||
$('#product_text_container_edit').hide();
|
||||
$('#product_name_text_edit').prop('required', false).val('');
|
||||
|
||||
$('#gross_amount_edit').prop('readonly', true).prop('type', 'text').prop('required', false);
|
||||
$('#commentaire_container_edit').hide();
|
||||
$('#commentaire_edit').val('');
|
||||
|
||||
$('#avance_amount_edit').off('keyup').on('keyup', updateDueEdit);
|
||||
$('#gross_amount_edit').off('keyup');
|
||||
}
|
||||
});
|
||||
|
||||
// ✅ CRÉATION avec actualisation automatique
|
||||
$('#create_avance_form').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const $form = $(this);
|
||||
var typeAvance = $('#type_avance').val();
|
||||
var brut = parseFloat($('#gross_amount').val()) || 0;
|
||||
var avance = parseFloat($('#avance_amount').val()) || 0;
|
||||
var minAvance = brut * 0.25;
|
||||
|
||||
if (avance < minAvance) {
|
||||
$("#messages").html(`
|
||||
<div class="alert alert-danger alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong>
|
||||
L'avance doit être au minimum de 25% du prix du produit (${minAvance.toFixed(2)} Ar).
|
||||
</div>
|
||||
`);
|
||||
if (typeAvance === 'terre') {
|
||||
var minAvance = brut * 0.25;
|
||||
if (avance < minAvance) {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Avance insuffisante',
|
||||
html: `L'avance doit être au minimum de <b>25%</b> du prix du produit (<b>${minAvance.toFixed(2)} Ar</b>).`,
|
||||
confirmButtonText: 'OK',
|
||||
confirmButtonColor: '#d33'
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Validation pour "mère"
|
||||
if (typeAvance === 'mere') {
|
||||
if (!$('#product_name_text').val() || brut === 0 || avance === 0) {
|
||||
Swal.fire({
|
||||
icon: 'warning',
|
||||
title: 'Champs manquants',
|
||||
text: 'Veuillez remplir tous les champs : produit, prix et avance.'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Désactiver le bouton de soumission
|
||||
}
|
||||
$form.find('button[type="submit"]').prop('disabled', true).text('Enregistrement...');
|
||||
|
||||
$.post('/avances/createAvance', $form.serialize(), function(res) {
|
||||
if (res.success === true) {
|
||||
$("#messages").html(`
|
||||
<div class="alert alert-success alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<strong><span class="glyphicon glyphicon-ok-sign"></span></strong> ${res.messages}
|
||||
</div>
|
||||
`);
|
||||
if (res.success === true) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Succès',
|
||||
text: res.messages,
|
||||
timer: 1500,
|
||||
showConfirmButton: false
|
||||
}).then(() => {
|
||||
$("#createModal").modal('hide');
|
||||
$form[0].reset(); // Reset le formulaire
|
||||
|
||||
// 🔄 MISE À JOUR DYNAMIQUE après ajout
|
||||
setTimeout(function() {
|
||||
location.reload();
|
||||
}, 500); // petit délai pour voir le message
|
||||
|
||||
// Auto-masquer le message après 3 secondes
|
||||
setTimeout(function() {
|
||||
$("#messages .alert").fadeOut();
|
||||
}, 3000);
|
||||
|
||||
} else {
|
||||
$("#createModal").modal('hide');
|
||||
$("#messages").html(`
|
||||
<div class="alert alert-warning alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong> ${res.messages}
|
||||
</div>
|
||||
`);
|
||||
// Réactiver le bouton en cas d'erreur
|
||||
$form.find('button[type="submit"]').prop('disabled', false).text('Enregistrer');
|
||||
}
|
||||
}, 'json');
|
||||
});
|
||||
|
||||
// 🔥 SUPPRESSION avec actualisation automatique
|
||||
$form[0].reset();
|
||||
location.reload();
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Erreur',
|
||||
text: res.messages
|
||||
});
|
||||
$form.find('button[type="submit"]').prop('disabled', false).text('Enregistrer');
|
||||
}
|
||||
}, 'json');
|
||||
});
|
||||
// 🔥 SUPPRESSION
|
||||
window.removeFunc = function(id, product_id) {
|
||||
$('#removeModal').modal('show');
|
||||
$('#removeForm input[name="avance_id"]').val(id);
|
||||
@ -496,11 +634,9 @@ $(document).ready(function() {
|
||||
|
||||
$('#removeForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var form = $(this);
|
||||
var submitButton = form.find('button[type="submit"]');
|
||||
|
||||
// Désactiver le bouton
|
||||
submitButton.prop('disabled', true).text('Suppression...');
|
||||
|
||||
$.ajax({
|
||||
@ -521,10 +657,8 @@ $(document).ready(function() {
|
||||
</div>
|
||||
`);
|
||||
|
||||
// 🔄 MISE À JOUR DYNAMIQUE après suppression
|
||||
refreshDataTable();
|
||||
|
||||
// Auto-masquer le message après 3 secondes
|
||||
setTimeout(function() {
|
||||
$("#messages .alert").fadeOut();
|
||||
location.reload();
|
||||
@ -542,19 +676,6 @@ $(document).ready(function() {
|
||||
`);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.log('Erreur AJAX:', error);
|
||||
$('#removeModal').modal('hide');
|
||||
|
||||
$("#messages").html(`
|
||||
<div class="alert alert-danger alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong> Une erreur est survenue lors de la suppression.
|
||||
</div>
|
||||
`);
|
||||
},
|
||||
complete: function() {
|
||||
submitButton.prop('disabled', false).text('Oui');
|
||||
}
|
||||
@ -563,12 +684,6 @@ $(document).ready(function() {
|
||||
return false;
|
||||
});
|
||||
|
||||
// Réinitialiser le modal à la fermeture
|
||||
$('#removeModal').on('hidden.bs.modal', function() {
|
||||
$('#removeForm')[0].reset();
|
||||
$('#removeForm button[type="submit"]').prop('disabled', false).text('Oui');
|
||||
});
|
||||
|
||||
}); // Fin document.ready
|
||||
|
||||
// --- Fonctions utilitaires ---
|
||||
@ -585,19 +700,17 @@ function getProductDataCreate() {
|
||||
var avance25 = brutCreate * 0.25;
|
||||
$('#avance_amount').val(avance25.toFixed(0));
|
||||
$('#amount_due').val((brutCreate - avance25).toFixed(0));
|
||||
updateDueCreate();
|
||||
}, 'json');
|
||||
}
|
||||
|
||||
function updateDueCreate() {
|
||||
var av = parseFloat($('#avance_amount').val()) || 0;
|
||||
var brutAmount = parseFloat($('#gross_amount').val()) || 0;
|
||||
$('#amount_due').val(Math.max(brutAmount - av, 0));
|
||||
$('#amount_due').val(Math.max(brutAmount - av, 0).toFixed(0));
|
||||
}
|
||||
|
||||
function getProductDataUpdate() {
|
||||
var id = $('#id_product_edit').val();
|
||||
console.log('getProductDataUpdate appelée avec ID:', id); // Pour déboguer
|
||||
|
||||
if (!id) {
|
||||
brutEdit = 0;
|
||||
@ -611,32 +724,22 @@ function getProductDataUpdate() {
|
||||
data: { product_id: id },
|
||||
dataType: 'json',
|
||||
success: function(r) {
|
||||
console.log('Données produit reçues:', r); // Pour déboguer
|
||||
|
||||
brutEdit = parseFloat(r.prix_vente) || 0;
|
||||
$('#gross_amount_edit').val(brutEdit.toFixed(0));
|
||||
var avance25 = brutEdit * 0.25;
|
||||
$('#avance_amount_edit').val(avance25.toFixed(0));
|
||||
$('#amount_due_edit').val((brutEdit - avance25).toFixed(0));
|
||||
updateDueEdit();
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.log('Erreur lors de la récupération des données produit:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateDueEdit() {
|
||||
var av = parseFloat($('#avance_amount_edit').val()) || 0;
|
||||
$('#amount_due_edit').val(Math.max(brutEdit - av, 0).toFixed(2));
|
||||
$('#amount_due_edit').val(Math.max(brutEdit - av, 0).toFixed(0));
|
||||
}
|
||||
|
||||
// ✅ MODIFICATION avec mise à jour dynamique - CORRIGÉ
|
||||
// ✅ MODIFICATION avec mise à jour dynamique - VERSION CORRIGÉE
|
||||
// ✅ MODIFICATION
|
||||
function editFunc(id) {
|
||||
console.log('editFunc appelée avec ID:', id);
|
||||
|
||||
// Réinitialiser d'abord le formulaire
|
||||
$('#update_avance_form')[0].reset();
|
||||
|
||||
$.ajax({
|
||||
@ -644,104 +747,94 @@ function editFunc(id) {
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function(r) {
|
||||
console.log('Données récupérées:', r);
|
||||
|
||||
// Pré-remplir le formulaire de modification avec les BONS IDs
|
||||
$('#avance_id_edit').val(r.id || id);
|
||||
$('#customer_name_avance_edit').val(r.customer_name || '');
|
||||
$('#customer_phone_avance_edit').val(r.customer_phone || '');
|
||||
$('#customer_address_avance_edit').val(r.customer_address || r.customer_adress || '');
|
||||
$('#customer_cin_avance_edit').val(r.customer_cin || '');
|
||||
$('#type_avance_edit').val(r.type_avance || '');
|
||||
$('#type_payment_edit').val(r.type_payment || '');
|
||||
$('#gross_amount_edit').val(r.gross_amount || '');
|
||||
$('#avance_amount_edit').val(r.avance_amount || '');
|
||||
$('#amount_due_edit').val(r.amount_due || '');
|
||||
$('#commentaire_edit').val(r.commentaire || '');
|
||||
|
||||
// CORRECTION 1: ID correct pour le type de paiement
|
||||
$('#type_payment_edit').val(r.type_payment || '');
|
||||
|
||||
// Récupérer l'ID du produit avec toutes les variantes possibles
|
||||
var productId = r.product_id || r.id_product || r.productId || r.idProduct;
|
||||
console.log('Product ID trouvé:', productId);
|
||||
// Gérer le produit selon le type
|
||||
if (r.type_avance === 'mere' && r.product_name) {
|
||||
$('#product_name_text_edit').val(r.product_name);
|
||||
}
|
||||
|
||||
var productId = r.product_id || r.id_product;
|
||||
brutEdit = parseFloat(r.gross_amount || 0);
|
||||
|
||||
// Réinitialiser le bouton
|
||||
$('#update_avance_form button[type="submit"]').prop('disabled', false).text('Modifier');
|
||||
|
||||
// Ouvrir le modal
|
||||
$('#updateModal').modal('show');
|
||||
|
||||
// CORRECTION 2: Sélection du produit après ouverture complète du modal
|
||||
$('#updateModal').on('shown.bs.modal', function(e) {
|
||||
if (productId) {
|
||||
console.log('Tentative de sélection du produit ID:', productId);
|
||||
|
||||
// Méthode robuste de sélection
|
||||
// Déclencher le change pour afficher les bons champs
|
||||
$('#type_avance_edit').trigger('change');
|
||||
|
||||
if (productId && r.type_avance === 'terre') {
|
||||
setTimeout(function() {
|
||||
// Vérifier d'abord si l'option existe
|
||||
var optionExists = $('#id_product_edit option[value="' + productId + '"]').length > 0;
|
||||
console.log('Option produit existe:', optionExists);
|
||||
|
||||
if (optionExists) {
|
||||
$('#id_product_edit').val(productId);
|
||||
console.log('Produit sélectionné:', $('#id_product_edit').val());
|
||||
|
||||
// Déclencher l'événement change pour mettre à jour les prix si nécessaire
|
||||
$('#id_product_edit').trigger('change');
|
||||
} else {
|
||||
console.log('Attention: Produit ID ' + productId + ' non trouvé dans les options');
|
||||
}
|
||||
}, 100); // Petit délai pour s'assurer que le modal est complètement chargé
|
||||
$('#id_product_edit').val(productId).trigger('change');
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Détacher l'événement pour éviter les appels multiples
|
||||
$(this).off('shown.bs.modal');
|
||||
});
|
||||
|
||||
// CORRECTION 3: Gestion du formulaire de soumission améliorée
|
||||
$('#update_avance_form').off('submit').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $form = $(this);
|
||||
var $submitBtn = $form.find('button[type="submit"]');
|
||||
var typeAvance = $('#type_avance_edit').val();
|
||||
var avance = parseFloat($('#avance_amount_edit').val()) || 0;
|
||||
var minAvance = brutEdit * 0.25;
|
||||
var brut = parseFloat($('#gross_amount_edit').val()) || 0;
|
||||
|
||||
// Validation 25%
|
||||
if (avance < minAvance) {
|
||||
$("#messages").html(`
|
||||
<div class="alert alert-danger alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong>
|
||||
L'avance doit être au minimum de 25% du prix du produit (${minAvance.toFixed(2)} Ar).
|
||||
</div>
|
||||
`);
|
||||
return;
|
||||
// Validation pour "terre"
|
||||
if (typeAvance === 'terre') {
|
||||
var minAvance = brutEdit * 0.25;
|
||||
if (avance < minAvance) {
|
||||
$("#messages").html(`
|
||||
<div class="alert alert-danger alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong>
|
||||
L'avance doit être au minimum de 25% du prix du produit (${minAvance.toFixed(2)} Ar).
|
||||
</div>
|
||||
`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Désactiver le bouton pendant l'opération
|
||||
$submitBtn.prop('disabled', true).text('Modification...');
|
||||
// Validation pour "mère"
|
||||
if (typeAvance === 'mere') {
|
||||
if (!$('#product_name_text_edit').val() || brut === 0 || avance === 0) {
|
||||
$("#messages").html(`
|
||||
<div class="alert alert-danger alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong>
|
||||
Veuillez remplir tous les champs requis.
|
||||
</div>
|
||||
`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// CORRECTION 4: Données du formulaire avec vérifications
|
||||
var formData = $form.serialize();
|
||||
console.log('Données envoyées:', formData);
|
||||
$submitBtn.prop('disabled', true).text('Modification...');
|
||||
|
||||
$.ajax({
|
||||
url: base_url + 'avances/updateAvance/' + id,
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
data: $form.serialize(),
|
||||
dataType: 'json',
|
||||
success: function(res) {
|
||||
console.log('Réponse serveur:', res);
|
||||
|
||||
if (res.success === true) {
|
||||
// Fermer le modal
|
||||
$('#updateModal').modal('hide');
|
||||
|
||||
// Message de succès
|
||||
$("#messages").html(`
|
||||
<div class="alert alert-success alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
@ -751,15 +844,12 @@ function editFunc(id) {
|
||||
</div>
|
||||
`);
|
||||
|
||||
// Mise à jour de la DataTable
|
||||
if (typeof manageTable !== 'undefined' && manageTable) {
|
||||
manageTable.ajax.reload(null, false);
|
||||
}
|
||||
|
||||
// Auto-masquer le message
|
||||
setTimeout(function() {
|
||||
location.reload();
|
||||
$("#messages .alert").fadeOut();
|
||||
location.reload();
|
||||
}, 1000);
|
||||
|
||||
} else {
|
||||
@ -773,47 +863,13 @@ function editFunc(id) {
|
||||
`);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.log('Erreur AJAX:', error);
|
||||
console.log('Réponse complète:', xhr.responseText);
|
||||
|
||||
$("#messages").html(`
|
||||
<div class="alert alert-danger alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong> Erreur lors de la modification.
|
||||
</div>
|
||||
`);
|
||||
},
|
||||
complete: function() {
|
||||
// Réactiver le bouton dans tous les cas
|
||||
$submitBtn.prop('disabled', false).text('Modifier');
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.log('Erreur lors du chargement des données:', error);
|
||||
console.log('Réponse:', xhr.responseText);
|
||||
|
||||
$("#messages").html(`
|
||||
<div class="alert alert-danger alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong> Erreur lors du chargement des données.
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
// Réinitialiser le modal à la fermeture
|
||||
$('#updateModal').on('hidden.bs.modal', function() {
|
||||
$('#update_avance_form')[0].reset();
|
||||
$('#update_avance_form button[type="submit"]').prop('disabled', false).text('Modifier');
|
||||
// Détacher les événements pour éviter les conflits
|
||||
$('#update_avance_form').off('submit');
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
@ -52,12 +52,7 @@
|
||||
<?php endif; ?>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
||||
</table>
|
||||
<!-- totaliter mvola = somme tranche 1 izay type mvola tranche 1 + somme tranche 2
|
||||
totaliter mvola dia - recouvrement izay sortie ùmvola plus recouvremnt entrer mvola
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -65,33 +60,34 @@
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
// datatable-fr.js
|
||||
$.extend(true, $.fn.dataTable.defaults, {
|
||||
language: {
|
||||
sProcessing: "Traitement en cours...",
|
||||
sSearch: "Rechercher :",
|
||||
sLengthMenu: "Afficher _MENU_ éléments",
|
||||
sInfo: "Affichage de l'élement _START_ à _END_ sur _TOTAL_ éléments",
|
||||
sInfoEmpty: "Affichage de l'élement 0 à 0 sur 0 élément",
|
||||
sInfoFiltered: "(filtré de _MAX_ éléments au total)",
|
||||
sLoadingRecords: "Chargement en cours...",
|
||||
sZeroRecords: "Aucun élément à afficher",
|
||||
sEmptyTable: "Aucune donnée disponible dans le tableau",
|
||||
oPaginate: {
|
||||
sFirst: "Premier",
|
||||
sPrevious: "Précédent",
|
||||
sNext: "Suivant",
|
||||
sLast: "Dernier"
|
||||
},
|
||||
oAria: {
|
||||
sSortAscending: ": activer pour trier la colonne par ordre croissant",
|
||||
sSortDescending: ": activer pour trier la colonne par ordre décroissant"
|
||||
}
|
||||
}
|
||||
});
|
||||
$.extend(true, $.fn.dataTable.defaults, {
|
||||
language: {
|
||||
sProcessing: "Traitement en cours...",
|
||||
sSearch: "Rechercher :",
|
||||
sLengthMenu: "Afficher _MENU_ éléments",
|
||||
sInfo: "Affichage de l'élement _START_ à _END_ sur _TOTAL_ éléments",
|
||||
sInfoEmpty: "Affichage de l'élement 0 à 0 sur 0 élément",
|
||||
sInfoFiltered: "(filtré de _MAX_ éléments au total)",
|
||||
sLoadingRecords: "Chargement en cours...",
|
||||
sZeroRecords: "Aucun élément à afficher",
|
||||
sEmptyTable: "Aucune donnée disponible dans le tableau",
|
||||
oPaginate: {
|
||||
sFirst: "Premier",
|
||||
sPrevious: "Précédent",
|
||||
sNext: "Suivant",
|
||||
sLast: "Dernier"
|
||||
},
|
||||
oAria: {
|
||||
sSortAscending: ": activer pour trier la colonne par ordre croissant",
|
||||
sSortDescending: ": activer pour trier la colonne par ordre décroissant"
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#remise_menu").addClass('active');
|
||||
|
||||
@ -102,107 +98,115 @@
|
||||
|
||||
manageTable = $('#manageTable').DataTable({
|
||||
ajax: '<?= base_url('remise/fetchRemiseData') ?>',
|
||||
order:[],
|
||||
order: [],
|
||||
columns: [
|
||||
{ data: 0 },
|
||||
{ data: 1 },
|
||||
{ data: 2 },
|
||||
{ data: 3 },
|
||||
{ data: 4 },
|
||||
{ data: 5 }
|
||||
],
|
||||
|
||||
{ data: 0 },
|
||||
{ data: 1 },
|
||||
{ data: 2 },
|
||||
{ data: 3 },
|
||||
{ data: 4 },
|
||||
{ data: 5 }
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
})
|
||||
|
||||
// Fonction pour refuser une demande de remise
|
||||
function refuseFunc(id) {
|
||||
Swal.fire({
|
||||
title: 'Confirmation',
|
||||
text: 'Êtes-vous sûr de vouloir refuser cette demande de remise ?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Oui, refuser',
|
||||
cancelButtonText: 'Annuler',
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
$.ajax({
|
||||
url: '<?= base_url('remise/updateRemise') ?>/' + id,
|
||||
type: 'POST',
|
||||
data: { 'demande_status': 'Refusé' },
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
manageTable.ajax.reload(null, false);
|
||||
|
||||
function refuseFunc(id) {
|
||||
|
||||
$.ajax({
|
||||
url: '<?= base_url('remise/updateRemise') ?>/' + id,
|
||||
type: 'POST',
|
||||
data: {
|
||||
'demande_status': 'rejete'
|
||||
},
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
|
||||
manageTable.ajax.reload(null, false);
|
||||
|
||||
if (response.success === true) {
|
||||
$("#messages").html('<div class="alert alert-warning alert-dismissible" role="alert">' +
|
||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
||||
'<strong> <span class="glyphicon glyphicon-ok-sign"></span> </strong>' + response.messages +
|
||||
'</div>');
|
||||
|
||||
} else {
|
||||
|
||||
if (response.messages instanceof Object) {
|
||||
$.each(response.messages, function(index, value) {
|
||||
var id = $("#" + index);
|
||||
|
||||
id.closest('.form-group')
|
||||
.removeClass('has-error')
|
||||
.removeClass('has-success')
|
||||
.addClass(value.length > 0 ? 'has-error' : 'has-success');
|
||||
|
||||
id.after(value);
|
||||
|
||||
});
|
||||
} else {
|
||||
$("#messages").html('<div class="alert alert-danger alert-dismissible" role="alert">' +
|
||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
||||
'<strong> <span class="glyphicon glyphicon-exclamation-sign"></span> </strong>' + response.messages +
|
||||
'</div>');
|
||||
}
|
||||
}
|
||||
if (response.success === true) {
|
||||
Swal.fire({
|
||||
icon: 'warning',
|
||||
title: 'Refusé',
|
||||
text: response.messages,
|
||||
showConfirmButton: false,
|
||||
timer: 2000
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Erreur',
|
||||
text: response.messages
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function() {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Erreur',
|
||||
text: 'Une erreur est survenue lors du traitement de la demande.'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Fonction pour valider une demande de remise
|
||||
function valideFunc(id) {
|
||||
|
||||
$.ajax({
|
||||
url: '<?= base_url('remise/updateRemise') ?>/' + id,
|
||||
type: 'POST',
|
||||
data: {
|
||||
'demande_status': 'accepte'
|
||||
},
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
Swal.fire({
|
||||
title: 'Confirmation',
|
||||
text: 'Êtes-vous sûr de vouloir accepter cette demande de remise ?',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Oui, accepter',
|
||||
cancelButtonText: 'Annuler',
|
||||
confirmButtonColor: '#28a745',
|
||||
cancelButtonColor: '#3085d6'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
$.ajax({
|
||||
url: '<?= base_url('remise/updateRemise') ?>/' + id,
|
||||
type: 'POST',
|
||||
data: { 'demande_status': 'Accepté' },
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
manageTable.ajax.reload(null, false);
|
||||
|
||||
manageTable.ajax.reload(null, false);
|
||||
|
||||
if (response.success === true) {
|
||||
$("#messages").html('<div class="alert alert-success alert-dismissible" role="alert">' +
|
||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
||||
'<strong> <span class="glyphicon glyphicon-ok-sign"></span> </strong>' + response.messages +
|
||||
'</div>');
|
||||
|
||||
} else {
|
||||
|
||||
if (response.messages instanceof Object) {
|
||||
$.each(response.messages, function(index, value) {
|
||||
var id = $("#" + index);
|
||||
|
||||
id.closest('.form-group')
|
||||
.removeClass('has-error')
|
||||
.removeClass('has-success')
|
||||
.addClass(value.length > 0 ? 'has-error' : 'has-success');
|
||||
|
||||
id.after(value);
|
||||
|
||||
});
|
||||
} else {
|
||||
$("#messages").html('<div class="alert alert-warning alert-dismissible" role="alert">' +
|
||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
||||
'<strong> <span class="glyphicon glyphicon-exclamation-sign"></span> </strong>' + response.messages +
|
||||
'</div>');
|
||||
}
|
||||
}
|
||||
if (response.success === true) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Accepté',
|
||||
text: response.messages,
|
||||
showConfirmButton: false,
|
||||
timer: 2000
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'warning',
|
||||
title: 'Attention',
|
||||
text: response.messages
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function() {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Erreur',
|
||||
text: 'Une erreur est survenue lors du traitement de la demande.'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
@ -56,7 +56,7 @@
|
||||
<th>Avance</th>
|
||||
<th>Reste à payer</th>
|
||||
<th>Date</th>
|
||||
<?php if (in_array('updateAvance', $user_permission) || in_array('deleteAvance', $user_permission) ||in_array('viewAvance', $user_permission)): ?>
|
||||
<?php if (in_array('updateAvance', $user_permission) || in_array('deleteAvance', $user_permission) || in_array('viewAvance', $user_permission)): ?>
|
||||
<th>Action</th>
|
||||
<?php endif;?>
|
||||
</tr>
|
||||
|
||||
@ -414,4 +414,183 @@
|
||||
$("#product_info_table tbody tr#row_" + tr_id).remove();
|
||||
subAmount();
|
||||
}
|
||||
function formatAllNumbers() {
|
||||
// Sélecteur pour tous les inputs que tu veux formater
|
||||
const inputs = document.querySelectorAll('input[type="text"], input[disabled]');
|
||||
|
||||
inputs.forEach(input => {
|
||||
if (input.value && !isNaN(input.value.replace(/\s/g, ''))) {
|
||||
let val = input.value.replace(/\s/g, '');
|
||||
input.value = Number(val).toLocaleString('fr-FR'); // ajoute les espaces tous les 3 chiffres
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Appel après que la page et le DOM sont chargés
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
formatAllNumbers();
|
||||
});
|
||||
|
||||
console.log('%c🚀 MODE EDIT AS NEW ACTIVÉ', 'color: green; font-weight: bold; font-size: 16px;');
|
||||
|
||||
// DEBUG: Afficher les données reçues
|
||||
var orderData = <?= json_encode($existing_order ?? []) ?>;
|
||||
var itemsData = <?= json_encode($existing_items ?? []) ?>;
|
||||
|
||||
console.log('📦 Order Data:', orderData);
|
||||
console.log('📦 Items Data:', itemsData);
|
||||
console.log('📊 Nombre de produits:', itemsData.length);
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
// ============================================
|
||||
// ÉTAPE 1: PRÉ-REMPLIR LES CHAMPS CLIENT
|
||||
// ============================================
|
||||
console.log('✅ Étape 1: Pré-remplissage des champs client');
|
||||
|
||||
$('#customer_name').val('<?= esc($existing_order['customer_name'] ?? '') ?>');
|
||||
$('#customer_address').val('<?= esc($existing_order['customer_address'] ?? '') ?>');
|
||||
$('#customer_phone').val('<?= esc($existing_order['customer_phone'] ?? '') ?>');
|
||||
$('#customer_cin').val('<?= esc($existing_order['customer_cin'] ?? '') ?>');
|
||||
|
||||
var originalDiscount = parseFloat('<?= $existing_order['discount'] ?? 0 ?>') || 0;
|
||||
if (originalDiscount > 0) {
|
||||
$('#discount').val(originalDiscount);
|
||||
console.log('💰 Rabais appliqué:', originalDiscount);
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// ÉTAPE 2: NETTOYER LE TABLEAU
|
||||
// ============================================
|
||||
console.log('✅ Étape 2: Nettoyage du tableau');
|
||||
$('#product_info_table tbody').empty();
|
||||
|
||||
// ============================================
|
||||
// ÉTAPE 3: CHARGER LES PRODUITS
|
||||
// ============================================
|
||||
<?php if (isset($existing_items) && !empty($existing_items)): ?>
|
||||
console.log('✅ Étape 3: Chargement de ' + itemsData.length + ' produit(s)');
|
||||
|
||||
// Fonction de formatage
|
||||
function formatNumber(num) {
|
||||
return parseFloat(num).toLocaleString('fr-FR', {
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 2
|
||||
});
|
||||
}
|
||||
|
||||
// Charger chaque produit
|
||||
itemsData.forEach(function(item, index) {
|
||||
var rowId = index + 1;
|
||||
console.log('🔄 Chargement ligne ' + rowId + ':', item);
|
||||
|
||||
// CONSTRUIRE LA LIGNE HTML
|
||||
var html = '<tr id="row_' + rowId + '">';
|
||||
|
||||
// COLONNE 1: SELECT PRODUIT
|
||||
html += '<td>';
|
||||
html += '<select class="form-control select_group product" ';
|
||||
html += 'data-row-id="' + rowId + '" ';
|
||||
html += 'id="product_' + rowId + '" ';
|
||||
html += 'name="product[]" ';
|
||||
html += 'style="width:100%;" ';
|
||||
html += 'onchange="getProductData(' + rowId + ')" required>';
|
||||
html += '<option value="">Sélectionner...</option>';
|
||||
|
||||
// OPTIONS DES PRODUITS
|
||||
<?php foreach ($products as $p): ?>
|
||||
<?php if ($p['product_sold'] == 0): ?>
|
||||
html += '<option value="<?= $p['id'] ?>"';
|
||||
if (item.product_id === <?= $p['id'] ?>) {
|
||||
html += ' selected="selected"';
|
||||
console.log(' ✓ Produit trouvé: <?= esc($p['name']) ?> (ID: <?= $p['id'] ?>)');
|
||||
}
|
||||
html += '>';
|
||||
html += '<?= esc($p['sku']) ?> | <?= esc($p['name']) ?> | ';
|
||||
html += '<?= esc($p['numero_de_moteur']) ?> | <?= esc($p['puissance']) ?>';
|
||||
html += '</option>';
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
|
||||
html += '</select></td>';
|
||||
|
||||
// COLONNE 2: PRIX UNITAIRE
|
||||
html += '<td>';
|
||||
html += '<input type="text" name="rate[]" ';
|
||||
html += 'id="rate_' + rowId + '" ';
|
||||
html += 'class="form-control" disabled ';
|
||||
html += 'value="' + formatNumber(item.rate) + '">';
|
||||
html += '<input type="hidden" name="rate_value[]" ';
|
||||
html += 'id="rate_value_' + rowId + '" ';
|
||||
html += 'value="' + item.rate + '">';
|
||||
html += '</td>';
|
||||
|
||||
// COLONNE 3: MONTANT
|
||||
html += '<td>';
|
||||
html += '<input type="text" name="amount[]" ';
|
||||
html += 'id="amount_' + rowId + '" ';
|
||||
html += 'class="form-control" disabled ';
|
||||
html += 'value="' + formatNumber(item.amount) + '">';
|
||||
html += '<input type="hidden" name="amount_value[]" ';
|
||||
html += 'id="amount_value_' + rowId + '" ';
|
||||
html += 'value="' + item.amount + '">';
|
||||
html += '</td>';
|
||||
|
||||
// COLONNE 4: BOUTON SUPPRIMER
|
||||
html += '<td>';
|
||||
html += '<button type="button" class="btn btn-default" ';
|
||||
html += 'onclick="removeRow(\'' + rowId + '\')">';
|
||||
html += '<i class="fa fa-close"></i></button>';
|
||||
html += '</td>';
|
||||
|
||||
// QTY CACHÉ (toujours 1 pour les motos)
|
||||
html += '<input type="hidden" name="qty[]" ';
|
||||
html += 'id="qty_' + rowId + '" ';
|
||||
html += 'value="' + item.qty + '" ';
|
||||
html += 'required onkeyup="getTotal(' + rowId + ')">';
|
||||
|
||||
html += '</tr>';
|
||||
|
||||
// AJOUTER AU TABLEAU
|
||||
$('#product_info_table tbody').append(html);
|
||||
console.log(' ✓ Ligne ' + rowId + ' ajoutée au DOM');
|
||||
});
|
||||
|
||||
// ============================================
|
||||
// ÉTAPE 4: INITIALISER SELECT2 ET RECALCULER
|
||||
// ============================================
|
||||
console.log('✅ Étape 4: Finalisation');
|
||||
|
||||
setTimeout(function() {
|
||||
// Initialiser Select2
|
||||
if ($.fn.select2) {
|
||||
$('.product').select2();
|
||||
console.log(' ✓ Select2 initialisé');
|
||||
}
|
||||
|
||||
// Recalculer les montants
|
||||
if (typeof subAmount === 'function') {
|
||||
subAmount();
|
||||
console.log(' ✓ Montants recalculés');
|
||||
}
|
||||
|
||||
// Formater les nombres
|
||||
if (typeof formatAllNumbers === 'function') {
|
||||
formatAllNumbers();
|
||||
console.log(' ✓ Nombres formatés');
|
||||
}
|
||||
|
||||
console.log('%c🎉 CHARGEMENT TERMINÉ AVEC SUCCÈS!', 'color: green; font-weight: bold; font-size: 14px;');
|
||||
|
||||
// Vérification finale
|
||||
var rowCount = $('#product_info_table tbody tr').length;
|
||||
console.log('📊 Nombre de lignes dans le tableau:', rowCount);
|
||||
|
||||
}, 500);
|
||||
|
||||
<?php else: ?>
|
||||
console.warn('⚠️ Aucun produit à charger');
|
||||
<?php endif; ?>
|
||||
|
||||
});
|
||||
</script>
|
||||
@ -1,3 +1,4 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
<div class="content-wrapper">
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
@ -26,16 +27,21 @@
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($errors = session()->getFlashdata('errors')): ?>
|
||||
<div class="alert alert-error alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
<ul>
|
||||
<?php foreach ($errors as $error): ?>
|
||||
<li><?= esc($error) ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="alert alert-danger alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<?php if (is_array($errors)): ?>
|
||||
<ul>
|
||||
<?php foreach ($errors as $error): ?>
|
||||
<li><?= esc($error) ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php else: ?>
|
||||
<?= esc($errors) ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title">Ajouter une commande</h3>
|
||||
@ -110,8 +116,8 @@
|
||||
<!-- <th style="width:10%">Quantité</th> -->
|
||||
<th style="width:10%">Prix unitaire</th>
|
||||
<th style="width:20%">Montant</th>
|
||||
<th style="width:10%"><button type="button" id="add_row"
|
||||
class="btn btn-default"><i class="fa fa-plus"></i></button></th>
|
||||
<!-- <th style="width:10%"><button type="button" id="add_row"
|
||||
class="btn btn-default"><i class="fa fa-plus"></i></button></th> -->
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -131,6 +137,7 @@
|
||||
autocomplete="off" value="<?= $pu ?>">
|
||||
<input type="hidden" name="rate_value[]" value="<?= $pu ?>"
|
||||
id="rate_value_1" class="form-control" autocomplete="off">
|
||||
<input type="hidden" id="min_price_1" name="min_price[]" value="">
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@ -207,16 +214,10 @@
|
||||
$(document).ready(function () {
|
||||
getTotal(1);
|
||||
$(".select_group").select2();
|
||||
// $("#description").wysihtml5();
|
||||
|
||||
$("#mainOrdersNav").addClass('active');
|
||||
$("#addOrderNav").addClass('active');
|
||||
|
||||
var btnCust = '<button type="button" class="btn btn-secondary" title="Add picture tags" ' +
|
||||
'onclick="alert(\'Call your custom code here.\')">' +
|
||||
'<i class="glyphicon glyphicon-tag"></i>' +
|
||||
'</button>';
|
||||
|
||||
// Add new row in the table
|
||||
$("#add_row").unbind('click').bind('click', function () {
|
||||
var table = $("#product_info_table");
|
||||
@ -228,8 +229,6 @@
|
||||
type: 'post',
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
|
||||
// console.log(reponse.x);
|
||||
var html = '<tr id="row_' + row_id + '">' +
|
||||
'<td>' +
|
||||
'<select class="form-control select_group product" data-row-id="' + row_id + '" id="product_' + row_id + '" name="product[]" style="width:100%;" onchange="getProductData(' + row_id + ')">' +
|
||||
@ -240,7 +239,7 @@
|
||||
|
||||
html += '</select>' +
|
||||
'</td>' +
|
||||
'<td><input type="text" name="rate[]" id="rate_' + row_id + '" class="form-control" disabled><input type="hidden" name="rate_value[]" id="rate_value_' + row_id + '" class="form-control"></td>' +
|
||||
'<td><input type="text" name="rate[]" id="rate_' + row_id + '" class="form-control" disabled><input type="hidden" name="rate_value[]" id="rate_value_' + row_id + '" class="form-control"><input type="hidden" id="min_price_' + row_id + '" name="min_price[]" value=""></td>' +
|
||||
'<td><input type="text" name="amount[]" id="amount_' + row_id + '" class="form-control" disabled><input type="hidden" name="amount_value[]" id="amount_value_' + row_id + '" class="form-control"></td>' +
|
||||
'<td><button type="button" class="btn btn-default" onclick="removeRow(\'' + row_id + '\')"><i class="fa fa-close"></i></button></td>' +
|
||||
'</tr>';
|
||||
@ -252,13 +251,25 @@
|
||||
}
|
||||
|
||||
$(".product").select2();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Vérifier lors de la saisie du rabais
|
||||
$("#discount").on('blur', function() {
|
||||
checkMinimalPrice();
|
||||
});
|
||||
|
||||
// Bloquer la soumission du formulaire
|
||||
$('form').on('submit', function(e) {
|
||||
if (!checkMinimalPrice()) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
}); // /document
|
||||
|
||||
function getTotal(row = null) {
|
||||
@ -281,9 +292,8 @@
|
||||
if (product_id == "") {
|
||||
$("#rate_" + row_id).val("");
|
||||
$("#rate_value_" + row_id).val("");
|
||||
|
||||
$("#min_price_" + row_id).val("");
|
||||
$("#qty_" + row_id).val("");
|
||||
|
||||
$("#amount_" + row_id).val("");
|
||||
$("#amount_value_" + row_id).val("");
|
||||
|
||||
@ -297,9 +307,9 @@
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
// setting the rate value into the rate input field
|
||||
|
||||
$("#rate_" + row_id).val(response.prix_vente);
|
||||
$("#rate_value_" + row_id).val(response.prix_vente);
|
||||
$("#min_price_" + row_id).val(response.prix_minimal); // ✅ Stockage du prix minimal
|
||||
|
||||
$("#qty_" + row_id).val(1);
|
||||
$("#qty_value_" + row_id).val(1);
|
||||
@ -310,8 +320,8 @@
|
||||
$("#amount_value_" + row_id).val(total);
|
||||
|
||||
subAmount();
|
||||
} // /success
|
||||
}); // /ajax function to fetch the product data
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,7 +338,7 @@
|
||||
count = count.substring(4);
|
||||
|
||||
totalSubAmount = Number(totalSubAmount) + Number($("#amount_" + count).val());
|
||||
} // /for
|
||||
}
|
||||
|
||||
totalSubAmount = totalSubAmount.toFixed(2);
|
||||
|
||||
@ -351,8 +361,7 @@
|
||||
// total amount
|
||||
var totalAmount = (Number(totalSubAmount));
|
||||
totalAmount = totalAmount.toFixed(2);
|
||||
// $("#net_amount").val(totalAmount);
|
||||
// $("#totalAmountValue;").val(totalAmount);
|
||||
|
||||
var discount = $("#discount").val();
|
||||
if (discount) {
|
||||
var grandTotal = Number(totalAmount) - Number(discount);
|
||||
@ -362,10 +371,41 @@
|
||||
} else {
|
||||
$("#net_amount").val(totalAmount);
|
||||
$("#net_amount_value").val(totalAmount);
|
||||
}
|
||||
}
|
||||
|
||||
} // /else discount
|
||||
// ✅ Vérification du rabais vs prix minimal
|
||||
function checkMinimalPrice() {
|
||||
var discount = Number($("#discount").val()) || 0;
|
||||
|
||||
// Si pas de rabais, pas de vérification nécessaire
|
||||
if (discount === 0) return true;
|
||||
|
||||
var tableProductLength = $("#product_info_table tbody tr").length;
|
||||
var error = false;
|
||||
var messages = [];
|
||||
|
||||
} // /sub total amount
|
||||
for (var i = 0; i < tableProductLength; i++) {
|
||||
var tr = $("#product_info_table tbody tr")[i];
|
||||
var rowId = $(tr).attr('id').replace('row_', '');
|
||||
var minPrice = Number($("#min_price_" + rowId).val()) || 0;
|
||||
|
||||
// ✅ Le rabais devient le prix de vente
|
||||
if (minPrice > 0 && discount < minPrice) {
|
||||
error = true;
|
||||
var productText = $("#product_" + rowId + " option:selected").text();
|
||||
messages.push("Le rabais (" + discount + ") pour « " + productText + " » est inférieur au prix minimal (" + minPrice + ")");
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
alert(messages.join("\n"));
|
||||
$("#discount").val('');
|
||||
subAmount();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function removeRow(tr_id) {
|
||||
$("#product_info_table tbody tr#row_" + tr_id).remove();
|
||||
@ -378,7 +418,7 @@
|
||||
const amount = document.getElementById('amount_1')
|
||||
const gross_amount_value = document.getElementById('gross_amount');
|
||||
const gross_amount_value2 = document.getElementById('gross_amount_value');
|
||||
const remise = document.getElementById('remise');
|
||||
const remise = document.getElementById('discount');
|
||||
const net_amount = document.getElementById('net_amount');
|
||||
const net_amount_value = document.getElementById('net_amount_value');
|
||||
const amount_value = document.getElementById('amount_value_1');
|
||||
@ -393,5 +433,6 @@
|
||||
remise.addEventListener('input', function () {
|
||||
net_amount.value = (gross_amount_value.value - remise.value);
|
||||
net_amount_value.value = (gross_amount_value.value - remise.value);
|
||||
subAmount();
|
||||
})
|
||||
</script>
|
||||
@ -172,7 +172,14 @@
|
||||
<div class="form-group">
|
||||
<label for="discount" class="col-sm-5 control-label">Rabais</label>
|
||||
<div class="col-sm-7">
|
||||
<input type="text" class="form-control" id="discount" name="discount" placeholder="Discount" onkeyup="subAmount()" value="<?php echo $order_data['order']['discount'] ?>" autocomplete="off">
|
||||
<?php
|
||||
$users = session()->get('user');
|
||||
if($users && $users['group_name'] == 'COMMERCIALE'):
|
||||
?>
|
||||
<input type="text" class="form-control" id="discount" name="discount" placeholder="Discount" onkeyup="subAmount()" value="<?php echo $order_data['order']['discount'] ?>" autocomplete="off">
|
||||
<?php else: ?>
|
||||
<input type="text" class="form-control" id="discount" name="discount" readonly value="<?php echo $order_data['order']['discount'] ?>" autocomplete="off">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@ -194,24 +201,34 @@
|
||||
</select>
|
||||
</div>
|
||||
</div> -->
|
||||
<?php
|
||||
$users = session()->get('user');
|
||||
if ($users && $users['group_name'] !== 'COMMERCIALE'):
|
||||
?>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="paid_status" class="col-sm-5 control-label">Tranche de paiement</label>
|
||||
<div class="col-sm-7">
|
||||
<select class="form-control" id="payment_mode" name="payment_mode">
|
||||
<option value="1" selected>une tranche</option>
|
||||
<option value="2">deux tranches</option>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- ✅ AJOUTEZ CE CHAMP AVANT LES TRANCHES -->
|
||||
<div class="form-group" id="montant_reference" style="display: none">
|
||||
<label class="col-sm-5 control-label">Montant à répartir</label>
|
||||
<div class="col-sm-7">
|
||||
<input type="text" class="form-control" id="montant_total_tranches" disabled>
|
||||
<input type="hidden" id="montant_total_tranches_value">
|
||||
<small class="text-muted" id="montant_source_label"></small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="payment-tranches">
|
||||
<div class="form-group" id="paid_status_1" style="display: none">
|
||||
<label for="paid_status_1" class="col-sm-5 control-label">Tranche 1</label>
|
||||
|
||||
<div class="col-sm-3">
|
||||
<select class="form-control" id="payment_mode_1" name="order_payment_mode_1">
|
||||
<option value="MVOLA">MVOLA</option>
|
||||
@ -220,12 +237,13 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" class="form-control" id="payment_amount_1" name="tranche_1" placeholder="Montant">
|
||||
<input type="number" class="form-control" id="payment_amount_1"
|
||||
name="tranche_1" placeholder="Montant" onkeyup="calculerTranche2()">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="paid_status_2" style="display: none">
|
||||
<label for="paid_status_2" class="col-sm-5 control-label">Tranche 2</label>
|
||||
|
||||
<label for="paid_status_2" class="col-sm-5 control-label">Tranche 2 (Reste)</label>
|
||||
<div class="col-sm-3">
|
||||
<select class="form-control" id="payment_mode_2" name="order_payment_mode_2">
|
||||
<option value="MVOLA">MVOLA</option>
|
||||
@ -234,11 +252,12 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" class="form-control" id="payment_amount_2" name="tranche_2" placeholder="Montant">
|
||||
<input type="number" class="form-control" id="payment_amount_2"
|
||||
name="tranche_2" placeholder="Montant" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
@ -280,20 +299,24 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<?php
|
||||
$users = session()->get('user');
|
||||
if ($users && $users['group_name'] !== 'COMMERCIALE'):
|
||||
?>
|
||||
|
||||
<div class="form-group">
|
||||
<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">Payé</option>
|
||||
<option value="2">Non payé</option>
|
||||
<option value="1">Validé</option>
|
||||
<option value="2">Refusé</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- /.box-body -->
|
||||
|
||||
<div class="box-footer">
|
||||
@ -337,42 +360,54 @@
|
||||
Imprimente.removeAttribute("href");
|
||||
Imprimente.setAttribute("href", base_url +'orders/printDivBLF/' + idData);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// function printOrder(id)
|
||||
// {
|
||||
// if(id) {
|
||||
// $.ajax({
|
||||
// url: base_url + 'orders/printDiv/' + id,
|
||||
// type: 'post',
|
||||
// success:function(response) {
|
||||
// var mywindow = window.open('', 'new div', 'height=400,width=600');
|
||||
// // mywindow.document.write('<html><head><title></title>');
|
||||
// // mywindow.document.write('<link rel="stylesheet" href="<?php //echo base_url('assets/bower_components/bootstrap/dist/css/bootstrap.min.css')
|
||||
?>" type="text/css" />');
|
||||
// // mywindow.document.write('</head><body >');
|
||||
// mywindow.document.write(response);
|
||||
// // mywindow.document.write('</body></html>');
|
||||
|
||||
// mywindow.print();
|
||||
// mywindow.close();
|
||||
|
||||
// return true;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
$(".select_group").select2();
|
||||
// $("#description").wysihtml5();
|
||||
|
||||
$("#mainOrdersNav").addClass('active');
|
||||
$("#manageOrdersNav").addClass('active');
|
||||
|
||||
// ============================================
|
||||
// 🔹 AJOUT : GESTION DES TRANCHES DE PAIEMENT
|
||||
// ============================================
|
||||
var paymentTranche = 1;
|
||||
var netAmount = parseFloat($('#net_amount_value').val()) || 0;
|
||||
$('#payment_amount_1').val(netAmount);
|
||||
|
||||
// Add new row in the table
|
||||
function addPaymentTranche(paymentTranche) {
|
||||
if (parseInt(paymentTranche) === 2) {
|
||||
$("#paid_status_1").show();
|
||||
$("#paid_status_2").show();
|
||||
|
||||
var amount1 = parseFloat($('#payment_amount_1').val()) || 0;
|
||||
var amount2 = netAmount - amount1;
|
||||
$('#payment_amount_2').val(amount2);
|
||||
} else {
|
||||
$("#paid_status_1").show();
|
||||
$("#paid_status_2").hide();
|
||||
$('#payment_mode_2').val('');
|
||||
}
|
||||
}
|
||||
|
||||
// Sélection du mode de paiement
|
||||
$("#payment_mode").on("change", function() {
|
||||
addPaymentTranche($(this).val());
|
||||
updateMontantTranches(); // ✅ pour mise à jour automatique
|
||||
});
|
||||
|
||||
// Modification du montant de la première tranche
|
||||
$('#payment_amount_1').on("input", function() {
|
||||
var amount1 = parseFloat($(this).val()) || 0;
|
||||
var amount2 = netAmount - amount1;
|
||||
$('#payment_amount_2').val(amount2);
|
||||
});
|
||||
|
||||
addPaymentTranche(paymentTranche);
|
||||
|
||||
// ============================================
|
||||
// 🔹 TABLEAU DE PRODUITS
|
||||
// ============================================
|
||||
$("#add_row").unbind('click').bind('click', function() {
|
||||
var table = $("#product_info_table");
|
||||
var count_table_tbody_tr = $("#product_info_table tbody tr").length;
|
||||
@ -383,9 +418,6 @@
|
||||
type: 'post',
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
|
||||
|
||||
// console.log(reponse.x);
|
||||
var html = '<tr id="row_' + row_id + '">' +
|
||||
'<td>' +
|
||||
'<select class="form-control select_group product" data-row-id="' + row_id + '" id="product_' + row_id + '" name="product[]" style="width:100%;" onchange="getProductData(' + row_id + ')">' +
|
||||
@ -409,70 +441,62 @@
|
||||
}
|
||||
|
||||
$(".product").select2();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
}); // /document.ready
|
||||
|
||||
}); // /document
|
||||
|
||||
// ============================================
|
||||
// 🔹 CALCUL DU TOTAL
|
||||
// ============================================
|
||||
function getTotal(row = null) {
|
||||
if (row) {
|
||||
var total = Number($("#rate_value_" + row).val()) * Number($("#qty_" + row).val());
|
||||
total = total.toFixed(2);
|
||||
$("#amount_" + row).val(total);
|
||||
$("#amount_value_" + row).val(total);
|
||||
|
||||
subAmount();
|
||||
|
||||
} else {
|
||||
alert('no row !! please refresh the page');
|
||||
}
|
||||
}
|
||||
|
||||
// get the product information from the server
|
||||
// 🔹 OBTENIR LES DONNÉES PRODUIT
|
||||
function getProductData(row_id) {
|
||||
var product_id = $("#product_" + row_id).val();
|
||||
if (product_id == "") {
|
||||
$("#rate_" + row_id).val("");
|
||||
$("#rate_value_" + row_id).val("");
|
||||
|
||||
$("#qty_" + row_id).val("");
|
||||
|
||||
$("#amount_" + row_id).val("");
|
||||
$("#amount_value_" + row_id).val("");
|
||||
|
||||
} else {
|
||||
$.ajax({
|
||||
url: base_url + 'orders/getProductValueById',
|
||||
type: 'post',
|
||||
data: {
|
||||
product_id: product_id
|
||||
},
|
||||
data: { product_id: product_id },
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
// setting the rate value into the rate input field
|
||||
|
||||
$("#rate_" + row_id).val(response.price);
|
||||
$("#rate_value_" + row_id).val(response.price);
|
||||
|
||||
$("#qty_" + row_id).val(1);
|
||||
$("#qty_value_" + row_id).val(1);
|
||||
|
||||
var total = Number(response.price) * 1;
|
||||
total = total.toFixed(2);
|
||||
$("#amount_" + row_id).val(total);
|
||||
$("#amount_value_" + row_id).val(total);
|
||||
|
||||
subAmount();
|
||||
} // /success
|
||||
}); // /ajax function to fetch the product data
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the total amount of the order
|
||||
// ============================================
|
||||
// 🔹 CALCUL DU MONTANT TOTAL (AVEC TVA, REMISE, ETC.)
|
||||
// ============================================
|
||||
function subAmount() {
|
||||
var service_charge = <?php echo ($company_data['service_charge_value'] > 0) ? $company_data['service_charge_value'] : 0; ?>;
|
||||
var vat_charge = <?php echo ($company_data['vat_charge_value'] > 0) ? $company_data['vat_charge_value'] : 0; ?>;
|
||||
@ -483,33 +507,25 @@
|
||||
var tr = $("#product_info_table tbody tr")[x];
|
||||
var count = $(tr).attr('id');
|
||||
count = count.substring(4);
|
||||
|
||||
totalSubAmount = Number(totalSubAmount) + Number($("#amount_" + count).val());
|
||||
} // /for
|
||||
}
|
||||
|
||||
totalSubAmount = totalSubAmount.toFixed(2);
|
||||
|
||||
// sub total
|
||||
$("#gross_amount").val(totalSubAmount);
|
||||
$("#gross_amount_value").val(totalSubAmount);
|
||||
|
||||
// vat
|
||||
var vat = (Number($("#gross_amount").val()) / 100) * vat_charge;
|
||||
vat = vat.toFixed(2);
|
||||
$("#vat_charge").val(vat);
|
||||
$("#vat_charge_value").val(vat);
|
||||
|
||||
// service
|
||||
var service = (Number($("#gross_amount").val()) / 100) * service_charge;
|
||||
service = service.toFixed(2);
|
||||
$("#service_charge").val(service);
|
||||
$("#service_charge_value").val(service);
|
||||
|
||||
// total amount
|
||||
var totalAmount = (Number(totalSubAmount));
|
||||
totalAmount = totalAmount.toFixed(2);
|
||||
// $("#net_amount").val(totalAmount);
|
||||
// $("#totalAmountValue").val(totalAmount);
|
||||
|
||||
var discount = $("#discount").val();
|
||||
if (discount) {
|
||||
@ -520,8 +536,7 @@
|
||||
} else {
|
||||
$("#net_amount").val(totalAmount);
|
||||
$("#net_amount_value").val(totalAmount);
|
||||
|
||||
} // /else discount
|
||||
}
|
||||
|
||||
var paid_amount = Number($("#paid_amount").val());
|
||||
if (paid_amount) {
|
||||
@ -531,27 +546,71 @@
|
||||
$("#remaining_value").val(remaning.toFixed(2));
|
||||
}
|
||||
|
||||
} // /sub total amount
|
||||
// ✅ Mise à jour automatique des tranches à chaque recalcul
|
||||
updateMontantTranches();
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 🔹 AUTRES FONCTIONS
|
||||
// ============================================
|
||||
function paidAmount() {
|
||||
var grandTotal = $("#net_amount_value").val();
|
||||
|
||||
if (grandTotal) {
|
||||
var dueAmount = Number($("#net_amount_value").val()) - Number($("#paid_amount").val());
|
||||
dueAmount = dueAmount.toFixed(2);
|
||||
$("#remaining").val(dueAmount);
|
||||
$("#remaining_value").val(dueAmount);
|
||||
} // /if
|
||||
} // /paid amoutn function
|
||||
}
|
||||
}
|
||||
|
||||
function removeRow(tr_id) {
|
||||
$("#product_info_table tbody tr#row_" + tr_id).remove();
|
||||
subAmount();
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 🔹 GESTION MONTANT DE TRANCHES (FONCTIONS NOUVELLES)
|
||||
// ============================================
|
||||
function getMontantPourTranches() {
|
||||
var discount = parseFloat($("#discount").val()) || 0;
|
||||
var grossAmount = parseFloat($("#gross_amount_value").val()) || 0;
|
||||
return discount > 0 ? discount : grossAmount;
|
||||
}
|
||||
|
||||
function updateMontantTranches() {
|
||||
var montant = getMontantPourTranches();
|
||||
var discount = parseFloat($("#discount").val()) || 0;
|
||||
|
||||
$("#montant_total_tranches").val(montant.toFixed(2));
|
||||
$("#montant_total_tranches_value").val(montant);
|
||||
|
||||
if (discount > 0) {
|
||||
$("#montant_source_label").text("(Prix avec remise acceptée)");
|
||||
} else {
|
||||
$("#montant_source_label").text("(Montant brut)");
|
||||
}
|
||||
|
||||
if ($("#payment_amount_1").val()) {
|
||||
calculerTranche2();
|
||||
}
|
||||
}
|
||||
|
||||
function calculerTranche2() {
|
||||
var montantTotal = getMontantPourTranches();
|
||||
var tranche1 = parseFloat($("#payment_amount_1").val()) || 0;
|
||||
var tranche2 = montantTotal - tranche1;
|
||||
if (tranche2 < 0) tranche2 = 0;
|
||||
$("#payment_amount_2").val(tranche2.toFixed(2));
|
||||
}
|
||||
|
||||
$("#discount").on('keyup', function() {
|
||||
updateMontantTranches();
|
||||
});
|
||||
|
||||
const net_amount_value = document.getElementById('net_amount_value');
|
||||
const net_amount = document.getElementById('net_amount');
|
||||
const payment_amount_1 = document.getElementById('payment_amount_1');
|
||||
payment_amount_1.value = net_amount.value
|
||||
console.log(net_amount_value.value, net_amount.value, payment_amount_1.value);
|
||||
</script>
|
||||
payment_amount_1.value = net_amount.value;
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
@ -56,9 +56,9 @@
|
||||
<th>Nom du client</th>
|
||||
<th>Téléphone du client</th>
|
||||
<th>Date et Heure</th>
|
||||
<th>Produits totaux</th>
|
||||
<th>Remise</th>
|
||||
<th>Prix de vente</th>
|
||||
<th>Statut payant</th>
|
||||
<th>Validation</th>
|
||||
|
||||
<?php if (
|
||||
in_array('updateOrder', $user_permission)
|
||||
@ -72,16 +72,17 @@
|
||||
<?php
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
if ($users['group_name'] === 'COMMERCIALE' || $users['group_name'] === 'Caissière' || $users['group_name'] === "Cheffe d'Agence") {
|
||||
if ($users['group_name'] === 'COMMERCIALE' || $users['group_name'] === 'Caissière' || $users['group_name'] === 'SECURITE' || $users['group_name'] === "Cheffe d'Agence") {
|
||||
?>
|
||||
<th>Nom du produit</th>
|
||||
<th>Commerciale</th>
|
||||
<th>Date et Heure</th>
|
||||
<th>Produits totaux</th>
|
||||
<th>Remise</th>
|
||||
<th>Prix de vente</th>
|
||||
<th>Statut payant</th>
|
||||
<th>Validation</th>
|
||||
<?php if (
|
||||
in_array('viewOrder', $user_permission)
|
||||
|| in_array('updateOrder', $user_permission)
|
||||
) { ?>
|
||||
<th>Action</th>
|
||||
<?php } ?>
|
||||
@ -144,6 +145,9 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<!-- Messages de la modal -->
|
||||
<div id="modal-messages"></div>
|
||||
|
||||
<!-- Ligne Date / Heure -->
|
||||
<div class="row">
|
||||
<div class="col-md-6 form-group">
|
||||
@ -181,31 +185,39 @@
|
||||
<h4>Produits</h4>
|
||||
<table class="table table-bordered table-striped" id="view_products_table">
|
||||
<thead>
|
||||
<tr><th>Produit</th><th>Quantité</th><th>Prix unitaire</th><th>Montant</th></tr>
|
||||
<tr><th>Marque</th><th>Designation</th><th>Numéro de Série</th><th>Prix Unitaire</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>Montant net</th><th>Statut</th>
|
||||
<tr><td id="gross_amount"></td><td id="discount"></td><td id="net_amount"></td><td id="paid_status"></td><tr>
|
||||
</table>
|
||||
|
||||
<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">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Fermer</button>
|
||||
|
||||
<?php
|
||||
$session = session();
|
||||
$users = $session->get('user');
|
||||
if ($users['group_name'] === 'SECURITE'): ?>
|
||||
<button type="button" class="btn btn-success" id="btn-mark-delivered" style="display:none;">
|
||||
<i class="fa fa-truck"></i> Marquer comme Livré
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
var manageTable;
|
||||
var base_url = "<?php echo base_url(); ?>";
|
||||
var currentOrderId = null; // Variable globale pour stocker l'ID de la commande actuelle
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
@ -213,31 +225,29 @@
|
||||
$("#manageOrdersNav").addClass('active');
|
||||
|
||||
// initialize the datatable
|
||||
|
||||
// datatable-fr.js
|
||||
$.extend(true, $.fn.dataTable.defaults, {
|
||||
language: {
|
||||
sProcessing: "Traitement en cours...",
|
||||
sSearch: "Rechercher :",
|
||||
sLengthMenu: "Afficher _MENU_ éléments",
|
||||
sInfo: "Affichage de l'élement _START_ à _END_ sur _TOTAL_ éléments",
|
||||
sInfoEmpty: "Affichage de l'élement 0 à 0 sur 0 élément",
|
||||
sInfoFiltered: "(filtré de _MAX_ éléments au total)",
|
||||
sLoadingRecords: "Chargement en cours...",
|
||||
sZeroRecords: "Aucun élément à afficher",
|
||||
sEmptyTable: "Aucune donnée disponible dans le tableau",
|
||||
oPaginate: {
|
||||
sFirst: "Premier",
|
||||
sPrevious: "Précédent",
|
||||
sNext: "Suivant",
|
||||
sLast: "Dernier"
|
||||
},
|
||||
oAria: {
|
||||
sSortAscending: ": activer pour trier la colonne par ordre croissant",
|
||||
sSortDescending: ": activer pour trier la colonne par ordre décroissant"
|
||||
}
|
||||
}
|
||||
});
|
||||
$.extend(true, $.fn.dataTable.defaults, {
|
||||
language: {
|
||||
sProcessing: "Traitement en cours...",
|
||||
sSearch: "Rechercher :",
|
||||
sLengthMenu: "Afficher _MENU_ éléments",
|
||||
sInfo: "Affichage de l'élement _START_ à _END_ sur _TOTAL_ éléments",
|
||||
sInfoEmpty: "Affichage de l'élement 0 à 0 sur 0 élément",
|
||||
sInfoFiltered: "(filtré de _MAX_ éléments au total)",
|
||||
sLoadingRecords: "Chargement en cours...",
|
||||
sZeroRecords: "Aucun élément à afficher",
|
||||
sEmptyTable: "Aucune donnée disponible dans le tableau",
|
||||
oPaginate: {
|
||||
sFirst: "Premier",
|
||||
sPrevious: "Précédent",
|
||||
sNext: "Suivant",
|
||||
sLast: "Dernier"
|
||||
},
|
||||
oAria: {
|
||||
sSortAscending: ": activer pour trier la colonne par ordre croissant",
|
||||
sSortDescending: ": activer pour trier la colonne par ordre décroissant"
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
manageTable = $('#manageTable').DataTable({
|
||||
'ajax': base_url + 'orders/fetchOrdersData',
|
||||
@ -245,8 +255,72 @@
|
||||
'columnDefs': [{
|
||||
targets: 6,
|
||||
className: 'text-right'
|
||||
} // Column index 3 corresponds to "Prix"
|
||||
]
|
||||
}]
|
||||
});
|
||||
|
||||
// Gestionnaire pour le bouton "Marquer comme Livré"
|
||||
$('#btn-mark-delivered').on('click', function() {
|
||||
if (!currentOrderId) {
|
||||
alert('Erreur : ID de commande introuvable.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (confirm('Êtes-vous sûr de vouloir marquer cette commande comme livrée ?')) {
|
||||
// Désactiver le bouton pendant le traitement
|
||||
$('#btn-mark-delivered').prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> Traitement...');
|
||||
|
||||
$.ajax({
|
||||
url: base_url + 'orders/markAsDelivered',
|
||||
type: 'POST',
|
||||
data: { order_id: currentOrderId },
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
if (response.success === true) {
|
||||
// Afficher un message de succès dans la modal
|
||||
$("#modal-messages").html(
|
||||
'<div class="alert alert-success alert-dismissible" role="alert">' +
|
||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
||||
'<strong><span class="glyphicon glyphicon-ok-sign"></span></strong> ' + response.messages +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Mettre à jour le statut dans la modal
|
||||
$('#paid_status').html('<span class="label label-info">Validé et Livré</span>');
|
||||
|
||||
// Cacher le bouton "Livré"
|
||||
$('#btn-mark-delivered').hide();
|
||||
|
||||
// Recharger la table immédiatement
|
||||
manageTable.ajax.reload(null, false);
|
||||
|
||||
} else {
|
||||
// Afficher un message d'erreur
|
||||
$("#modal-messages").html(
|
||||
'<div class="alert alert-danger alert-dismissible" role="alert">' +
|
||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
||||
'<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong> ' + response.messages +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Réactiver le bouton
|
||||
$('#btn-mark-delivered').prop('disabled', false).html('<i class="fa fa-truck"></i> Marquer comme Livré');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Erreur AJAX:', xhr.responseText);
|
||||
$("#modal-messages").html(
|
||||
'<div class="alert alert-danger alert-dismissible" role="alert">' +
|
||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
||||
'<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong> Erreur de communication avec le serveur.<br>' +
|
||||
'Détails: ' + (xhr.responseText || error) +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Réactiver le bouton
|
||||
$('#btn-mark-delivered').prop('disabled', false).html('<i class="fa fa-truck"></i> Marquer comme Livré');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@ -255,38 +329,32 @@
|
||||
function removeFunc(id) {
|
||||
if (id) {
|
||||
$("#removeForm").on('submit', function() {
|
||||
|
||||
var form = $(this);
|
||||
|
||||
// remove the text-danger
|
||||
$(".text-danger").remove();
|
||||
|
||||
$.ajax({
|
||||
url: form.attr('action'),
|
||||
type: form.attr('method'),
|
||||
data: {
|
||||
order_id: id
|
||||
},
|
||||
data: { order_id: id },
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
|
||||
manageTable.ajax.reload(null, false);
|
||||
|
||||
if (response.success === true) {
|
||||
$("#messages").html('<div class="alert alert-success alert-dismissible" role="alert">' +
|
||||
$("#messages").html(
|
||||
'<div class="alert alert-success alert-dismissible" role="alert">' +
|
||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
||||
'<strong> <span class="glyphicon glyphicon-ok-sign"></span> </strong>' + response.messages +
|
||||
'</div>');
|
||||
|
||||
// hide the modal
|
||||
'</div>'
|
||||
);
|
||||
$("#removeModal").modal('hide');
|
||||
|
||||
} else {
|
||||
|
||||
$("#messages").html('<div class="alert alert-warning alert-dismissible" role="alert">' +
|
||||
$("#messages").html(
|
||||
'<div class="alert alert-warning alert-dismissible" role="alert">' +
|
||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
||||
'<strong> <span class="glyphicon glyphicon-exclamation-sign"></span> </strong>' + response.messages +
|
||||
'</div>');
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -297,55 +365,84 @@
|
||||
}
|
||||
|
||||
$(document).on('click', '.btn-view', function(e) {
|
||||
e.preventDefault();
|
||||
var orderId = $(this).data('order-id');
|
||||
var url = base_url + 'orders/lookOrder/' + orderId;
|
||||
e.preventDefault();
|
||||
var orderId = $(this).data('order-id');
|
||||
currentOrderId = orderId; // Stocker l'ID de la commande
|
||||
var url = base_url + 'orders/lookOrder/' + orderId;
|
||||
|
||||
// Requête AJAX pour récupérer les données JSON
|
||||
$.getJSON(url, function(response) {
|
||||
var d = response.order_data.order;
|
||||
var sum_order_data = response.order_data.sum_order_data;
|
||||
// Réinitialiser les messages
|
||||
$('#modal-messages').empty();
|
||||
|
||||
// Remplir les champs de la modal
|
||||
$('#order_date').text(d.date_time || '');
|
||||
$('#customer_name').text(d.customer_name);
|
||||
$('#customer_address').text(d.customer_address);
|
||||
$('#customer_phone').text(d.customer_phone);
|
||||
$('#customer_cin').text(d.customer_cin);
|
||||
// Requête AJAX pour récupérer les données JSON
|
||||
$.getJSON(url, function(response) {
|
||||
var d = response.order_data.order;
|
||||
|
||||
// Produits
|
||||
var $tb = $('#view_products_table tbody');
|
||||
$tb.empty();
|
||||
$.each(response.order_data.order_item, function(_, item) {
|
||||
// Trouver le nom du produit
|
||||
var prodName = '';
|
||||
$.each(response.products, function(_, p) {
|
||||
if (p.id == item.product_id) {
|
||||
prodName = p.name;
|
||||
return false;
|
||||
// Remplir les champs de la modal
|
||||
$('#order_date').text(d.date_time || '');
|
||||
$('#customer_name').text(d.customer_name);
|
||||
$('#customer_address').text(d.customer_address);
|
||||
$('#customer_phone').text(d.customer_phone);
|
||||
$('#customer_cin').text(d.customer_cin);
|
||||
|
||||
// Produits
|
||||
var $tb = $('#view_products_table tbody');
|
||||
$tb.empty();
|
||||
$.each(response.order_data.order_item, function(_, item) {
|
||||
var product = null;
|
||||
$.each(response.products, function(_, p) {
|
||||
if (p.id == item.product_id) {
|
||||
product = p;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (product) {
|
||||
var brandName = '';
|
||||
$.each(response.brands, function(_, brand) {
|
||||
if (brand.id == product.marque) {
|
||||
brandName = brand.name;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$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>' +
|
||||
'</tr>'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Ajouter une ligne au tableau des produits
|
||||
$tb.append(
|
||||
'<tr><td>' + prodName + '</td>' +
|
||||
'<td>' + sum_order_data + '</td>' +
|
||||
'<td>' + parseInt(item.rate).toLocaleString('fr-MG', { minimumFractionDigits: 0, maximumFractionDigits:0 }) + ' Ar</td>' +
|
||||
'<td>' + parseInt(item.amount).toLocaleString('fr-MG', { minimumFractionDigits: 0, maximumFractionDigits: 0 }) + ' Ar</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');
|
||||
});
|
||||
|
||||
// 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');
|
||||
$('#net_amount').text(parseInt(d.net_amount).toLocaleString('fr-MG', { minimumFractionDigits: 0, maximumFractionDigits: 0 }) + ' Ar');
|
||||
|
||||
// Statut de paiement
|
||||
var statut = (d.paid_status == 2) ? "non payé" : "payé";
|
||||
$('#paid_status').text(statut);
|
||||
|
||||
// Afficher la modal
|
||||
$('#viewOrderModal').modal('show');
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
@ -54,7 +54,7 @@
|
||||
<h3 class="box-title">Ajouter une Moto</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<form role="form" action="<?php base_url('create') ?>" method="post" enctype="multipart/form-data">
|
||||
<form role="form" action="<?= base_url('products/create') ?>" method="post" enctype="multipart/form-data">
|
||||
<?php if (isset($validation) && $validation->getErrors()) : ?>
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
@ -356,4 +356,43 @@
|
||||
})
|
||||
|
||||
});
|
||||
// --- Vérification prix minimal vs prix de vente ---
|
||||
const priceVenteInput = document.getElementById('price_vente');
|
||||
const priceMinInput = document.getElementById('price_min');
|
||||
|
||||
function verifierPrix() {
|
||||
const prixVente = parseFloat(priceVenteInput.value) || 0;
|
||||
const prixMin = parseFloat(priceMinInput.value) || 0;
|
||||
|
||||
if (prixMin > prixVente) {
|
||||
priceMinInput.style.borderColor = 'red';
|
||||
if (!document.getElementById('price_min_error')) {
|
||||
const small = document.createElement('small');
|
||||
small.id = 'price_min_error';
|
||||
small.style.color = 'red';
|
||||
small.textContent = 'Le prix minimal ne peut pas être supérieur au prix de vente';
|
||||
priceMinInput.parentNode.appendChild(small);
|
||||
}
|
||||
} else {
|
||||
priceMinInput.style.borderColor = '';
|
||||
const errorMsg = document.getElementById('price_min_error');
|
||||
if (errorMsg) errorMsg.remove();
|
||||
}
|
||||
}
|
||||
|
||||
priceVenteInput.addEventListener('input', verifierPrix);
|
||||
priceMinInput.addEventListener('input', verifierPrix);
|
||||
|
||||
// Vérification au submit
|
||||
document.querySelector('form').addEventListener('submit', function(e) {
|
||||
const prixVente = parseFloat(priceVenteInput.value) || 0;
|
||||
const prixMin = parseFloat(priceMinInput.value) || 0;
|
||||
|
||||
if (prixMin > prixVente) {
|
||||
e.preventDefault();
|
||||
alert('❌ Le prix minimal ne peut pas être supérieur au prix de vente !');
|
||||
priceMinInput.focus();
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
@ -5,8 +5,6 @@
|
||||
{
|
||||
// Ensure the string is properly formatted for JSON decoding
|
||||
$data = str_replace("'", '"', $data); // Convert single quotes to double quotes
|
||||
|
||||
// Decode JSON to an array
|
||||
return json_decode($data, true);
|
||||
}
|
||||
?>
|
||||
@ -24,10 +22,8 @@
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<!-- Small boxes (Stat box) -->
|
||||
<div class="row">
|
||||
<div class="col-md-12 col-xs-12">
|
||||
|
||||
<div id="messages"></div>
|
||||
|
||||
<?php if (session()->getFlashdata('success')): ?>
|
||||
@ -42,19 +38,20 @@
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title">Mise à jours Moto</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
|
||||
<form role="form" action="<?php base_url('users/update') ?>" method="post" enctype="multipart/form-data">
|
||||
<div class="box-body">
|
||||
<!-- Image actuelle -->
|
||||
<div class="form-group">
|
||||
<label>Image: </label>
|
||||
<img src="<?php echo base_url() . 'assets/images/product_image/' . $product_data['image'] ?>" width="150" height="150" class="img-circle">
|
||||
</div>
|
||||
|
||||
<!-- Nouvelle Image -->
|
||||
<div class="form-group">
|
||||
<label for="product_image">Nouvelle Image</label>
|
||||
<div class="kv-avatar">
|
||||
@ -64,195 +61,178 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Nom du produit -->
|
||||
<div class="form-group">
|
||||
<label for="product_name">Nom de Moto</label>
|
||||
<input type="text" class="form-control" id="product_name" name="nom_de_produit" placeholder="Nom du moto" autocomplete="off" value="<?php echo $product_data['name']; ?>" />
|
||||
</div>
|
||||
|
||||
<!-- Marque -->
|
||||
<div class="form-group">
|
||||
<label for="marque">Marque</label>
|
||||
<select class="form-control" id="marque" name="marque">
|
||||
<?php foreach ($marque as $k => $v): ?>
|
||||
<option value="<?php echo $v['id'] ?>" <?php if ($product_data['marque'] == $v['id']) {
|
||||
echo "selected='selected'";
|
||||
} ?>><?php echo $v['name'] ?></option>
|
||||
<option value="<?php echo $v['id'] ?>" <?php if ($product_data['marque'] == $v['id']) echo "selected"; ?>><?php echo $v['name'] ?></option>
|
||||
<?php endforeach ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Numéro de moteur -->
|
||||
<div class="form-group">
|
||||
<label for="moteur">Numéro de moteur</label>
|
||||
<input type="text" class="form-control" id="moteur" name="numero_de_moteur" placeholder="Numéro de série" autocomplete="off" value="<?php echo $product_data['numero_de_moteur']; ?>" />
|
||||
</div>
|
||||
|
||||
<!-- Châssis -->
|
||||
<div class="form-group">
|
||||
<label for="chassis">Châssis</label>
|
||||
<input type="text" class="form-control" id="chassis" name="chasis" placeholder="Chassis" autocomplete="off" value="<?php echo $product_data['chasis']; ?>" />
|
||||
</div>
|
||||
|
||||
<!-- Prix d'achat -->
|
||||
<div class="form-group">
|
||||
<label for="price">Prix d'Achat</label>
|
||||
<input type="number" min="0" class="form-control" id="price" name="price" placeholder="Prix d'achat" autocomplete="off" value="<?php echo $product_data['price']; ?>" />
|
||||
</div>
|
||||
|
||||
<!-- Prix de vente -->
|
||||
<div class="form-group">
|
||||
<label for="price_vente">Prix de Vente</label>
|
||||
<input type="number" min="0" class="form-control" id="price_vente" name="price_vente" placeholder="Prix de vente" autocomplete="off" value="<?php echo $product_data['prix_vente']; ?>" />
|
||||
<input type="number" min="0" class="form-control" id="price_vente" name="price_vente" placeholder="Prix de vente" autocomplete="off" value="<?php echo $product_data['prix_vente']; ?>" required />
|
||||
</div>
|
||||
|
||||
<!-- Prix minimal -->
|
||||
<div class="form-group">
|
||||
<label for="qty">Quantiter</label>
|
||||
<input type="number" min="0" class="form-control" id="qty" name="quantiter" placeholder="Quantiter" autocomplete="off" value="<?php echo $product_data['qty']; ?>" />
|
||||
<label for="price_min">Prix Minimal</label>
|
||||
<input type="number" min="0" class="form-control" id="price_min" name="price_min" placeholder="Prix de vente minimal autorisé" autocomplete="off" value="<?= old('price_min') ?: $prix_minimal ?>" required />
|
||||
<small id="price_min_error" style="color:red; display:none;">Le prix minimal ne peut pas être supérieur au prix de vente</small>
|
||||
</div>
|
||||
|
||||
<!-- Date d'arrivage -->
|
||||
<div class="form-group">
|
||||
<label for="datea">Date d'arrivage</label>
|
||||
<input type="date" class="form-control" id="datea" name="datea" autocomplete="off" value="<?php echo $product_data['date_arivage']; ?>" />
|
||||
</div>
|
||||
|
||||
<!-- Puissance -->
|
||||
<div class="form-group">
|
||||
<label for="puissance">Puissances</label>
|
||||
<input type="text" class="form-control" id="puissance" name="puissance" placeholder="Puissances" autocomplete="off" value="<?php echo $product_data['puissance']; ?>" />
|
||||
</div>
|
||||
|
||||
<!-- Clé -->
|
||||
<div class="form-group">
|
||||
<label for="cler">Clé</label>
|
||||
<input type="text" class="form-control" id="cler" name="cler" placeholder="Type de clé" autocomplete="off" value="<?php echo $product_data['cler']; ?>" />
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<textarea type="text" class="form-control" id="description" name="description" placeholder="Description" autocomplete="off">
|
||||
<?php echo $product_data['description']; ?>
|
||||
</textarea>
|
||||
<textarea type="text" class="form-control" id="description" name="description" placeholder="Description" autocomplete="off"><?php echo $product_data['description']; ?></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Numéro de série -->
|
||||
<div class="form-group">
|
||||
<label for="sku">Numéro de série</label>
|
||||
<input type="text" class="form-control" id="sku" name="numero_de_serie" placeholder="Numéro de série" autocomplete="off" value="<?php echo $product_data['sku']; ?>" />
|
||||
</div>
|
||||
|
||||
<!-- Catégories -->
|
||||
<div class="form-group">
|
||||
<label for="categorie">Catégories</label>
|
||||
<?php
|
||||
// Normalisation de la valeur de product_data['categorie_id']
|
||||
$rawCats = $product_data['categorie_id'] ?? null;
|
||||
|
||||
if (is_array($rawCats)) {
|
||||
$catIds = array_map('intval', $rawCats);
|
||||
} elseif (is_string($rawCats)) {
|
||||
// transforme "1,2,3" en [1,2,3]
|
||||
$catIds = array_filter(array_map('intval', explode(',', $rawCats)), fn($id) => $id > 0);
|
||||
} elseif (is_int($rawCats) || ctype_digit((string)$rawCats)) {
|
||||
// wrap l'int en tableau
|
||||
$catIds = [(int) $rawCats];
|
||||
} else {
|
||||
$catIds = [];
|
||||
}
|
||||
?>
|
||||
|
||||
<select class="form-control select_group" id="categorie" name="categorie[]" multiple="multiple">
|
||||
<?php foreach ($categorie as $k => $v): ?>
|
||||
<option value="<?= $v['id']; ?>"
|
||||
<?= in_array($v['id'], $catIds, true) ? 'selected="selected"' : '' ?>>
|
||||
<?= esc($v['name']); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
||||
|
||||
<?php
|
||||
$rawCats = $product_data['categorie_id'] ?? null;
|
||||
if (is_array($rawCats)) {
|
||||
$catIds = array_map('intval', $rawCats);
|
||||
} elseif (is_string($rawCats)) {
|
||||
$catIds = array_filter(array_map('intval', explode(',', $rawCats)), fn($id) => $id > 0);
|
||||
} elseif (is_int($rawCats) || ctype_digit((string)$rawCats)) {
|
||||
$catIds = [(int) $rawCats];
|
||||
} else {
|
||||
$catIds = [];
|
||||
}
|
||||
?>
|
||||
<select class="form-control select_group" id="categorie" name="categorie[]" multiple="multiple">
|
||||
<?php foreach ($categorie as $k => $v): ?>
|
||||
<option value="<?= $v['id']; ?>" <?= in_array($v['id'], $catIds, true) ? 'selected="selected"' : '' ?>><?= esc($v['name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Magasin -->
|
||||
<div class="form-group">
|
||||
<label for="store">Magasin</label>
|
||||
<select class="form-control select_group" id="store" name="store">
|
||||
<?php foreach ($stores as $k => $v): ?>
|
||||
<option value="<?php echo $v['id'] ?>" <?php if ($product_data['store_id'] == $v['id']) {
|
||||
echo "selected='selected'";
|
||||
} ?>><?php echo $v['name'] ?></option>
|
||||
<option value="<?php echo $v['id'] ?>" <?php if ($product_data['store_id'] == $v['id']) echo "selected"; ?>><?php echo $v['name'] ?></option>
|
||||
<?php endforeach ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Disponibilité -->
|
||||
<div class="form-group">
|
||||
<label for="store">Disponibilité</label>
|
||||
<select class="form-control" id="availability" name="availability">
|
||||
<option value="1" <?php if ($product_data['availability'] == 1) {
|
||||
echo "selected='selected'";
|
||||
} ?>>Oui</option>
|
||||
<option value="0" <?php if ($product_data['availability'] == 0) {
|
||||
echo "selected='selected'";
|
||||
} ?>>Non</option> <!-- Changé de 2 à 0 -->
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="store">Etats</label>
|
||||
<select class="form-control" id="etat" name="etats">
|
||||
<option value="1" <?php if ($product_data['etats'] == 1) {
|
||||
echo "selected='selected'";
|
||||
} ?>>Kit</option>
|
||||
<option value="2" <?php if ($product_data['etats'] != 1) {
|
||||
echo "selected='selected'";
|
||||
} ?>>Non Kit</option>
|
||||
<label for="availability">Disponibilité</label>
|
||||
<select class="form-control" id="availability" name="availability">
|
||||
<option value="1" <?php if ($product_data['availability'] == 1) echo "selected"; ?>>Oui</option>
|
||||
<option value="0" <?php if ($product_data['availability'] == 0) echo "selected"; ?>>Non</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Etats -->
|
||||
<div class="form-group">
|
||||
<label for="etat">Etats</label>
|
||||
<select class="form-control" id="etat" name="etats">
|
||||
<option value="1" <?php if ($product_data['etats'] == 1) echo "selected"; ?>>Kit</option>
|
||||
<option value="2" <?php if ($product_data['etats'] != 1) echo "selected"; ?>>Non Kit</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="boxsuplementairekit"></div>
|
||||
|
||||
<!-- Pièce manquante -->
|
||||
<div class="form-group">
|
||||
<label for="store">Pièce Manquant</label>
|
||||
<label for="info">Pièce Manquant</label>
|
||||
<select class="form-control" id="info" name="info">
|
||||
<option value="2" <?php if ($product_data['info'] != 1) {
|
||||
echo "selected='selected'";
|
||||
} ?>>Non</option>
|
||||
<option value="1" <?php if ($product_data['info'] == 1) {
|
||||
echo "selected='selected'";
|
||||
} ?>>Oui</option>
|
||||
<option value="2" <?php if ($product_data['info'] != 1) echo "selected"; ?>>Non</option>
|
||||
<option value="1" <?php if ($product_data['info'] == 1) echo "selected"; ?>>Oui</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="boxsuplementaire"></div>
|
||||
<div class="form-group">
|
||||
<label for="store">type</label>
|
||||
<select class="form-control" id="type" name="type">
|
||||
<option value="A" <?php if ($product_data['type'] == "A") echo "selected"; ?>>A</option>
|
||||
<option value="B" <?php if ($product_data['type'] == "B") echo "selected"; ?>>B</option>
|
||||
<option value="C" <?php if ($product_data['type'] == "C") echo "selected"; ?>>C</option>
|
||||
<option value="D" <?php if ($product_data['type'] == "D") echo "selected"; ?>>D</option>
|
||||
|
||||
<!-- Type -->
|
||||
<div class="form-group">
|
||||
<label for="type">Type</label>
|
||||
<select class="form-control" id="type" name="type">
|
||||
<option value="A" <?php if ($product_data['type'] == "A") echo "selected"; ?>>A</option>
|
||||
<option value="B" <?php if ($product_data['type'] == "B") echo "selected"; ?>>B</option>
|
||||
<option value="C" <?php if ($product_data['type'] == "C") echo "selected"; ?>>C</option>
|
||||
<option value="D" <?php if ($product_data['type'] == "D") echo "selected"; ?>>D</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div> <!-- /.box-body -->
|
||||
|
||||
<div class="box-footer">
|
||||
<button type="submit" class="btn btn-primary">Enregistrer</button>
|
||||
<a href="<?php echo base_url('products/') ?>" class="btn btn-warning">Retour</a>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="box-footer">
|
||||
<button type="submit" class="btn btn-primary">Enregistrer</button>
|
||||
<a href="<?php echo base_url('products/') ?>" class="btn btn-warning">Retour</a>
|
||||
</div>
|
||||
</form>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
<!-- col-md-12 -->
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
|
||||
|
||||
</section>
|
||||
<!-- /.content -->
|
||||
</div>
|
||||
<!-- /.content-wrapper -->
|
||||
</form>
|
||||
</div> <!-- /.box -->
|
||||
</div> <!-- /.col-md-12 -->
|
||||
</div> <!-- /.row -->
|
||||
</section> <!-- /.content -->
|
||||
</div> <!-- /.content-wrapper -->
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$(document).ready(function() {
|
||||
// --- Initialisations ---
|
||||
$(".select_group").select2();
|
||||
$("#description").wysihtml5();
|
||||
|
||||
$("#mainProductNav").addClass('active');
|
||||
$("#manageProductNav").addClass('active');
|
||||
|
||||
// --- Gestion image ---
|
||||
var btnCust = '<button type="button" class="btn btn-secondary" title="Add picture tags" ' +
|
||||
'onclick="alert(\'Call your custom code here.\')">' +
|
||||
'<i class="glyphicon glyphicon-tag"></i>' +
|
||||
@ -269,60 +249,94 @@
|
||||
removeTitle: 'Cancel or reset changes',
|
||||
elErrorContainer: '#kv-avatar-errors-1',
|
||||
msgErrorClass: 'alert alert-block alert-danger',
|
||||
// defaultPreviewContent: '<img src="/uploads/default_avatar_male.jpg" alt="Your Avatar">',
|
||||
layoutTemplates: {
|
||||
main2: '{preview} ' + btnCust + ' {remove} {browse}'
|
||||
},
|
||||
allowedFileExtensions: ["jpg", "png", "gif", "jpeg", 'webp']
|
||||
layoutTemplates: { main2: '{preview} ' + btnCust + ' {remove} {browse}' },
|
||||
allowedFileExtensions: ["jpg", "png", "gif", "jpeg", "webp"]
|
||||
});
|
||||
|
||||
// --- Gestion champs supplémentaires ---
|
||||
const info = document.getElementById('info');
|
||||
const divSupp = document.getElementById('boxsuplementaire')
|
||||
const divSupp = document.getElementById('boxsuplementaire');
|
||||
const etat = document.getElementById('etat');
|
||||
const boxsuplementairekit = document.getElementById('boxsuplementairekit');
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
if (info.value == 1) {
|
||||
divSupp.innerHTML = `
|
||||
<label for="infoManque">Information</label>
|
||||
<textarea type="text" class="form-control" id="infoManque" name="infoManque" placeholder="Description sur des trucs manquants" autocomplete="off"><?php echo $product_data['infoManque']; ?></textarea>
|
||||
`;
|
||||
function afficherSupplements() {
|
||||
if (info && info.value == 1) {
|
||||
divSupp.innerHTML = `<label for="infoManque">Information</label>
|
||||
<textarea type="text" class="form-control" id="infoManque" name="infoManque" placeholder="Description sur des trucs manquants" autocomplete="off"><?php echo $product_data['infoManque']; ?></textarea>`;
|
||||
} else {
|
||||
divSupp.innerHTML = '';
|
||||
}
|
||||
|
||||
if (etat.value == 1) {
|
||||
boxsuplementairekit.innerHTML = `
|
||||
<label for="infoManquekit">Information sur le kit</label>
|
||||
<textarea type="text" class="form-control" id="infoManquekit" name="infoManquekit" placeholder="Description sur le kit" autocomplete="off"><?php echo $product_data['infoManquekit']; ?></textarea>
|
||||
`;
|
||||
if (etat && etat.value == 1) {
|
||||
boxsuplementairekit.innerHTML = `<label for="infoManquekit">Information sur le kit</label>
|
||||
<textarea type="text" class="form-control" id="infoManquekit" name="infoManquekit" placeholder="Description sur le kit" autocomplete="off"><?php echo $product_data['infoManquekit']; ?></textarea>`;
|
||||
} else {
|
||||
boxsuplementairekit.innerHTML = '';
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
info.addEventListener('change', () => {
|
||||
if (info.value == 1) {
|
||||
divSupp.innerHTML = `
|
||||
<label for="infoManque">Information</label>
|
||||
<textarea type="text" class="form-control" id="infoManque" name="infoManque" placeholder="Description sur des trucs manquants" autocomplete="off"><?php echo $product_data['infoManque']; ?></textarea>
|
||||
`;
|
||||
window.addEventListener('load', afficherSupplements);
|
||||
if (info) info.addEventListener('change', afficherSupplements);
|
||||
if (etat) etat.addEventListener('change', afficherSupplements);
|
||||
|
||||
// --- Vérification prix minimal < prix de vente ---
|
||||
const priceMinInput = document.getElementById('price_min');
|
||||
const priceVenteInput = document.getElementById('price_vente');
|
||||
const priceMinError = document.getElementById('price_min_error');
|
||||
|
||||
function verifierPrix() {
|
||||
let prixMin = parseFloat(priceMinInput.value.replace(/\s/g, '')) || 0;
|
||||
let prixVente = parseFloat(priceVenteInput.value.replace(/\s/g, '')) || 0;
|
||||
if (prixMin > prixVente) {
|
||||
priceMinError.style.display = 'block';
|
||||
} else {
|
||||
divSupp.innerHTML = '';
|
||||
priceMinError.style.display = 'none';
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const etat = document.getElementById('etat');
|
||||
const boxsuplementairekit = document.getElementById('boxsuplementairekit')
|
||||
if (priceMinInput) priceMinInput.addEventListener('input', verifierPrix);
|
||||
if (priceVenteInput) priceVenteInput.addEventListener('input', verifierPrix);
|
||||
|
||||
etat.addEventListener('change', () => {
|
||||
if (etat.value == 1) {
|
||||
boxsuplementairekit.innerHTML = `
|
||||
<label for="infoManquekit">Information sur le kit</label>
|
||||
<textarea type="text" class="form-control" id="infoManquekit" name="infoManquekit" placeholder="Description sur le kit" autocomplete="off"><?php echo $product_data['infoManquekit']; ?></textarea>
|
||||
`;
|
||||
} else {
|
||||
boxsuplementairekit.innerHTML ='';
|
||||
// --- Formatage automatique des prix (avec affichage initial) ---
|
||||
['price', 'price_vente', 'price_min'].forEach(id => {
|
||||
const input = document.getElementById(id);
|
||||
if (input) {
|
||||
// Si c’est un input number, on le convertit en texte pour garder les espaces
|
||||
if (input.type === "number") input.type = "text";
|
||||
|
||||
// 🟢 Formate dès la frappe
|
||||
input.addEventListener('input', function(e) {
|
||||
let val = e.target.value.replace(/\D/g, ''); // garde seulement les chiffres
|
||||
e.target.value = val.replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
|
||||
});
|
||||
|
||||
// 🟢 Formate aussi dès le chargement de la page (valeurs de la base)
|
||||
let initialVal = input.value.replace(/\D/g, '');
|
||||
if (initialVal) {
|
||||
input.value = initialVal.replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// --- Nettoyage des espaces avant soumission du formulaire ---
|
||||
$("form").on('submit', function(e) {
|
||||
let prixMin = parseFloat(priceMinInput.value.replace(/\s/g, '')) || 0;
|
||||
let prixVente = parseFloat(priceVenteInput.value.replace(/\s/g, '')) || 0;
|
||||
|
||||
if (prixMin > prixVente) {
|
||||
e.preventDefault();
|
||||
alert("❌ Le prix minimal ne peut pas être supérieur au prix de vente !");
|
||||
priceMinInput.focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 🧹 Supprime les espaces avant envoi
|
||||
['price', 'price_vente', 'price_min'].forEach(id => {
|
||||
const input = document.getElementById(id);
|
||||
if (input) {
|
||||
input.value = input.value.replace(/\s/g, '');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@ -113,7 +113,6 @@ $(function() {
|
||||
],
|
||||
order: [[1, 'asc']]
|
||||
});
|
||||
});
|
||||
|
||||
// ===== Edition / validation =====
|
||||
function editFunc(id) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,151 +1,122 @@
|
||||
<header class="main-header">
|
||||
<!-- Logo -->
|
||||
<a href="#" class="logo">
|
||||
<!-- mini logo for sidebar mini 50x50 pixels -->
|
||||
<span class="logo-mini"><b><img src="<?= base_url('assets/images/company_logo.jpg') ?>"></b></span>
|
||||
<!-- logo for regular state and mobile devices -->
|
||||
<span class="logo-lg"><b>MotorBike</b></span>
|
||||
</a>
|
||||
<!-- Header Navbar: style can be found in header.less -->
|
||||
<nav class="navbar navbar-static-top" style="position: relative; height: 50px; background: #3c8dbc;">
|
||||
<!-- Sidebar toggle button -->
|
||||
<a href="#" class="sidebar-toggle" onclick="toggleSidebar()">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
|
||||
</a>
|
||||
|
||||
<!-- Notifications à droite -->
|
||||
<ul class="navbar-nav" style="position: absolute; right: 15px; top: 50%; transform: translateY(-50%); margin: 0; padding: 0; list-style: none;">
|
||||
<li class="nav-item dropdown" style="position: relative;">
|
||||
<i class="fa fa-bell" id="notificationIcon" style="font-size: 20px; cursor: pointer; color:white;" data-toggle="dropdown"></i>
|
||||
<span id="notificationCount" class="badge badge-warning navbar-badge"></span>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right"
|
||||
style="width: 400px; padding: 5%; max-height: 500px; overflow: auto; margin-right: 5px;">
|
||||
<span class="dropdown-header" id="notificationHeader">0 Notifications</span>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div id="notificationList"></div>
|
||||
<div class="dropdown-divider"></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<!-- Header Navbar -->
|
||||
<nav class="navbar navbar-static-top" style="position: relative; height: 50px; background: #3c8dbc;">
|
||||
<!-- Sidebar toggle button -->
|
||||
<a href="#" class="sidebar-toggle" onclick="toggleSidebar()">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
</a>
|
||||
|
||||
<!-- Notifications -->
|
||||
<ul class="navbar-nav" style="position: absolute; right: 15px; top: 50%; transform: translateY(-50%); margin: 0; padding: 0; list-style: none;">
|
||||
<li class="nav-item dropdown" style="position: relative;">
|
||||
<i class="fa fa-bell" id="notificationIcon" style="font-size: 20px; cursor: pointer; color:white;" data-toggle="dropdown"></i>
|
||||
<span id="notificationCount" class="badge badge-warning navbar-badge"></span>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right"
|
||||
style="width: 400px; padding: 5%; max-height: 500px; overflow: auto; margin-right: 5px;">
|
||||
<span class="dropdown-header" id="notificationHeader">0 Notifications</span>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div id="notificationList"></div>
|
||||
<div class="dropdown-divider"></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const checkElement = setInterval(() => {
|
||||
const notificationList = document.getElementById('notificationList');
|
||||
if (notificationList && notificationList.innerHTML) {
|
||||
clearInterval(checkElement); // Stop checking
|
||||
|
||||
const elementother = document.querySelectorAll('.notification_item');
|
||||
|
||||
elementother.forEach((notif) => {
|
||||
notif.addEventListener('click', () => {
|
||||
let notifId = notif.dataset.id;
|
||||
|
||||
// AJAX request to mark the notification as read
|
||||
fetch("<?= base_url('notifications/markAsRead') ?>/" + notifId, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
})
|
||||
.then(response => response.json()) // Parse JSON response
|
||||
.then(data => {
|
||||
console.log("Notification marked as read:", data);
|
||||
location.reload(); // Refresh to update notification count
|
||||
})
|
||||
.catch(error => console.error("Error:", error));
|
||||
});
|
||||
});
|
||||
}
|
||||
}, 100); // Check every 100ms
|
||||
})
|
||||
|
||||
function fetchNotifications() {
|
||||
$.ajax({
|
||||
url: '/notifications', // Change this URL to your actual PHP script
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
|
||||
let notificationCount = data.length;
|
||||
$('#notificationHeader').text(notificationCount + ' Notifications');
|
||||
|
||||
if (notificationCount > 0) {
|
||||
$('#notificationCount').text(notificationCount).show();
|
||||
} else {
|
||||
$('#notificationCount').hide();
|
||||
}
|
||||
|
||||
let notificationHTML = `
|
||||
|
||||
`;
|
||||
|
||||
data.forEach(notif => {
|
||||
// On enlève d’éventuels slashs au début puis on préfixe d’un slash
|
||||
const href = '/' + notif.link.replace(/^\/+/, '');
|
||||
|
||||
notificationHTML += `
|
||||
<a href="${href}"
|
||||
class="dropdown-item notification_item"
|
||||
data-id="${notif.id}"
|
||||
data-message="${notif.message}"
|
||||
style="font-size: 15px; display: flex; align-items: center; justify-content: space-between;">
|
||||
<span style="display: flex; align-items: center; gap:10px;">
|
||||
<i class="fas fa-exclamation-circle mr-9"></i> ${notif.message}
|
||||
</span>
|
||||
<span class="float-right text-muted text-sm">${notif.created_at}</span>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
`;
|
||||
});
|
||||
|
||||
|
||||
notificationHTML += `
|
||||
|
||||
`;
|
||||
|
||||
$('#notificationList').html(notificationHTML);
|
||||
|
||||
|
||||
const elementother = document.querySelectorAll('.notification_item');
|
||||
|
||||
elementother.forEach((notif) => {
|
||||
notif.addEventListener('click', () => {
|
||||
let notifId = notif.dataset.id;
|
||||
|
||||
// AJAX request to mark the notification as read
|
||||
fetch("<?= base_url('notifications/markAsRead') ?>/" + notifId, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
})
|
||||
.then(response => response.json()) // Parse JSON response
|
||||
.then(data => {
|
||||
console.log("Notification marked as read:", data);
|
||||
// location.reload(); // Refresh to update notification count
|
||||
})
|
||||
.catch(error => console.error("Error:", error));
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
error: function(error) {
|
||||
console.error('Error fetching notifications:', error);
|
||||
}
|
||||
});
|
||||
<!-- Styles -->
|
||||
<style>
|
||||
/* Notifications non lues */
|
||||
.notification_item.unread {
|
||||
font-weight: bold;
|
||||
background-color: #f0f8ff; /* bleu clair */
|
||||
}
|
||||
|
||||
// Fetch notifications every 10 seconds
|
||||
setInterval(fetchNotifications, 10000);
|
||||
/* Icône bleue pour notifications non lues */
|
||||
.icon-unread {
|
||||
color: #007bff; /* bleu */
|
||||
}
|
||||
</style>
|
||||
|
||||
// Initial fetch when the page loads
|
||||
fetchNotifications();
|
||||
<script>
|
||||
function fetchNotifications() {
|
||||
$.ajax({
|
||||
url: '/notifications', // route NotificationController::getNotification
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
let notificationCount = 0;
|
||||
let notificationHTML = '';
|
||||
|
||||
data.forEach(notif => {
|
||||
// Compter les notifications non lues
|
||||
if (notif.is_read == 0) {
|
||||
notificationCount++;
|
||||
}
|
||||
|
||||
const href = '/' + notif.link.replace(/^\/+/, '');
|
||||
const notifClass = notif.is_read == 0 ? "notification_item unread" : "notification_item";
|
||||
|
||||
// Icône uniquement pour non lu
|
||||
const iconHTML = notif.is_read == 0 ? '<i class="fa fa-exclamation-circle icon-unread mr-9"></i>' : '';
|
||||
|
||||
notificationHTML += `
|
||||
<a href="${href}"
|
||||
class="${notifClass}"
|
||||
data-id="${notif.id}"
|
||||
style="font-size: 15px; display: flex; align-items: center; justify-content: space-between;">
|
||||
<span style="display: flex; align-items: center; gap:10px;">
|
||||
${iconHTML} ${notif.message}
|
||||
</span>
|
||||
<span class="float-right text-muted text-sm">${notif.created_at}</span>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
`;
|
||||
});
|
||||
|
||||
// Injecter les notifications
|
||||
$('#notificationList').html(notificationHTML);
|
||||
$('#notificationHeader').text(data.length + ' Notifications');
|
||||
|
||||
// Badge pour non lues
|
||||
if (notificationCount > 0) {
|
||||
$('#notificationCount').text(notificationCount).show();
|
||||
} else {
|
||||
$('#notificationCount').hide();
|
||||
}
|
||||
|
||||
// Ajouter l'événement clic pour marquer comme lu
|
||||
const items = document.querySelectorAll('.notification_item');
|
||||
items.forEach(item => {
|
||||
item.addEventListener('click', () => {
|
||||
const notifId = item.dataset.id;
|
||||
fetch("<?= base_url('notifications/markAsRead') ?>/" + notifId, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" }
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log("Notification marked as read:", data);
|
||||
// l'icône disparaîtra au prochain fetch
|
||||
})
|
||||
.catch(error => console.error("Error:", error));
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
error: function(err) {
|
||||
console.error('Error fetching notifications:', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Rafraîchir toutes les 10 secondes
|
||||
setInterval(fetchNotifications, 10000);
|
||||
// Premier chargement
|
||||
fetchNotifications();
|
||||
</script>
|
||||
|
||||
<!-- Left side column. contains the logo and sidebar -->
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user