Wave 3 of replacing the fixed-data mock adapter: cart, orders, shipments and invoices flip together, so one purchase runs end to end against the backend. - cart: CartItemView carries the line's shop and the SKU's stock, so the cart keeps grouping per shop and the quantity stepper caps at real stock instead of a hard-coded 999 - contract: Shipment.items is optional and Invoice.invoice_no nullable, both matching what the API actually returns. Invoice was declared twice in types.ts and TypeScript merges duplicate interfaces, so the duplicate had to go for the change to take effect at all - an anonymous add-to-cart redirects to /login?redirect=..., and sign-in honours only same-origin paths - the fixed-data adapter learns the new cart fields, and its persisted state key moves to v2 because a cart saved by an older build is no longer valid - order surfaces drop their storeById lookups and keep the generic store label until the public store read arrives Verified end to end: two-shop cart grouping with live shop names, stock caps read from the API, checkout, payment, shipment, delivery confirmation and an issued invoice. Rollback re-verified with every domain on fixed data and the backend stopped. Also checks off Wave 3 in docs/TBD-migrate-wave.md and re-points that file at the mock content that remains. OpenSpec change: openspec/changes/replace-mock-api-wave-3
19 lines
1.1 KiB
Markdown
19 lines
1.1 KiB
Markdown
# Spec Delta
|
|
|
|
## MODIFIED Requirements
|
|
|
|
### Requirement: Server-side cart
|
|
Authenticated shoppers SHALL have a Redis-backed cart keyed by user id, containing sku_id + qty entries. Reading the cart SHALL return, for every line, the SKU's current price, currency and stock together with the product's name, image and owning shop, so the storefront can group lines by shop and cap quantity without reading the fixed-data catalog. Lines whose SKU has become inactive or unpurchasable SHALL be omitted from the view.
|
|
|
|
#### Scenario: add and update
|
|
- **WHEN** a shopper POSTs sku + qty, then PUTs a new qty
|
|
- **THEN** GET /api/cart reflects the latest qty with current price/name snapshot
|
|
|
|
#### Scenario: unpurchasable SKU rejected
|
|
- **WHEN** adding a SKU that is inactive or whose product is not published
|
|
- **THEN** the API returns 400
|
|
|
|
#### Scenario: cart view carries shop and stock
|
|
- **WHEN** a shopper reads a cart holding SKUs from more than one shop
|
|
- **THEN** each line reports its shop and the SKU's current stock, so the storefront can group the lines per shop and cap quantity from the response alone
|