Overview
Functional requirements in plain language — what customers and staff can do, split by role. Every entry maps to a real API endpoint; no screen invents behavior the backend does not grant.
How to read
Must = shipped and covered by real screens. Should = shipped. Planned = designed but not yet implemented.
Customer Requirements
| ID | Requirement | Status |
|---|---|---|
| FR-01 | Browse the catalog — listing with search, brand filter, sort (-created_at), pagination; category pages; product detail with ordered images (is_primary) and ACTIVE variants carrying computed final_price | Must |
| FR-02 | Pick an exact variant — color/size availability tied to inventory; gallery switches per variant; unavailable variants shown as out-of-stock | Must |
| FR-03 | Maintain a server-side cart — add variant (merge-on-duplicate), update quantity (1–999), remove line, clear cart; live Decimal pricing resolved server-side | Must |
| FR-04 | Check out in three steps — choose a saved address, optionally apply a coupon (uppercased), watch shipping rules settle; POST /orders creates the order, payment record, shipment copy, and clears the cart in one transaction | Must |
| FR-05 | View order history and order detail — status-filtered, paginated, with a timeline and immutable order_items / shipments snapshots (price, SKU, attributes, address frozen at purchase) | Must |
| FR-06 | Leave reviews — one live review per product with rating (1–5), title, comment, and images via signed ImageKit uploads; edit or delete own review; read rating summaries | Must |
| FR-07 | Register, log in, verify email (/verify-email link), resend verification, recover password via emailed link/OTP (/forgot-password wizard, POST /auth/password-reset + OTP verify) | Must |
| FR-08 | Manage account — profile names, password change (with re-login), email change (link flow), phone change (OTP), account deletion behind a confirm dialog | Must |
| FR-09 | Manage an address book — CRUD with per-type default flags; defaults promote the oldest remaining address when the current default is deleted; used at checkout | Must |
| FR-10 | Manage personal reviews and sessions — "My reviews" list with edit, and device session list with revoke-one / revoke-others | Must |
Staff Requirements
| ID | Requirement | Status |
|---|---|---|
| FR-11 | See dashboard KPIs — order/revenue stats, status pipeline quick links, revenue trend chart — with super-admin-only P&L analytics split into overview / coupons / expenses | Must |
| FR-12 | Manage the catalog — product CRUD (auto-slug -2 suffix, soft-delete with variant cascade), variant CRUD (SKU 80-char global uniqueness, status nullable), product and variant images with exactly-one-primary invariant and direct-to-ImageKit signed uploads | Must |
| FR-13 | Manage categories — CRUD with is_active visibility, idempotent product assign/unassign, transactional soft-delete | Must |
| FR-14 | Operate inventory — per-variant quantity_on_hand / quantity_reserved / reorder_level, manual adjust and manual reserve/release behind guarded endpoints | Must |
| FR-15 | Fulfill orders through a legal transition matrix — order-status-actions.tsx renders only allowed next steps; each transition carries server-side stock/payment/coupon side effects asserted by affected-row counts | Must |
| FR-16 | Moderate reviews, manage customers — user list, suspend/activate; role changes require SUPER_ADMIN; last SUPER_ADMIN is protected | Must |
| FR-17 | Manage coupons — CRUD with validity windows, global/per-user limits, max-discount caps; usage drawer shows coupon_usages per order | Must |
| FR-18 | Inspect the audit trail and admin roster — append-only audit_logs (actor, action, entity, redacted body, diff, IP/UA) and admin-account management under SUPER_ADMIN | Must |
| FR-19 | Upload images via signed ImageKit params — short-lived HMAC token/expire/signature from GET …/uploads/imagekit-auth; persisted URLs re-validated for host, folder allowlist, and extension | Must |
Behavior that matters
- Same-origin, always — every request flows through
lib/api/axios-instance.ts(baseURL = /api/v1,withCredentials: true). The Next.js rewrite is the only network hop; CORS never appears. - No phantom stock — cart quantity inputs are clamped 1–999;
409(insufficient stock) fromPOST /cart/itemsorPATCH /cart/items/{variant}surfaces inline. - Order history never lies — later catalog edits do not rewrite
order_itemsorshipments; the detail screen reads frozen values. - Every admin mutation is visible —
audit_logsrecords who did what, with redacted bodies and diffs; the Audit viewer issuper_adminonly.
Out of scope (current version)
- Real payment gateway — checkout stays on
mock(Paymob tracked asT19/T-081…T-087, markedwon't dosince 2026-08-25). - Loyalty, wishlist, recommendations.
- Review purchase-verification — implemented behind
REVIEWS_REQUIRE_PURCHASEon the API, currently off. - Client-side E2E suite —
vitestunit harness +axios-mock-adapteronly today.
Why it matters
Every gap is a documented decision with a task number — not an undocumented surprise.