Price Lists
Overview
Price lists allow you to create custom pricing for specific customer groups. They can override base prices at the variant, product, or category level.
Price List Structure
interface PriceList {
id: string;
name: string;
type: "STANDARD" | "SALE" | "CUSTOM";
priority: number; // Lower = higher priority
isActive: boolean;
startDate?: Date;
endDate?: Date;
items: PriceListItem[];
}
Price List Items
Price list items define overrides at different specificity levels:
Variant-Level Override
Most specific, applies to a single product variant:
{
"productVariantId": "variant-123",
"overrideType": "FIXED",
"overrideValue": 999.99
}
Product-Level Override
Applies to all variants of a product:
{
"productId": "product-456",
"overrideType": "PERCENTAGE",
"overrideValue": 15
}
Category-Level Override
Applies to all products in a category:
{
"categoryId": "category-789",
"overrideType": "PERCENTAGE",
"overrideValue": 10
}
Priority System
When multiple price lists apply to the same customer group:
- Priority Number: Lower number = higher priority
- Specificity: Variant > Product > Category
- Active Status: Only active price lists are considered
- Date Range: Only price lists within start/end dates are considered
Customer Group Association
Price lists are associated with customer groups:
interface CustomerGroup {
id: string;
name: string;
priceLists: Array<{
priceListId: string;
priority: number;
}>;
}
A customer group can have multiple price lists, ordered by priority.
Creating a Price List
Example: VIP Customer Pricing
POST /admin/pricing/price-lists
Content-Type: application/json
{
"name": "VIP Customer Pricing",
"type": "STANDARD",
"priority": 1,
"isActive": true,
"items": [
{
"productVariantId": "variant-123",
"overrideType": "FIXED",
"overrideValue": 899.99
},
{
"categoryId": "electronics",
"overrideType": "PERCENTAGE",
"overrideValue": 15
}
]
}
Price List Resolution
When calculating price for a variant:
- Get customer's group
- Load all price lists for that group (ordered by priority)
- For each price list, check for overrides (variant → product → category)
- Select most specific override from highest priority price list
- Apply override to base price
Override Types
FIXED Override
Replaces base price with fixed amount:
effectivePrice = overrideValue;
PERCENTAGE Override
Applies percentage discount:
effectivePrice = basePrice * (1 - overrideValue / 100);
Date-Based Price Lists
Price lists can have start and end dates for time-limited pricing:
{
"name": "Holiday Sale",
"startDate": "2025-12-01T00:00:00Z",
"endDate": "2025-12-31T23:59:59Z",
"isActive": true
}
API Endpoints
GET /admin/pricing/price-lists- List all price listsPOST /admin/pricing/price-lists- Create price listGET /admin/pricing/price-lists/:id- Get price listPATCH /admin/pricing/price-lists/:id- Update price listDELETE /admin/pricing/price-lists/:id- Delete price listPOST /admin/pricing/price-lists/:id/items- Add price list item
Caching
Price lists are cached in Redis:
- Cache Key:
pricing:price-list:{id} - TTL: 1 hour
- Invalidation: On price list create/update/delete
Best Practices
- Use Variant Overrides Sparingly: Prefer product or category overrides for easier management
- Set Clear Priorities: Use consistent priority numbering (1, 10, 100)
- Test Override Conflicts: Ensure most specific override wins as expected
- Monitor Performance: Large price lists may impact pricing calculation speed
- Use Date Ranges: Set start/end dates for time-limited pricing
Edge Cases
- No Override Found: Uses base price
- Multiple Overrides: Most specific wins (variant > product > category)
- Expired Price List: Ignored if outside date range
- Inactive Price List: Ignored even if within date range
- Circular Dependencies: Not possible (price lists don't reference each other)