Discount Stacking
Control how multiple discounts combine
Discount Stacking
A common challenge: allowing some discount combinations while preventing abuse.
The Scenario
Your B2B pricing policy needs to handle:
- Volume discounts: Based on order quantity
- Customer tier discounts: Based on relationship
- Promotional discounts: Seasonal offers
- Stacking limits: Preventing abuse
Business rules:
- Maximum total discount: 25%
- Margin must stay above 15%
- Volume orders (100+ units) get up to 15% discount
- Smaller orders limited to 10%
The Policy
import { PolicyEngine } from '@guardrail-sim/policy-engine';
import type { Policy, PolicyRule } from '@guardrail-sim/policy-engine';
const stackingPolicy: Policy = {
id: 'discount-stacking-rules',
name: 'Discount Stacking Rules',
rules: [
// Overall discount cap
{
name: 'max_discount',
conditions: {
all: [{ fact: 'proposed_discount', operator: 'greaterThan', value: 0.25 }],
},
event: {
type: 'violation',
params: { message: 'Total discount cannot exceed 25%' },
},
priority: 1,
},
// Margin floor
{
name: 'margin_floor',
conditions: {
all: [{ fact: 'calculated_margin', operator: 'lessThan', value: 0.15 }],
},
event: {
type: 'violation',
params: { message: 'Discount would reduce margin below 15%' },
},
priority: 2,
},
// Volume tier limit
{
name: 'volume_tier',
conditions: {
all: [
{ fact: 'quantity', operator: 'lessThan', value: 100 },
{ fact: 'proposed_discount', operator: 'greaterThan', value: 0.1 },
],
},
event: {
type: 'violation',
params: { message: 'Orders under 100 units limited to 10% discount' },
},
priority: 3,
},
],
};
const engine = new PolicyEngine(stackingPolicy);Testing Scenarios
// Scenario 1: Small order, small discount (allowed)
const result1 = await engine.evaluate(
{ order_value: 1000, quantity: 50, product_margin: 0.4 },
0.08 // 8% discount
);
// result1.approved: true
// result1.calculated_margin: 0.32
// Scenario 2: Small order, large discount (rejected)
const result2 = await engine.evaluate(
{ order_value: 1000, quantity: 50, product_margin: 0.4 },
0.15 // 15% discount
);
// result2.approved: false
// result2.violations: [{ rule: 'volume_tier', message: '...' }]
// Scenario 3: Large order, large discount (allowed)
const result3 = await engine.evaluate(
{ order_value: 10000, quantity: 200, product_margin: 0.4 },
0.15 // 15% discount
);
// result3.approved: true
// result3.calculated_margin: 0.25
// Scenario 4: Any order, excessive discount (rejected)
const result4 = await engine.evaluate(
{ order_value: 10000, quantity: 200, product_margin: 0.4 },
0.3 // 30% discount
);
// result4.approved: false
// result4.violations: [{ rule: 'max_discount', message: '...' }]Using with MCP
Test discount requests via MCP tools:
{
"name": "evaluate_policy",
"arguments": {
"order": {
"order_value": 5000,
"quantity": 150,
"product_margin": 0.4,
"customer_segment": "gold"
},
"proposed_discount": 0.12
}
}Finding Maximum Allowed
Use get_max_discount to find the ceiling:
{
"name": "get_max_discount",
"arguments": {
"order": {
"order_value": 5000,
"quantity": 50,
"product_margin": 0.4
}
}
}Response:
{
"max_discount": 0.1,
"max_discount_pct": "10%",
"limiting_factor": "volume_tier",
"details": "Orders under 100 units limited to 10% discount"
}