You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

584 lines
27 KiB

<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
.border-danger {
border: 2px solid #d9534f !important;
box-shadow: 0 0 5px rgba(217, 83, 79, 0.5) !important;
}
</style>
<div class="content-wrapper">
<section class="content-header">
<h1>
Gérer les
<small>Commandes</small>
</h1>
<ol class="breadcrumb">
<li><a href="#"><i class="fa fa-dashboard"></i> Accueil</a></li>
<li class="active">Commandes</li>
</ol>
</section>
<section class="content">
<div class="row">
<div class="col-md-12 col-xs-12">
<?php if (session()->getFlashdata('success')): ?>
<div class="alert alert-success alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<?php echo session()->getFlashdata('success'); ?>
</div>
<?php elseif (session()->getFlashdata('error')): ?>
<div class="alert alert-error alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<?php echo session()->getFlashdata('error'); ?>
</div>
<?php endif; ?>
<?php if ($errors = session()->getFlashdata('errors')): ?>
<div class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</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>
</div>
<form role="form" action="/orders/create" method="post" class="form-horizontal">
<?php if (isset($validation) && $validation->getErrors()): ?>
<div class="alert alert-danger">
<ul>
<?= $validation->listErrors() ?>
</ul>
</div>
<?php endif; ?>
<div class="box-body">
<div class="form-group">
<label for="gross_amount" class="col-sm-12 control-label">Date:
<?php echo date('Y-m-d') ?></label>
</div>
<div class="form-group">
<label for="gross_amount" class="col-sm-12 control-label">Heure:
<?php echo date('h:i a') ?></label>
</div>
<div class="col-md-4 col-xs-12 pull pull-left">
<div class="form-group">
<label for="customer_name" class="col-sm-5 control-label"
style="text-align:left;">Nom du client</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="customer_name"
value="<?= old('customer_name') ?>"
name="customer_name"
placeholder="Entrer le nom du client" required autocomplete="off" />
</div>
</div>
<div class="form-group">
<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"
value="<?= old('customer_address') ?>"
name="customer_address" placeholder="Entrer l'adresse du client" required autocomplete="off" />
</div>
</div>
<div class="form-group">
<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"
value="<?= old('customer_phone') ?>"
name="customer_phone" placeholder="Entrer le téléphone du client" autocomplete="off">
</div>
</div>
<div class="form-group">
<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"
value="<?= old('customer_cin') ?>" required placeholder="Entrer le CIN du client"
autocomplete="off">
</div>
</div>
</div>
<br /> <br />
<!-- ✅ TABLEAU AVEC COLONNE PUISSANCE -->
<table class="table table-bordered" id="product_info_table">
<thead>
<tr>
<th style="width:40%">Produit</th>
<th style="width:15%">Puissance (CC)</th>
<th style="width:15%">Prix unitaire</th>
<th style="width:20%">Montant</th>
<th style="width:10%"></th>
</tr>
</thead>
<tbody>
<tr id="row_1">
<td>
<select class="form-control select_group product" data-row-id="row_1"
id="product_1" name="product[]" style="width:100%;"
onchange="getProductData(1)" required>
<option value="<?= $products['id'] ?>">
<?= $products['sku'] . ' | ' . $products['name'] . ' | ' . $products['numero_de_moteur'] ?>
</option>
</select>
</td>
<!-- ✅ COLONNE PUISSANCE -->
<td>
<input type="number" name="puissance[]" id="puissance_1"
class="form-control" placeholder="CC"
value="<?= esc($products['puissance'] ?? '1') ?>"
min="1" autocomplete="off">
</td>
<td>
<input type="text" name="rate[]" id="rate_1" class="form-control" disabled
autocomplete="off" value="<?= esc($pu) ?>" min="0">
<input type="hidden" name="rate_value[]" id="rate_value_1"
value="<?= esc($pu) ?>" class="form-control" autocomplete="off">
<input type="hidden" id="min_price_1" name="min_price[]" value="">
</td>
<td>
<input type="text" name="amount[]" id="amount_1" class="form-control"
disabled autocomplete="off" min="0">
<input type="hidden" name="amount_value[]" id="amount_value_1"
class="form-control" autocomplete="off">
</td>
<td>
<button type="button" class="btn btn-default" onclick="removeRow('1')">
<i class="fa fa-close"></i>
</button>
</td>
</tr>
</tbody>
</table>
<!-- ✅ Champ qty caché (toujours = 1) -->
<input type="hidden" name="qty[]" value="1" id="qty_1" class="form-control">
<br /> <br />
<div class="col-md-6 col-xs-12 pull pull-right">
<div class="form-group">
<label for="gross_amount" class="col-sm-5 control-label">Prix affiché</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="gross_amount" name="gross_amount"
disabled autocomplete="off" min="0">
<input type="hidden" class="form-control" id="gross_amount_value"
name="gross_amount_value" autocomplete="off">
</div>
</div>
<div class="form-group">
<label for="discount" class="col-sm-5 control-label">Prix demandé</label>
<div class="col-sm-7">
<div id="discount_error" class="alert alert-danger" style="display:none; padding: 8px; margin-bottom: 5px; font-size: 13px;">
<i class="fa fa-exclamation-triangle"></i> <span id="discount_error_text"></span>
</div>
<input type="number" class="form-control numeric-input" id="discount" name="discount"
placeholder="Prix demandé" min="0" step="0.01"
onkeyup="subAmount()" oninput="validatePrixDemande(this)" autocomplete="off">
</div>
</div>
<div class="form-group">
<label for="net_amount" class="col-sm-5 control-label">Remise</label>
<div class="col-sm-7">
<input type="hidden" class="form-control" id="net_amount_value"
name="net_amount" hidden autocomplete="off">
<input type="text" class="form-control" id="net_amount" name="net_amount"
disabled autocomplete="off" min="0">
</div>
</div>
</div>
<div class="box-footer">
<input type="hidden" name="service_charge_rate"
value="<?php echo $company_data['service_charge_value'] ?>" autocomplete="off">
<input type="hidden" name="vat_charge_rate"
value="<?php echo $company_data['vat_charge_value'] ?>" autocomplete="off">
</div>
<button onclick="window.history.back()" type="button"
class="btn btn-warning">Retour</button>
<button type="submit" class="btn btn-primary">Créer une commande</button>
</div>
</form>
</div>
</div>
</div>
</section>
</div>
<script type="text/javascript">
var base_url = "<?php echo base_url(); ?>";
// ✅ Fonction pour valider les nombres positifs
function validatePositiveNumber(input) {
let value = parseFloat(input.value);
if (isNaN(value) || value < 0) {
input.value = '';
return false;
}
return true;
}
// ✅ Fonction pour afficher l'erreur sur le champ prix demandé
function showDiscountError(message) {
$('#discount_error_text').text(message);
$('#discount_error').slideDown(200);
$('#discount').addClass('border-danger');
}
// ✅ Fonction pour masquer l'erreur sur le champ prix demandé
function hideDiscountError() {
$('#discount_error').slideUp(200);
$('#discount').removeClass('border-danger');
}
// ✅ Fonction pour valider que le prix demandé ne dépasse pas le prix affiché
function validatePrixDemande(input) {
let prixDemande = parseFloat(input.value);
let prixAffiche = parseFloat($('#gross_amount').val()) || 0;
if (isNaN(prixDemande) || prixDemande < 0) {
input.value = '';
showDiscountError('Le prix demandé ne peut pas être négatif.');
setTimeout(hideDiscountError, 3000);
return false;
}
if (prixDemande > prixAffiche) {
showDiscountError('Le prix demandé (' + prixDemande.toFixed(2) + ') ne peut pas être supérieur au prix affiché (' + prixAffiche.toFixed(2) + ').');
input.value = prixAffiche;
subAmount();
setTimeout(hideDiscountError, 4000);
return false;
}
hideDiscountError();
return true;
}
// ✅ Fonction pour empêcher la saisie de caractères négatifs
function preventNegativeInput(e) {
if (e.key === '-' || e.key === 'e' || e.key === 'E' || e.key === '+') {
e.preventDefault();
return false;
}
}
$(document).ready(function () {
// ✅ INITIALISATION : Calculer le total au chargement
getTotal(1);
// ✅ INITIALISATION : S'assurer que rate_value_1 est bien rempli
$("#rate_value_1").val($("#rate_1").val());
$(".select_group").select2();
$("#mainOrdersNav").addClass('active');
$("#addOrderNav").addClass('active');
// ✅ Appliquer la validation sur tous les champs numériques
$(document).on('keydown', '.numeric-input, input[type="number"]', function(e) {
preventNegativeInput(e);
});
$(document).on('input', '.numeric-input, input[type="number"]', function() {
validatePositiveNumber(this);
});
// ✅ Validation sur le champ discount
$("#discount").on('input', function() {
validatePrixDemande(this);
});
$("#discount").on('blur', function() {
validatePrixDemande(this);
checkMinimalPrice();
});
// Bloquer la soumission du formulaire
$('form').on('submit', function(e) {
let hasNegative = false;
$('.numeric-input, input[type="number"]').each(function() {
if (parseFloat($(this).val()) < 0) {
hasNegative = true;
$(this).val('');
}
});
if (hasNegative) {
alert('Les valeurs négatives ne sont pas autorisées.');
e.preventDefault();
return false;
}
if (!checkMinimalPrice()) {
e.preventDefault();
return false;
}
});
// Add new row in the table
$("#add_row").unbind('click').bind('click', function () {
var table = $("#product_info_table");
var count_table_tbody_tr = $("#product_info_table tbody tr").length;
var row_id = count_table_tbody_tr + 1;
$.ajax({
url: base_url + '/orders/getTableProductRow/',
type: 'post',
dataType: 'json',
success: function (response) {
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 + ')">' +
'<option value=""></option>';
$.each(response, function (index, value) {
// ✅ NE PLUS AFFICHER LA PUISSANCE DANS LE SELECT
html += '<option value="' + value.id + '">' + value.sku + ' | ' + value.name + ' | ' + value.numero_de_moteur + '</option>';
});
html += '</select>' +
'</td>' +
// ✅ COLONNE PUISSANCE
'<td><input type="number" name="puissance[]" id="puissance_' + row_id + '" class="form-control" placeholder="CC" min="1" value="1" autocomplete="off"></td>' +
'<td><input type="text" name="rate[]" id="rate_' + row_id + '" class="form-control numeric-input" disabled min="0"><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 numeric-input" disabled min="0"><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>';
if (count_table_tbody_tr >= 1) {
$("#product_info_table tbody tr:last").after(html);
} else {
$("#product_info_table tbody").html(html);
}
$(".product").select2();
}
});
return false;
});
}); // /document
function getTotal(row = null) {
if (row) {
var rate = Number($("#rate_value_" + row).val());
var qty = Number($("#qty_" + row).val());
if (rate < 0) rate = 0;
if (qty < 0) qty = 0;
var total = rate * qty;
total = total.toFixed(2);
$("#amount_" + row).val(total);
$("#amount_value_" + row).val(total);
subAmount();
} else {
alert('no row !! please refresh the page');
}
}
// ✅ GET PRODUCT DATA - Récupère prix + puissance
function getProductData(row_id) {
var product_id = $("#product_" + row_id).val();
if (product_id == "") {
$("#rate_" + row_id).val("");
$("#rate_value_" + row_id).val("");
$("#min_price_" + row_id).val("");
$("#puissance_" + row_id).val("1");
$("#amount_" + row_id).val("");
$("#amount_value_" + row_id).val("");
} else {
$.ajax({
url: base_url + 'orders/getProductValueById',
type: 'post',
data: {
product_id: product_id
},
dataType: 'json',
success: function (response) {
console.log('✅ Response:', response); // Debug
var prixVente = parseFloat(response.prix_vente) || 0;
var prixMinimal = parseFloat(response.prix_minimal) || 0;
if (prixVente < 0) prixVente = 0;
if (prixMinimal < 0) prixMinimal = 0;
$("#rate_" + row_id).val(prixVente);
$("#rate_value_" + row_id).val(prixVente);
$("#min_price_" + row_id).val(prixMinimal);
// ✅ REMPLIR LA PUISSANCE
var puissanceValue = response.puissance || '1';
console.log('✅ Puissance extraite:', puissanceValue); // Debug
$("#puissance_" + row_id).val(puissanceValue);
$("#qty_" + row_id).val(1);
var total = prixVente * 1;
total = total.toFixed(2);
$("#amount_" + row_id).val(total);
$("#amount_value_" + row_id).val(total);
subAmount();
}
});
}
}
// calculate the total amount of the order
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; ?>;
var tableProductLength = $("#product_info_table tbody tr").length;
var totalSubAmount = 0;
for (x = 0; x < tableProductLength; x++) {
var tr = $("#product_info_table tbody tr")[x];
var count = $(tr).attr('id');
count = count.substring(4);
var amount = Number($("#amount_" + count).val());
if (amount < 0) amount = 0;
totalSubAmount = Number(totalSubAmount) + amount;
}
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);
var discount = Number($("#discount").val()) || 0;
if (discount < 0) {
discount = 0;
$("#discount").val('');
}
if (discount) {
var grandTotal = Number(totalAmount) - Number(discount);
if (grandTotal < 0) grandTotal = 0;
grandTotal = grandTotal.toFixed(2);
$("#net_amount").val(grandTotal);
$("#net_amount_value").val(grandTotal);
} else {
$("#net_amount").val(totalAmount);
$("#net_amount_value").val(totalAmount);
}
}
// ✅ Vérification du rabais vs prix minimal
function checkMinimalPrice() {
var discount = Number($("#discount").val()) || 0;
if (discount < 0) {
alert("Le prix demandé ne peut pas être négatif.");
$("#discount").val('');
subAmount();
return false;
}
if (discount === 0) return true;
var tableProductLength = $("#product_info_table tbody tr").length;
var error = false;
var messages = [];
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;
if (minPrice > 0 && discount < minPrice) {
error = true;
var productText = $("#product_" + rowId + " option:selected").text();
messages.push("Le prix demandé (" + discount.toFixed(2) + ") pour « " + productText + " » est inférieur au prix minimal (" + minPrice.toFixed(2) + ")");
}
}
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();
subAmount();
}
// ✅ INITIALISATION AU CHARGEMENT
const quantity = document.getElementById('qty_1')
const rates = document.getElementById('rate_1')
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('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');
amount_value.value = gross_amount_value.value
amount.value = (rates.value * quantity.value).toFixed(2)
gross_amount_value.value = (rates.value * quantity.value).toFixed(2)
gross_amount_value2.value = (gross_amount_value.value);
net_amount.value = (gross_amount_value.value - remise.value);
net_amount_value.value = (gross_amount_value.value - remise.value);
remise.addEventListener('input', function () {
if (validatePrixDemande(this)) {
var discountValue = parseFloat(this.value) || 0;
var grossValue = parseFloat(gross_amount_value.value) || 0;
var netValue = grossValue - discountValue;
if (netValue < 0) netValue = 0;
net_amount.value = netValue.toFixed(2);
net_amount_value.value = netValue.toFixed(2);
subAmount();
}
})
</script>