Pricing

Manage price lists, tiered pricing, and customer-group pricing. Support multiple currencies and pricing strategies for different customer segments.

PriceList Model

class PriceList {
  id: string;                    // Unique UUID identifier
  name: string;                  // Price list name (e.g. "Standard", "Wholesale")
  currency: string;              // ISO 4217 currency code (e.g. "USD", "EUR")
  customerGroupId: string | null; // Optional customer group this list applies to
  priority: number;              // Priority for resolution (higher = checked first)
  validFrom: Date | null;        // Optional start date
  validTo: Date | null;          // Optional end date
  isActive: boolean;             // Active status (default: true)
}

PriceEntry Model

class PriceEntry {
  id: string;                    // Unique UUID identifier
  priceListId: string;           // Reference to parent price list
  productId: string;             // Reference to product
  productVariantId: string | null; // Optional reference to specific variant
  strategy: "FIXED" | "TIERED"; // Pricing strategy
  unitPrice: number;             // Price in cents (used when strategy is FIXED)
  tierPrices: TierPrice[];       // Tier brackets (used when strategy is TIERED)
}

interface TierPrice {
  minQuantity: number;           // Minimum quantity for this tier
  unitPrice: number;             // Price in cents for this tier
}

Create Price List

Standard price list:

import { createPricingService } from "commercio";

const pricingService = createPricingService();

// Create a standard price list
const standardList = await pricingService.createPriceList({
  name: "Standard",
  currency: "USD",
});

console.log(standardList.id);       // UUID
console.log(standardList.name);     // "Standard"
console.log(standardList.currency); // "USD"
console.log(standardList.isActive); // true

Customer-group price list with date range:

// Create a wholesale price list for a specific customer group
const wholesaleList = await pricingService.createPriceList({
  name: "Wholesale",
  currency: "USD",
  customerGroupId: "group-123",
  priority: 10,
  validFrom: new Date("2025-01-01"),
  validTo: new Date("2025-12-31"),
});

console.log(wholesaleList.customerGroupId); // "group-123"
console.log(wholesaleList.priority);        // 10

Pricing Operations

Set Prices

Set a fixed price:

// Set a fixed price for a product in a price list
await pricingService.setPrice({
  priceListId: standardList.id,
  productId: "product-123",
  strategy: "FIXED",
  unitPrice: 1999, // $19.99 in cents
});

// Set a fixed price for a specific variant
await pricingService.setPrice({
  priceListId: standardList.id,
  productId: "product-123",
  productVariantId: "variant-456",
  strategy: "FIXED",
  unitPrice: 2499, // $24.99 in cents
});

Set tiered pricing:

// Set tiered pricing (volume discounts)
await pricingService.setTieredPrice({
  priceListId: wholesaleList.id,
  productId: "product-123",
  tierPrices: [
    { minQuantity: 1, unitPrice: 1999 },   // 1-9 units: $19.99 each
    { minQuantity: 10, unitPrice: 1799 },   // 10-49 units: $17.99 each
    { minQuantity: 50, unitPrice: 1499 },   // 50-99 units: $14.99 each
    { minQuantity: 100, unitPrice: 1199 },  // 100+ units: $11.99 each
  ],
});

Complete Example

import { createServices } from "commercio";

const { pricingService } = createServices();

// 1. Create a standard price list
const standardList = await pricingService.createPriceList({
  name: "Standard Retail",
  currency: "USD",
  priority: 1,
});

// 2. Create a wholesale price list for VIP customers
const wholesaleList = await pricingService.createPriceList({
  name: "Wholesale",
  currency: "USD",
  customerGroupId: "vip-group-id",
  priority: 10,
});

// 3. Set fixed prices in the standard list
await pricingService.setPrice({
  priceListId: standardList.id,
  productId: "product-laptop",
  strategy: "FIXED",
  unitPrice: 99900, // $999.00
});

await pricingService.setPrice({
  priceListId: standardList.id,
  productId: "product-mouse",
  strategy: "FIXED",
  unitPrice: 2999, // $29.99
});

// 4. Set tiered prices in the wholesale list
await pricingService.setTieredPrice({
  priceListId: wholesaleList.id,
  productId: "product-mouse",
  tierPrices: [
    { minQuantity: 1, unitPrice: 2499 },    // 1-24: $24.99
    { minQuantity: 25, unitPrice: 1999 },    // 25-99: $19.99
    { minQuantity: 100, unitPrice: 1499 },   // 100+: $14.99
  ],
});

// 5. Get effective price for a regular customer
const retailPrice = await pricingService.getEffectivePrice({
  productId: "product-mouse",
  quantity: 1,
});
console.log(retailPrice.unitPrice); // 2999 ($29.99)

// 6. Get effective price for a VIP customer ordering in bulk
const bulkPrice = await pricingService.getEffectivePrice({
  productId: "product-mouse",
  quantity: 50,
  customerGroupId: "vip-group-id",
});
console.log(bulkPrice.unitPrice); // 1999 ($19.99, wholesale 25-99 tier)

// 7. Get effective price for large VIP order
const largeBulkPrice = await pricingService.getEffectivePrice({
  productId: "product-mouse",
  quantity: 150,
  customerGroupId: "vip-group-id",
});
console.log(largeBulkPrice.unitPrice); // 1499 ($14.99, wholesale 100+ tier)

Best Practices

1. Always Use Cents

Store all prices in the smallest currency unit to avoid floating-point errors:

// Good: Use cents
await pricingService.setPrice({
  priceListId: listId,
  productId: productId,
  strategy: "FIXED",
  unitPrice: 1999, // $19.99
});

// Bad: Don't use decimals
// unitPrice: 19.99 // Will cause precision issues

2. Set Priority for Price Lists

Use priority to control which price list takes precedence when multiple lists match:

// Higher priority = checked first
const vipList = await pricingService.createPriceList({
  name: "VIP",
  currency: "USD",
  customerGroupId: "vip-group",
  priority: 100, // Checked before standard list
});

const standardList = await pricingService.createPriceList({
  name: "Standard",
  currency: "USD",
  priority: 1, // Fallback
});

3. Use Tiered Pricing for Volume Discounts

Tiered pricing automatically selects the best price based on quantity:

// Define clear tier boundaries
await pricingService.setTieredPrice({
  priceListId: listId,
  productId: productId,
  tierPrices: [
    { minQuantity: 1, unitPrice: 1000 },   // Always start at 1
    { minQuantity: 10, unitPrice: 900 },    // 10% discount
    { minQuantity: 50, unitPrice: 750 },    // 25% discount
    { minQuantity: 100, unitPrice: 600 },   // 40% discount
  ],
});

4. Use Date Ranges for Promotions

Create time-limited price lists for sales and promotions:

const summerSale = await pricingService.createPriceList({
  name: "Summer Sale 2025",
  currency: "USD",
  priority: 50,
  validFrom: new Date("2025-06-01"),
  validTo: new Date("2025-08-31"),
});