HOCO B2B
SRSRequirements

Stock

Global or per-warehouse stock, physical, reserved and available quantities, reservation and deduction by order status with automatic restock on cancellation and return, the movement ledger, alerts, inventories, availability-only display and overrides.

This area controls commercial availability (cahier §3, §4.1, §4.3, §8, §11, §12): how much stock HOCO has, how orders reserve and consume it, how cancellations and returns put it back, how every variation is journaled, how the stock team is alerted and counts, and what resellers may see — availability only, never a quantity (decision of 17 Oct 2026). The server's inventory module owns Warehouse, StockLevel, StockMovement, InventorySession and InventoryLine; the orders module triggers reservations and deductions through the order lifecycle. Back-office operations are on API › Stock; stock effects of order statuses on Lifecycles › Stock effects.

IDRequirementReleasePrioritySourceApps
STK-01Global stock or stock per warehouseV1MUST§4.3API · BO
STK-02Physical, reserved and available stock (available = physical − reserved) with alert thresholdsV1MUST§4.3, §8API · BO
STK-03Reservation and deduction triggered by configurable order statuses; cancellations and returns put quantities back automaticallyV1MUST§8, §12API
STK-04Every stock variation is journaled (movement ledger)V1MUST§4.3API · BO
STK-05Low-stock and out-of-stock alertsV1MUST§4.1, §4.3API · BO
STK-06Inventory sessions and adjustments with reasonsV1SHOULD§3API · BO
STK-07Resellers and guests only ever see availability (in stock / out of stock) — never quantitiesV1MUSTTeam decision (17 Oct 2026), §4.3API · RA · RW
STK-08No order validated beyond available stock unless an authorised override is recordedV1MUST§4.3API · BO
STK-09Synchronisation with the client's existing stock system (V1 import, V2 API)V2SHOULD§11API

Settings used in this area

SettingDefaultMeaning
stock.multiWarehousefalsefalse: one sellable warehouse (Dépôt principal); true: stock per warehouse (D-02).
stock.reserveOnVALIDATEDOrder status at which quantities are reserved: SUBMITTED or VALIDATED (D-22).
stock.deductOnSHIPPEDOrder status at which quantities leave physical stock: READY, SHIPPED or DELIVERED.
stock.lowThresholdDefault10Alert threshold of a variant without its own threshold.

Requirements

STK-01 — Global stock or stock per warehouse

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §4.3API · BOSRV-13 · DSH-05

Statement — The system shall keep stock per variant and per warehouse, and work either with one sellable warehouse (global stock) or with several.

Rules

  1. A Warehouse has a code (WH- + 2–10 capitals or digits), a name, a commune, an active flag, a sellable flag and a default flag; exactly one warehouse is the default. The seed creates Dépôt principal (WH-MAIN).
  2. StockLevel holds, per variant and warehouse, physical, reserved and an optional alert threshold; available = physical − reserved (STK-02). A new variant gets rows at 0 in every active warehouse.
  3. With stock.multiWarehouse = false (default) only one warehouse may be sellable (422 MULTI_WAREHOUSE_DISABLED otherwise) and the warehouse picker is hidden in the back-office. With true, reseller availability is computed over all sellable warehouses and an order is fulfilled from one warehouse chosen at confirmation (the default one unless changed).
  4. Warehouses are managed in BO-37 (stock.administer); deactivating one with physical stock, reservations or an open inventory session, or removing the only default, answers 409 RESOURCE_IN_USE.
  5. Transfers between warehouses (TRANSFER_OUT / TRANSFER_IN) exist in the ledger but have no V1 operation; they come with multi-warehouse use if HOCO needs it.

Acceptance criteria

  • After the seed, BO-33 shows one warehouse and no warehouse picker.
  • Making a second warehouse sellable with stock.multiWarehouse = false returns 422 MULTI_WAREHOUSE_DISABLED.
  • With two sellable warehouses holding 4 and 6 available units of a variant, the reseller sees En stock and an order of 8 is fulfilled from the warehouse chosen at confirmation (stock control per that warehouse).
  • Deactivating a warehouse that still holds stock returns 409 RESOURCE_IN_USE.

Data — Warehouse, StockLevel.

