Anatomy of a quote
Subtotal, rule adjustments, VAT, total. How the maths works and where each line comes from.
A quote is a snapshot of what the guest configured: every line item, every applied rule, VAT, and the total. It's stored separately from your live catalogue so you can change products and prices later without rewriting history.
The four totals
| Field | What it includes |
|---|---|
subtotal_pence | Sum of all included line items, excluding rule adjustments. Pre-VAT. |
rules_pence | The single pricing-rule adjustment that matched. Positive for surcharges, negative for discounts. |
vat_pence | VAT, calculated per line and summed. |
total_pence | Final amount: subtotal + rules + vat. |
All values are stored in pence (the smallest unit of GBP). The proposal page formats them as pounds for display.
Quote items
Every line on a quote is a quote item. There are three flavours:
| Type | Source |
|---|---|
product | A product the guest selected (venue hire, A/V, late licence). |
menu_item | A menu item the guest selected (starter, main, drinks package). |
rule_adjustment | A surcharge or discount from a pricing rule. Not toggleable. |
Each item stores: name, description, quantity, quantity unit, unit price, line total, VAT rate,
toggleable flag, included flag. The configuration field on the parent quote also
snapshots the full submitted payload.
Quote statuses
| Status | When |
|---|---|
draft | Reserved for operator-built quotes. Widget submissions skip this. |
sent | Created from the widget. The proposal link is live. |
viewed | The guest has opened the proposal at least once. Set automatically. |
accepted | Reserved for the deposit/acceptance flow (coming). |
paid | Deposit received (coming). |
expired | Past expires_at. Reserved — not yet enforced. |
Live recalculation on toggle
When a guest toggles a line item on the proposal page, the server recalculates the totals via
QuoteCalculator. The included flag flips on the item; subtotal, VAT and total are
recomputed from scratch. The rule adjustment does not re-evaluate — it's frozen at
the moment the quote was created.
Why don't rules re-evaluate? Because guests toggling items shouldn't silently move themselves below a minimum-spend threshold. The original adjustment is what they agreed to.
Expiry
Every quote is created with an expires_at 30 days out. Currently it's a flag — the
proposal still renders past it. A future release will gate the proposal page on expiry. Plan
accordingly: if a guest comes back six months later, you'll likely want to re-quote them
anyway because your prices may have changed.
Something missing or wrong? Tell us.
Updated regularly. UK English. No AI slop.