Oversell race: stock is checked at invoice time but only decremented at settlement, with no refund path #10
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
build_order_with_payment(services.py:117-126) callscompute_products_new_quantitypurely as a check — it mutatesp.quantityin memory and never persists — then creates the invoice. The real decrement happens inhandle_order_paid→update_products_for_order(services.py:351-352, marked# todo: lock) viaupdate_product_quantity(crud.py:430-439), which is an unconditionalSET quantity = :quantity. Two customers ordering the last unit both get invoices; both can pay; the second settlement fails the quantity check after the sats are captured and the customer is told "Order cannot be fulfilled" (services.py:381) with no automatic refund.Fix direction: reserve at invoice creation with a guarded
UPDATE ... SET quantity = quantity - :n WHERE id = :id AND quantity >= :nand branch on rowcount; release on invoice expiry; make the settlement path idempotent. Same shape as the events-extension reservation fix.Found during reforge run #1 (sandbox nostrmarket#3).