Sarobidy22 1 month ago
parent
commit
6f2b1d3661
  1. 40
      app/Controllers/OrderController.php
  2. 10
      app/Models/Orders.php
  3. 29
      app/Views/orders/createbyid.php
  4. 54
      app/Views/orders/edit.php

40
app/Controllers/OrderController.php

@ -343,12 +343,18 @@ class OrderController extends AdminController
return redirect()->back()->withInput()->with('errors', ['product' => 'Chaque produit sélectionné doit être unique.']);
}
// ✅ AJOUT DES RÈGLES DE VALIDATION
$validation->setRules([
'product[]' => 'required'
'product[]' => 'required',
'customer_type' => 'required',
'source' => 'required'
]);
// ✅ AJOUT DES DONNÉES DE VALIDATION
$validationData = [
'product[]' => $this->request->getPost('product[]')
'product[]' => $this->request->getPost('product[]'),
'customer_type' => $this->request->getPost('customer_type'),
'source' => $this->request->getPost('source')
];
$Orders = new Orders();
@ -361,7 +367,6 @@ class OrderController extends AdminController
$users = $session->get('user');
$user_id = $users['id'];
// ✅ UTILISER LA NOUVELLE MÉTHODE
$bill_no = $this->generateBillNo($users['store_id']);
// Récupération des produits
@ -372,7 +377,7 @@ class OrderController extends AdminController
$discount = (float)$this->request->getPost('discount') ?? 0;
$gross_amount = $this->calculGross($amounts);
// Vérification prix minimal SI rabais existe
// Vérification prix minimal SI rabais existe
if ($discount > 0) {
$FourchettePrix = new \App\Models\FourchettePrix();
@ -399,7 +404,7 @@ class OrderController extends AdminController
}
}
// Calculer le montant à payer et net_amount
// Calculer le montant à payer et net_amount
$montant_a_payer = ($discount > 0) ? $discount : $gross_amount;
$tranche_1 = (float)$this->request->getPost('tranche_1') ?? 0;
@ -411,13 +416,15 @@ class OrderController extends AdminController
$net_amount = $montant_a_payer;
}
// ✅ Création de la commande
// ✅ AJOUT DES NOUVEAUX CHAMPS ICI
$data = [
'bill_no' => $bill_no,
'customer_name' => $this->request->getPost('customer_name'),
'customer_address' => $this->request->getPost('customer_address'),
'customer_phone' => $this->request->getPost('customer_phone'),
'customer_cin' => $this->request->getPost('customer_cin'),
'customer_type' => $this->request->getPost('customer_type'), // ✅ NOUVEAU
'source' => $this->request->getPost('source'), // ✅ NOUVEAU
'date_time' => date('Y-m-d H:i:s'),
'service_charge_rate' => 0,
'vat_charge_rate' => 0,
@ -689,7 +696,9 @@ public function update(int $id)
$Orders = new Orders();
$current_order = $Orders->getOrdersData($id);
if (!$current_order) {
// ✅ AJOUT : Vérification plus détaillée
if (!$current_order || !isset($current_order['id'])) {
log_message('error', 'Commande introuvable pour ID: ' . $id);
session()->setFlashData('errors', 'Commande introuvable.');
return redirect()->to('orders/');
}
@ -731,17 +740,14 @@ public function update(int $id)
$paid_status = $this->request->getPost('paid_status');
}
// ✅ AJOUT : TRACER LA VALIDATION PAR LE CAISSIER
$validated_by = $current_order['validated_by'] ?? null; // Garder l'ancienne valeur si existe
$validated_by = $current_order['validated_by'] ?? null;
$validated_at = $current_order['validated_at'] ?? null;
// Si le statut passe à "Validé" (1) et que l'utilisateur est un caissier
if ($old_paid_status != 1 && $paid_status == 1 && $role === 'Caissière') {
$validated_by = $user['id'];
$validated_at = date('Y-m-d H:i:s');
}
// Si le statut repasse à "En attente" ou "Refusé", effacer la validation
if (in_array($paid_status, [0, 2])) {
$validated_by = null;
$validated_at = null;
@ -758,6 +764,8 @@ public function update(int $id)
'customer_address' => $this->request->getPost('customer_address'),
'customer_phone' => $this->request->getPost('customer_phone'),
'customer_cin' => $this->request->getPost('customer_cin'),
'customer_type' => $this->request->getPost('customer_type'),
'source' => $this->request->getPost('source'),
'gross_amount' => $this->request->getPost('gross_amount_value'),
'service_charge_rate' => $this->request->getPost('service_charge_rate'),
'service_charge' => max(0, (float)$this->request->getPost('service_charge_value')),
@ -775,7 +783,6 @@ public function update(int $id)
'tranche_2' => $role !== 'COMMERCIALE' ? $this->request->getPost('tranche_2') : null,
'order_payment_mode' => $role !== 'COMMERCIALE' ? $this->request->getPost('order_payment_mode_1') : null,
'order_payment_mode_1' => $role !== 'COMMERCIALE' ? $this->request->getPost('order_payment_mode_2') : null,
// ✅ AJOUT DES CHAMPS DE TRACABILITÉ
'validated_by' => $validated_by,
'validated_at' => $validated_at
];
@ -797,7 +804,6 @@ public function update(int $id)
'orders'
);
// ✅ AJOUT : Notification pour la Direction quand un caissier valide
if ($role === 'Caissière') {
$Notification->createNotification(
"Commande validée par la caisse: {$bill_no}",
@ -854,6 +860,7 @@ public function update(int $id)
}
}
// ✅ Affichage du formulaire
$company = $Company->getCompanyData(1);
$data['company_data'] = $company;
$data['is_vat_enabled'] = ($company['vat_charge_value'] > 0);
@ -861,6 +868,13 @@ public function update(int $id)
$orders_data = $Orders->getOrdersData($id);
// ✅ VÉRIFICATION SUPPLÉMENTAIRE
if (!$orders_data || !isset($orders_data['id'])) {
log_message('error', 'Données de commande vides pour ID: ' . $id);
session()->setFlashData('errors', 'Impossible de charger les données de la commande.');
return redirect()->to('orders/');
}
$data['is_editable'] = !in_array($orders_data['paid_status'], [1, 3]);
$orders_data['montant_tranches'] = (!empty($orders_data['discount']) && $orders_data['discount'] > 0)

10
app/Models/Orders.php

@ -20,6 +20,8 @@ class Orders extends Model
'customer_address',
'customer_phone',
'customer_cin',
'customer_type',
'source',
'date_time',
'gross_amount',
'service_charge_rate',
@ -84,17 +86,17 @@ class Orders extends Model
$session = session();
$user = $session->get('user');
// Si on demande UNE commande spécifique (pas de GROUP_CONCAT)
// ✅ CORRECTION : Si on demande UNE commande spécifique
if ($id !== null) {
return $this->db->table('orders')
->select([
'orders.*',
'orders.*', // ✅ Ceci inclut déjà customer_type et source
"CONCAT(users.firstname, ' ', users.lastname) AS user_name"
])
->join('users', 'orders.user_id = users.id', 'left')
->where('orders.id', $id)
->get()
->getRowArray();
->getRowArray(); // ✅ Retourne bien un tableau associatif
}
// Pour la LISTE des commandes (avec GROUP_CONCAT)
@ -107,6 +109,8 @@ class Orders extends Model
'orders.customer_phone',
'orders.customer_cin',
'orders.customer_address',
'orders.customer_type', // ✅ DÉJÀ PRÉSENT
'orders.source', // ✅ DÉJÀ PRÉSENT
'orders.discount',
'orders.date_time',
'orders.gross_amount',

29
app/Views/orders/createbyid.php

