Stage M7
This commit is contained in:
@@ -158,7 +158,7 @@ sport-store/
|
||||
│
|
||||
├── docs/
|
||||
│ ├── architecture.md Boundaries, conventions, risks — read this first
|
||||
│ └── adr/ 19 decision records
|
||||
│ └── adr/ 22 decision records
|
||||
│
|
||||
├── docker-compose.yml Backing services; `--profile full` runs everything
|
||||
├── turbo.json pnpm-workspace.yaml package.json
|
||||
@@ -253,11 +253,11 @@ locale-in-path would buy nothing.
|
||||
| **M4** ✅ | Storefront catalog — listings, PDP, variant selector, filters, sort control, load-more pagination and a mobile filter sheet |
|
||||
| **M5** ✅ | Cart (Redis), guest checkout, orders with stock reservation and an admin order lifecycle |
|
||||
| **M6** ✅ | Search: PostgreSQL full-text + trigram, diacritic-folded, ranked, with type-ahead and refinable results |
|
||||
| **M7** | Promotions, coupons, reviews, CMS |
|
||||
| **M7** ◐ | Discounts end-to-end: one engine, one admin screen, stacking, windows, limits, redemptions. Reviews and CMS remain |
|
||||
| **M8** | Customer account |
|
||||
| **M9** | Payments (VNPay, MoMo, ZaloPay, COD), shipping, notifications |
|
||||
|
||||
**Recommended next step: M7 (promotions, coupons, reviews, CMS) or M9 (payments).** The store can
|
||||
**Recommended next step: M8 (customer accounts).** The store can
|
||||
now be browsed, searched, filled into a bag and checked out, and every order moves stock through a
|
||||
ledger. What it still cannot do is take money — which is the one gap between this and a shop that
|
||||
trades.
|
||||
@@ -270,9 +270,9 @@ Everything below was run, not assumed:
|
||||
|
||||
- `pnpm lint` · `pnpm typecheck` · `pnpm test` · `pnpm build` — 27/27 Turborepo tasks pass;
|
||||
`pnpm format:check` clean
|
||||
- 7 migrations, 35 tables; seed loads 36 permissions, 6 roles, 3 brands, 8 categories,
|
||||
- 10 migrations, 43 tables; seed loads 36 permissions, 6 roles, 3 brands, 8 categories,
|
||||
3 collections, 12 products, **155 variants**, 64 uploaded images and 3 dev accounts
|
||||
- **60 tests** — RBAC guards, password hashing, translation fallback, `Accept-Language`, the
|
||||
- **78 tests** — RBAC guards, password hashing, translation fallback, `Accept-Language`, the
|
||||
variant matrix planner, the HTTP client's fetch receiver and retry recursion, the inventory
|
||||
list's variant-driven projection, the two admin-schema defects that caused silent data loss, and
|
||||
order-number round-tripping
|
||||
@@ -303,6 +303,24 @@ through Chrome with the console and network panel open:
|
||||
media library upload driven from the browser (presign → PUT to MinIO → register, 400×500 PNG
|
||||
landed at 10,962 bytes with a date-partitioned UUID key); inventory adjustment from the table
|
||||
wrote a ledger entry and the storefront went `OUT_OF_STOCK` → `IN_STOCK` on the next request
|
||||
- **Discounts (M7):** an automatic promotion and a coupon stack to −150.000 ₫ on a 1.290.000 ₫
|
||||
bag; a lowercase code is accepted; a fully-claimed code is refused with a reason and the bag
|
||||
falls back to the automatic offer; a two-use limit allows exactly two orders; cancelling an
|
||||
order returns its use; two simultaneous redemptions of the last use produce one discounted
|
||||
order and one clear refusal; a bogus code reports once and is not remembered
|
||||
- **The discount admin (M7):** a promotion authored at 09:00 local stores as 02:00Z and reopens
|
||||
at 09:00, not shifted; a discount scheduled for next week reads "Scheduled" and stays out of
|
||||
the bag; switching one off in admin drops it from a shopper's bag on the next load; retiring
|
||||
one soft-deletes it, leaving redemptions and the audit trail intact
|
||||
- **Content (M7):** a post published in one language still lists on the other locale's journal
|
||||
rather than vanishing; a body containing `<script>` and `<img onerror>` renders as visible text
|
||||
and executes nothing; a Markdown link to `/men` keeps its locale prefix; a published page
|
||||
appears in the footer; a draft is not reachable from the storefront
|
||||
- **Reviews (M7):** a review can only be written against a line on an order whose email matches,
|
||||
and a wrong email 404s exactly like an unknown order; the same item cannot be reviewed twice;
|
||||
a submitted review stays invisible until approved; approving updates the product's rating
|
||||
immediately rather than after the cache expires; rejecting an approved review takes its stars
|
||||
back out; a rejected review never reaches the storefront
|
||||
- **Checkout is idempotent:** a request without an `Idempotency-Key` is refused; the same key
|
||||
twice returns the _same_ order rather than a second one; two simultaneous requests with one key
|
||||
yield one order and one clear refusal — total order count grows by exactly one in every case
|
||||
|
||||
Reference in New Issue
Block a user