Promotions

Create discounts and coupon codes. Apply percentage or fixed-amount promotions to orders with configurable limits and validity periods.

Promotion Model

class Promotion {
  id: string;                      // Unique UUID identifier
  name: string;                    // Promotion name (e.g. "Summer Sale")
  description: string | null;      // Optional description
  discountType: DiscountType;      // Type of discount
  discountValue: number;           // Discount amount (percentage or cents)
  minOrderAmount: number | null;   // Minimum order total in cents (optional)
  maxDiscountAmount: number | null; // Maximum discount cap in cents (optional)
  validFrom: Date;                 // Start date
  validTo: Date;                   // End date
  isActive: boolean;               // Active status (default: true)
}

enum DiscountType {
  PERCENTAGE    // Percentage off (e.g. 10 = 10%)
  FIXED_AMOUNT  // Fixed amount off in cents (e.g. 500 = $5.00)
}

Coupon Model

class Coupon {
  id: string;              // Unique UUID identifier
  code: string;            // Unique coupon code (e.g. "SAVE10")
  promotionId: string;     // Associated promotion ID
  maxUses: number | null;  // Maximum number of uses (null = unlimited)
  currentUses: number;     // Current number of times used (default: 0)
  isActive: boolean;       // Active status (default: true)
}

Promotion Operations

Create Promotions

Percentage discount:

import { createServices } from "commercio";

const { promotionService } = createServices();

// Create a 10% off promotion
const promo = await promotionService.createPromotion({
  name: "Summer Sale",
  description: "10% off all orders this summer",
  discountType: "PERCENTAGE",
  discountValue: 10,              // 10%
  minOrderAmount: 5000,           // Minimum $50.00 order
  maxDiscountAmount: 2000,        // Cap discount at $20.00
  validFrom: new Date("2026-06-01"),
  validTo: new Date("2026-08-31"),
});

console.log(promo.id);               // UUID
console.log(promo.name);             // "Summer Sale"
console.log(promo.discountType);     // "PERCENTAGE"
console.log(promo.discountValue);    // 10
console.log(promo.minOrderAmount);   // 5000
console.log(promo.maxDiscountAmount); // 2000
console.log(promo.isActive);         // true

Fixed amount discount:

// Create a $5 off promotion
const fixedPromo = await promotionService.createPromotion({
  name: "Welcome Discount",
  description: "$5 off your first order",
  discountType: "FIXED_AMOUNT",
  discountValue: 500,             // $5.00 in cents
  minOrderAmount: 2000,           // Minimum $20.00 order
  validFrom: new Date("2026-01-01"),
  validTo: new Date("2026-12-31"),
});

console.log(fixedPromo.discountType);  // "FIXED_AMOUNT"
console.log(fixedPromo.discountValue); // 500

Complete Example

import { createServices } from "commercio";

const { promotionService } = createServices();

// 1. Create a 10% off promotion
const summerSale = await promotionService.createPromotion({
  name: "Summer Sale 2026",
  description: "10% off orders over $50",
  discountType: "PERCENTAGE",
  discountValue: 10,
  minOrderAmount: 5000,
  maxDiscountAmount: 2000,
  validFrom: new Date("2026-06-01"),
  validTo: new Date("2026-08-31"),
});

// 2. Create a coupon code for the promotion
const coupon = await promotionService.createCoupon({
  code: "SUMMER10",
  promotionId: summerSale.id,
  maxUses: 500,
});

// 3. Customer enters coupon at checkout
const orderTotal = 12000; // $120.00

const result = await promotionService.applyCoupon("SUMMER10", {
  orderAmount: orderTotal,
});

console.log(`Order total:  $${orderTotal / 100}`);       // $120.00
console.log(`Discount:     $${result.discountAmount / 100}`); // $12.00
console.log(`Final amount: $${result.finalAmount / 100}`);    // $108.00

// 4. Check coupon usage
const used = await promotionService.getCouponByCode("SUMMER10");
console.log(`Uses: ${used.currentUses}/${used.maxUses}`); // "Uses: 1/500"

// 5. View all valid promotions
const valid = await promotionService.getValidPromotions();
console.log(`Active promotions: ${valid.length}`);

// 6. End of season: deactivate the promotion
await promotionService.deactivatePromotion(summerSale.id);

Best Practices

1. Set Maximum Discount Caps

Always set a maxDiscountAmount on percentage promotions to limit exposure on high-value orders:

// Good: Cap the discount
const promo = await promotionService.createPromotion({
  name: "Flash Sale",
  discountType: "PERCENTAGE",
  discountValue: 20,
  maxDiscountAmount: 5000, // Cap at $50 max discount
  validFrom: new Date("2026-04-01"),
  validTo: new Date("2026-04-02"),
});

2. Use Minimum Order Amounts

Require a minimum order amount to prevent abuse of discount codes:

// Require at least $25 to use the coupon
const promo = await promotionService.createPromotion({
  name: "Small Discount",
  discountType: "FIXED_AMOUNT",
  discountValue: 500,        // $5.00 off
  minOrderAmount: 2500,      // Minimum $25.00 order
  validFrom: new Date("2026-01-01"),
  validTo: new Date("2026-12-31"),
});

3. Limit Coupon Usage

Set maxUses on coupons to control how many times they can be redeemed:

// Limited-use coupon for a flash sale
const coupon = await promotionService.createCoupon({
  code: "FLASH50",
  promotionId: promo.id,
  maxUses: 50,  // First 50 customers only
});

// Check remaining uses
const current = await promotionService.getCouponByCode("FLASH50");
const remaining = current.maxUses - current.currentUses;
console.log(`${remaining} uses remaining`);

4. Use Clear Coupon Codes

Use memorable, descriptive coupon codes that customers can easily type:

// Good: Clear and descriptive
await promotionService.createCoupon({ code: "SUMMER10", ... });
await promotionService.createCoupon({ code: "WELCOME5", ... });
await promotionService.createCoupon({ code: "FREESHIP", ... });

// Avoid: Hard to remember
await promotionService.createCoupon({ code: "X7K9M2P", ... });