feat(ADM-018): completed feature
This commit is contained in:
31
work/artifacts/F-019/architect.md
Normal file
31
work/artifacts/F-019/architect.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Architect — F-019 Promotions v1
|
||||
|
||||
## Feature
|
||||
F-019 adds server-side promo code validation and discount calculation. Discounts are recalculated from current cart totals and never trusted from the client.
|
||||
|
||||
## Design
|
||||
|
||||
### Module boundaries
|
||||
Create `project/src/modules/promotions/` with domain/application/infrastructure/api/tests. Promotions owns promo definitions and validation. Cart receives a public `PromotionServicePort` from the composition root and stores only the selected promo code, not discount amounts.
|
||||
|
||||
### Data model
|
||||
Add migration `014_promotions.js`:
|
||||
- `promotions_promotions`: code, type (`percent`, `fixed_amount`), value, validity window, usage_limit, usage_count, active, timestamps.
|
||||
- Add `promo_code text` to `cart_carts`.
|
||||
|
||||
### Rules
|
||||
- Percent discounts are basis points over current cart total.
|
||||
- Fixed amount discounts are cents and capped at current cart total.
|
||||
- Validity checks: active, starts_at <= now, ends_at >= now, usage_count < usage_limit when limit exists.
|
||||
- No stacking in v1: one promo code per cart.
|
||||
- Client discount fields are stripped/ignored by cart schemas.
|
||||
|
||||
### API
|
||||
- Admin `POST /promotions` creates promo codes.
|
||||
- Public/authenticated cart endpoint `POST /cart/promo-code` stores a code after server validation.
|
||||
- `GET /cart` recalculates discount through `PromotionService`.
|
||||
|
||||
## Acceptance trace
|
||||
- Valid promo: cart read applies recalculated server discount.
|
||||
- Expired/exhausted: applying code returns HTTP 422 reason.
|
||||
- Client discount ignored: schemas strip discount fields and cart stores no discount amount.
|
||||
Reference in New Issue
Block a user