Interfaces

Notes / open points — One depot or several is D-02 (default: one).

STK-02 — Physical, reserved and available stock with alert thresholds

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §4.3, §8API · BOSRV-13 · DSH-05 · DES-17

Statement — The system shall track physical, reserved and available stock (available = physical − reserved) for every variant and warehouse, and classify each level against an alert threshold.

Rules

  1. physical is what is on the shelf; reserved is what confirmed orders hold before deduction (STK-03); available = physical − reserved is what can still be sold. Every control — cart, checkout, confirmation — uses available (cahier §8).
  2. Alert level per level: OUT when available ≤ 0, LOW when 0 < available ≤ threshold, OK above. The threshold is the level's own value, else the variant's, else stock.lowThresholdDefault. Thresholds are set in bulk (admin.stock.thresholds, at most 1 000 pairs per call, stock.update); they move no stock.
  3. Available may become negative only through an authorised over-stock confirmation (STK-08) or an inventory count below reservations; BO-33 then lists the shortage and the orders to arbitrate. Physical never becomes negative through an adjustment (422 STOCK_BELOW_RESERVED when a manual adjustment would put physical under reserved).
  4. BO-33 shows per variant and warehouse: physical, reserved, available, threshold, alert level and — with pricing.view — stock value at purchase price; filters by brand, category, alert level and warehouse.
  5. These quantities are back-office data only (STK-07).

Acceptance criteria

  • With physical 100 and 20 reserved, BO-33 shows available 80; confirming an order of 30 shows reserved 50 and available 50.
  • With threshold 10, available 8 shows LOW; available 0 shows OUT.
  • An adjustment to physical 40 while 50 are reserved returns 422 STOCK_BELOW_RESERVED.
  • A stock manager without pricing.view sees no stock value column.

Data — StockLevel, ProductVariant (default threshold), Warehouse.

Interfaces

STK-03 — Reservation and deduction by order status; automatic restock on cancellation and return

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §8, §12APISRV-13 · SRV-16 · SRV-20 · DSH-13

Statement — The system shall reserve stock when an order reaches the configured reservation status, deduct it when the order reaches the configured deduction status, and put quantities back automatically when an order is refused, cancelled, expired or returned.

Rules

  1. Defaults: reserve at VALIDATED — the back-office confirmation (ORD-14) — and deduct at SHIPPED. stock.reserveOn accepts SUBMITTED or VALIDATED; stock.deductOn accepts READY, SHIPPED or DELIVERED, always later than the reservation.

  2. Crossing rule: a movement happens when an order reaches or passes its status, exactly once — a pickup order going from READY to DELIVERED still gets its deduction.

  3. Movements (each one a StockMovement with the order as reference, in the transaction of the order change):

    EventMovementEffect
    Order reaches reserveOnRESERVATION per linereserved + q
    Line modified on a reserved orderRESERVATION or RESERVATION_RELEASE for the differencereserved ± Δ
    Order reaches deductOnSHIPMENT per linephysical − q, reserved − q (the reservation is consumed)
    Order refused, cancelled or assisted order expired, before deductionRESERVATION_RELEASE for what is reservedreserved − q
    Order cancelled after a deduction (possible only with deductOn = READY)RETURN for what was deductedphysical + q
    Order refused at the door (SHIPPED → RETURNED)a return in transit is created; its reception posts RETURNphysical + accepted q
    Return reception (ORD-13)RETURN per item for the restockable quantityphysical + restockQty
  4. Automatic means automatic: nobody re-enters stock by hand after a cancellation or a return; defective or damaged returned units are recorded on the return but not re-entered as sellable stock.

  5. Concurrency: a reservation runs under a row lock on the StockLevel (or an atomic conditional update) so two confirmations cannot both take the last units; the loser gets 422 STOCK_INSUFFICIENT unless an override is recorded (STK-08).

  6. Changing stock.reserveOn or stock.deductOn applies to orders that reach a status after the change; existing reservations and deductions are not replayed.

  7. Every crossing of the zero line recomputes product availability and status (OUT_OF_STOCK ↔ ACTIVE, CAT-04) and the alert level (STK-05).

