Shop It Docs
Developer Resourcespromotion

Promotion Module Backend Documentation

Promotion schema, digital eligibility constraints, runtime contracts, and file ownership map.

Promotion Module - Backend Documentation

1. Digital Eligibility Model

Promotion eligibility is aligned to the digital-only commerce contract.

  • cartTypeEligibility: digital
  • paymentMethodEligibility: online
  • no COD-specific branch

cart_type_eligibility and payment_method_eligibility remain enums to preserve stable schema contracts for future controlled expansion.

2. Schema Overview

Primary schema files:

  • packages/db/src/schema/promotion/enums.ts
  • packages/db/src/schema/promotion/promotion.ts
  • packages/db/src/schema/promotion/promotion-scope.ts
  • packages/db/src/schema/promotion/promotion-usage.ts

Core invariants:

  • promotion_usage_target_check: num_nonnulls(cart_id, order_id) >= 1
  • promotion_scope_target_check: num_nonnulls(product_id, category_id, tag_id) = 1
  • promotion_discount_value_non_negative: discount_value >= 0
  • promotion_max_discount_cap_non_negative: max_discount_cap IS NULL OR max_discount_cap >= 0
  • promotion_min_cart_value_non_negative: min_cart_value IS NULL OR min_cart_value >= 0

3. Core Backend Responsibilities

  • create/update/disable/delete promotions (admin)
  • customer coupon validate/apply/remove
  • customer active-promotion browsing and usage-history retrieval
  • scope-based applicability checks by product/category/tag
  • usage-limit enforcement with stable code normalization

4. API Routes

Admin routes (/api/admin/promotions):

  • GET /
  • GET /:id
  • POST /
  • PATCH /:id
  • DELETE /:id
  • POST /:id/disable

Customer routes (/api/promotions):

  • POST /apply
  • POST /remove
  • GET /
  • GET /my-usage

Mobile equivalents are composed under /api/mobile/promotions/....

5. Cache Keyspaces

SurfacePrefix
Admin listpromotions:admin:list:
Admin detailpromotions:admin:detail:
Customer listpromotions:customer:list:
Promotion by codepromotions:code:

All keys use deterministic segments and admin writes invalidate affected prefixes.

6. Idempotency & Integrity

  • create path uses conflict-safe code uniqueness handling
  • coupon usage writes remain transactionally consistent with cart coupon updates
  • input code normalization is deterministic (trim + uppercase)
  • invalid legacy usage rows are remediated or rejected before strict checks are enforced

7. Integration Notes

  • customer promotion operations are tightly integrated with cart totals and applied-coupon fields
  • promotion scope lookups integrate with catalog entities (product/category/tag)
  • removed physical/COD behavior must not be reintroduced without schema and API contract changes

8. Runtime Configuration

Admin rate limit:

  • PROMOTION_ADMIN_RATE_LIMIT (default 120)
  • PROMOTION_ADMIN_RATE_WINDOW_SECONDS (default 60)

Customer operation rate limit:

  • PROMOTION_CUSTOMER_OPERATION_RATE_LIMIT (default 60)
  • PROMOTION_CUSTOMER_RATE_WINDOW_SECONDS (default 60)

Cache TTL:

  • PROMOTION_ADMIN_CACHE_TTL_SECONDS (default 120)
  • PROMOTION_CUSTOMER_CACHE_TTL_SECONDS (default 120)

9. Error Handling

HTTPerrorCodeMessage
400PROMOTION_USAGE_CONFLICTCannot extend end date for promotions that already have usage.
400PROMOTION_USAGE_CONFLICTCannot change code for promotions that already have usage.
400PROMOTION_USAGE_CONFLICTCannot delete promotion with usage history.
400PROMOTION_INVALID_DATE_RANGEInvalid startDate or endDate.
400PROMOTION_INVALID_DATE_RANGEendDate must be after startDate.
400PROMOTION_DISCOUNT_INVALIDdiscountValue must be greater than zero.
400PROMOTION_DISCOUNT_INVALIDmaxDiscountCap must be greater than or equal to discountValue for percentage discounts.
400PROMOTION_SCOPE_INVALIDOne or more scoped IDs are invalid.
400PROMOTION_NOT_APPLICABLECoupon not applicable to cart/product context.
404PROMOTION_NOT_FOUNDPromotion not found.
409PROMOTION_CODE_EXISTSPromotion code already exists.
429RATE_LIMIT_EXCEEDEDToo many requests. Please try again later.

10. Backend Diagram

11. Module Composition

  • PromotionModule - shared module
    • imports: ConfigModule, DatabaseModule, RedisModule
  • PromotionAdminModule - admin leaf
    • controller: PromotionAdminController
    • service: PromotionAdminService
  • PromotionCustomerModule - customer leaf
    • controller: PromotionCustomerController
    • service: PromotionCustomerService

12. File Map

  • apps/api/src/modules/promotion/admin/*
  • apps/api/src/modules/promotion/customer/*
  • apps/api/src/modules/promotion/__tests__/*
  • packages/db/src/schema/promotion/enums.ts
  • packages/db/src/schema/promotion/promotion.ts
  • packages/db/src/schema/promotion/promotion-scope.ts
  • packages/db/src/schema/promotion/promotion-usage.ts

13. Environment Variables

VariableDefaultDescription
PROMOTION_ADMIN_RATE_LIMIT120Rate limit for admin promotion operations
PROMOTION_ADMIN_RATE_WINDOW_SECONDS60Rate limit window for admin operations
PROMOTION_CUSTOMER_OPERATION_RATE_LIMIT60Rate limit for customer promotion operations
PROMOTION_CUSTOMER_RATE_WINDOW_SECONDS60Rate limit window for customer operations
PROMOTION_ADMIN_CACHE_TTL_SECONDS120Cache TTL for admin promotion views
PROMOTION_CUSTOMER_CACHE_TTL_SECONDS120Cache TTL for customer promotion views

Time fields in this module are stored as timezone-aware values and should be handled as ISO-8601 instants by API consumers.


See Also