From 071f29cb527e54e60477d6afbb8b7e486f27fb45 Mon Sep 17 00:00:00 2001 From: Vahid Ahmadi Date: Wed, 27 May 2026 11:00:01 +0200 Subject: [PATCH 1/7] Add firm-level VAT planning docs page (#1320 #1333) #1320 and #1333 are filed as planning trackers for a Firm-entity VAT implementation. Persist the plan in-repo as a "planned: not yet modelled" docs page mirroring the BiK plan added in #1654. The page covers: - the current state (household-side VAT only; no Firm entity), - the policy questions that firm-side VAT enables (registration threshold reforms, supplier-side rate changes, flat-rate scheme), - Phase 1 MVP scope: Firm entity, threshold logic, supply split, output/input/net VAT, - proposed entity definition and variable/parameter trees, - the data gap and a synthetic-firm-panel imputation approach consistent with the second-stage pattern flagged in #1621, - effort estimate and open questions (panel location, MTD mechanics, Datalab access). When the MVP lands the "planned" warning at the top is dropped and the file becomes the live VAT-firm-side docs page. --- changelog.d/1320.md | 1 + docs/book/programs/gov/hmrc/firm-vat.md | 195 ++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 changelog.d/1320.md create mode 100644 docs/book/programs/gov/hmrc/firm-vat.md diff --git a/changelog.d/1320.md b/changelog.d/1320.md new file mode 100644 index 0000000000..30d2260e54 --- /dev/null +++ b/changelog.d/1320.md @@ -0,0 +1 @@ +- Persist the firm-VAT plan in-repo as a "planned: not yet modelled" docs page at `docs/book/programs/gov/hmrc/firm-vat.md` capturing the proposed `Firm` entity, Phase 1 MVP scope (registration threshold, supply split, output/input/net VAT), data needs and synthetic-firm-panel approach, and open questions — mirroring the BiK plan pattern from #1654. diff --git a/docs/book/programs/gov/hmrc/firm-vat.md b/docs/book/programs/gov/hmrc/firm-vat.md new file mode 100644 index 0000000000..9c543f4628 --- /dev/null +++ b/docs/book/programs/gov/hmrc/firm-vat.md @@ -0,0 +1,195 @@ +# Firm-level VAT (planned) + +```{warning} +**Not yet modelled.** PolicyEngine UK currently models VAT only at the +*household consumption* level (the `vat` variable, computed from +consumption-category spending and rate parameters under +`gov.hmrc.vat`). This page captures the agreed scope and roadmap for +adding firm-level VAT and a new `Firm` entity, tracked under +[#1320](https://github.com/PolicyEngine/policyengine-uk/issues/1320) and +[#1333](https://github.com/PolicyEngine/policyengine-uk/issues/1333). It +mirrors the [BiK plan](./benefits-in-kind.md) pattern. +``` + +## Why firm-level VAT? + +Household-side VAT in PolicyEngine answers the question "what does this +household pay in VAT on the goods and services it buys?" but it can't +answer policy questions framed at the business side: + +- How does changing the VAT registration threshold (currently £90,000 + annual turnover) affect the number of firms in scope, and through + them the consumer prices that households face? +- What's the revenue effect of moving a supply between standard, reduced + and zero rates seen from the *supplier* side (input/output netting)? +- How does the flat-rate scheme distort the modelled compliance picture? + +Closing those questions needs a separate entity that *carries* turnover, +sector, and registration status, and variables for input/output VAT and +net liability. + +## Scope + +### Phase 1 — MVP + +1. **`Firm` entity** with the bare attributes needed for the threshold + and rate questions: `firm_turnover`, `firm_industry_sector`, + `firm_vat_registered`. Firms are linked to households for sole + traders and partnerships (unincorporated business income flows + already exist in the FRS) and stand alone for incorporated entities. +2. **Registration threshold logic**: a firm is VAT-registered if + turnover meets or exceeds `gov.hmrc.vat.registration_threshold` (or + the firm has elected to register voluntarily). Threshold currently + £90,000 since April 2024. +3. **Standard / reduced / zero-rated supply split** at the firm level, + driven by sector-specific share parameters. +4. **`firm_vat_on_sales`** (output VAT) and **`firm_vat_on_purchases`** + (input VAT), each computed from share-based decompositions of + turnover and intermediate consumption. +5. **`firm_net_vat_liability`** = output VAT − input VAT. + +### Phase 2 — distributional refinements + +- **Flat-rate scheme** for small businesses (`gov.hmrc.vat.flat_rate_scheme/`). +- **VAT groups** and partial exemption (de minimis rules for + exempt-versus-taxable splits). +- **Cross-border VAT** post-Brexit changes (Northern Ireland Protocol, + postponed accounting). + +### Phase 3 — incidence + +- **Pass-through** of VAT rate changes to consumer prices, joining up + the household-side `vat` variable and the firm-side + `firm_net_vat_liability` through an explicit incidence assumption + (already modelled in spirit via `vat_change` on the household side; + Phase 3 promotes it to a first-class link). + +## Implementation plan + +### Entity + +A new `Firm` entity in `policyengine_uk/entities.py` next to the +existing `Household`, `BenUnit`, `Person`: + +```python +Firm = build_entity( + key="firm", + plural="firms", + label="Firm", + doc="A business entity that may register for VAT.", + roles=[{"key": "owner", "plural": "owners", + "label": "Owner", + "doc": "Person or household that owns the firm."}], + containing_entities=["state"], +) +``` + +The `containing_entities` set deliberately does *not* include +`household` because incorporated firms have no household; the link for +sole traders is via an explicit `firm_owning_household_id` input +variable rather than entity nesting. + +### Variables + +Under a new `variables/gov/hmrc/vat/firm/` tree: + +- `firm_turnover` (input) +- `firm_industry_sector` (input, enum) +- `firm_vat_registered` (derived from turnover and the threshold; can + also be set as input for voluntary registration) +- `firm_standard_rated_share`, `firm_reduced_rated_share`, + `firm_zero_rated_share`, `firm_exempt_share` (derived from sector or + input override) +- `firm_vat_on_sales` (output VAT) +- `firm_vat_on_purchases` (input VAT) +- `firm_net_vat_liability` (output − input) + +The household-side `vat` variable stays untouched; the two sides only +meet in Phase 3. + +### Parameters + +A new tree under `parameters/gov/hmrc/vat/firm/`: + +- `registration_threshold.yaml` — currently £90,000 from April 2024. +- `deregistration_threshold.yaml` — currently £88,000 from April 2024. +- `rates/standard.yaml`, `reduced.yaml`, `zero.yaml` — these already + exist on the household-side tree and will be referenced rather than + duplicated. +- `sector_supply_split/` — share parameters by industry sector for the + standard/reduced/zero/exempt split (Phase 1.5 refinement; MVP can use + a single national split per sector). +- `flat_rate_scheme/` — Phase 2. + +### Tests + +- Unit tests around the threshold (firm just below, just above, just + above the deregistration threshold). +- Tests of rate-split arithmetic for each sector. +- Integration test asserting that summing `firm_net_vat_liability` + across a representative firm panel reproduces published HMRC VAT + receipts to within calibration tolerance. + +## Data needs + +This is the harder half of the project. Summary of where each Phase 1 +component sits w.r.t. our current data: + +| Component | Public source | FRS coverage | Datalab source | +|-----------|---------------|--------------|----------------| +| Firm turnover distribution | ONS *Business Demography* | sole-trader / partnership turnover via FRS self-employment income | HMRC Datalab — anonymised VAT returns | +| Industry sector | SIC codes from ONS *Inter-Departmental Business Register (IDBR)* | not in FRS | HMRC Datalab | +| VAT registration share | HMRC *VAT statistics* (annual) | not in FRS | HMRC Datalab | +| Input VAT shares | ONS *Supply and Use tables* | not applicable | HMRC Datalab | + +### Proposed imputation approach + +1. Build a **synthetic firm panel** weighted to ONS Business Demography + counts by SIC sector and turnover band. +2. Attach to each firm a registration status, supply split, and + intermediate-consumption ratio drawn from HMRC VAT statistics and + ONS Supply and Use tables. +3. Calibrate the panel so that summed `firm_net_vat_liability` matches + the HMRC VAT receipts outturn for the year. This mirrors the + second-stage imputation pattern flagged in + [#1621](https://github.com/PolicyEngine/policyengine-uk/issues/1621). +4. For sole traders and partnerships, link the synthetic firm row back + to the FRS household that owns it via self-employment income. + +The companion repo [`policyengine/uk-vatlab`][vatlab] hosts the analysis +files (#1333) used to size each step before they are productionised. + +## Effort estimate + +- Adding the `Firm` entity, `firm_turnover` input, threshold logic, and + a single-rate liability variable: ~1–2 days. +- Phase 1 MVP (full Firm entity, sector-driven supply split, calibrated + synthetic firm panel, threshold/rate tests, integration test against + HMRC outturn): ~3–4 weeks, with most time on the data side. +- Phase 2 (flat-rate scheme, VAT groups, partial exemption): another + 2–3 weeks once the panel is stable. +- Phase 3 (cross-side incidence): tied to the + `consumer_incident_tax_revenue_change` infrastructure already in the + repo; the link itself is small but the elasticity assumptions need + agreement. + +## Open questions + +- Should the synthetic firm panel live in `policyengine-uk-data` (matching + the FRS calibration pipeline) or in this repo? Recommendation: it + belongs in `policyengine-uk-data`, with the rules variables here. +- Do we need to model Making Tax Digital filing-frequency mechanics, or + is annualised liability sufficient for nowcasting purposes? +- HMRC Datalab access for anonymised VAT returns: pursue, or stick to + ONS / public-aggregate calibration? + +## References + +- HMRC, [VAT rates](https://www.gov.uk/vat-rates) and [VAT registration thresholds](https://www.gov.uk/vat-registration-thresholds). +- [Value Added Tax Act 1994](https://www.legislation.gov.uk/ukpga/1994/23/contents) — primary statute. +- HMRC, [VAT statistics](https://www.gov.uk/government/collections/value-added-tax-vat-statistics) — annual outturn used for calibration. +- ONS, [UK Business: Activity, Size and Location](https://www.ons.gov.uk/businessindustryandtrade/business/activitysizeandlocation) (the IDBR-based business demography release). +- ONS, [Supply and Use tables](https://www.ons.gov.uk/economy/nationalaccounts/supplyandusetables) — intermediate consumption shares. +- Companion analysis repo: [`policyengine/uk-vatlab`][vatlab] (#1333). + +[vatlab]: https://github.com/policyengine/uk-vatlab From fdb117613f6a594026f8c5c8f86dbc28c6c6ab29 Mon Sep 17 00:00:00 2001 From: vahid-ahmadi Date: Thu, 8 Oct 2026 15:54:29 +0100 Subject: [PATCH 2/7] Refresh the planning page against the current code and type its changelog fragment Checked every variable, parameter, path and link against main in October 2026, updated the data pipeline references to Microcosm UK, and renamed the changelog fragment to a Towncrier type. Co-Authored-By: Claude Opus 5.5 --- changelog.d/1320.added.md | 1 + changelog.d/1320.md | 1 - docs/book/programs/gov/hmrc/firm-vat.md | 41 +++++++++++++------------ 3 files changed, 23 insertions(+), 20 deletions(-) create mode 100644 changelog.d/1320.added.md delete mode 100644 changelog.d/1320.md diff --git a/changelog.d/1320.added.md b/changelog.d/1320.added.md new file mode 100644 index 0000000000..c6e7a297c2 --- /dev/null +++ b/changelog.d/1320.added.md @@ -0,0 +1 @@ +- Add a planning docs page for firm-level VAT (`docs/book/programs/gov/hmrc/firm-vat.md`): a proposed `Firm` entity, the registration threshold and supply split, output, input and net VAT, the data needed for a synthetic firm panel, and open questions. diff --git a/changelog.d/1320.md b/changelog.d/1320.md deleted file mode 100644 index 30d2260e54..0000000000 --- a/changelog.d/1320.md +++ /dev/null @@ -1 +0,0 @@ -- Persist the firm-VAT plan in-repo as a "planned: not yet modelled" docs page at `docs/book/programs/gov/hmrc/firm-vat.md` capturing the proposed `Firm` entity, Phase 1 MVP scope (registration threshold, supply split, output/input/net VAT), data needs and synthetic-firm-panel approach, and open questions — mirroring the BiK plan pattern from #1654. diff --git a/docs/book/programs/gov/hmrc/firm-vat.md b/docs/book/programs/gov/hmrc/firm-vat.md index 9c543f4628..9a362c4733 100644 --- a/docs/book/programs/gov/hmrc/firm-vat.md +++ b/docs/book/programs/gov/hmrc/firm-vat.md @@ -1,14 +1,15 @@ # Firm-level VAT (planned) ```{warning} -**Not yet modelled.** PolicyEngine UK currently models VAT only at the -*household consumption* level (the `vat` variable, computed from -consumption-category spending and rate parameters under -`gov.hmrc.vat`). This page captures the agreed scope and roadmap for -adding firm-level VAT and a new `Firm` entity, tracked under +**Not yet modelled.** PolicyEngine UK models VAT only on *household +consumption*: the `vat` variable applies `gov.hmrc.vat.standard_rate` and +`gov.hmrc.vat.reduced_rate` to each household's standard- and reduced-rate +spending (`full_rate_vat_consumption`, `reduced_rate_vat_consumption`), then +grosses the result up to VAT receipts. There is no business side. This page +sets out the scope for adding firm-level VAT and a `Firm` entity, tracked in [#1320](https://github.com/PolicyEngine/policyengine-uk/issues/1320) and -[#1333](https://github.com/PolicyEngine/policyengine-uk/issues/1333). It -mirrors the [BiK plan](./benefits-in-kind.md) pattern. +[#1333](https://github.com/PolicyEngine/policyengine-uk/issues/1333). Both +issues are still open (October 2026). ``` ## Why firm-level VAT? @@ -37,10 +38,10 @@ net liability. `firm_vat_registered`. Firms are linked to households for sole traders and partnerships (unincorporated business income flows already exist in the FRS) and stand alone for incorporated entities. -2. **Registration threshold logic**: a firm is VAT-registered if - turnover meets or exceeds `gov.hmrc.vat.registration_threshold` (or - the firm has elected to register voluntarily). Threshold currently - £90,000 since April 2024. +2. **Registration threshold logic**: a firm must register if its taxable + turnover is more than a new `gov.hmrc.vat.firm.registration_threshold` + parameter, or it can register voluntarily. The threshold has been + £90,000 since 1 April 2024. 3. **Standard / reduced / zero-rated supply split** at the firm level, driven by sector-specific share parameters. 4. **`firm_vat_on_sales`** (output VAT) and **`firm_vat_on_purchases`** @@ -113,9 +114,9 @@ A new tree under `parameters/gov/hmrc/vat/firm/`: - `registration_threshold.yaml` — currently £90,000 from April 2024. - `deregistration_threshold.yaml` — currently £88,000 from April 2024. -- `rates/standard.yaml`, `reduced.yaml`, `zero.yaml` — these already - exist on the household-side tree and will be referenced rather than - duplicated. +- Rates: reference the existing `gov/hmrc/vat/standard_rate.yaml` and + `reduced_rate.yaml` rather than duplicating them. Zero-rated supplies + need no rate parameter. - `sector_supply_split/` — share parameters by industry sector for the standard/reduced/zero/exempt split (Phase 1.5 refinement; MVP can use a single national split per sector). @@ -151,7 +152,7 @@ component sits w.r.t. our current data: ONS Supply and Use tables. 3. Calibrate the panel so that summed `firm_net_vat_liability` matches the HMRC VAT receipts outturn for the year. This mirrors the - second-stage imputation pattern flagged in + second-stage imputation pattern discussed in [#1621](https://github.com/PolicyEngine/policyengine-uk/issues/1621). 4. For sole traders and partnerships, link the synthetic firm row back to the FRS household that owns it via self-employment income. @@ -175,9 +176,11 @@ files (#1333) used to size each step before they are productionised. ## Open questions -- Should the synthetic firm panel live in `policyengine-uk-data` (matching - the FRS calibration pipeline) or in this repo? Recommendation: it - belongs in `policyengine-uk-data`, with the rules variables here. +- Should the synthetic firm panel live in the data pipeline or in this + repo? Recommendation: in the data pipeline, which for PolicyEngine UK is + now [Microcosm UK](https://github.com/PolicyEngine/microcosm) (it replaced + the Enhanced FRS build; its first certified national release is dated + 4 October 2026), with the rules variables here. - Do we need to model Making Tax Digital filing-frequency mechanics, or is annualised liability sufficient for nowcasting purposes? - HMRC Datalab access for anonymised VAT returns: pursue, or stick to @@ -187,7 +190,7 @@ files (#1333) used to size each step before they are productionised. - HMRC, [VAT rates](https://www.gov.uk/vat-rates) and [VAT registration thresholds](https://www.gov.uk/vat-registration-thresholds). - [Value Added Tax Act 1994](https://www.legislation.gov.uk/ukpga/1994/23/contents) — primary statute. -- HMRC, [VAT statistics](https://www.gov.uk/government/collections/value-added-tax-vat-statistics) — annual outturn used for calibration. +- HMRC, [VAT statistics](https://www.gov.uk/government/statistics/value-added-tax-vat-annual-statistics) — annual outturn used for calibration. - ONS, [UK Business: Activity, Size and Location](https://www.ons.gov.uk/businessindustryandtrade/business/activitysizeandlocation) (the IDBR-based business demography release). - ONS, [Supply and Use tables](https://www.ons.gov.uk/economy/nationalaccounts/supplyandusetables) — intermediate consumption shares. - Companion analysis repo: [`policyengine/uk-vatlab`][vatlab] (#1333). From 68f51b67844343c2aa8b387af279b1739278cc40 Mon Sep 17 00:00:00 2001 From: vahid-ahmadi Date: Mon, 12 Oct 2026 11:04:46 +0200 Subject: [PATCH 3/7] Bring the firm-level VAT plan up to date with main and house style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Anchor the VAT thresholds to 1 April 2024 (gov.uk lists £90,000 to register and £88,000 to deregister) instead of "currently", drop the unverified Microcosm UK release date and replacement claim, name the Windsor Framework rather than the Northern Ireland Protocol, put the flat-rate scheme under the planned gov.hmrc.vat.firm tree, remove em dashes and sentence-case the phase headings. Drop the leading bullet from the changelog fragment so towncrier does not render it twice. Co-Authored-By: Claude Opus 5.5 --- changelog.d/1320.added.md | 2 +- docs/book/programs/gov/hmrc/firm-vat.md | 42 ++++++++++++------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/changelog.d/1320.added.md b/changelog.d/1320.added.md index c6e7a297c2..0c7cedbd66 100644 --- a/changelog.d/1320.added.md +++ b/changelog.d/1320.added.md @@ -1 +1 @@ -- Add a planning docs page for firm-level VAT (`docs/book/programs/gov/hmrc/firm-vat.md`): a proposed `Firm` entity, the registration threshold and supply split, output, input and net VAT, the data needed for a synthetic firm panel, and open questions. +Add a planning docs page for firm-level VAT (`docs/book/programs/gov/hmrc/firm-vat.md`): a proposed `Firm` entity, the registration threshold and supply split, output, input and net VAT, the data needed for a synthetic firm panel, and open questions. diff --git a/docs/book/programs/gov/hmrc/firm-vat.md b/docs/book/programs/gov/hmrc/firm-vat.md index 9a362c4733..fc26309efc 100644 --- a/docs/book/programs/gov/hmrc/firm-vat.md +++ b/docs/book/programs/gov/hmrc/firm-vat.md @@ -18,8 +18,8 @@ Household-side VAT in PolicyEngine answers the question "what does this household pay in VAT on the goods and services it buys?" but it can't answer policy questions framed at the business side: -- How does changing the VAT registration threshold (currently £90,000 - annual turnover) affect the number of firms in scope, and through +- How does changing the VAT registration threshold (£90,000 of taxable + turnover since 1 April 2024) affect the number of firms in scope, and through them the consumer prices that households face? - What's the revenue effect of moving a supply between standard, reduced and zero rates seen from the *supplier* side (input/output netting)? @@ -31,7 +31,7 @@ net liability. ## Scope -### Phase 1 — MVP +### Phase 1: minimum viable product 1. **`Firm` entity** with the bare attributes needed for the threshold and rate questions: `firm_turnover`, `firm_industry_sector`, @@ -49,15 +49,16 @@ net liability. turnover and intermediate consumption. 5. **`firm_net_vat_liability`** = output VAT − input VAT. -### Phase 2 — distributional refinements +### Phase 2: distributional refinements -- **Flat-rate scheme** for small businesses (`gov.hmrc.vat.flat_rate_scheme/`). +- **Flat-rate scheme** for small businesses (a new + `gov.hmrc.vat.firm.flat_rate_scheme` parameter tree). - **VAT groups** and partial exemption (de minimis rules for exempt-versus-taxable splits). -- **Cross-border VAT** post-Brexit changes (Northern Ireland Protocol, - postponed accounting). +- **Cross-border VAT** after Brexit (Northern Ireland under the Windsor + Framework, postponed VAT accounting on imports). -### Phase 3 — incidence +### Phase 3: incidence - **Pass-through** of VAT rate changes to consumer prices, joining up the household-side `vat` variable and the firm-side @@ -112,15 +113,15 @@ meet in Phase 3. A new tree under `parameters/gov/hmrc/vat/firm/`: -- `registration_threshold.yaml` — currently £90,000 from April 2024. -- `deregistration_threshold.yaml` — currently £88,000 from April 2024. +- `registration_threshold.yaml`: £90,000 from 1 April 2024. +- `deregistration_threshold.yaml`: £88,000 from 1 April 2024. - Rates: reference the existing `gov/hmrc/vat/standard_rate.yaml` and `reduced_rate.yaml` rather than duplicating them. Zero-rated supplies need no rate parameter. -- `sector_supply_split/` — share parameters by industry sector for the +- `sector_supply_split/`: share parameters by industry sector for the standard/reduced/zero/exempt split (Phase 1.5 refinement; MVP can use a single national split per sector). -- `flat_rate_scheme/` — Phase 2. +- `flat_rate_scheme/`: Phase 2. ### Tests @@ -134,11 +135,11 @@ A new tree under `parameters/gov/hmrc/vat/firm/`: ## Data needs This is the harder half of the project. Summary of where each Phase 1 -component sits w.r.t. our current data: +component sits against our current data: | Component | Public source | FRS coverage | Datalab source | |-----------|---------------|--------------|----------------| -| Firm turnover distribution | ONS *Business Demography* | sole-trader / partnership turnover via FRS self-employment income | HMRC Datalab — anonymised VAT returns | +| Firm turnover distribution | ONS *Business Demography* | sole-trader / partnership turnover via FRS self-employment income | HMRC Datalab: anonymised VAT returns | | Industry sector | SIC codes from ONS *Inter-Departmental Business Register (IDBR)* | not in FRS | HMRC Datalab | | VAT registration share | HMRC *VAT statistics* (annual) | not in FRS | HMRC Datalab | | Input VAT shares | ONS *Supply and Use tables* | not applicable | HMRC Datalab | @@ -177,10 +178,9 @@ files (#1333) used to size each step before they are productionised. ## Open questions - Should the synthetic firm panel live in the data pipeline or in this - repo? Recommendation: in the data pipeline, which for PolicyEngine UK is - now [Microcosm UK](https://github.com/PolicyEngine/microcosm) (it replaced - the Enhanced FRS build; its first certified national release is dated - 4 October 2026), with the rules variables here. + repo? Recommendation: in the data pipeline + ([Microcosm UK](https://github.com/PolicyEngine/microcosm)), with the + rules variables here. - Do we need to model Making Tax Digital filing-frequency mechanics, or is annualised liability sufficient for nowcasting purposes? - HMRC Datalab access for anonymised VAT returns: pursue, or stick to @@ -189,10 +189,10 @@ files (#1333) used to size each step before they are productionised. ## References - HMRC, [VAT rates](https://www.gov.uk/vat-rates) and [VAT registration thresholds](https://www.gov.uk/vat-registration-thresholds). -- [Value Added Tax Act 1994](https://www.legislation.gov.uk/ukpga/1994/23/contents) — primary statute. -- HMRC, [VAT statistics](https://www.gov.uk/government/statistics/value-added-tax-vat-annual-statistics) — annual outturn used for calibration. +- [Value Added Tax Act 1994](https://www.legislation.gov.uk/ukpga/1994/23/contents): primary statute. +- HMRC, [VAT statistics](https://www.gov.uk/government/statistics/value-added-tax-vat-annual-statistics): annual outturn used for calibration. - ONS, [UK Business: Activity, Size and Location](https://www.ons.gov.uk/businessindustryandtrade/business/activitysizeandlocation) (the IDBR-based business demography release). -- ONS, [Supply and Use tables](https://www.ons.gov.uk/economy/nationalaccounts/supplyandusetables) — intermediate consumption shares. +- ONS, [Supply and Use tables](https://www.ons.gov.uk/economy/nationalaccounts/supplyandusetables): intermediate consumption shares. - Companion analysis repo: [`policyengine/uk-vatlab`][vatlab] (#1333). [vatlab]: https://github.com/policyengine/uk-vatlab From a5c5f60605a9ba19e0dab915401558dfe316cb94 Mon Sep 17 00:00:00 2001 From: vahid-ahmadi Date: Mon, 12 Oct 2026 13:02:21 +0200 Subject: [PATCH 4/7] Format the page's Python code block with ruff The Lint job now runs ruff format --check on Markdown code blocks for every pull request, docs-only ones included. Co-Authored-By: Claude Opus 5.5 --- docs/book/programs/gov/hmrc/firm-vat.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/book/programs/gov/hmrc/firm-vat.md b/docs/book/programs/gov/hmrc/firm-vat.md index fc26309efc..9ae9e79977 100644 --- a/docs/book/programs/gov/hmrc/firm-vat.md +++ b/docs/book/programs/gov/hmrc/firm-vat.md @@ -79,9 +79,14 @@ Firm = build_entity( plural="firms", label="Firm", doc="A business entity that may register for VAT.", - roles=[{"key": "owner", "plural": "owners", + roles=[ + { + "key": "owner", + "plural": "owners", "label": "Owner", - "doc": "Person or household that owns the firm."}], + "doc": "Person or household that owns the firm.", + } + ], containing_entities=["state"], ) ``` From 6e45f438b160fdba2b135237a453bfa37d19ee4d Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 23 Oct 2026 02:02:15 -0400 Subject: [PATCH 5/7] Correct the firm-level VAT planning page against main and its sources - #1333 was closed on 20 October 2026 as a duplicate of #1320. - The proposed Firm entity no longer copies the "state" containing entity (PolicyEngine UK has no state entity, entities.py:46), and its owner role holds people, since only people can be members of a group entity. - FRS self-employment income is profit, not turnover (self_employment_income.py:8), and the FRS does carry the main job's SIC division (sic_industry_division.py). - Turnover-band counts come from ONS UK business: activity, size and location, not Business demography; the reference now names that release. - Cut the unsupported link to #1621's second-stage imputation and the claim that uk-vatlab sizes each step; fixed the redirected GOV.UK VAT thresholds link. - Replaced the released .added fragment with a .changed fragment. Co-Authored-By: Claude Opus 5.5 --- .../1320-firm-vat-page-corrections.changed.md | 1 + changelog.d/1320.added.md | 1 - docs/book/programs/gov/hmrc/firm-vat.md | 36 ++++++++++--------- 3 files changed, 20 insertions(+), 18 deletions(-) create mode 100644 changelog.d/1320-firm-vat-page-corrections.changed.md delete mode 100644 changelog.d/1320.added.md diff --git a/changelog.d/1320-firm-vat-page-corrections.changed.md b/changelog.d/1320-firm-vat-page-corrections.changed.md new file mode 100644 index 0000000000..87cc5feab1 --- /dev/null +++ b/changelog.d/1320-firm-vat-page-corrections.changed.md @@ -0,0 +1 @@ +Corrected the firm-level VAT planning page (`docs/book/programs/gov/hmrc/firm-vat.md`): #1333 is closed as a duplicate of #1320, the proposed `Firm` entity no longer names a non-existent `state` containing entity, the data table now says FRS self-employment income is profit rather than turnover and that the FRS carries a main-job SIC division, and turnover-band counts come from ONS *UK business: activity, size and location* rather than Business demography. diff --git a/changelog.d/1320.added.md b/changelog.d/1320.added.md deleted file mode 100644 index 0c7cedbd66..0000000000 --- a/changelog.d/1320.added.md +++ /dev/null @@ -1 +0,0 @@ -Add a planning docs page for firm-level VAT (`docs/book/programs/gov/hmrc/firm-vat.md`): a proposed `Firm` entity, the registration threshold and supply split, output, input and net VAT, the data needed for a synthetic firm panel, and open questions. diff --git a/docs/book/programs/gov/hmrc/firm-vat.md b/docs/book/programs/gov/hmrc/firm-vat.md index 9ae9e79977..d45369d2d4 100644 --- a/docs/book/programs/gov/hmrc/firm-vat.md +++ b/docs/book/programs/gov/hmrc/firm-vat.md @@ -7,9 +7,10 @@ consumption*: the `vat` variable applies `gov.hmrc.vat.standard_rate` and spending (`full_rate_vat_consumption`, `reduced_rate_vat_consumption`), then grosses the result up to VAT receipts. There is no business side. This page sets out the scope for adding firm-level VAT and a `Firm` entity, tracked in -[#1320](https://github.com/PolicyEngine/policyengine-uk/issues/1320) and -[#1333](https://github.com/PolicyEngine/policyengine-uk/issues/1333). Both -issues are still open (October 2026). +[#1320](https://github.com/PolicyEngine/policyengine-uk/issues/1320), which is +still open (October 2026). The companion analysis issue, +[#1333](https://github.com/PolicyEngine/policyengine-uk/issues/1333), was +closed on 20 October 2026 as a duplicate of #1320. ``` ## Why firm-level VAT? @@ -84,17 +85,20 @@ Firm = build_entity( "key": "owner", "plural": "owners", "label": "Owner", - "doc": "Person or household that owns the firm.", + "doc": "Person who owns the firm.", } ], - containing_entities=["state"], + containing_entities=[], ) ``` The `containing_entities` set deliberately does *not* include `household` because incorporated firms have no household; the link for sole traders is via an explicit `firm_owning_household_id` input -variable rather than entity nesting. +variable rather than entity nesting. (The existing `Household` and +`BenUnit` entities list a `"state"` containing entity, but PolicyEngine UK +has no `state` entity, so the firm should not copy it.) Only people can be +members of a group entity, so the owner role holds people. ### Variables @@ -144,27 +148,25 @@ component sits against our current data: | Component | Public source | FRS coverage | Datalab source | |-----------|---------------|--------------|----------------| -| Firm turnover distribution | ONS *Business Demography* | sole-trader / partnership turnover via FRS self-employment income | HMRC Datalab: anonymised VAT returns | -| Industry sector | SIC codes from ONS *Inter-Departmental Business Register (IDBR)* | not in FRS | HMRC Datalab | +| Firm turnover distribution | ONS *UK business: activity, size and location* | sole-trader / partnership profit (not turnover) via FRS self-employment income | HMRC Datalab: anonymised VAT returns | +| Industry sector | SIC codes from ONS *Inter-Departmental Business Register (IDBR)* | main-job SIC 2007 division only (`sic_industry_division`); no firm-level sector | HMRC Datalab | | VAT registration share | HMRC *VAT statistics* (annual) | not in FRS | HMRC Datalab | | Input VAT shares | ONS *Supply and Use tables* | not applicable | HMRC Datalab | ### Proposed imputation approach -1. Build a **synthetic firm panel** weighted to ONS Business Demography - counts by SIC sector and turnover band. +1. Build a **synthetic firm panel** weighted to ONS *UK business: + activity, size and location* counts by SIC sector and turnover band. 2. Attach to each firm a registration status, supply split, and intermediate-consumption ratio drawn from HMRC VAT statistics and ONS Supply and Use tables. 3. Calibrate the panel so that summed `firm_net_vat_liability` matches - the HMRC VAT receipts outturn for the year. This mirrors the - second-stage imputation pattern discussed in - [#1621](https://github.com/PolicyEngine/policyengine-uk/issues/1621). + the HMRC VAT receipts outturn for the year. 4. For sole traders and partnerships, link the synthetic firm row back to the FRS household that owns it via self-employment income. -The companion repo [`policyengine/uk-vatlab`][vatlab] hosts the analysis -files (#1333) used to size each step before they are productionised. +The companion repo [`policyengine/uk-vatlab`][vatlab] hosts the firm-level +VAT analysis files linked from #1333. ## Effort estimate @@ -193,10 +195,10 @@ files (#1333) used to size each step before they are productionised. ## References -- HMRC, [VAT rates](https://www.gov.uk/vat-rates) and [VAT registration thresholds](https://www.gov.uk/vat-registration-thresholds). +- HMRC, [VAT rates](https://www.gov.uk/vat-rates) and [VAT thresholds](https://www.gov.uk/how-vat-works/vat-thresholds). - [Value Added Tax Act 1994](https://www.legislation.gov.uk/ukpga/1994/23/contents): primary statute. - HMRC, [VAT statistics](https://www.gov.uk/government/statistics/value-added-tax-vat-annual-statistics): annual outturn used for calibration. -- ONS, [UK Business: Activity, Size and Location](https://www.ons.gov.uk/businessindustryandtrade/business/activitysizeandlocation) (the IDBR-based business demography release). +- ONS, [UK business: activity, size and location](https://www.ons.gov.uk/businessindustryandtrade/business/activitysizeandlocation/datasets/ukbusinessactivitysizeandlocation): enterprise counts by industry (SIC) and turnover band from the Inter-Departmental Business Register (IDBR). - ONS, [Supply and Use tables](https://www.ons.gov.uk/economy/nationalaccounts/supplyandusetables): intermediate consumption shares. - Companion analysis repo: [`policyengine/uk-vatlab`][vatlab] (#1333). From 167ab176f06809c992b03dbecd6e883bab7f9573 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 23 Oct 2026 03:09:58 -0400 Subject: [PATCH 6/7] Note core's one-group-per-person rule and the IDBR count coverage From the independent review of the corrections: policyengine-core puts every person in exactly one instance of each group entity and gives anyone unlisted a one-person instance (simulation_builder.py:449-458), which the proposed Firm design has to handle; and ONS's UK business counts cover only VAT- and/or PAYE-based enterprises. Co-Authored-By: Claude Opus 5.5 --- docs/book/programs/gov/hmrc/firm-vat.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/book/programs/gov/hmrc/firm-vat.md b/docs/book/programs/gov/hmrc/firm-vat.md index d45369d2d4..10a07fe149 100644 --- a/docs/book/programs/gov/hmrc/firm-vat.md +++ b/docs/book/programs/gov/hmrc/firm-vat.md @@ -97,8 +97,12 @@ The `containing_entities` set deliberately does *not* include sole traders is via an explicit `firm_owning_household_id` input variable rather than entity nesting. (The existing `Household` and `BenUnit` entities list a `"state"` containing entity, but PolicyEngine UK -has no `state` entity, so the firm should not copy it.) Only people can be -members of a group entity, so the owner role holds people. +has no `state` entity, so the firm should not copy it.) In policyengine-core +only people can be members of a group entity, so the owner role holds people. +Core also places each person in exactly one instance of every group entity: a +person cannot own two firms, and anyone not listed in a firm is given a +one-person firm of their own, so the design needs a way to represent people +who own no firm and incorporated firms with no owner in the data. ### Variables @@ -198,7 +202,7 @@ VAT analysis files linked from #1333. - HMRC, [VAT rates](https://www.gov.uk/vat-rates) and [VAT thresholds](https://www.gov.uk/how-vat-works/vat-thresholds). - [Value Added Tax Act 1994](https://www.legislation.gov.uk/ukpga/1994/23/contents): primary statute. - HMRC, [VAT statistics](https://www.gov.uk/government/statistics/value-added-tax-vat-annual-statistics): annual outturn used for calibration. -- ONS, [UK business: activity, size and location](https://www.ons.gov.uk/businessindustryandtrade/business/activitysizeandlocation/datasets/ukbusinessactivitysizeandlocation): enterprise counts by industry (SIC) and turnover band from the Inter-Departmental Business Register (IDBR). +- ONS, [UK business: activity, size and location](https://www.ons.gov.uk/businessindustryandtrade/business/activitysizeandlocation/datasets/ukbusinessactivitysizeandlocation): counts of VAT- and/or PAYE-based enterprises by industry (SIC) and turnover band from the Inter-Departmental Business Register (IDBR). - ONS, [Supply and Use tables](https://www.ons.gov.uk/economy/nationalaccounts/supplyandusetables): intermediate consumption shares. - Companion analysis repo: [`policyengine/uk-vatlab`][vatlab] (#1333). From ae8513db5a9a612ddf30ad9eccd212c5e46b02d5 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 23 Oct 2026 03:47:42 -0400 Subject: [PATCH 7/7] Describe core's group membership rule for each way of building Second-round review: a situation that lists households but no firms puts everyone in one firm (simulation_builder.py add_default_group_entity), and a dataset build must give every person a group id; only a situation that lists firms gives the unlisted a one-person firm. Co-Authored-By: Claude Opus 5.5 --- docs/book/programs/gov/hmrc/firm-vat.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/book/programs/gov/hmrc/firm-vat.md b/docs/book/programs/gov/hmrc/firm-vat.md index 10a07fe149..b06be28580 100644 --- a/docs/book/programs/gov/hmrc/firm-vat.md +++ b/docs/book/programs/gov/hmrc/firm-vat.md @@ -99,10 +99,13 @@ variable rather than entity nesting. (The existing `Household` and `BenUnit` entities list a `"state"` containing entity, but PolicyEngine UK has no `state` entity, so the firm should not copy it.) In policyengine-core only people can be members of a group entity, so the owner role holds people. -Core also places each person in exactly one instance of every group entity: a -person cannot own two firms, and anyone not listed in a firm is given a -one-person firm of their own, so the design needs a way to represent people -who own no firm and incorporated firms with no owner in the data. +Core also places each person in exactly one instance of every group entity, +so a person cannot own two firms and everyone belongs to some firm: a +situation that lists firms gives anyone it leaves out a one-person firm, one +that lists households but no firms puts all its people in a single firm, and +a dataset build must assign every person a firm. The design therefore needs +a way to represent people who own no firm and incorporated firms with no +owner in the data. ### Variables