Example with the defaults — HOCO X89 câble USB-C, physical 100, reserved 20, available 80. An order of 30 is confirmed → reserved 50, available 50. It ships → physical 70, reserved 20, available 50. Had it been cancelled while READY → reserved 20, available 80. If 10 cables come back later and 8 are accepted as sellable at reception → physical 78, available 58.

Acceptance criteria

  • With the defaults, cart.checkout creates no stock movement; admin.orders.validate creates one RESERVATION per line.
  • Moving the order to SHIPPED creates SHIPMENT movements and lowers physical and reserved by the line quantities.
  • Cancelling a READY order releases its reservations in the same transaction, with no manual step; the movements reference the order number.
  • Receiving a return with 8 sellable units out of 10 creates one RETURN movement of +8; the 2 damaged units do not change stock.
  • Two users confirming two orders for the last 5 units at the same second: one succeeds, the other gets 422 STOCK_INSUFFICIENT.
  • With stock.reserveOn = SUBMITTED, checkout reserves and a refusal releases.

Data — StockLevel, StockMovement, Order, OrderItem, ReturnRequest, ReturnItem.

Interfaces

Notes / open points — Reservation and deduction statuses are D-22 (default: reserve at confirmation, deduct at shipping).

STK-04 — Movement ledger

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §4.3API · BOSRV-13 · DSH-05

Statement — The system shall record every variation of physical or reserved stock as an immutable movement, so that every stock level can be explained by its history.

Rules

  1. A StockMovement has: time, type (StockMovementType), variant, warehouse, signed physical change, signed reserved change, the physical, reserved and available quantities after the movement, a reference (order, receipt, adjustment, inventory, return or import, with its number), a reason when required, the unit cost for receipts (visible with pricing.view), the actor (or system) and the client app.
  2. A StockLevel is never written without its movement, in the same transaction; movements are append-only — a correction is a new movement.
  3. Manual movements: goods receipts (admin.stock.receipt, stock.create: warehouse, lines, supplier reference, reception date, optional unit cost) → RECEIPT; adjustments (admin.stock.adjust, stock.update, reason 3–500 characters required) → ADJUSTMENT; inventory validation → INVENTORY (STK-06). Every other movement is posted automatically (STK-03).
  4. A nightly check compares every level with the sum of its movements and alerts the stock manager on any drift.
  5. The journal (BO-34, admin.stock.movements) filters by variant, product, warehouse, type, date range, actor and reference number, and shows each row's balances after the movement.
ValueUI label (fr)Meaning
RECEIPTRéception
ADJUSTMENTAjustement
INVENTORYInventaire
RESERVATIONRéservation
RESERVATION_RELEASELibération de réservation
SHIPMENTSortie (expédition)
RETURNRetour
TRANSFER_OUTTransfert sortant
TRANSFER_INTransfert entrant

Acceptance criteria

  • After a receipt of 200 X14 cables with supplier reference FRN-8812, BO-34 shows one RECEIPT of +200 with physical after, the actor and the reference.
  • An adjustment without reason returns 422 REASON_REQUIRED.
  • Filtering BO-34 on CMD-2026-000158 shows its reservation, shipment and any release.
  • The nightly check reports no drift on a database where levels equal the sum of movements, and raises an alert after a level is altered directly in the database.

Data — StockMovement, StockLevel, AuditLog.

Interfaces

STK-05 — Low-stock and out-of-stock alerts

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §4.1, §4.3API · BOSRV-13 · DSH-05

Statement — The system shall alert the stock team when a variant's available stock falls to or under its threshold and when it runs out, and show the alerts on the stock dashboard.

Rules

  1. An alert is raised when a level's alert level changes to LOW or OUT, and cleared when it goes back to OK; staying LOW raises nothing new, so a variant never alerts twice for the same state.
  2. Channels: live event stock.alert to back-office users holding stock.view (BO-07, BO-33 badges); in-app notifications stock.low and stock.out to stock managers; a daily e-mail digest of current alerts (notifications matrix).
  3. BO-07 (stock dashboard) and the general dashboard (ANA-01) show the counts of LOW and OUT variants and the shortages created by overrides; BO-33 filters by alert level.
  4. Out-of-stock also changes what resellers see — En rupture — and may set the product OUT_OF_STOCK (CAT-04); it never sends anything to resellers by itself.

