Skip to main content

Stock rules by channel

Warehouse quantities live in WarehouseStock (backend-main/warehouse/models.py). Ecommerce reads/writes through ecommerce/services.py (backend-main/ecommerce/services.py) (get_product_stock, allocate_and_decrement_stock). POS catalog visibility uses stock filters in pos/views.py (backend-main/pos/views.py) / customer-link services, but POS order create does not decrement stock.

Summary​

ChannelWhen stock is checkedWhen stock is decremented
Ecommerce CODPre-check get_product_stock in EcommerceCheckoutView; then locked allocateSame request, before create_cod_order
Ecommerce RazorpaySnapshot records stock_items at start; no holdOn verify/webhook via _decrement_snapshot_stock
Ecommerce custom / design linesNot checkedNot decremented (quantity forced to 1)
POS order createCatalog listing requires stock to show productsNever in POSOrderCreateSerializer.create
Customer / catalog linkCatalog APIs expose stock for displayNever on step3 / catalog submit / link create

Caveats (oversell, swallowed Razorpay failures, POS divergence): Known limitations (from report.md).

Ecommerce allocation​

allocate_and_decrement_stock(product, quantity):

  1. Resolve enabled ecommerce warehouses / listings.
  2. Walk listings by warehouse_id; select_for_update on WarehouseStock.
  3. First warehouse with quantity >= requested decrements and writes StockHistoryEntry (reason='Ecommerce order').
  4. Else raises InsufficientStockError.

get_product_stock sums quantities across enabled listing warehouses (unlocked read). COD therefore does a TOCTOU-style pre-check then a locked decrement — concurrent carts can both pass the pre-check; the lock only serializes the final allocate.

COD (EcommerceCheckoutView)​

For each non-custom line: require available >= quantity, append to stock_items, then after totals:

for item in stock_items:
allocate_and_decrement_stock(...)
create_cod_order(prepared)

Failure → 400 and no order.

Razorpay​

  • Start: stock_items stored in PendingRazorpayCheckout.snapshot only; warehouses unchanged.
  • Fulfill: _decrement_snapshot_stock loops snapshot lines; missing product / InsufficientStockError → name appended to missing; order still created as verified with a system comment when missing is non-empty (backend-main/ecommerce/checkout_orders.py).

Custom lines​

In EcommerceCheckoutView, is_custom products:

  • quantity = 1 (client quantity ignored)
  • Not added to stock_items
  • No get_product_stock check
  • POS product lists filter by WarehouseStock for the POS warehouses so out-of-stock SKUs may not appear.
  • POSOrderCreateSerializer.create (backend-main/pos/serializers.py) writes POSOrder / POSOrderItem only — no WarehouseStock update.
  • Customer-link and catalog submit persist line snapshots and payment proof; they do not call allocate_and_decrement_stock.

Any warehouse correction for POS/link sales must happen via warehouse admin adjust/transfer (or future workflow hooks) — not automatic at order create.