VAT base composition
In most places VAT is charged on the room alone and the tourist tax sits beside it. But in some countries the tourist tax is legally part of what the operator supplies — so VAT is charged on room + tourist tax. TaxLens models both with one primitive: base_includes plus calculation_order.
The operator-vs-guest question
When a guest pays a tourist or occupancy tax, who is the legal debtor — the operator or the guest? That single question decides whether the tax sits inside the VAT base or beside it.
- Guest-borne — the operator merely collects the tax and remits it on the guest's behalf (a disbursement, a suplido, a débours). It is not part of the consideration for the room, so VAT is charged on the room only. This is the common case and the engine's default.
- Operator-levied — the tax is legally owed by the operator and forms part of the price of the supply. VAT is then charged on
room + tourist tax.
base_includes + calculation_order
There is no per-country special case for this. The engine models the in-base case with two fields already on every rate:
base_includes— a list of tax-category codes whose computed amounts are added to this rate's taxable base before it computes. The default is the room only (base_amount).calculation_order— an integer ordering (lower = first). Any category listed inbase_includesmust have a lower order than this rate, so it computes first and its amount is available to fold in.
To put the tourist tax inside the VAT base, the VAT rate lists the tourist-tax category in its base_includes and is given a higher calculation_order than the tourist tax. The tourist tax computes first; the VAT then computes on the larger base.
{
"tax_category": "vat_reduced",
"rate_type": "percentage",
"rate_value": 0.10,
"calculation_order": 20,
"base_includes": ["base_amount", "tourism_flat_person_night"]
}
// the tourism rate has calculation_order 10 (lower → computes first),
// so its amount is folded into this VAT rate's base.base_includes + calculation_order pattern.Which countries are in, which are out
Determined against primary law. These lists reflect the dominant operator-redevable case per country:
Germany (Übernachtungsteuer), Spain (IEET), Bulgaria, Latvia, Netherlands (toeristenbelasting), Belgium — plus the pre-existing Canada (HST-on-MAT) and GB cascades.
Italy (imposta di soggiorno, invoice code N1), Austria, Portugal, Greece, Croatia, Hungary, Poland, Slovenia, Lithuania, France (taxe de séjour au réel), Switzerland, Romania.
Honest caveats
This primitive is precise but not unlimited. Two boundaries to know:
- No per-operator election. The lists model the dominant case. A few jurisdictions (NL, BE) allow an individual operator to elect a disbursement treatment that flips the tax OUT of the base — there is no field to express that per-operator choice, so the country-level default stands.
- Matches by accumulated category, not by city.
base_includesmatches a category code accumulated across the whole booking. It does not cleanly generalize to a single shared country-level VAT rate that must include the tax for some cities but exclude it for others (e.g. Mexico's ISH) — see Limitations.
Where to go next
The folding only matters because each layer is its own row — see Layered & additive stacking. Which category each layer carries is in Tax categories. And because VAT is the recoverable, invoice-grade layer, this composition flows straight into VAT-only invoicing.