Acceptance criteria

  • When a confirmation brings a variant from 12 to 8 available with threshold 10, stock managers get one stock.low notification and BO-33 shows it under Stock faible; a further confirmation to 5 raises nothing new.
  • At 0 available, stock.out is raised and the product shows En rupture to resellers.
  • A receipt bringing it back above 10 clears the alert from the dashboard.

Data — StockLevel (alert level), Notification, OutboxEvent.

Interfaces

STK-06 — Inventory sessions and adjustments with reasons

ReleasePrioritySourceAppsOwner tasks
V1SHOULDcahier §3API · BOSRV-13 · DSH-05

Statement — The system should let the stock team count stock in inventory sessions, review the differences and post them as journaled corrections, and adjust stock outside inventories with a reason.

Rules

  1. A session (InventorySession) targets one warehouse with a scope: all variants, some categories or brands, or a list of variants. Two OPEN or IN_REVIEW sessions of a warehouse cannot overlap (409 INVENTORY_SESSION_CONFLICT); a variant in an open session cannot be adjusted outside it (same code).
  2. Counting (OPEN): counters enter quantities per variant or by barcode scan (InventoryLine); a variant outside the scope answers 422 VARIANT_NOT_IN_SCOPE. Orders keep shipping during the count.
  3. Review (IN_REVIEW): each line shows expected, counted and difference, where the difference is computed as counted − (expected at opening + movements since opening), so shipments during the count are not counted twice. Recounts need a reason.
  4. Validation (admin.inventory.validate, stock.validate): posts one INVENTORY movement per non-zero difference, all or nothing; uncounted lines are either rejected (422 INVENTORY_LINES_INCOMPLETE) or treated as unchanged, as chosen at validation. VALIDATED and CANCELLED are final (409 INVENTORY_TRANSITION_NOT_ALLOWED); a wrong count is corrected by a new session. A count below reservations is accepted and shown as a shortage.
  5. Adjustments outside sessions follow STK-04 R3 (reason required, free text in V1).
  6. Validation recomputes alert levels and product statuses and is journaled (VALIDATE) with a summary of differences.

Acceptance criteria

  • A session opened with 166 expected, 6 shipped during the count and 157 counted posts an INVENTORY movement of −3 at validation (physical 157).
  • Opening a second session on the same warehouse and category returns 409 INVENTORY_SESSION_CONFLICT.
  • Validating with 4 uncounted lines and the reject option returns 422 INVENTORY_LINES_INCOMPLETE with uncounted: 4.
  • A stock manager without stock.validate cannot validate (403 PERMISSION_DENIED).

Data — InventorySession, InventoryLine, StockMovement, StockLevel, AuditLog.

Interfaces

STK-07 — Availability only for resellers and guests

ReleasePrioritySourceAppsOwner tasks
V1MUSTTeam decision (17 Oct 2026), §4.3API · RA · RWSRV-13 · MRA-02

Statement — The system shall show resellers, guests and delegates only whether a product is available — En stock or En rupture — and never a stock quantity, a threshold or a remaining-units hint.

Rules

  1. A variant is IN_STOCK when its available stock over the sellable warehouses is above 0, otherwise OUT_OF_STOCK (StockAvailability); a product is OUT_OF_STOCK only when every visible variant is.
  2. No reseller-, guest- or delegate-facing response carries physical, reserved, available, a threshold or availableQty; the « Plus que N pièces » hint of the reference mock-up is not implemented; there is no stock display setting.
  3. When a requested quantity exceeds what is available, the cart refuses it with 422 STOCK_INSUFFICIENT (details.availability only) and never suggests the available quantity, which would reveal it (ORD-02).
  4. Availability is recomputed on every read (no cross-caller cache) and filters on it (availability=IN_STOCK) are available to everyone (CAT-12).
  5. Exact quantities exist only in the back-office, for users holding stock.view.
ValueUI label (fr)Meaning
IN_STOCKEn stockAvailable quantity greater than 0.
OUT_OF_STOCKEn ruptureAvailable quantity is 0.

