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.
Add ``getStatusBadge()`` to ``Orders`` returning Bootstrap badge HTML
per status: warning (En attente), info (Préparation), primary
(Expédié), success (Livré), danger (Annulé). Applied to all four
order DataTables (admin, admin customer, shop, shop customer).
When a Paybox callback confirms payment on an order with status 4
(Annulé), the payment is still recorded but the order status is no
longer forced to « Préparation ». Instead, an alert email is sent to
``commande@jardinenvie.com`` warning that a refund is likely needed.
New ``AlertePaiementAnnule`` mailable with DB template providing order
ref, amount, customer info and payment reference. New method
``OrderMails::sendCancelledOrderPaymentAlert()`` handles the dispatch.
Add ``restoreStock()``, ``decreaseStockForOrder()``, and
``checkStockForOrder()`` to ``OfferStocks``. When an order is cancelled
(status 4), stock is restored. When un-cancelling, stock availability is
checked first—insufficient stock blocks the transition with an error
message—then decremented.
The ``scopeNotCancelled`` scope on ``Order`` filters out orders with
status 4 (Annulé). All ``OrderMetrics`` methods now chain
``notCancelled()`` so that dashboard counts and totals ignore cancelled
orders.
When a purchase causes an offer's ``stock_current`` to drop to or below
its ``minimum_ondemand`` threshold, an email is sent to
``commande@jardinenvie.com`` using an editable mail template (Spatie
``MailTemplate``).
The check runs in ``OfferStocks::decreaseStock()`` after updating stock.
Only threshold-crossing events trigger the alert (not every low-stock
sale). Failures are caught and logged to avoid disrupting the order
flow.
Add ``'Annulé'`` at index 4 in ``Orders::statuses()``, allowing
administrators to mark orders as cancelled from the admin edit page.
This is a label-only change; side-effects (dashboard stats, stock
restoration, Paybox guard) are documented in ``admin.org`` for
client review.
Two issues prevented the shelf tree reordering from working:
- The JS used ``onDragStop`` (only fires for drags outside the
tree) instead of the ``tree.move`` event to send the AJAX
request. Moved the POST into the ``tree.move`` handler.
- The ``inside`` case used ``appendNode`` (last child), but
jqTree sends ``inside`` when dropping before the first child.
Switched to ``prependNode`` so the node lands first.
- Added missing ``before`` case with ``insertBeforeNode``.
- Replace ``<br>`` with ``\n`` in ``InvoicePDF::makeAddress()`` so
dompdf renders line breaks instead of showing raw HTML tags.
- Translate ``order number`` to ``Numéro de commande`` in the custom
fields passed to the invoice builder.
The amount-in-words was already in English because the container
lacked French ICU data (``icu-data-full``); that was fixed at
runtime, not in code.
Display a tailored confirmation message when the customer pays by
check or wire transfer, including a warning about the 30-day
cancellation policy. The payment type is passed as a query parameter
so the message survives page reloads.
- Add ``getOrderConfirmedByCheckContent()`` and
``getOrderConfirmedByWireContent()`` to ``Contents`` repository
- Flash ``payment_type`` through redirect query parameter
- Add migration inserting content rows (id 10, 11)
- Update confirmed view with green checkmark and warning icon
``getArticlesToSell()`` returned ``false`` when no articles matched,
causing ``collect(false)`` to produce ``[false]``. The view then
iterated over that single-element array and tried to access array
offsets on a boolean value.