From 1552cc2eefb228a6aaaae134582fce99bce0fccd Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 23 Aug 2026 16:32:59 +0200 Subject: [PATCH 1/2] Carry the OBR Table 4.1 council tax decomposition rows Adds rows 15 ('Total council tax receipts', the sum of the England, Scotland and Wales rows), 17 ('Council tax accruals adjustment') and 18 ('High-value Council tax surcharge', printed from 2028-29 only) to obr-efo-expenditure-march-2026 (+17 facts, FY2024-FY2030). The active UK calibration reference binds council_tax_less_benefit to row 19, which is row 15 plus NI domestic rates plus the accruals adjustment (plus the surcharge from 2028-29) - components with no household counterpart - so these rows make the redesign of that binding, and the activation of the nation decomposition, expressible as publisher facts. A new test pins the row-15 and row-19 identities for every year. Co-Authored-By: Claude Fable 5 --- docs/pe-uk-source-checklist.md | 2 +- .../source_package.yaml | 771 ++++++++++++++++++ ...chronicle_obr_council_tax_decomposition.py | 73 ++ 3 files changed, 845 insertions(+), 1 deletion(-) create mode 100644 tests/test_chronicle_obr_council_tax_decomposition.py diff --git a/docs/pe-uk-source-checklist.md b/docs/pe-uk-source-checklist.md index a4ce3f07..df4ec50b 100644 --- a/docs/pe-uk-source-checklist.md +++ b/docs/pe-uk-source-checklist.md @@ -47,7 +47,7 @@ cannot be obtained. Nothing in uk-data is absent from this table. | uk-data family (module) | targets | status | Chronicle package(s) | PR | source reuse / notes | |---|---|---|---|---|---| | Region×age population ([`ons_demographics.py`](https://github.com/PolicyEngine/policyengine-uk-data/blob/ebf733c/policyengine_uk_data/targets/sources/ons_demographics.py)) | 142 `ons/{region}_age_{band}` | **ported** | `ons-mye-2023-uk-countries`, `ons-mye-2023-england-regions`, `ons-mye-2024-uk`, `ons-uk-population-projections-2024` | [#137](https://github.com/PolicyEngine/chronicle/pull/137) | **Replaced.** uk-data reads a committed `demographics.csv` with no artifact lineage (the SNPP has no stable machine-readable URL). Chronicle packages the publisher MYE workbooks ([mid-2023 UK](https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/datasets/populationestimatesforukenglandandwalesscotlandandnorthernireland), [mid-2023 E&W regions](https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/datasets/estimatesofthepopulationforenglandandwales), mid-2024 UK) and the [2024-based NPP principal](https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationprojections/datasets/z1zippedpopulationprojectionsdatafilesuk) at single year of age; the fixture's 10-year bands (proven exhaustive, `_age_80_89` = 80+) are a populace-side mapping. | -| OBR EFO receipts + expenditure ([`obr.py`](https://github.com/PolicyEngine/policyengine-uk-data/blob/ebf733c/policyengine_uk_data/targets/sources/obr.py)) | ~28 realized `obr/*` | **ported** | `obr-efo-receipts-march-2026`, `obr-efo-expenditure-march-2026` (196 facts, FY2024–30) | [#139](https://github.com/PolicyEngine/chronicle/pull/139) | **Same bytes.** uk-data commits the March-2026 EFO workbooks under `storage/obr_efo/` (obr.uk 403s CI); the Chronicle artifacts are sha256-identical to them (`f65b6cb7…`, `700bfd70…`), double-fetched from [obr.uk](https://obr.uk/efo/economic-and-fiscal-outlook-march-2026/) on a residential connection. | +| OBR EFO receipts + expenditure ([`obr.py`](https://github.com/PolicyEngine/policyengine-uk-data/blob/ebf733c/policyengine_uk_data/targets/sources/obr.py)) | ~28 realized `obr/*` | **ported** | `obr-efo-receipts-march-2026`, `obr-efo-expenditure-march-2026` (213 facts, FY2024–30; the expenditure package carries the whole Table 4.1 council tax block, including the GB receipts total, the accruals adjustment and the high-value surcharge rows) | [#139](https://github.com/PolicyEngine/chronicle/pull/139) | **Same bytes.** uk-data commits the March-2026 EFO workbooks under `storage/obr_efo/` (obr.uk 403s CI); the Chronicle artifacts are sha256-identical to them (`f65b6cb7…`, `700bfd70…`), double-fetched from [obr.uk](https://obr.uk/efo/economic-and-fiscal-outlook-march-2026/) on a residential connection. | | ONS savings interest ([`ons_savings.py`](https://github.com/PolicyEngine/policyengine-uk-data/blob/ebf733c/policyengine_uk_data/targets/sources/ons_savings.py)) | 1 `ons/savings_interest_income` | **ported** | `ons-savings-interest-income` (8 facts, 2018–2025) | [#139](https://github.com/PolicyEngine/chronicle/pull/139) | **Same series, pinned snapshot.** Both read the [HAXV/UKEA series](https://www.ons.gov.uk/economy/grossdomesticproductgdp/timeseries/haxv/ukea); uk-data downloads at runtime and flat-fills the last actual through 2029 (**excluded, computed**); Chronicle pins the 2026-06-30 CSV release bytes. | | Household types ([`ons_households.py`](https://github.com/PolicyEngine/policyengine-uk-data/blob/ebf733c/policyengine_uk_data/targets/sources/ons_households.py)) | household-type counts | **ported** | `ons-families-households-2025` (80 facts, Table 7, 2018–2025) | [#139](https://github.com/PolicyEngine/chronicle/pull/139) | **Same artifact.** Same `familiesandhouseholdsuk2025.xlsx` "current" edition of [Families and households](https://www.ons.gov.uk/peoplepopulationandcommunity/birthsdeathsandmarriages/families/datasets/familiesandhouseholdsfamiliesandhouseholds); Chronicle pins the bytes (LFS-derived → `survey_aggregate`). | | Salary-sacrifice relief ([`hmrc_salary_sacrifice.py`](https://github.com/PolicyEngine/policyengine-uk-data/blob/ebf733c/policyengine_uk_data/targets/sources/hmrc_salary_sacrifice.py)) | 3 `hmrc/salary_sacrifice_*` | **ported** | `hmrc-salary-sacrifice-relief-2024` (6 facts, TY2024-25) | [#139](https://github.com/PolicyEngine/chronicle/pull/139) | **Updated — uk-data's asset is dead.** uk-data pins `media/687a294e…/Tables_6_1_and_6_2.csv`, which now returns `{"status":"gone"}` (its runtime download silently drops the targets). Chronicle packages the current asset from [Private pension statistics](https://www.gov.uk/government/statistics/personal-and-stakeholder-pensions-statistics) (updated 2026-07-30). uk-data's ×1.03 growth uprating off a 2023-24 base is **excluded (computed)**. | diff --git a/packages/obr/efo_expenditure_march_2026/source_package.yaml b/packages/obr/efo_expenditure_march_2026/source_package.yaml index 56b2f936..20d76b24 100644 --- a/packages/obr/efo_expenditure_march_2026/source_package.yaml +++ b/packages/obr/efo_expenditure_march_2026/source_package.yaml @@ -7,6 +7,15 @@ # record sets carry assertion observation; fy2025-fy2030 remain # source_projection. Row labels are exact # cell text including OBR footnote markers (e.g. 'Incapacity benefits2'). +# Table 4.1's council tax block is carried in full: the England, Scotland and +# Wales receipts rows, 'Total council tax receipts' (row 15, their sum), 'NI +# domestic rates', the 'Council tax accruals adjustment' (row 17), the +# 'High-value Council tax surcharge' (row 18, forecast from 2028-29 only; the +# earlier cells are blank and emit no facts) and 'Total net council tax +# receipts' (row 19, which equals rows 15 + 16 + 17 + 18). Consumers that bind +# a household council tax liability choose between the nation rows or row 15 +# (cash receipts, GB) and row 19 (which adds NI domestic rates and the +# accruals adjustment); the percentage-change rows are not ported. schema_version: ledger.source_package.v1 package_id: obr-efo-expenditure-march-2026 label: 'OBR EFO March 2026 detailed forecast tables: expenditure' @@ -5741,3 +5750,765 @@ record_sets: aggregation: sum value_scale: 1000000000 expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2024 + provenance_class: model_output + assertion: observation + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2024.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2024 + sheet_name: '4.1' + period_type: fiscal_year + period: 2024 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_receipts_england_scotland_wales + label: Total council tax receipts + ordinal: 0 + row_number: 15 + expected_row_header_column: B + expected_row_header: Total council tax receipts + table_record_kind: total + measures: + - measure_id: amount + label: Total council tax receipts, FY2024-25 + ordinal: 0 + column: C + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2024-25 + concept: obr.council_tax_receipts_england_scotland_wales + source_concept: obr.council_tax_receipts_england_scotland_wales + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 15 + (''Total council tax receipts''): the sum of the England, Scotland and Wales council + tax receipts rows, before NI domestic rates, the council tax accruals adjustment and + the high-value council tax surcharge that make up row 19 (''Total net council tax receipts''), + GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2025 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2025.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2025 + sheet_name: '4.1' + period_type: fiscal_year + period: 2025 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_receipts_england_scotland_wales + label: Total council tax receipts + ordinal: 0 + row_number: 15 + expected_row_header_column: B + expected_row_header: Total council tax receipts + table_record_kind: total + measures: + - measure_id: amount + label: Total council tax receipts, FY2025-26 + ordinal: 0 + column: D + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2025-26 + concept: obr.council_tax_receipts_england_scotland_wales + source_concept: obr.council_tax_receipts_england_scotland_wales + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 15 + (''Total council tax receipts''): the sum of the England, Scotland and Wales council + tax receipts rows, before NI domestic rates, the council tax accruals adjustment and + the high-value council tax surcharge that make up row 19 (''Total net council tax receipts''), + GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2026 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2026.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2026 + sheet_name: '4.1' + period_type: fiscal_year + period: 2026 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_receipts_england_scotland_wales + label: Total council tax receipts + ordinal: 0 + row_number: 15 + expected_row_header_column: B + expected_row_header: Total council tax receipts + table_record_kind: total + measures: + - measure_id: amount + label: Total council tax receipts, FY2026-27 + ordinal: 0 + column: E + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2026-27 + concept: obr.council_tax_receipts_england_scotland_wales + source_concept: obr.council_tax_receipts_england_scotland_wales + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 15 + (''Total council tax receipts''): the sum of the England, Scotland and Wales council + tax receipts rows, before NI domestic rates, the council tax accruals adjustment and + the high-value council tax surcharge that make up row 19 (''Total net council tax receipts''), + GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2027 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2027.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2027 + sheet_name: '4.1' + period_type: fiscal_year + period: 2027 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_receipts_england_scotland_wales + label: Total council tax receipts + ordinal: 0 + row_number: 15 + expected_row_header_column: B + expected_row_header: Total council tax receipts + table_record_kind: total + measures: + - measure_id: amount + label: Total council tax receipts, FY2027-28 + ordinal: 0 + column: F + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2027-28 + concept: obr.council_tax_receipts_england_scotland_wales + source_concept: obr.council_tax_receipts_england_scotland_wales + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 15 + (''Total council tax receipts''): the sum of the England, Scotland and Wales council + tax receipts rows, before NI domestic rates, the council tax accruals adjustment and + the high-value council tax surcharge that make up row 19 (''Total net council tax receipts''), + GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2028 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2028.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2028 + sheet_name: '4.1' + period_type: fiscal_year + period: 2028 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_receipts_england_scotland_wales + label: Total council tax receipts + ordinal: 0 + row_number: 15 + expected_row_header_column: B + expected_row_header: Total council tax receipts + table_record_kind: total + measures: + - measure_id: amount + label: Total council tax receipts, FY2028-29 + ordinal: 0 + column: G + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2028-29 + concept: obr.council_tax_receipts_england_scotland_wales + source_concept: obr.council_tax_receipts_england_scotland_wales + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 15 + (''Total council tax receipts''): the sum of the England, Scotland and Wales council + tax receipts rows, before NI domestic rates, the council tax accruals adjustment and + the high-value council tax surcharge that make up row 19 (''Total net council tax receipts''), + GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2029 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2029.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2029 + sheet_name: '4.1' + period_type: fiscal_year + period: 2029 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_receipts_england_scotland_wales + label: Total council tax receipts + ordinal: 0 + row_number: 15 + expected_row_header_column: B + expected_row_header: Total council tax receipts + table_record_kind: total + measures: + - measure_id: amount + label: Total council tax receipts, FY2029-30 + ordinal: 0 + column: H + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2029-30 + concept: obr.council_tax_receipts_england_scotland_wales + source_concept: obr.council_tax_receipts_england_scotland_wales + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 15 + (''Total council tax receipts''): the sum of the England, Scotland and Wales council + tax receipts rows, before NI domestic rates, the council tax accruals adjustment and + the high-value council tax surcharge that make up row 19 (''Total net council tax receipts''), + GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2030 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2030.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_receipts_england_scotland_wales.fy2030 + sheet_name: '4.1' + period_type: fiscal_year + period: 2030 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_receipts_england_scotland_wales + label: Total council tax receipts + ordinal: 0 + row_number: 15 + expected_row_header_column: B + expected_row_header: Total council tax receipts + table_record_kind: total + measures: + - measure_id: amount + label: Total council tax receipts, FY2030-31 + ordinal: 0 + column: I + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2030-31 + concept: obr.council_tax_receipts_england_scotland_wales + source_concept: obr.council_tax_receipts_england_scotland_wales + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 15 + (''Total council tax receipts''): the sum of the England, Scotland and Wales council + tax receipts rows, before NI domestic rates, the council tax accruals adjustment and + the high-value council tax surcharge that make up row 19 (''Total net council tax receipts''), + GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2024 + provenance_class: model_output + assertion: observation + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2024.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2024 + sheet_name: '4.1' + period_type: fiscal_year + period: 2024 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_accruals_adjustment + label: Council tax accruals adjustment + ordinal: 0 + row_number: 17 + expected_row_header_column: B + expected_row_header: Council tax accruals adjustment + table_record_kind: total + measures: + - measure_id: amount + label: Council tax accruals adjustment, FY2024-25 + ordinal: 0 + column: C + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2024-25 + concept: obr.council_tax_accruals_adjustment + source_concept: obr.council_tax_accruals_adjustment + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 17 + (''Council tax accruals adjustment''): the accruals adjustment the OBR adds to cash + council tax receipts in row 19 (''Total net council tax receipts''), GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2025 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2025.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2025 + sheet_name: '4.1' + period_type: fiscal_year + period: 2025 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_accruals_adjustment + label: Council tax accruals adjustment + ordinal: 0 + row_number: 17 + expected_row_header_column: B + expected_row_header: Council tax accruals adjustment + table_record_kind: total + measures: + - measure_id: amount + label: Council tax accruals adjustment, FY2025-26 + ordinal: 0 + column: D + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2025-26 + concept: obr.council_tax_accruals_adjustment + source_concept: obr.council_tax_accruals_adjustment + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 17 + (''Council tax accruals adjustment''): the accruals adjustment the OBR adds to cash + council tax receipts in row 19 (''Total net council tax receipts''), GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2026 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2026.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2026 + sheet_name: '4.1' + period_type: fiscal_year + period: 2026 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_accruals_adjustment + label: Council tax accruals adjustment + ordinal: 0 + row_number: 17 + expected_row_header_column: B + expected_row_header: Council tax accruals adjustment + table_record_kind: total + measures: + - measure_id: amount + label: Council tax accruals adjustment, FY2026-27 + ordinal: 0 + column: E + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2026-27 + concept: obr.council_tax_accruals_adjustment + source_concept: obr.council_tax_accruals_adjustment + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 17 + (''Council tax accruals adjustment''): the accruals adjustment the OBR adds to cash + council tax receipts in row 19 (''Total net council tax receipts''), GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2027 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2027.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2027 + sheet_name: '4.1' + period_type: fiscal_year + period: 2027 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_accruals_adjustment + label: Council tax accruals adjustment + ordinal: 0 + row_number: 17 + expected_row_header_column: B + expected_row_header: Council tax accruals adjustment + table_record_kind: total + measures: + - measure_id: amount + label: Council tax accruals adjustment, FY2027-28 + ordinal: 0 + column: F + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2027-28 + concept: obr.council_tax_accruals_adjustment + source_concept: obr.council_tax_accruals_adjustment + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 17 + (''Council tax accruals adjustment''): the accruals adjustment the OBR adds to cash + council tax receipts in row 19 (''Total net council tax receipts''), GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2028 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2028.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2028 + sheet_name: '4.1' + period_type: fiscal_year + period: 2028 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_accruals_adjustment + label: Council tax accruals adjustment + ordinal: 0 + row_number: 17 + expected_row_header_column: B + expected_row_header: Council tax accruals adjustment + table_record_kind: total + measures: + - measure_id: amount + label: Council tax accruals adjustment, FY2028-29 + ordinal: 0 + column: G + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2028-29 + concept: obr.council_tax_accruals_adjustment + source_concept: obr.council_tax_accruals_adjustment + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 17 + (''Council tax accruals adjustment''): the accruals adjustment the OBR adds to cash + council tax receipts in row 19 (''Total net council tax receipts''), GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2029 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2029.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2029 + sheet_name: '4.1' + period_type: fiscal_year + period: 2029 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_accruals_adjustment + label: Council tax accruals adjustment + ordinal: 0 + row_number: 17 + expected_row_header_column: B + expected_row_header: Council tax accruals adjustment + table_record_kind: total + measures: + - measure_id: amount + label: Council tax accruals adjustment, FY2029-30 + ordinal: 0 + column: H + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2029-30 + concept: obr.council_tax_accruals_adjustment + source_concept: obr.council_tax_accruals_adjustment + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 17 + (''Council tax accruals adjustment''): the accruals adjustment the OBR adds to cash + council tax receipts in row 19 (''Total net council tax receipts''), GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2030 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2030.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_accruals_adjustment.fy2030 + sheet_name: '4.1' + period_type: fiscal_year + period: 2030 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_accruals_adjustment + label: Council tax accruals adjustment + ordinal: 0 + row_number: 17 + expected_row_header_column: B + expected_row_header: Council tax accruals adjustment + table_record_kind: total + measures: + - measure_id: amount + label: Council tax accruals adjustment, FY2030-31 + ordinal: 0 + column: I + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2030-31 + concept: obr.council_tax_accruals_adjustment + source_concept: obr.council_tax_accruals_adjustment + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 17 + (''Council tax accruals adjustment''): the accruals adjustment the OBR adds to cash + council tax receipts in row 19 (''Total net council tax receipts''), GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_high_value_surcharge.fy2028 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_high_value_surcharge.fy2028.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_high_value_surcharge.fy2028 + sheet_name: '4.1' + period_type: fiscal_year + period: 2028 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_high_value_surcharge + label: High-value Council tax surcharge + ordinal: 0 + row_number: 18 + expected_row_header_column: B + expected_row_header: High-value Council tax surcharge + table_record_kind: total + measures: + - measure_id: amount + label: High-value Council tax surcharge, FY2028-29 + ordinal: 0 + column: G + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2028-29 + concept: obr.council_tax_high_value_surcharge + source_concept: obr.council_tax_high_value_surcharge + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 18 + (''High-value Council tax surcharge''): the surcharge on high-value properties forecast + from 2028-29, a component of row 19 (''Total net council tax receipts''), GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_high_value_surcharge.fy2029 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_high_value_surcharge.fy2029.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_high_value_surcharge.fy2029 + sheet_name: '4.1' + period_type: fiscal_year + period: 2029 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_high_value_surcharge + label: High-value Council tax surcharge + ordinal: 0 + row_number: 18 + expected_row_header_column: B + expected_row_header: High-value Council tax surcharge + table_record_kind: total + measures: + - measure_id: amount + label: High-value Council tax surcharge, FY2029-30 + ordinal: 0 + column: H + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2029-30 + concept: obr.council_tax_high_value_surcharge + source_concept: obr.council_tax_high_value_surcharge + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 18 + (''High-value Council tax surcharge''): the surcharge on high-value properties forecast + from 2028-29, a component of row 19 (''Total net council tax receipts''), GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number +- record_set_id: obr.efo_2026_03.expenditure.council_tax_high_value_surcharge.fy2030 + provenance_class: model_output + assertion: source_projection + record_set_spec_id: obr.efo_2026_03.expenditure.council_tax_high_value_surcharge.fy2030.v1 + source_record_id_prefix: obr.efo_2026_03.expenditure.council_tax_high_value_surcharge.fy2030 + sheet_name: '4.1' + period_type: fiscal_year + period: 2030 + geography_id: K02000001 + geography_level: country + geography_name: United Kingdom + geography_vintage: current + entity: person + entity_role: resident_population + domain: public_sector_finances + groupby_dimension: obr.efo_line + rows: + - value_id: council_tax_high_value_surcharge + label: High-value Council tax surcharge + ordinal: 0 + row_number: 18 + expected_row_header_column: B + expected_row_header: High-value Council tax surcharge + table_record_kind: total + measures: + - measure_id: amount + label: High-value Council tax surcharge, FY2030-31 + ordinal: 0 + column: I + source_column_id: amount + expected_column_header_row: 5 + expected_column_header: 2030-31 + concept: obr.council_tax_high_value_surcharge + source_concept: obr.council_tax_high_value_surcharge + concept_relation: source_label + concept_authority: obr + concept_evidence_url: https://obr.uk/download/march-2026-economic-and-fiscal-outlook-detailed-forecast-tables-expenditure/ + concept_evidence_notes: 'OBR EFO March 2026 detailed forecast tables, sheet 4.1, row 18 + (''High-value Council tax surcharge''): the surcharge on high-value properties forecast + from 2028-29, a component of row 19 (''Total net council tax receipts''), GBP billion.' + unit: gbp + aggregation: sum + value_scale: 1000000000 + expected_cell_type: number diff --git a/tests/test_chronicle_obr_council_tax_decomposition.py b/tests/test_chronicle_obr_council_tax_decomposition.py new file mode 100644 index 00000000..f1783d88 --- /dev/null +++ b/tests/test_chronicle_obr_council_tax_decomposition.py @@ -0,0 +1,73 @@ +"""OBR EFO March 2026 Table 4.1 council tax block, carried in full. + +Row 19 'Total net council tax receipts' (concept obr.council_tax_total) equals +row 15 'Total council tax receipts' (England + Scotland + Wales) plus NI +domestic rates, the council tax accruals adjustment and, from 2028-29, the +high-value council tax surcharge. The decomposition rows let a consumer bind a +household council tax liability to the GB cash-receipts total instead of the +UK total that carries components with no household counterpart. +""" + +from __future__ import annotations + +import pytest + +from chronicle.source_package import load_source_package + +RECEIPTS_GB = "obr.council_tax_receipts_england_scotland_wales" +ACCRUALS = "obr.council_tax_accruals_adjustment" +SURCHARGE = "obr.council_tax_high_value_surcharge" + + +def _by_concept_period(facts): + table = {} + for fact in facts: + table[(fact.measure.concept, fact.period.value)] = fact + return table + + +def test_obr_table_4_1_council_tax_decomposition_rows(): + package = load_source_package("obr-efo-expenditure-march-2026") + facts = package.build_facts(2026) + table = _by_concept_period(facts) + + receipts_years = {period for concept, period in table if concept == RECEIPTS_GB} + accruals_years = {period for concept, period in table if concept == ACCRUALS} + surcharge_years = {period for concept, period in table if concept == SURCHARGE} + assert receipts_years == set(range(2024, 2031)) + assert accruals_years == set(range(2024, 2031)) + # The publisher prints the surcharge from 2028-29 only; blank cells emit no facts. + assert surcharge_years == {2028, 2029, 2030} + + # FY2025-26: GBP 49.569bn GB receipts, GBP 0.862bn accruals adjustment. + assert table[(RECEIPTS_GB, 2025)].value == pytest.approx(49_569_234_862.02, abs=0.01) + assert table[(ACCRUALS, 2025)].value == pytest.approx(861_928_964.29, abs=0.01) + assert table[(SURCHARGE, 2028)].value == 454_292_600 + assert table[(RECEIPTS_GB, 2024)].assertion == "observation" + assert table[(RECEIPTS_GB, 2025)].assertion == "source_projection" + assert {table[(RECEIPTS_GB, y)].geography.id for y in range(2024, 2031)} == { + "K02000001" + } + + for year in range(2024, 2031): + nations = sum( + table[(concept, year)].value + for concept in ( + "obr.council_tax_england", + "obr.council_tax_scotland", + "obr.council_tax_wales", + ) + ) + # Row 15 is the sum of the three nation rows. + assert table[(RECEIPTS_GB, year)].value == pytest.approx(nations, rel=1e-9) + # Row 19 is row 15 + NI domestic rates + accruals (+ surcharge from 2028-29). + components = ( + table[(RECEIPTS_GB, year)].value + + table[("obr.domestic_rates", year)].value + + table[(ACCRUALS, year)].value + + (table[(SURCHARGE, year)].value if (SURCHARGE, year) in table else 0) + ) + assert table[("obr.council_tax_total", year)].value == pytest.approx( + components, rel=1e-9 + ) + assert len(facts) == 150 From 4f31f7a1ff87ec532283fa7bfad92e02c6a799fd Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 23 Aug 2026 16:32:59 +0200 Subject: [PATCH 2/2] Update Chronicle bundle count goldens for the OBR decomposition rows Co-Authored-By: Claude Fable 5 --- tests/test_chronicle_bundle.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/test_chronicle_bundle.py b/tests/test_chronicle_bundle.py index 70dbdd36..9c390783 100644 --- a/tests/test_chronicle_bundle.py +++ b/tests/test_chronicle_bundle.py @@ -73,7 +73,7 @@ def test_build_bundle_writes_merged_consumer_contract(tmp_path): "aggregate_duplicate_key_count": 0, "entity_count": 11, "error_count": 0, - "fact_count": 156131, + "fact_count": 156148, "geography_count": 12536, "period_count": 191, "semantic_duplicate_key_count": 117, @@ -82,7 +82,7 @@ def test_build_bundle_writes_merged_consumer_contract(tmp_path): "source_package_count": 144, "warning_count": 1, } - assert len(rows) == 156131 + assert len(rows) == 156148 assert {row["provenance_class"] for row in rows} <= { "administrative", "census", @@ -114,7 +114,7 @@ def test_build_bundle_writes_merged_consumer_contract(tmp_path): "jct-obbba-revenue-estimates-2025", "jct-tax-expenditures-2024", ] - assert coverage["fact_count"] == 156131 + assert coverage["fact_count"] == 156148 assert coverage["counts"]["by_source"] == { "bea": 445, "bfp_economic_outlook": 5, @@ -142,7 +142,7 @@ def test_build_bundle_writes_merged_consumer_contract(tmp_path): "nbb_national_accounts": 1, "nisra": 510, "nrs": 5589, - "obr": 253, + "obr": 270, "onem_rva_unemployment": 1, "ons": 65646, "onss_contributions": 1, @@ -515,13 +515,13 @@ def test_build_bundle_writes_merged_consumer_contract(tmp_path): "fiscal_year:2021": 52, "fiscal_year:2022": 52, "fiscal_year:2023": 405, - "fiscal_year:2024": 695, - "fiscal_year:2025": 1308, - "fiscal_year:2026": 1443, - "fiscal_year:2027": 32, - "fiscal_year:2028": 32, - "fiscal_year:2029": 32, - "fiscal_year:2030": 28, + "fiscal_year:2024": 697, + "fiscal_year:2025": 1310, + "fiscal_year:2026": 1445, + "fiscal_year:2027": 34, + "fiscal_year:2028": 35, + "fiscal_year:2029": 35, + "fiscal_year:2030": 31, "month:2021-03": 1, "month:2021-04": 1, "month:2021-05": 1, @@ -634,7 +634,7 @@ def test_build_bundle_writes_merged_consumer_contract(tmp_path): assert ( coverage["counts"]["by_geography"]["congressional_district:5001700US0601"] == 56 ) - assert coverage["counts"]["by_geography"]["country:K02000001"] == 4262 + assert coverage["counts"]["by_geography"]["country:K02000001"] == 4279 assert coverage["counts"]["by_geography"]["country:K03000001"] == 497 assert len(coverage["counts"]["by_geography"]) == 12536 assert coverage["counts"]["by_entity"] == { @@ -646,7 +646,7 @@ def test_build_bundle_writes_merged_consumer_contract(tmp_path): "household": 40513, "institutional_sector": 103, "pension_plan": 2, - "person": 60279, + "person": 60296, "social_protection_scheme": 27, "tax_unit": 40069, }