Acceptance criteria

  • catalog.products.get, cart.get, delegate.assisted.update and catalog.facets responses contain no stock number (contract test on every reseller and delegate schema).
  • With 3 units available, adding 5 to the cart returns 422 STOCK_INSUFFICIENT whose body contains no 3.
  • A product with one variant in stock and one out of stock shows En stock on its card and En rupture on the out-of-stock variant.

Data — StockLevel (read), ProductVariant.

Interfaces

STK-08 — No confirmation beyond available stock without an authorised override

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §4.3API · BOSRV-13 · SRV-16 · DSH-06

Statement — The system shall refuse to confirm an order whose lines exceed available stock unless a user holding stock.validate records an explicit override with a reason.

Rules

  1. The stock control of an order compares each line with available stock (excluding the order's own reservation) in its fulfilment warehouse; it is re-run on every read of an order waiting for confirmation and inside the confirmation transaction (ORD-05).
  2. admin.orders.validate on an order with an insufficient line answers 422 STOCK_INSUFFICIENT with the lines (requested, available, short by) unless the request carries override.stock = true and a reason (3–500 characters, 422 REASON_REQUIRED otherwise) and the caller holds stock.validate (403 PERMISSION_DENIED with details.required otherwise).
  3. With an override the reservation is made anyway: available becomes negative, a stock.alert follows and the shortage appears on the stock dashboard until goods arrive.
  4. The override is stored on the order (kind STOCK, reason, user, time) and journaled as an OVERRIDE entry next to the VALIDATE entry (AUD-01).
  5. The alternative to an override is a controlled modification of the order (reduce the line — ORD-05) or a refusal.

Acceptance criteria

  • Confirming an order of 10 units with 6 available returns 422 STOCK_INSUFFICIENT with shortBy: 4.
  • The same confirmation by a commercial administrator without stock.validate and override.stock = true returns 403 PERMISSION_DENIED.
  • A stock manager confirming with override.stock = true and a reason succeeds; reserved rises by 10, available shows −4 in BO-33 and the activity log has an OVERRIDE entry with the reason.

Data — Order (controls, overrides), StockLevel, StockMovement, AuditLog.

Interfaces

STK-09 — Synchronisation with HOCO's stock system

ReleasePrioritySourceAppsOwner tasks
V2SHOULDcahier §11APISRV-37

Statement — The system should synchronise stock with HOCO's existing stock system — by file import in V1 and by API in V2.

Rules

  1. V1: stock levels are loaded and corrected through the stock import of ADM-06 — mode SET (posts ADJUSTMENT movements to reach the file's quantity) or ADD (posts RECEIPT movements) — with a dry run and a report.
  2. V2: an API synchronisation agreed with HOCO's system — which side is master of physical stock, how often, how conflicts are resolved; reservations always stay in the HOCO platform.
  3. Every synchronised change is a journaled movement with reference IMPORT (or the V2 integration), never a direct write.

Acceptance criteria

  • A V1 stock file setting X14 to 250 in SET mode posts the movement that brings physical to 250 and shows it in BO-34 with reference IMPORT.

Data — ImportJob, StockMovement, StockLevel.

Interfaces

  • Screens: none dedicated
  • API: no dedicated operation

Notes / open points — Which system is master at go-live is D-34. V2 work is SRV-37.

Error codes

CodeHTTPRaised when
STOCK_INSUFFICIENT422A cart line, checkout or confirmation exceeds available stock (no quantity in the body for resellers)
STOCK_BELOW_RESERVED422A manual adjustment would put physical under reserved
REASON_REQUIRED422Adjustment, recount or override without reason
MULTI_WAREHOUSE_DISABLED422A second sellable warehouse while stock.multiWarehouse = false
WAREHOUSE_INACTIVE422Receipt, adjustment or inventory on an inactive warehouse
VARIANT_NOT_IN_SCOPE · INVENTORY_LINES_INCOMPLETE422Counting outside the session scope; validating with uncounted lines
INVENTORY_SESSION_CONFLICT · INVENTORY_TRANSITION_NOT_ALLOWED409Overlapping sessions; move not allowed
RESOURCE_IN_USE409Deactivating a warehouse in use
PERMISSION_DENIED403Override without stock.validate, validation without stock.validate

On this page