Orders and delivery
Page specs BO-38 to BO-43 and BO-69: orders list, order detail, order on behalf, the orders-to-confirm queue, delivery board, carriers, and returns and after-sales claims.
These pages run the order cycle from submission to delivery, return and refund (cahier §4.4).
No order is ever confirmed automatically (ORD-14). Every order lands in BO-41, whatever its channel: reseller app, reseller web, assisted by a delegate, or entered by phone in the back-office. It arrives as SUBMITTED, or PENDING when on hold, and waits there until a person with orders.validate confirms it. Confirmation reserves the stock. Shipping deducts it. A cancellation or a return reception puts it back automatically (STK-03). Each status change reaches the reseller live and as a notification (ORD-15).
The lifecycle and its transition table are in OrderStatus. The UI never derives transitions itself. It renders the allowedActions that admin.orders.get returns.
| ID | Screen | Section | Template | Release | Design | Build |
|---|---|---|---|---|---|---|
BO-38 | Orders list | Orders | bespoke | V1 | Day 18 | DSH-06 |
BO-39 | Order detail (controls, actions, history) | Orders | bespoke | V1 | Day 18 | DSH-06 |
BO-40 | New order on behalf of a reseller | Orders | template | V1 | Day 18 | DSH-06 |
BO-41 | Orders to confirm (new, on hold, assisted) | Orders | template | V1 | Day 18 | DSH-06 |
BO-42 | Delivery board | Orders | bespoke | V1 | Day 18 | DSH-06 |
BO-43 | Carriers | Orders | template | V1 | Day 18 | DSH-06 |
BO-69 | Returns & after-sales claims | Orders | template | V1 | Day 18 | DSH-13 |
BO-38 — Orders list
| Field | Value |
|---|---|
| Template | Bespoke (List skeleton) |
| Release | V1 |
| Design day | Day 18 — DES-18 |
| Build task | DSH-06 |
| Route | /orders |
| Requirements | ORD-04 · ORD-05 · ORD-03 · ORD-09 · ANA-05 |
| Permissions required | orders.view (page) · orders.update (bulk « Passer en préparation ») · delivery.view (picking lists) · orders.export (export) · orders.create (« Nouvelle commande ») |
Purpose. Find and follow every order at every stage, with the same filters the cahier lists (channel, delegate, reseller, wilaya, dates). It meets the acceptance « Une commande validée reçoit un numéro et apparaît dans le back-office » (cahier §12, §5.3). The confirmation work itself happens in BO-41.
Who uses it. Commercial admin, delivery manager, finance manager, stock manager, direction.
Entry points.
- Commandes › Commandes.
- Global search.
- Dashboard cards and status segments (BO-04).
- The Commandes tab of the reseller 360° (BO-11).
order.createdtoasts.
Layout
- Header: « Commandes » with the count. Actions: « Nouvelle commande » (BO-40), « Exporter ». A link card « 12 commandes à confirmer » leads to BO-41; it is shown with
orders.validate, in red when the oldest waits more than 2 h. - Status tabs (
view), each with a counter:- « Toutes ».
- « À confirmer » (
SUBMITTED,PENDING; read-only here, rows open in BO-41). - « Validées », « En préparation », « Prêtes », « Expédiées », « Livrées ».
- « Annulées et refusées », « Retournées ».
- « Brouillons »: back-office drafts. Delegate drafts are read-only and labelled « Commande assistée en préparation ».
| Column | Source field | Sortable | Default visible |
|---|---|---|---|
| N° commande | number (CMD-2026-000158, mono) | Yes | Yes |
| Date | submittedAt (or createdAt for drafts) | Yes | Yes |
| Revendeur | reseller.storeName + REV number | Yes | Yes |
| Type de client | reseller.customerType at checkout (CustomerType pill) | Yes | Yes |
| Wilaya / commune | Delivery address snapshot | Yes | Yes |
| Canal | channel (OrderChannel icon + label) | Yes | Yes |
| Délégué | Attributed delegate (source delegate for assisted orders) | Yes | Yes |
| Articles | linesCount · totalQuantity | No | Yes |
| Montant TTC | totals.totalTtc | Yes | Yes |
| Paiement | paymentMethod (PaymentMethod) | Yes | Yes |
| Statut | status (OrderStatus pill) | Yes | Yes |
| Confirmée par | validatedBy.displayName + validatedAt | Yes | No |
| Délai de confirmation | validatedAt − submittedAt | Yes | No |
| Contrôles | Summary icon: OK / warnings / blocking | No | No |
| 1re commande | isFirstOrder badge (ORD-09) | Yes | No |
| Livraison | delivery.status (DeliveryStatus) + carrier | Yes | No |
| Facture | invoice.number + InvoiceStatus (needs finance.view) | No | No |
| Mis à jour | updatedAt | Yes | No |
| Filter | Control | URL parameter |
|---|---|---|
| Search (number, store name, phone) | Text | q |
| Statut | Multi-select (preset by the tab) | status |
| Canal | Multi-select of OrderChannel | channel |
| Délégué | Select | delegate |
| Revendeur | Search select | reseller |
| Type de client | Multi-select of CustomerType | customerType |
| Wilaya, Commune | Selects | wilaya, commune |
| Mode de paiement | Multi-select | paymentMethod |
| Date de commande | Date range | from, to |
| Date de validation | Date range | validatedFrom, validatedTo |
| Première commande | Toggle | firstOrder=true |
| Contrôles | Select: bloquant / avertissement / OK | controls |
| Montant TTC | Min–max | amountMin, amountMax |
- Default sort:
submittedAtdescending. - Bulk actions:
- « Passer en préparation » (
VALIDATEDonly):admin.orders.transitionper order, with the progress report. - « Imprimer les bons de préparation »: a combined PDF from
admin.deliveries.pickingList. - « Exporter la sélection ».
- « Passer en préparation » (
- Row actions: « Ouvrir », « Copier le numéro », « Ouvrir le revendeur », « Bon de préparation », « Annuler » (when allowed).
- Export: XLSX, CSV or PDF of the filters and visible columns, through
admin.exports.create(type: "orders").
Data. admin.orders.list (page, pageSize, sort, order, filters above), admin.orders.transition, admin.deliveries.pickingList, admin.exports.create.
Actions. « Passer en préparation » on a selection asks « Passer 8 commandes en préparation ? Les bons de préparation pourront être imprimés. ». It is not optimistic, audits STATUS_CHANGE per order and notifies each reseller (push, in-app and live).
Rules.
- Rows in
SUBMITTEDorPENDINGshow their age (« il y a 3 h ») and open in BO-41 for confirmation. - Bulk confirmation lives in BO-41 only, so that every confirmation is a deliberate act (ORD-14).
- Amounts are TTC, as ordered. Revenue KPIs elsewhere are HT.
- Drafts never count in totals or KPIs.
Real-time.
order.createdshows the banner « 2 nouvelles commandes — Afficher » on « Toutes » and « À confirmer ». Rows are not inserted under the cursor.order.status_changedupdates the status pill of visible rows and the tab counters in place.
States.
- Empty: « Aucune commande », with « Nouvelle commande ».
- Filter with no result: reset link.
- Picking lists: the bulk action is disabled with a tooltip when the selection contains orders not yet
VALIDATED.
Acceptance criteria.
- An order submitted from the reseller app appears within 5 s with its number, channel Application revendeur and status Envoyée (cahier §5.3 acceptance).
- The tab counters equal the result counts of the matching
statusfilters. channel=DELEGATE_ASSISTED&firstOrder=truelists exactly the first orders prepared by delegates.- The « Passer en préparation » bulk action is refused, per order, for any order that is not
VALIDATED, and the report names them.
BO-39 — Order detail (controls, actions, history)
| Field | Value |
|---|---|
| Template | Bespoke (Detail skeleton) |
| Release | V1 |
| Design day | Day 18 — DES-18 |
| Build task | DSH-06 |
| Route | /orders/[orderId] (?tab=) |
| Requirements | ORD-05 · ORD-06 · STK-08 · ORD-12 · ORD-14 · ORD-10 · ORD-08 · FIN-05 |
| Permissions required | orders.view (page) · orders.validate (confirm, refuse, confirm an assisted order, override) · orders.update (put on hold, modify lines, fulfilment transitions, cancel, documents) · delivery.update (carrier, tracking, proof) · delivery.view (picking list) · finance.view (credit and invoice cards) |
Purpose. Process one order end to end (cahier §4.4):
- read the automatic controls (stock, prices, promotions, credit, address);
- confirm it, put it on hold, refuse it with a reason, or modify it in a controlled way;
- move it through preparation and shipping;
- produce the invoice and delivery note;
- see its full history.
Who uses it. Commercial admin (confirmation, modification, refusal), delivery manager (fulfilment), finance manager (credit context), direction (read).
Entry points. BO-38 and BO-41 rows, global search, toasts, the delivery-board drawer (BO-42), BO-11, and notifications.
Layout
- Header:
CMD-2026-000158, theOrderStatuspill, and theAssistedConfirmationpill for assisted orders.- Badges: channel, « 1re commande ».
- Submitted at, waiting time while
SUBMITTED/PENDING. - Reseller: link to BO-11, with the
CustomerTypepill (« Prix Demi-gros »). - Source delegate.
- Total TTC and payment method.
- Primary actions from
allowedActions, for example « Confirmer la commande », « Passer en préparation », « Expédier ». - « Plus » menu: « Mettre en attente », « Modifier les articles », « Refuser », « Annuler », « Bon de préparation », « Régénérer les documents ».
- Main column, the lines table:
- Image, product and variant, SKU, quantity.
- Prix unitaire HT at checkout, at the reseller's customer type, with a strike-through and the promotion name when discounted.
- Line discount, line total HT.
- Line controls: available stock vs ordered, with « Disponible : 12 » in danger when short; current price vs order price, with « Prix actuel : 250,00 DA ».
- Footer: Sous-total HT, Remises, Frais de livraison, TVA, Total TTC (shared
Totalsschema). - Order note from the reseller, and the delegate's note for assisted orders.
- Side rail:
- Contrôles card (below).
- Revendeur card: status, customer type, phone, WhatsApp, open tickets. With
finance.view: credit limit, used, available, overdue invoices. - Livraison card: address snapshot, mode, carrier, tracking,
DeliveryStatus. - Paiement card: method, invoice number and status, allocated payments (needs
finance.view).
- Tabs:
- Articles (default).
- Historique:
admin.orders.history. Status changes with actor, time and reason, and line changes (OrderChange: before → after, reason), newest first. - Livraison: delivery record, picking list, proof photo and recipient.
- Documents: invoice
FAC-…and delivery noteBL-…PDFs (signed URLs), plus « Générer » / « Régénérer ». - Retours et SAV: return requests (
RET-…) and after-sales claims linked to the order, with status and resolution; links to BO-69 and BO-56.
Controls panel
Results come with admin.orders.get and are recomputed on every read and again at confirmation. « Relancer les contrôles » simply refetches.
| Control | Checks | Severity |
|---|---|---|
| Stock | Each line's quantity ≤ available stock of the variant (warehouse rules of BO-33) | Blocking when short (STK-08) |
| Prix | Each line's unit price = the variant's current price for the reseller's customer type | Warning (PRICE_CHANGED); the order keeps its checkout price |
| Promotions | Each applied promotion is still valid (dates, cap, target) | Warning; the discount stays as ordered |
| Crédit | With payment method CREDIT: order total ≤ available credit; account not blocked | Blocking when exceeded or blocked (FIN-05) |
| Adresse | Complete address, commune in the reference, valid phone | Blocking when incomplete |
| Minimums | Minimum amount, quantities, steps and maxima (ORD-02) | Warning (already enforced at checkout) |
| Compte | Reseller ACTIVE and not SUSPENDED | Blocking |
Each control shows OK (success), a warning or a block (danger), with its detail: « Câble X14 : 40 commandés, 25 disponibles ».
Actions
| Action | Offered when (per allowedActions) | Endpoint | Confirmation (FR) | Reason | Optimistic | Audit | Notifies |
|---|---|---|---|---|---|---|---|
| « Confirmer la commande » | SUBMITTED, PENDING (not awaiting the reseller) | admin.orders.validate | « Confirmer CMD-2026-000158 ? Le stock sera réservé et le revendeur sera informé. » | — | No | VALIDATE + STATUS_CHANGE | Reseller: push, in-app and live (« Votre commande CMD-… est confirmée ») |
| « Confirmer malgré les alertes » (override) | Same, with at least one blocking control | admin.orders.validate with override: { controls, reason } | « Certains contrôles ont échoué : Stock (2 lignes), Crédit (dépassement de 18 400,00 DA). Je confirme la commande malgré ces alertes. » (checkbox) | Required, at least 10 characters | No | VALIDATE + OVERRIDE (failed controls snapshot and reason) | Reseller as above. Finance is notified when the credit control was overridden. |
| « Mettre en attente » | SUBMITTED | admin.orders.transition (PENDING). Assumption — the transition table must allow it (see contract notes). | « Mettre la commande en attente ? Elle restera dans la file à confirmer. » | Required (shown to the reseller: « Commande en attente : … ») | No | STATUS_CHANGE | Reseller (push, in-app, live) |
| « Confirmer pour le revendeur » | Assisted order awaiting the reseller | admin.orders.confirmAssisted | « Le revendeur a confirmé par téléphone ? Indiquez avec qui et quand. » | Required (person and time) | No | VALIDATE (CONFIRMED_BY_ADMIN) | Reseller and source delegate |
| « Refuser » | SUBMITTED, PENDING | admin.orders.refuse | « Refuser la commande CMD-2026-000158 ? Cette action est définitive et le revendeur sera informé du motif. » | ORDER_REFUSAL_REASON + comment (required for « Autre ») | No | REJECT + STATUS_CHANGE | Reseller; source delegate for assisted orders |
| « Modifier les articles » | SUBMITTED, PENDING, VALIDATED (before PREPARING) | admin.orders.modify | A diff dialog: « 2 lignes modifiées : Câble X14 40 → 25 ; Chargeur N5 supprimé. Nouveau total : 45 600,00 DA. » | Required | No | UPDATE (OrderChange per line) | Reseller: push, in-app and live (« Votre commande a été modifiée ») |
| « Passer en préparation » | VALIDATED | admin.orders.transition (PREPARING) | — | — | No | STATUS_CHANGE | Reseller |
| « Marquer prête » | PREPARING | admin.orders.transition (READY) | — | — | No | STATUS_CHANGE | Reseller |
| « Expédier » | READY | admin.deliveries.update (mode, carrier, tracking, driver), then admin.orders.transition (SHIPPED) | The shipping dialog of BO-42 | — | No | STATUS_CHANGE | Reseller, with tracking |
| « Marquer livrée » | SHIPPED | admin.deliveries.proof | The proof dialog of BO-42 | — | No | STATUS_CHANGE | Reseller |
| « Annuler » | SUBMITTED → READY (per the table) | admin.orders.cancel | « Annuler la commande ? Les quantités réservées seront remises en stock automatiquement. » | ORDER_CANCEL_REASON + comment | No | STATUS_CHANGE | Reseller; source delegate |
| « Générer » / « Régénérer les documents » | Per the billing setting | admin.orders.documents | Regenerating: « Régénérer la facture FAC-… ? L'ancienne version reste dans l'historique. » | — | No | UPDATE | — |
| « Bon de préparation » | VALIDATED → READY | admin.deliveries.pickingList | — | — | — | — | — |
Rules
- Explicit confirmation (ORD-14):
- Only a person with
orders.validatemoves an order fromSUBMITTED/PENDINGtoVALIDATED. No job, rule or control result does it. - Assisted orders first need the reseller's confirmation, or « Confirmer pour le revendeur » (ORD-08), and then the back-office confirmation. The UI offers « Confirmer pour le revendeur et confirmer la commande » as two chained calls, each audited.
- Only a person with
- Overrides (STK-08):
- Confirming beyond available stock or credit requires
orders.validate, the explicit checkbox and a reason. - The override is logged as
OVERRIDEwith the failed controls. The stock may then go below 0 for the variant (shown as « Dérogation » in BO-33). - When the credit policy is « bloquer » (BO-64), the credit override is not offered. Finance must raise the limit first (BO-46).
- Confirming beyond available stock or credit requires
- Transitions: only those in
allowedActionsare rendered. They follow theOrderStatustransition table and the user's permissions (ORD-04). A stale screen trying another gets409 ORDER_TRANSITION_NOT_ALLOWEDand reloads. - Prices are frozen at checkout at the reseller's customer type (PRC-02).
- In a controlled modification, unchanged lines keep their price, while added lines take the variant's current price for the reseller's type and the promotions valid now.
- No manual unit-price override in V1. Assumption — confirm.
- History (ORD-06): every modification and status change is historised with actor, time and reason, and notified.
- Stock: reserved at
VALIDATEDand deducted atSHIPPED(default settings). A cancellation releases or re-enters quantities automatically (STK-03). - Concurrency: the order carries
version. A second person confirming the same order gets409 VERSION_CONFLICT, with « Déjà confirmée par Karim B. à 10:42 ». - Sensitive data: purchase prices and margins are never shown on this page (ACL-04).
Real-time.
order.status_changedfor this order shows a banner « Cette commande vient de passer à Validée (par Samir K.) » and refreshes.- When a modification form is open, the change is shown before saving and saving is blocked until reload.
States.
- Draft (back-office): editable in BO-40, with a « Brouillon » banner.
- Assisted order awaiting the reseller: banner « En attente de la confirmation du revendeur — expire le 12/11 à 09:12 » (72 h).
- Refused or cancelled: read-only with the reason. A returned order links to its return.
- Delegate draft: read-only.
- Control service error: the panel shows « Contrôles indisponibles », and confirmation is disabled.
Acceptance criteria
- An order whose controls all pass is still
SUBMITTEDuntil someone clicks « Confirmer la commande ». No job or rule confirms it. - Confirming with a blocking stock control is impossible without the override checkbox and a reason. With them, the order becomes
VALIDATEDand the activity log showsVALIDATEandOVERRIDEwith the failed controls. - The reseller app shows the new status within 5 s of confirmation (live event) and receives a push notification (ORD-15).
- Modifying a line from 40 to 25 records an
OrderChangewith before/after and reason, re-runs the controls and notifies the reseller. - Refusing requires a
ORDER_REFUSAL_REASONitem. The reseller sees the refusal reason in the app. - Cancelling a
VALIDATEDorder releases its reserved quantities with no manual action (BO-33 shows them available again). - Only the actions listed in
allowedActionsare visible for each status.
BO-40 — New order on behalf of a reseller
| Field | Value |
|---|---|
| Template | Form (four steps) |
| Release | V1 |
| Design day | Day 18 — DES-18 |
| Build task | DSH-06 |
| Route | /orders/new (?reseller=) · drafts open as /orders/[orderId]/edit |
| Requirements | ORD-11 · ORD-02 · PRC-02 · ORD-14 |
| Permissions required | orders.create · orders.update (draft line edits through admin.orders.modify) · orders.validate (optional « Envoyer et confirmer ») · finance.view (credit details) |
Purpose. Enter an order taken by phone or WhatsApp for a reseller (cahier §4.4; ORD-11), priced exactly as the reseller would see it: the price of their customer type plus promotions.
Who uses it. Commercial admin.
Entry points. « Nouvelle commande » on BO-38 and BO-11 (reseller preselected).
Layout.
- Revendeur:
- Search by name,
REVor phone. - Card with status, account status, customer type (« Les prix Demi-gros s'appliquent »), delegate, and credit available (needs
finance.view). - A
SUSPENDEDreseller, or an account not yet validated, cannot be chosen (« Compte non validé »).
- Search by name,
- Articles:
- A variant search with scanner support. Each result shows the reseller's price HT and TTC, and the availability En stock / En rupture plus the available quantity (back-office only).
- Lines show quantity steppers that respect minimum, multiple and maximum, the unit price, the applied promotion and the line total.
- Issues come from the server (
Issuelist: stock, minimums).
- Livraison et paiement:
- The reseller's addresses (the default is preselected). A missing address links to « Modifier la fiche revendeur » (BO-12).
- Payment method: the methods enabled for this reseller, with credit availability.
- Note pour le revendeur.
- Récapitulatif:
- Totals, the controls panel (as BO-39), and the channel
BACK_OFFICE. - Primary « Envoyer la commande ». Secondary « Envoyer et confirmer » (with
orders.validate).
- Totals, the controls panel (as BO-39), and the channel
Data.
admin.orders.create: creates theDRAFTwith the first line; returns the priced order and its issues.admin.orders.modify: each later line change, re-priced, no reason needed on a draft.admin.orders.transition:DRAFT→SUBMITTED.- Optionally
admin.orders.validate. - Option data:
admin.resellers.list,admin.products.list.
Actions.
- « Envoyer la commande »: « Envoyer la commande de 45 600,00 DA TTC pour Boutique Nour ? Elle rejoindra les commandes à confirmer. ». The order gets its
CMD-number and lands in BO-41. The reseller is notified (push, in-app: « HOCO a enregistré une commande pour vous »). AuditedCREATEandSTATUS_CHANGE. - « Envoyer et confirmer »: the same, followed by the BO-39 confirmation dialog. It is two explicit steps by the same person; the override rules apply.
- « Enregistrer le brouillon » keeps the
DRAFTin BO-38 « Brouillons ». - « Supprimer le brouillon » cancels the draft.
Rules.
- Prices, promotions, stock and credit are evaluated by the server exactly as for a reseller checkout (ORD-02, PRC-02). The UI never computes a price.
- Like every order, it waits for an explicit confirmation (ORD-14).
- The order is attributed to the reseller's assigned delegate for reporting. The channel is
BACK_OFFICE.
Real-time. None.
States.
- Price changed while drafting: warning line « Prix mis à jour : 245,00 → 250,00 DA ».
- Out-of-stock variant: addable with the warning « Stock insuffisant — confirmation par dérogation uniquement ».
- Unsaved draft: guarded.
Acceptance criteria.
- For a Super-gros reseller, every line shows the variant's Super-gros price, and the totals equal what the reseller app would show for the same cart.
- « Envoyer la commande » produces a
SUBMITTEDorder with channel Back-office that appears in BO-41 within 5 s. - A suspended reseller cannot be selected.
- Drafts never appear in BO-41 or in KPIs.
BO-41 — Orders to confirm (new, on hold, assisted)
| Field | Value |
|---|---|
| Template | List (queue with a preview panel) |
| Release | V1 |
| Design day | Day 18 — DES-18 |
| Build task | DSH-06 |
| Route | /orders/to-confirm (?view=, ?id= selected) |
| Requirements | ORD-14 · ORD-08 · ORD-05 · STK-08 |
| Permissions required | orders.validate (page, confirm, refuse, confirm an assisted order) · orders.update (put on hold, modify, cancel) |
Purpose. The single queue where every order waits for its human confirmation (§1b.2): new orders (SUBMITTED), orders on hold (PENDING) and assisted orders, oldest first, with their controls, so a person can confirm, hold or refuse each one quickly.
Who uses it. Commercial admin, many times a day. The super admin.
Entry points.
- Commandes › Commandes à confirmer (live badge).
- The Commandes à confirmer card of BO-04.
- The
order.createdtoast (« Confirmer »). - The BO-38 link card.
Layout.
- Tabs (
view), each with a live counter:- « Toutes ».
- « Nouvelles » (
SUBMITTED). - « En attente » (
PENDING, on hold by the back-office or by a failed control). - « Assistées »: assisted orders, both
PENDINGawaiting the reseller (AWAITING_RESELLER) and those the reseller has confirmed. - « Dérogation requise »: at least one blocking control.
- Left, the queue, oldest first. Each row:
| Column | Source field | Default visible |
|---|---|---|
| Attente | Time since submittedAt (amber after 1 h, red after 2 h; setting orders.confirmationAlertMinutes) | Yes |
| N° | number | Yes |
| Revendeur | Store name, wilaya, CustomerType pill, « 1re commande » badge | Yes |
| Canal | OrderChannel icon (and the source delegate for assisted orders) | Yes |
| Montant TTC | totals.totalTtc | Yes |
| Paiement | paymentMethod | Yes |
| Contrôles | OK / warnings / blocking icons, by control | Yes |
| Statut | SUBMITTED / PENDING + AssistedConfirmation pill + hold reason | Yes |
| Expire | For assisted orders awaiting the reseller: countdown to 72 h | Yes |
- Right, the preview panel of the selected order:
- lines with prices and stock check;
- the controls panel of BO-39;
- reseller summary (customer type, credit with
finance.view, last orders); - notes.
- Decision bar: « Confirmer », « Mettre en attente », « Refuser », « Modifier » (opens BO-39 in edit mode), « Ouvrir le détail ».
- Filters:
channel,wilaya,delegate,paymentMethod,controls,customerType. - Keyboard: J / K next or previous, C confirm, H hold, R refuse, O open the detail.
- Bulk action: « Confirmer la sélection ».
- Only rows whose controls are all OK can be selected; the other checkboxes are disabled with a tooltip.
- One confirmation dialog for all, then one
admin.orders.validateper order with its ownIdempotency-Key, and a per-order report.
Data.
admin.orders.toConfirm:SUBMITTEDandPENDING, oldest first, with control results.admin.orders.get(panel).- The BO-39 actions:
admin.orders.validate,admin.orders.refuse,admin.orders.confirmAssisted,admin.orders.transition(hold),admin.orders.cancel.
Actions. The confirmation, override, hold, refusal and assisted confirmation dialogs are exactly those of BO-39, with the same audit entries and notifications. Bulk confirmation asks: « Confirmer 6 commandes (184 300,00 DA TTC) ? Toutes ont passé les contrôles. Le stock sera réservé et chaque revendeur sera informé. »
Rules.
- Nothing leaves this queue except a confirmation (→
VALIDATED), a refusal (→REFUSED) or a cancellation (→CANCELLED, by the reseller whileSUBMITTED/PENDING, or by the back-office). Expiry is the only automatic exit: an assisted order not confirmed by the reseller within 72 h becomesEXPIREDand is cancelled. Assumption — confirm the expiry outcome in the lifecycle page. - Orders that need a decision (a blocking control) cannot be bulk-confirmed. They need the per-order override.
- Hold: an order on hold stays in the queue with its reason, and its waiting time keeps counting from submission.
- Concurrency: two users working the queue never confirm twice. The second gets
409and the row disappears with « Déjà traitée par … ».
Real-time.
order.createdinserts the new order at the end of the queue (oldest first) with a highlight, bumps the counters and badge, and plays no sound. Assumption — an optional sound is off by default.order.status_changedremoves rows that leftSUBMITTED/PENDING(confirmed elsewhere, cancelled by the reseller, expired). A selected row that disappears shows « Cette commande a été traitée par … » and moves to the next.
States.
- Empty queue: « Aucune commande à confirmer. » (success tone), with the median confirmation delay of the day.
- Control service error: confirmation disabled for that order.
- Stream lost: the queue polls every 30 s, and the banner shows.
Acceptance criteria.
- Orders from the reseller app, the reseller web, a delegate (after the reseller's confirmation) and BO-40 all appear here, and none reaches
VALIDATEDwithout a confirmation action (ORD-14). - A new order appears within 5 s with its controls, and the badge and BO-04 card increase by 1.
- Confirming removes the order from the queue in every open tab within 5 s.
- Bulk confirmation is impossible for an order with a blocking control.
- An assisted order shows its countdown. After 72 h without the reseller's confirmation, it leaves the queue as expired.
- Pressing C on an order with all controls OK opens the confirmation dialog, and Enter confirms it.
BO-42 — Delivery board
| Field | Value |
|---|---|
| Template | Bespoke |
| Release | V1 |
| Design day | Day 18 — DES-18 |
| Build task | DSH-06 |
| Route | /delivery (?display=board or table, ?mode=screen) |
| Requirements | DLV-01 · DLV-02 · DLV-03 · DLV-06 · STK-03 |
| Permissions required | delivery.view (board, picking lists) · orders.update (status moves through admin.orders.transition) · delivery.update (mode, carrier, tracking, driver, proof, failure) · finance.create (record a cash-on-delivery collection) |
Purpose. Run preparation, shipping and delivery for confirmed orders (cahier §3 « Responsable livraison : préparation, expédition, affectation transporteur et preuve de livraison »; §4.4).
Who uses it. Delivery manager, all day, on desktop and on a warehouse screen. Commercial admin reads it.
Entry points. Commandes › Livraisons (badge « à préparer »), BO-39 Livraison, and the delivery cards.
Layout
- Toolbar:
- Filters: Wilaya (
wilaya), Transporteur (carrier), Mode (mode,DeliveryMode), Entrepôt (warehouse), Paiement à la livraison (cod=true), Confirmée entre (validatedFrom/validatedTo), search (q: CMD, BL, store). - « Board / Tableau » switch, « Mode écran », « Imprimer les bons de préparation ».
- Filters: Wilaya (
- Columns (
DeliveryStatus), each with a count and the total of cash to collect:- « À préparer » (
TO_PREPARE, ordersVALIDATED); - « En préparation » (
PREPARING); - « Prêtes » (
READY); - « Expédiées » (
SHIPPED); - « Livrées » (
DELIVERED, last 3 days, then hidden); - « Échecs » (
FAILED).
- « À préparer » (
- Card:
CMDnumber, store name, commune / wilaya.- Lines and units (« 6 lignes · 140 pièces »).
- Amount TTC, and « À encaisser : 45 600,00 DA » for cash on delivery.
- Carrier or driver, tracking.
- Age since confirmation: amber after 24 h, red after 48 h. Assumption — SLA to confirm.
- Flags: « 1re commande », « Dérogation stock ».
- Sorted oldest first in each column.
- Card drawer (click, without leaving the board):
- picking list (lines, SKU, quantity, warehouse location if any);
- address and contact (call, WhatsApp);
- delivery fields;
- proof (photo, recipient);
- status history;
- « Ouvrir la commande » (BO-39).
- « Mode écran » (warehouse TV, large screens): only the first three columns, large cards, auto-refresh, no drawers.
Transitions
Moves are by drag-and-drop or by the card's « Déplacer vers… » menu (the tablet and keyboard alternative). Drop zones that the transition table does not allow are greyed with a tooltip; backward moves are not allowed.
| Move | Endpoint(s) | Dialog and required inputs | Effect |
|---|---|---|---|
| À préparer → En préparation | admin.orders.transition (PREPARING) | None; option « Imprimer le bon de préparation » (admin.deliveries.pickingList) | Reseller notified « Votre commande est en préparation » |
| En préparation → Prête | admin.orders.transition (READY) | Optional: Nombre de colis, Poids (kg) (admin.deliveries.update) | — |
| Prête → Expédiée | admin.deliveries.update, then admin.orders.transition (SHIPPED) | « Expédier CMD-… » with Mode (OWN_FLEET → Livreur and Téléphone required; CARRIER → Transporteur and N° de suivi required; PICKUP → no shipping, go to « Livrée ») | Stock deducted (default setting); the invoice and delivery note are generated per the billing setting; reseller notified with the tracking link |
| Expédiée → Livrée | admin.deliveries.proof | « Preuve de livraison » with Nom du destinataire (required), Photo (DELIVERY_PROOF; required except for PICKUP), Livrée le (default now). For cash on delivery with finance.create: Montant encaissé, chaining admin.payments.record. | Order DELIVERED; reseller notified; may trigger the reseller's ACTIVE status |
| Expédiée → Échec | admin.deliveries.update (status: FAILED, reason). Assumption — see contract notes. | Motif: « Absent », « Refusée à la livraison », « Adresse introuvable », « Injoignable », « Autre » + comment | The order stays SHIPPED; card in « Échecs » |
| Échec → Expédiée (« Nouvelle tentative ») | admin.deliveries.update | New date, driver or tracking | Attempt counter +1 |
| Échec → Retour au dépôt | admin.orders.transition (RETURNED) | « Retourner la commande au dépôt ? Un retour RET-… sera créé ; la réception remettra les quantités en stock. » | A return is created in BO-69 (IN_TRANSIT). Assumption — the server creates it. Reception restocks automatically. |
Every move audits STATUS_CHANGE (or UPDATE). None is optimistic: the card moves after the server answers, and shows a spinner meanwhile.
Bulk actions (selection on the board or table):
- « Imprimer les bons de préparation » (combined PDF).
- « Passer en préparation ».
- « Expédier » with one mode and driver for
OWN_FLEET.CARRIERrequires a tracking number per card, so it is not available in bulk.
Data. admin.deliveries.list (columns with cards and counts), the operations above, admin.carriers.crud (GET for pickers), files.createUpload (proof photo).
Rules
- Only confirmed orders enter the board:
VALIDATEDappears as « À préparer » (ORD-14). - Moves follow the order transition table. A stale board attempting a disallowed move gets
409 ORDER_TRANSITION_NOT_ALLOWED, and the card snaps back. - Delivery fees come from the order (DLV-06 policy at checkout). The board never recomputes them.
- Proof (DLV-03): the photo is a private file, read through signed URLs.
- Stock: deduction at
SHIPPED; re-entry only at return reception in BO-69, automatically (STK-03).
Real-time. order.status_changed moves cards between columns (animated) for changes made by others, with « Mis à jour par Samir K. » on the card for 5 s. A newly confirmed order appears in « À préparer » within 5 s.
States.
- Empty column: « Rien à préparer » (success tone).
- Drag on touch screens: a long press starts the drag, or use the menu.
- Failed proof upload: the dialog keeps its input and offers « Réessayer ».
- Stream lost: polls every 30 s, with the banner.
Acceptance criteria
- Confirming an order in BO-41 makes its card appear in « À préparer » within 5 s.
- Moving a card to « Expédiée » with mode Société de livraison is impossible without a carrier and a tracking number. Afterwards the stock of its variants is deducted, and the reseller is notified with the tracking link.
- « Livrée » requires the recipient name and, except for pickup, a photo. The proof shows in BO-39 Livraison.
- A failed delivery returned to the depot creates a return in BO-69. Its reception puts the quantities back in stock without manual adjustment.
- Every move is possible without drag-and-drop through « Déplacer vers… ».
BO-43 — Carriers
| Field | Value |
|---|---|
| Template | List (with drawer) |
| Release | V1 |
| Design day | Day 18 — DES-18 |
| Build task | DSH-06 |
| Route | /delivery/carriers |
| Requirements | DLV-04 · DLV-02 |
| Permissions required | delivery.administer |
Purpose. Maintain the list of delivery companies, API-capable or manual (cahier §11 « Livraison : connexion aux agences disposant d'une API ; sinon gestion manuelle structurée »).
Who uses it. Delivery manager, super admin.
Entry points. Commandes › Transporteurs, and « Gérer les transporteurs » in the shipping dialog.
Layout.
- Table: Nom, Contact, Téléphone, Wilayas desservies (count), Intégration API (« Manuel » / « API — V2 »), Modèle d'URL de suivi, Actif, Expéditions (30 j).
- Drawer:
- Nom: required, unique.
- Téléphone, Email.
- Wilayas desservies: multi-select, or « Toutes ».
- URL de suivi: a template with the placeholder
{tracking}, which must contain it, e.g.https://suivi.exemple.dz/{tracking}. - Intégration API: disabled toggle, labelled « V2 » (DLV-05).
- Notes.
- Actif.
Data. admin.carriers.crud.
Actions. Create and edit (audited). There is no delete: carriers are deactivated (« Désactiver ce transporteur ? Il ne sera plus proposé à l'expédition ; les envois en cours ne changent pas. »).
Rules.
- The shipping dialog offers only active carriers serving the order's wilaya.
- The tracking link sent to the reseller is the URL template with the tracking number.
Real-time. None.
States. First use: « Ajoutez vos transporteurs (Yalidine, ZR Express…) ou utilisez Livreur HOCO ». Assumption — the carrier names are examples.
Acceptance criteria.
- A deactivated carrier disappears from the shipping dialog.
- A tracking URL template without
{tracking}is refused. - The reseller's notification contains the resolved tracking link.
BO-69 — Returns & after-sales claims
| Field | Value |
|---|---|
| Template | List (with a return detail) |
| Release | V1 |
| Design day | Day 18 — DES-18 |
| Build task | DSH-13 |
| Route | /orders/returns · /orders/returns/[returnId] (?view=) |
| Requirements | ORD-13 · SUP-04 · STK-03 · FIN-08 |
| Permissions required | orders.view (page) · orders.validate (approve or reject a return) · stock.update (record the reception) · support.view (after-sales tab) · finance.view (credit-note amounts) |
Purpose. Handle returns in V1 (§1b.9–10) and keep the after-sales claims (SAV) that relate to orders in view. A return goes through four steps:
- A reseller requests it on a delivered order (
returns.create), or it comes from an after-sales resolutionRETURN, or from a delivery refused at the door. - The back-office approves or rejects it.
- The goods travel back.
- Reception re-enters the accepted quantities into stock automatically (
RETURNmovements) and issues a credit note.
The after-sales claims themselves are resolved in BO-56.
Who uses it.
- Commercial admin: decides returns.
- Stock manager / warehouse: records receptions.
- Finance manager: reads the credit notes.
Entry points.
- Commandes › Retours et SAV (badge).
- BO-39 Retours et SAV tab.
- BO-56 (a
RETURNresolution creates a return). - BO-42 (« Retour au dépôt »).
- BO-11 Tickets et SAV.
Layout.
- Tabs (
view):- « À décider » (
REQUESTED). - « À réceptionner » (
APPROVED,IN_TRANSIT). - « Reçus » (
RECEIVED). - « Avoirs émis » (
REFUNDED). - « Refusés » (
REJECTED). - « Réclamations SAV »: tickets of type
AFTER_SALES, with issue, lines, status and resolution. A row opens BO-56.
- « À décider » (
| Column | Source field | Sortable | Default visible |
|---|---|---|---|
| N° retour | number (RET-2026-000012) | Yes | Yes |
| Date | requestedAt | Yes (default ascending in « À décider ») | Yes |
| Revendeur | Store name + CustomerType pill | Yes | Yes |
| Commande | order.number (link to BO-39) | Yes | Yes |
| Origine | « Demande revendeur », « Résolution SAV TKT-… », « Refus à la livraison » | No | Yes |
| Articles | Lines and quantities | No | Yes |
| Motif | Reason (and AfterSalesIssue for SAV) | No | Yes |
| Statut | status (ReturnStatus) | Yes | Yes |
| Montant de l'avoir | Credit note total TTC (needs finance.view) | Yes | No |
| Avoir | Credit note number + PDF | No | No |
- Return detail (page): header with
RETnumber,ReturnStatuspill, reseller, order, origin and dates. Then:- Lines: variant, quantity delivered, quantity requested, Quantité acceptée (decision), Reçue, Remise en stock.
- Reseller's reason and photos (gallery).
- Linked ticket.
- Timeline of status changes.
- The credit note: number, amount, PDF.
Decision (REQUESTED, with orders.validate), through admin.returns.decide:
- « Accepter le retour »: per line Quantité acceptée (≤ requested; default = requested). Confirmation « Accepter le retour de 3 articles ? Le revendeur sera informé et pourra renvoyer la marchandise. ». The return becomes
APPROVED, thenIN_TRANSIT. The reseller is notified (push, in-app, live throughevents.stream). AuditedVALIDATE. - « Refuser »: a reason is required and shown to the reseller (e.g. « Délai de retour dépassé »). The return becomes
REJECTED. AuditedREJECT, and the reseller is notified.
Reception (APPROVED / IN_TRANSIT, with stock.update), through admin.returns.receive:
- Header: Entrepôt de retour (the default warehouse is preselected) and Reçu le (default now).
- Per line:
- Quantité reçue, at most the accepted quantity.
- Article défectueux — ne pas remettre en stock: a checkbox, preset for SAV issues
DEFECTIVEandDAMAGED. Assumption — defective items are credited but not restocked. - Commentaire.
- Confirmation: « Enregistrer la réception ? 3 articles seront remis en stock automatiquement et un avoir de 8 750,00 DA TTC sera émis. »
- Effects:
RETURNstock movements are posted automatically for the restocked quantities (BO-34).- The
CreditNoteis issued (FIN-08). The return becomesRECEIVED, thenREFUNDEDonce the credit note exists. - The order becomes
RETURNEDwhen all its delivered quantities came back. - Audited
UPDATE+CREATE(credit note). The reseller is notified (« Retour reçu — avoir AV-… émis »).
Data. admin.returns.list, admin.returns.get, admin.returns.decide, admin.returns.receive, admin.tickets.list (type=AFTER_SALES), files.downloadUrl.
Rules.
- Eligibility: a return can only concern delivered quantities of a
DELIVEREDorder. Per line, Σ returned ≤ delivered. - No manual restock step: reception does it (STK-03). Nobody adjusts stock by hand for a return.
- Credit note amount = Σ received quantities × the order's unit price TTC after discounts. Delivery fees are not credited unless the whole order is returned. Assumption — confirm.
- Credit notes reduce the reseller's balance in finance (BO-44).
- Concurrency: a return decided or received elsewhere answers
409. - Number format: the credit note number shown here (
AV-…) is illustrative. Assumption — its format is not in the canonical list.
Real-time. The admin stream has no return event in V1. The page polls every 60 s while visible. order.status_changed refreshes returns linked to that order.
States.
- Empty: « Aucun retour à traiter ».
- Photos still uploading from the reseller: « Photos en cours d'envoi ».
- Reception refused (
409): the return was cancelled by the reseller meanwhile.
Acceptance criteria.
- A reseller's return request on a delivered order appears under « À décider » with its lines, reason and photos.
- Approving with a reduced quantity limits the reception to that quantity.
- Recording the reception of 3 units creates
RETURNmovements of +3 (BO-34) and a credit note, and moves the return toREFUNDED, with no manual stock action (ORD-13). - A line marked defective is credited but not restocked.
- An after-sales claim resolved as
RETURNin BO-56 creates a return here, linked to the ticket.
Catalog and stock
Page specs BO-27 to BO-37 and BO-71: products, the product editor with the three customer-type prices and attributes, brands, categories, the price grid, the import wizard, stock pages and attribute definitions.
Finance
Page specs BO-44 to BO-48: invoices and credit notes, payments and declarations, credit accounts, and the V2 overdue-reminders and accounting-export pages.