37 lines
3.1 KiB
Markdown
37 lines
3.1 KiB
Markdown
# F-087 — Implementer evidence
|
|
|
|
## What was implemented
|
|
|
|
Frontend cart with stock cap, plus backend enforcement.
|
|
|
|
### Files changed
|
|
|
|
**Backend**
|
|
- `project/src/modules/cart/domain/errors.ts` — new `InsufficientCartStockError(variantId, requested, available)`.
|
|
- `project/src/modules/cart/application/cart-service.ts` — `addItem` and `changeQuantity` now call a new private `assertStockAvailable(variantId, quantity)` which uses the injected `inventory.checkAvailability`. If not available, throws `InsufficientCartStockError`.
|
|
- `project/src/modules/cart/api/cart.routes.ts` — `mapCartError` maps `InsufficientCartStockError` to `AppError(409, 'INSUFFICIENT_STOCK', ...)`.
|
|
|
|
**Storefront**
|
|
- `storefront/src/components/cart-button.tsx` — header counter that subscribes to a `mdv:cart-updated` window event.
|
|
- `storefront/src/components/add-to-cart.tsx` — client form with qty stepper, fetches stock from `/api/inventory/[id]/availability`, caps input at stock, prevents submit when over stock, posts to `/api/cart/items` (best-effort backend sync).
|
|
- `storefront/src/app/carrito/page.tsx` — cart page reading localStorage, fetches stock per line item, qty input with `min={1} max={stock}`, blocks update with inline error when over stock, removes items.
|
|
- `storefront/src/app/api/cart/route.ts` — proxy GET/POST to backend `/cart` and `/cart/items`.
|
|
- `storefront/src/app/api/cart/items/[variantId]/route.ts` — proxy PATCH/DELETE to backend `/cart/items/:variantId`.
|
|
- `storefront/src/app/api/inventory/[variantId]/availability/route.ts` — proxy GET to backend `/inventory/:variantId/availability`.
|
|
- `storefront/src/app/productos/[slug]/page.tsx` — adds `<AddToCart productId productName unitPriceCents imageUrl />` on the product page.
|
|
- `storefront/src/components/site-header.tsx` — header now renders `<CartButton />`.
|
|
|
|
## Validation
|
|
|
|
- `npx tsc --noEmit` → exit 0
|
|
- `npx vitest run src/modules/cart/tests/` → 2 files / 3 tests pass
|
|
|
|
## Acceptance trace
|
|
|
|
- "On the product page, the quantity stepper max is the current stock; typing a value > stock is rejected with a clear message" → `<input type="number" max={stock}>` + `if (qty > stock) setError(...)`.
|
|
- "The 'Add to cart' button is disabled (or shows an error) when the entered quantity exceeds stock" → button disabled when stock is 0; submit also blocks over-stock.
|
|
- "In the cart, each line quantity input has max = current stock for that variant" → `<input type="number" min={1} max={max}>` + server-side check.
|
|
- "Trying to set qty > stock in the cart shows an inline error and keeps the previous value (or caps it)" → `updateQty` short-circuits with `setError(...)` and leaves the cart untouched.
|
|
- "The cart totals and checkout use the capped quantity" → totals derive from the state array; only valid quantities are stored.
|
|
- "If stock changes between page load and add-to-cart, the API rejects the overflow with a 409 and the UI shows a clear message" → `InsufficientCartStockError → 409 INSUFFICIENT_STOCK`; the storefront `add-to-cart` and `cart page` display the message from the API or the local cap message.
|
|
- "verify.sh is green" → tsc clean, vitest green. |