@ -72,6 +72,35 @@
<div class="col-md-4 col-xs-12 pull pull-left">
<!-- ✅ NOUVEAU CHAMP : Type de client -->
<div class="form-group">
<label for="customer_type" class="col-sm-5 control-label"
style="text-align:left;">Type de client</label>
<div class="col-sm-7">
<select class="form-control" id="customer_type" name="customer_type" required>
<option value="">-- Sélectionner --</option>
<option value="particulier" <?= old('customer_type') == 'particulier' ? 'selected' : '' ?>>Particulier</option>
<option value="revendeur" <?= old('customer_type') == 'revendeur' ? 'selected' : '' ?>>Revendeur</option>
</select>
</div>
</div>
<!-- ✅ NOUVEAU CHAMP : Source -->
<div class="form-group">
<label for="source" class="col-sm-5 control-label"
style="text-align:left;">Source</label>
<div class="col-sm-7">
<select class="form-control" id="source" name="source" required>
<option value="">-- Sélectionner --</option>
<option value="facebook_perso" <?= old('source') == 'facebook_perso' ? 'selected' : '' ?>>Facebook perso</option>
<option value="page_motorbike" <?= old('source') == 'page_motorbike' ? 'selected' : '' ?>>Page motorbike</option>
<option value="bouche_a_oreille" <?= old('source') == 'bouche_a_oreille' ? 'selected' : '' ?>>Bouche à oreille</option>
<option value="commercial_interne" <?= old('source') == 'commercial_interne' ? 'selected' : '' ?>>Commercial interne</option>
<option value="autre" <?= old('source') == 'autre' ? 'selected' : '' ?>>Autre</option>
</select>
</div>
</div>
<div class="form-group">
<label for="customer_name" class="col-sm-5 control-label"
style="text-align:left;">Nom du client</label>

54
app/Views/orders/edit.php

