POST /api/v1/checkout/ always converted the customer's entire
multi-store cart into orders. Add an optional store_uuids field to
CheckoutSerializer — when given, checkout() only processes those
stores' cart groups and only clears their items, leaving the rest of
the cart intact for a later checkout. Omitted, behavior is unchanged
(whole cart checks out).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
checkout() decrements stock_quantity/increments sold_count per order
item, but cancellation never reversed it, so a cancelled order's stock
stayed permanently reduced. Add _restock_order_items(), called from
_transition() on the CANCELLED transition, using F() expressions to
reverse both counters atomically; wrap _transition() itself in
@transaction.atomic so the status change and restock can't partially
apply.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Seller sets this at registration (default 60 min). Exposed on store
list/detail, the seller's own store, cart groups (GET /api/v1/cart/),
and order/order-group responses, so the checkout page's estimated
delivery time no longer needs a frontend mock.
Also document CartSerializer's groups/grand_total for swagger (were
untyped SerializerMethodFields showing as opaque strings) since that's
the endpoint carrying this new field to the checkout page.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Django 6 + DRF resource server against the Gooyal accounts OAuth2 service,
matching the Winsoo ecosystem's conventions. Covers locations, stores,
catalog, cart, checkout/orders (with the multi-store-cart split and the
status stepper), reviews, and notifications, plus a demo-data seed command.
Payment integration (wallet debits, online gateway, seller payouts) is
intentionally left out here — see feature/payment.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>