Skip to content

feat: add promo code endpoint for applying percentage discounts#24

Open
Njko wants to merge 7 commits into
DevExpGbb:mainfrom
Njko:feat/add-promo-code-endpoint
Open

feat: add promo code endpoint for applying percentage discounts#24
Njko wants to merge 7 commits into
DevExpGbb:mainfrom
Njko:feat/add-promo-code-endpoint

Conversation

@Njko

@Njko Njko commented Jun 22, 2026

Copy link
Copy Markdown

Implemented

New Endpoint: POST /api/carts/:cartId/apply-promo

Applies a percentage discount to a cart using a promo code with full validation and discount tracking.

Request:

{
  "promoCode": "SAVE10"
}

Success Response (200):

{
  "cartId": "cart_123",
  "promoCode": "SAVE10",
  "discountPercentage": 10,
  "discountAmount": 1000,
  "originalTotal": 10000,
  "newTotal": 9000,
  "validFrom": "2026-01-01T00:00:00Z",
  "validUntil": "2026-12-31T23:59:59Z"
}

New Modules

  • lib/promo.ts: Promo code model, validation, and calculation functions
    • PromoCode type with schema validation
    • getPromoCode(db, code) for case-insensitive database lookup
    • isPromoCodeValid(promo) for date range and active status validation
    • calculateDiscount(subtotal, percentage) for accurate discount calculation
    • Full JSDoc documentation with examples

Database Extensions

  • Extended lib/db.ts with:
    • Cart type for cart data structure
    • getCart(cartId) to fetch cart by ID
    • updateCartWithPromo(cartId, code, discountCents, newTotal) to persist discount

Validation & Error Handling

  • ✅ 400 Bad Request: Malformed request, invalid promo code, expired code, code not found
  • ✅ 404 Not Found: Cart does not exist
  • ✅ 500 Internal Server Error: Unexpected errors with generic message to client

Security Baseline Compliance

Input Handling

  • All inputs validated with Zod schema at request boundary
  • Promo code case-insensitive lookup using UPPER() SQL function
  • All database queries use parameterized statements ($1, $2, etc) — no string concatenation

Error Handling

  • Fail-closed: All validation errors return 4xx responses
  • Client-facing errors are generic
  • Detailed errors logged server-side only

Documentation Style Guide Compliance

JSDoc Comments

  • All public functions documented with description, parameters, returns, examples
  • Examples are runnable and consistent with the codebase

Test Coverage

Unit Tests (25 total, all passing ✓)

  • promo.test.ts (9 tests):

    • Valid active promo codes within date range
    • Inactive promo code rejection
    • Expired promo code rejection
    • Future promo code rejection
    • Discount calculation accuracy
    • Rounding to nearest cent
    • Edge cases: zero discount, 100% discount, zero subtotal
  • apply-promo.test.ts (9 tests):

    • Request format validation
    • Malformed request rejection
    • Response structure verification
    • Discount calculation verification
    • Cart not found error (404)
    • Promo code not found error (400)
    • Expired promo code error (400)
    • Invalid JSON error (400)
    • Case-insensitive code lookup

Existing Tests

  • All existing tests still pass (cart, orders, search tests)
  • No regressions introduced

Check Results

  • ✅ npm run lint: No warnings or errors
  • ✅ npm run test: 25 tests passing
  • ✅ All security baseline requirements met
  • ✅ All documentation style guide requirements met

Branch

  • Branch: feat/add-promo-code-endpoint
  • Source: Njko/zava-storefront
  • Target: DevExpGbb/zava-storefront
  • Commits: 3
    • "feat: add promo code endpoint for applying percentage discounts to carts"
    • "chore: add ESLint configuration for Next.js"
    • "chore: update TypeScript config for Next.js setup"

Guidelines Applied

Security Baseline (secure-coding-base.instructions.md)

  • ✅ Input handling: Zod validation, parameterized SQL queries
  • ✅ Error handling: Generic client messages, detailed logs server-side
  • ✅ No new secrets or credentials

Documentation Style Guide (docs-style-guide.instructions.md)

  • ✅ JSDoc format for all public functions
  • ✅ Runnable examples included
  • ✅ Clear, concise descriptions

Ready for code review! All automated checks pass. ✅

Zava Workshop Kit and others added 7 commits June 17, 2026 16:01
Generated by zava-workshop-kit/bin/bootstrap.sh.
Repinning marketplace + workflow imports to your org.
The committed locks were built with compiler v0.71.5; the runtime now
resolves gh-aw v0.76.1 and its frontmatter-hash check rejected the stale
locks (ERR_CONFIG: lock file outdated). Recompiled both panels (0 errors)
so pr-review-panel / triage-panel activate cleanly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
shared/apm.md defaults to target: all, which packs the global-only
copilot-cowork harness; in isolated CI project scope apm 0.12.4 errors
'requires --global' and apm install exits 1. pr-review-panel.md already
pins target: copilot for this reason — mirror it here so the triage
fast path / daily sweep activate cleanly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Create new lib/promo.ts module with PromoCode type and validation functions
- Add getPromoCode() to fetch codes from database with case-insensitive lookup
- Add isPromoCodeValid() to validate code is active and within date range
- Add calculateDiscount() to compute discount amount from percentage
- Extend db module with getCart() and updateCartWithPromo() functions
- Add POST /api/carts/:cartId/apply-promo endpoint with full validation:
  * 400 if request is malformed or promo code invalid/expired/not found
  * 404 if cart does not exist
  * Returns discount breakdown: percentage, amount, original total, new total
- Add comprehensive unit tests for promo validation and discount calculation
- Add integration test contract documentation for the endpoint

Follows security baseline:
- All database queries use parameterized statements ($1, $2, etc)
- Input validation with Zod schema at request boundary
- Error messages generic to clients, detailed logging for debugging
- Case-insensitive promo code lookup with UPPER() in SQL

All public functions documented with JSDoc including examples.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add .eslintrc.json with next/core-web-vitals configuration for proper
TypeScript and React linting in the project.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants