Discounts, tiers and price ranges
On this page
A percentage needs a base, a tier needs a boundary, and a range needs a meaning. This guide works through those choices using the Cleaning and Website design templates and a separate graduated-mileage example.
A cleaning quote with two modifiers
Use the Residential cleaning template with three bedrooms, two bathrooms, 1,000 square feet, oven cleaning, no interior windows, a deep clean and weekly frequency.
| Charge | Amount |
|---|---|
| Visit and supplies | $60.00 |
| 3 bedrooms × $18 | $54.00 |
| 2 bathrooms × $25 | $50.00 |
| 1,000 square feet × $0.03 | $30.00 |
| Oven | $35.00 |
| Subtotal | $229.00 |
The deep-clean rule adds 50% using running_total: $114.50. The running total is now $343.50. The weekly discount then subtracts 15% of that amount: $51.525, rounded to $51.53. The final total is $291.97.
The discount follows the deep-clean adjustment, so it discounts that adjustment too. If its basis were subtotal, it would subtract $34.35 instead and produce $309.15. Neither interpretation is inherently correct; choose the one your business intends and test it.
Compare percentage bases
Suppose the subtotal is $100 and two rules add 10% and 20%:
| Configuration | First adjustment | Second adjustment | Total |
|---|---|---|---|
| Both use subtotal | $10 | $20 | $130 |
| Both use running total | $10 | $22 | $132 |
subtotal means accumulated charge rules before the percentage; it does not include prior percentage adjustments. running_total also includes earlier adjustments. Place all relevant charges before the percentage and use labels that communicate the business meaning.
A negative percentage represents a discount. The schema rejects percentages below -100, and the final price cannot become negative.
Graduated tiers are cumulative
Consider a separate mileage rule: the first 10 miles cost $2 each, the next 40 cost $1.60 each and additional miles cost $1.30 each. The portable rule fragment is:
{
"id": "graduated_distance",
"label": "Graduated mileage",
"type": "tiered",
"field": "distance",
"tiers": [
{ "upTo": 10, "rateMinor": 200 },
{ "upTo": 50, "rateMinor": 160 },
{ "upTo": null, "rateMinor": 130 }
]
}For 51 miles, the amount is 10 × 200 + 40 × 160 + 1 × 130 = 8530, or $85.30. It is not 51 × $1.30. upTo is the cumulative upper boundary, and the final tier must be open-ended.
Test 0, 10, 10.5, 50 and 51 miles. At 10.5, only the extra half-mile uses the second rate. Boundary cases catch confusion between a tier width and a cumulative boundary.
A website quote with a range
The Website design template combines a chosen package, a price for every page, optional functionality and a rush percentage. Package pricing does not include a free-page allowance.
Choose Launch, five pages, no store, no booking integration, no copywriting and no priority delivery:
Launch package $1,200
5 pages × $180 $900
Total $2,100
Range $1,890 – $2,520The template range is 10% below and 20% above the total. With priority delivery, the 25% running-total adjustment produces $2,625, with a range of $2,362.50–$3,150.
The “Booking integration” and “Online store” choices price agency work. They do not turn OpenQuoteStack into a booking or payment system.
Bounds and ranges serve different purposes
Minimum and maximum alter the final quoted total and appear as adjustments. A range describes uncertainty around the bounded total and does not change it. Its endpoints can extend beyond a configured minimum or maximum.
If your contractual minimum must also be the lowest displayed endpoint, the current range semantics do not enforce that requirement. Adjust the estimator's presentation or wait for a separately designed feature; do not assume bounds clamp the range.
Explain why the range exists, such as discovery work or property conditions. A range is not a statistical confidence interval unless your own pricing process gives it that meaning.