@ -85,25 +85,53 @@
</div>
<div class="form-group">
<label for="gross_amount" class="col-sm-5 control-label" style="text-align:left;">Adresse du client</label>
<label for="customer_address" class="col-sm-5 control-label" style="text-align:left;">Adresse du client</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="customer_address" name="customer_address" placeholder="Enter Customer Address" value="<?php echo $order_data['order']['customer_address'] ?>" autocomplete="off">
</div>
</div>
<div class="form-group">
<label for="gross_amount" class="col-sm-5 control-label" style="text-align:left;">Téléphone du client</label>
<label for="customer_phone" class="col-sm-5 control-label" style="text-align:left;">Téléphone du client</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="customer_phone" name="customer_phone" placeholder="Enter Customer Phone" value="<?php echo $order_data['order']['customer_phone'] ?>" autocomplete="off">
</div>
</div>
<div class="form-group">
<label for="gross_amount" class="col-sm-5 control-label" style="text-align:left;">CIN du client</label>
<label for="customer_cin" class="col-sm-5 control-label" style="text-align:left;">CIN du client</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="customer_cin" name="customer_cin" placeholder="Enter Customer CIN" value="<?php echo $order_data['order']['customer_cin'] ?>" autocomplete="off">
</div>
</div>
<!-- ✅ NOUVEAU CHAMP : Type de client -->
<div class="form-group">
<label for="customer_type" class="col-sm-5 control-label" style="text-align:left;">Type de client <span class="text-danger">*</span></label>
<div class="col-sm-7">
<select class="form-control" id="customer_type" name="customer_type" required>
<option value="">-- Sélectionner --</option>
<option value="particulier" <?php echo (isset($order_data['order']['customer_type']) && strtolower($order_data['order']['customer_type']) == 'particulier') ? 'selected' : ''; ?>>Particulier</option>
<option value="revendeur" <?php echo (isset($order_data['order']['customer_type']) && strtolower($order_data['order']['customer_type']) == 'revendeur') ? 'selected' : ''; ?>>Revendeur</option>
</select>
</div>
</div>
<!-- ✅ NOUVEAU CHAMP : Source -->
<div class="form-group">
<label for="source" class="col-sm-5 control-label" style="text-align:left;">Source <span class="text-danger">*</span></label>
<div class="col-sm-7">
<select class="form-control" id="source" name="source" required>
<option value="">-- Sélectionner --</option>
<option value="facebook_perso" <?php echo (isset($order_data['order']['source']) && $order_data['order']['source'] == 'facebook_perso') ? 'selected' : ''; ?>>Facebook perso</option>
<option value="page_motorbike" <?php echo (isset($order_data['order']['source']) && $order_data['order']['source'] == 'page_motorbike') ? 'selected' : ''; ?>>Page motorbike</option>
<option value="bouche_a_oreille" <?php echo (isset($order_data['order']['source']) && $order_data['order']['source'] == 'bouche_a_oreille') ? 'selected' : ''; ?>>Bouche à oreille</option>
<option value="commercial_interne" <?php echo (isset($order_data['order']['source']) && $order_data['order']['source'] == 'commercial_interne') ? 'selected' : ''; ?>>Commercial interne</option>
<option value="autre" <?php echo (isset($order_data['order']['source']) && $order_data['order']['source'] == 'autre') ? 'selected' : ''; ?>>Autre</option>
</select>
</div>
</div>
</div>
<br /> <br />
@ -142,7 +170,6 @@
</select>
</td>
<!-- ✅ COLONNE PUISSANCE VISIBLE -->
<td>
<input type="number" name="puissance[]" id="puissance_<?php echo $x; ?>"
class="form-control" placeholder="Puissance"
@ -204,6 +231,7 @@
<?php endif; ?>
</div>
</div>
<div class="form-group">
<label for="net_amount" class="col-sm-5 control-label">Remise</label>
<div class="col-sm-7">
@ -327,10 +355,8 @@
$("#mainOrdersNav").addClass('active');
$("#manageOrdersNav").addClass('active');
// ✅ CORRECTION : Gestion des tranches de paiement
var paymentTranche = 1;
// ✅ Fonction pour obtenir le montant à répartir (discount ou gross_amount)
function getMontantTotal() {
var discount = parseFloat($('#discount').val()) || 0;
var grossAmount = parseFloat($('#gross_amount_value').val()) || 0;
@ -344,7 +370,7 @@
if (parseInt(paymentTranche) === 2) {
$("#paid_status_1").show();
$("#paid_status_2").show();
$("#montant_reference").show(); // ✅ Afficher le montant de référence
$("#montant_reference").show();
var amount1 = parseFloat($('#payment_amount_1').val()) || 0;
var montantTotal = getMontantTotal();
@ -353,10 +379,9 @@
} else {
$("#paid_status_1").show();
$("#paid_status_2").hide();
$("#montant_reference").hide(); // ✅ Cacher le montant de référence
$("#montant_reference").hide();
$('#payment_mode_2').val('');
// ✅ Remplir tranche 1 avec le montant total
var montantTotal = getMontantTotal();
$('#payment_amount_1').val(montantTotal.toFixed(2));
}
@ -367,7 +392,6 @@
updateMontantTranches();
});
// ✅ CORRECTION : Recalculer tranche 2 quand tranche 1 change
$('#payment_amount_1').on("input", function() {
var amount1 = parseFloat($(this).val()) || 0;
var montantTotal = getMontantTotal();
@ -408,7 +432,7 @@
html += '</select>' +
'</td>' +
'<td><input type="text" name="puissance[]" id="puissance_' + row_id + '" class="form-control" placeholder="Puissance" autocomplete="off"></td>' +
'<td><input type="number" name="puissance[]" id="puissance_' + row_id + '" class="form-control" placeholder="Puissance" autocomplete="off" min="1"></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="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>' +
@ -519,7 +543,6 @@
$("#remaining_value").val(remaning.toFixed(2));
}
// ✅ CORRECTION : Mettre à jour les tranches après chaque calcul
updateMontantTranches();
}
@ -538,14 +561,12 @@
subAmount();
}
// ✅ CORRECTION : Fonction pour obtenir le montant pour les tranches
function getMontantPourTranches() {
var discount = parseFloat($("#discount").val()) || 0;
var grossAmount = parseFloat($("#gross_amount_value").val()) || 0;
return discount > 0 ? discount : grossAmount;
}
// ✅ CORRECTION : Mettre à jour l'affichage du montant de référence
function updateMontantTranches() {
var montant = getMontantPourTranches();
var discount = parseFloat($("#discount").val()) || 0;
@ -559,17 +580,14 @@
$("#montant_source_label").text("(Montant brut)");
}
// ✅ CORRECTION : Mettre à jour tranche 1 si en mode 1 tranche
var paymentMode = $("#payment_mode").val();
if (parseInt(paymentMode) === 1) {
$("#payment_amount_1").val(montant.toFixed(2));
} else {
// ✅ En mode 2 tranches, recalculer tranche 2
calculerTranche2();
}
}
// ✅ CORRECTION : Calculer tranche 2 basé sur le montant total actuel
function calculerTranche2() {
var montantTotal = getMontantPourTranches();
var tranche1 = parseFloat($("#payment_amount_1").val()) || 0;
@ -578,12 +596,10 @@
$("#payment_amount_2").val(tranche2.toFixed(2));
}
// ✅ CORRECTION : Écouter les changements de discount
$("#discount").on('keyup', function() {
subAmount();
});
// ✅ Initialisation au chargement
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');

Loading…
Cancel
Save