No stock validation existed in the ordering flow, allowing customers to order more items than available. Cap quantity to ``stock_current`` in ``Baskets::getBasketData()`` when adding to cart. Add ``min=1`` and ``max=stock`` attributes on the basket quantity input, with JS clamping in the change handler. Verify stock again in ``Shop\OrderController::store()`` before saving the order as a race-condition safeguard.
81 lines
2.5 KiB
PHP
81 lines
2.5 KiB
PHP
@component('components.card', [
|
|
'id_card' => $model . '-basket',
|
|
'title' => $title,
|
|
'class' => 'mb-3 addBasket ' . ($bgClass ?? null),
|
|
'classTitle' => 'mb-0',
|
|
'outline' => false,
|
|
])
|
|
@include('components.form.select', [
|
|
'name' => 'offer_id',
|
|
'id_name' => $model . '-offer_id',
|
|
'list' => collect($data)->pluck('name', 'id')->toArray(),
|
|
'class' => 'select2 mb-2 offer_id',
|
|
])
|
|
|
|
<div class="row">
|
|
<div class="col-5">
|
|
@include('components.form.inputs.number', [
|
|
'name' => 'quantity',
|
|
'class' => 'quantity',
|
|
'id_name' => $model . '-quantity',
|
|
'value' => 1,
|
|
'min' => 1,
|
|
'max' => $data[0]['stock'] ?? false,
|
|
'step' => 1,
|
|
])
|
|
</div>
|
|
<div class="col-7 text-right">
|
|
<span id="{{ $model }}-price" style="font-size:2em; font-weight: 600;">
|
|
{{ $data[0]['prices'][0]['price_taxed'] }}
|
|
</span>
|
|
€ TTC
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-12">
|
|
@include('components.form.button', [
|
|
'metadata' => 'data-type=' . $model,
|
|
'class' => 'btn-success basket w-100 ' . $model,
|
|
'txt' => 'Ajouter au panier',
|
|
])
|
|
</div>
|
|
</div>
|
|
@endcomponent
|
|
|
|
@push('js')
|
|
<script>
|
|
var {{ $model }}Stocks = {
|
|
@foreach ($data as $offer)
|
|
{{ $offer['id'] }}: {{ $offer['stock'] !== null ? $offer['stock'] : 'null' }},
|
|
@endforeach
|
|
};
|
|
|
|
function update{{ ucfirst($model) }}Max() {
|
|
var offerId = $('#{{ $model }}-offer_id').find('option:selected').val();
|
|
var stock = {{ $model }}Stocks[offerId];
|
|
var input = $('#{{ $model }}-quantity');
|
|
if (stock !== null && stock !== undefined) {
|
|
input.attr('max', stock);
|
|
if (parseInt(input.val()) > stock) {
|
|
input.val(stock);
|
|
}
|
|
} else {
|
|
input.removeAttr('max');
|
|
}
|
|
if (parseInt(input.val()) < 1) {
|
|
input.val(1);
|
|
}
|
|
}
|
|
|
|
$('#{{ $model }}-quantity').change(function() {
|
|
update{{ ucfirst($model) }}Max();
|
|
setPrice('{{ $model }}');
|
|
});
|
|
$('#{{ $model }}-offer_id').change(function() {
|
|
update{{ ucfirst($model) }}Max();
|
|
setPrice('{{ $model }}');
|
|
});
|
|
</script>
|
|
@endpush
|