diff --git a/changelog.d/scotgov-council-tax-stock-pins.fixed.md b/changelog.d/scotgov-council-tax-stock-pins.fixed.md new file mode 100644 index 00000000..e535bff2 --- /dev/null +++ b/changelog.d/scotgov-council-tax-stock-pins.fixed.md @@ -0,0 +1 @@ +Pin the nine scotgov.council_tax_stock UK calibration targets to Scotland: the substring geography rule saw no "scotland" in "scotgov" and pinned them to the UK, so the Scotland-stamped CTAXBASE chargeable-dwelling facts could never match and the whole family was held as no_fact_at_or_before_period. diff --git a/packages/microcosm-build/src/microcosm/build/uk/target_reference_membership.json b/packages/microcosm-build/src/microcosm/build/uk/target_reference_membership.json index 6ef0d46f..3bbfd605 100644 --- a/packages/microcosm-build/src/microcosm/build/uk/target_reference_membership.json +++ b/packages/microcosm-build/src/microcosm/build/uk/target_reference_membership.json @@ -3,11 +3,11 @@ "target_period": 2025, "candidate_count": 417, "contract_target_count": 189, - "active_reference_count": 388, + "active_reference_count": 397, "status_counts": { - "active": 388, + "active": 397, "multi_fact": 1, - "no_fact_at_or_before_period": 27, + "no_fact_at_or_before_period": 18, "signed_excluded": 1 }, "geography_pins": { @@ -609,7 +609,7 @@ }, "scotgov.council_tax_stock.band_a": { "geography_level": "country", - "geography_id": "K02000001" + "geography_id": "S92000003" }, "voa.council_tax_stock.band_b": { "geography_level": "country", @@ -617,7 +617,7 @@ }, "scotgov.council_tax_stock.band_b": { "geography_level": "country", - "geography_id": "K02000001" + "geography_id": "S92000003" }, "voa.council_tax_stock.band_c": { "geography_level": "country", @@ -625,7 +625,7 @@ }, "scotgov.council_tax_stock.band_c": { "geography_level": "country", - "geography_id": "K02000001" + "geography_id": "S92000003" }, "voa.council_tax_stock.band_d": { "geography_level": "country", @@ -633,7 +633,7 @@ }, "scotgov.council_tax_stock.band_d": { "geography_level": "country", - "geography_id": "K02000001" + "geography_id": "S92000003" }, "voa.council_tax_stock.band_e": { "geography_level": "country", @@ -641,7 +641,7 @@ }, "scotgov.council_tax_stock.band_e": { "geography_level": "country", - "geography_id": "K02000001" + "geography_id": "S92000003" }, "voa.council_tax_stock.band_f": { "geography_level": "country", @@ -649,7 +649,7 @@ }, "scotgov.council_tax_stock.band_f": { "geography_level": "country", - "geography_id": "K02000001" + "geography_id": "S92000003" }, "voa.council_tax_stock.band_g": { "geography_level": "country", @@ -657,7 +657,7 @@ }, "scotgov.council_tax_stock.band_g": { "geography_level": "country", - "geography_id": "K02000001" + "geography_id": "S92000003" }, "voa.council_tax_stock.band_h": { "geography_level": "country", @@ -665,7 +665,7 @@ }, "scotgov.council_tax_stock.band_h": { "geography_level": "country", - "geography_id": "K02000001" + "geography_id": "S92000003" }, "voa.council_tax_stock.total": { "geography_level": "country", @@ -673,7 +673,7 @@ }, "scotgov.council_tax_stock.total": { "geography_level": "country", - "geography_id": "K02000001" + "geography_id": "S92000003" }, "scotgov.scottish_child_payment_spending": { "geography_level": "country", @@ -2487,46 +2487,91 @@ "from": "2025-03", "to": "2025" }, + { + "name": "scotgov.council_tax_stock.band_a", + "from": "2025-09", + "to": "2025" + }, { "name": "voa.council_tax_stock.band_b", "from": "2025-03", "to": "2025" }, + { + "name": "scotgov.council_tax_stock.band_b", + "from": "2025-09", + "to": "2025" + }, { "name": "voa.council_tax_stock.band_c", "from": "2025-03", "to": "2025" }, + { + "name": "scotgov.council_tax_stock.band_c", + "from": "2025-09", + "to": "2025" + }, { "name": "voa.council_tax_stock.band_d", "from": "2025-03", "to": "2025" }, + { + "name": "scotgov.council_tax_stock.band_d", + "from": "2025-09", + "to": "2025" + }, { "name": "voa.council_tax_stock.band_e", "from": "2025-03", "to": "2025" }, + { + "name": "scotgov.council_tax_stock.band_e", + "from": "2025-09", + "to": "2025" + }, { "name": "voa.council_tax_stock.band_f", "from": "2025-03", "to": "2025" }, + { + "name": "scotgov.council_tax_stock.band_f", + "from": "2025-09", + "to": "2025" + }, { "name": "voa.council_tax_stock.band_g", "from": "2025-03", "to": "2025" }, + { + "name": "scotgov.council_tax_stock.band_g", + "from": "2025-09", + "to": "2025" + }, { "name": "voa.council_tax_stock.band_h", "from": "2025-03", "to": "2025" }, + { + "name": "scotgov.council_tax_stock.band_h", + "from": "2025-09", + "to": "2025" + }, { "name": "voa.council_tax_stock.total", "from": "2025-03", "to": "2025" }, + { + "name": "scotgov.council_tax_stock.total", + "from": "2025-09", + "to": "2025" + }, { "name": "ons.public_sector_employment", "from": "2024-12", @@ -7071,14 +7116,17 @@ ] }, "scotgov.council_tax_stock.band_a": { - "status": "no_fact_at_or_before_period", + "status": "active", "candidates": [ { "name": "scotgov.council_tax_stock.band_a", - "status": "no_fact_at_or_before_period", - "matched_fact_count_overall": 0, - "matched_fact_count_at_or_before_period": 0, - "error": "ledger_reference_compile_status_no_fact_at_or_before_period" + "status": "active", + "matched_fact_count_overall": 1, + "matched_fact_count_at_or_before_period": 1, + "resolved_period": 2025, + "resolved_value": 498707.0, + "resolved_fact_period": "2025-09", + "resolved_fact_key": "ledger_aggregate_fact_v2_d16c53fe6a1c8f4f5886b7e5" } ] }, @@ -7098,14 +7146,17 @@ ] }, "scotgov.council_tax_stock.band_b": { - "status": "no_fact_at_or_before_period", + "status": "active", "candidates": [ { "name": "scotgov.council_tax_stock.band_b", - "status": "no_fact_at_or_before_period", - "matched_fact_count_overall": 0, - "matched_fact_count_at_or_before_period": 0, - "error": "ledger_reference_compile_status_no_fact_at_or_before_period" + "status": "active", + "matched_fact_count_overall": 1, + "matched_fact_count_at_or_before_period": 1, + "resolved_period": 2025, + "resolved_value": 583705.0, + "resolved_fact_period": "2025-09", + "resolved_fact_key": "ledger_aggregate_fact_v2_2f95ec98ae61f9898bd47ed9" } ] }, @@ -7125,14 +7176,17 @@ ] }, "scotgov.council_tax_stock.band_c": { - "status": "no_fact_at_or_before_period", + "status": "active", "candidates": [ { "name": "scotgov.council_tax_stock.band_c", - "status": "no_fact_at_or_before_period", - "matched_fact_count_overall": 0, - "matched_fact_count_at_or_before_period": 0, - "error": "ledger_reference_compile_status_no_fact_at_or_before_period" + "status": "active", + "matched_fact_count_overall": 1, + "matched_fact_count_at_or_before_period": 1, + "resolved_period": 2025, + "resolved_value": 426388.0, + "resolved_fact_period": "2025-09", + "resolved_fact_key": "ledger_aggregate_fact_v2_c9781708df55dc5d197e6623" } ] }, @@ -7152,14 +7206,17 @@ ] }, "scotgov.council_tax_stock.band_d": { - "status": "no_fact_at_or_before_period", + "status": "active", "candidates": [ { "name": "scotgov.council_tax_stock.band_d", - "status": "no_fact_at_or_before_period", - "matched_fact_count_overall": 0, - "matched_fact_count_at_or_before_period": 0, - "error": "ledger_reference_compile_status_no_fact_at_or_before_period" + "status": "active", + "matched_fact_count_overall": 1, + "matched_fact_count_at_or_before_period": 1, + "resolved_period": 2025, + "resolved_value": 369621.0, + "resolved_fact_period": "2025-09", + "resolved_fact_key": "ledger_aggregate_fact_v2_ae1fe03809a505b820479598" } ] }, @@ -7179,14 +7236,17 @@ ] }, "scotgov.council_tax_stock.band_e": { - "status": "no_fact_at_or_before_period", + "status": "active", "candidates": [ { "name": "scotgov.council_tax_stock.band_e", - "status": "no_fact_at_or_before_period", - "matched_fact_count_overall": 0, - "matched_fact_count_at_or_before_period": 0, - "error": "ledger_reference_compile_status_no_fact_at_or_before_period" + "status": "active", + "matched_fact_count_overall": 1, + "matched_fact_count_at_or_before_period": 1, + "resolved_period": 2025, + "resolved_value": 366881.0, + "resolved_fact_period": "2025-09", + "resolved_fact_key": "ledger_aggregate_fact_v2_e83153e0de40fb74471c805f" } ] }, @@ -7206,14 +7266,17 @@ ] }, "scotgov.council_tax_stock.band_f": { - "status": "no_fact_at_or_before_period", + "status": "active", "candidates": [ { "name": "scotgov.council_tax_stock.band_f", - "status": "no_fact_at_or_before_period", - "matched_fact_count_overall": 0, - "matched_fact_count_at_or_before_period": 0, - "error": "ledger_reference_compile_status_no_fact_at_or_before_period" + "status": "active", + "matched_fact_count_overall": 1, + "matched_fact_count_at_or_before_period": 1, + "resolved_period": 2025, + "resolved_value": 221282.0, + "resolved_fact_period": "2025-09", + "resolved_fact_key": "ledger_aggregate_fact_v2_b24b6409c1473600c03999ec" } ] }, @@ -7233,14 +7296,17 @@ ] }, "scotgov.council_tax_stock.band_g": { - "status": "no_fact_at_or_before_period", + "status": "active", "candidates": [ { "name": "scotgov.council_tax_stock.band_g", - "status": "no_fact_at_or_before_period", - "matched_fact_count_overall": 0, - "matched_fact_count_at_or_before_period": 0, - "error": "ledger_reference_compile_status_no_fact_at_or_before_period" + "status": "active", + "matched_fact_count_overall": 1, + "matched_fact_count_at_or_before_period": 1, + "resolved_period": 2025, + "resolved_value": 142084.0, + "resolved_fact_period": "2025-09", + "resolved_fact_key": "ledger_aggregate_fact_v2_c86494a855b00998122989d6" } ] }, @@ -7260,14 +7326,17 @@ ] }, "scotgov.council_tax_stock.band_h": { - "status": "no_fact_at_or_before_period", + "status": "active", "candidates": [ { "name": "scotgov.council_tax_stock.band_h", - "status": "no_fact_at_or_before_period", - "matched_fact_count_overall": 0, - "matched_fact_count_at_or_before_period": 0, - "error": "ledger_reference_compile_status_no_fact_at_or_before_period" + "status": "active", + "matched_fact_count_overall": 1, + "matched_fact_count_at_or_before_period": 1, + "resolved_period": 2025, + "resolved_value": 14481.0, + "resolved_fact_period": "2025-09", + "resolved_fact_key": "ledger_aggregate_fact_v2_60d9ae638eff29fc1c88907e" } ] }, @@ -7287,14 +7356,17 @@ ] }, "scotgov.council_tax_stock.total": { - "status": "no_fact_at_or_before_period", + "status": "active", "candidates": [ { "name": "scotgov.council_tax_stock.total", - "status": "no_fact_at_or_before_period", - "matched_fact_count_overall": 0, - "matched_fact_count_at_or_before_period": 0, - "error": "ledger_reference_compile_status_no_fact_at_or_before_period" + "status": "active", + "matched_fact_count_overall": 1, + "matched_fact_count_at_or_before_period": 1, + "resolved_period": 2025, + "resolved_value": 2623149.0, + "resolved_fact_period": "2025-09", + "resolved_fact_key": "ledger_aggregate_fact_v2_ca77a0f0a777ccba05e4bef9" } ] }, @@ -7625,8 +7697,8 @@ { "family": "council_tax_stock", "status": "active_declared_rows", - "active_reference_count": 9, - "signed_rationale": "VOA council-tax stock bands are declared as nine explicit target rows, including total, and each resolves with its country-level geography and band pin." + "active_reference_count": 18, + "signed_rationale": "VOA (England and Wales) and Scottish Government CTAXBASE (Scotland) council-tax stock bands are declared as nine explicit target rows each, including total, and each resolves with its country-level geography and band pin." } ], "signed_exclusion_rationales": [ diff --git a/packages/microcosm-build/src/microcosm/build/uk/target_references.json b/packages/microcosm-build/src/microcosm/build/uk/target_references.json index 055e61fe..2bc9a065 100644 --- a/packages/microcosm-build/src/microcosm/build/uk/target_references.json +++ b/packages/microcosm-build/src/microcosm/build/uk/target_references.json @@ -8994,6 +8994,25 @@ "uprating_from_period": "2025-03", "uprating_to_period": 2025 }, + { + "name": "scotgov.council_tax_stock.band_a", + "ledger_selector": { + "source_name": "scotgov", + "source_measure_id": "band_a", + "geography_level": "country", + "geography_id": "S92000003" + }, + "entity": "household", + "measure": "voa/council_tax/SCOTLAND/band_a", + "family": "council_tax_stock", + "period": 2025, + "metadata": { + "contract_target_id": "scotgov.council_tax_stock.band_a", + "measure_kind": "prepared_column" + }, + "uprating_from_period": "2025-09", + "uprating_to_period": 2025 + }, { "name": "voa.council_tax_stock.band_b", "ledger_selector": { @@ -9013,6 +9032,25 @@ "uprating_from_period": "2025-03", "uprating_to_period": 2025 }, + { + "name": "scotgov.council_tax_stock.band_b", + "ledger_selector": { + "source_name": "scotgov", + "source_measure_id": "band_b", + "geography_level": "country", + "geography_id": "S92000003" + }, + "entity": "household", + "measure": "voa/council_tax/SCOTLAND/band_b", + "family": "council_tax_stock", + "period": 2025, + "metadata": { + "contract_target_id": "scotgov.council_tax_stock.band_b", + "measure_kind": "prepared_column" + }, + "uprating_from_period": "2025-09", + "uprating_to_period": 2025 + }, { "name": "voa.council_tax_stock.band_c", "ledger_selector": { @@ -9032,6 +9070,25 @@ "uprating_from_period": "2025-03", "uprating_to_period": 2025 }, + { + "name": "scotgov.council_tax_stock.band_c", + "ledger_selector": { + "source_name": "scotgov", + "source_measure_id": "band_c", + "geography_level": "country", + "geography_id": "S92000003" + }, + "entity": "household", + "measure": "voa/council_tax/SCOTLAND/band_c", + "family": "council_tax_stock", + "period": 2025, + "metadata": { + "contract_target_id": "scotgov.council_tax_stock.band_c", + "measure_kind": "prepared_column" + }, + "uprating_from_period": "2025-09", + "uprating_to_period": 2025 + }, { "name": "voa.council_tax_stock.band_d", "ledger_selector": { @@ -9051,6 +9108,25 @@ "uprating_from_period": "2025-03", "uprating_to_period": 2025 }, + { + "name": "scotgov.council_tax_stock.band_d", + "ledger_selector": { + "source_name": "scotgov", + "source_measure_id": "band_d", + "geography_level": "country", + "geography_id": "S92000003" + }, + "entity": "household", + "measure": "voa/council_tax/SCOTLAND/band_d", + "family": "council_tax_stock", + "period": 2025, + "metadata": { + "contract_target_id": "scotgov.council_tax_stock.band_d", + "measure_kind": "prepared_column" + }, + "uprating_from_period": "2025-09", + "uprating_to_period": 2025 + }, { "name": "voa.council_tax_stock.band_e", "ledger_selector": { @@ -9070,6 +9146,25 @@ "uprating_from_period": "2025-03", "uprating_to_period": 2025 }, + { + "name": "scotgov.council_tax_stock.band_e", + "ledger_selector": { + "source_name": "scotgov", + "source_measure_id": "band_e", + "geography_level": "country", + "geography_id": "S92000003" + }, + "entity": "household", + "measure": "voa/council_tax/SCOTLAND/band_e", + "family": "council_tax_stock", + "period": 2025, + "metadata": { + "contract_target_id": "scotgov.council_tax_stock.band_e", + "measure_kind": "prepared_column" + }, + "uprating_from_period": "2025-09", + "uprating_to_period": 2025 + }, { "name": "voa.council_tax_stock.band_f", "ledger_selector": { @@ -9089,6 +9184,25 @@ "uprating_from_period": "2025-03", "uprating_to_period": 2025 }, + { + "name": "scotgov.council_tax_stock.band_f", + "ledger_selector": { + "source_name": "scotgov", + "source_measure_id": "band_f", + "geography_level": "country", + "geography_id": "S92000003" + }, + "entity": "household", + "measure": "voa/council_tax/SCOTLAND/band_f", + "family": "council_tax_stock", + "period": 2025, + "metadata": { + "contract_target_id": "scotgov.council_tax_stock.band_f", + "measure_kind": "prepared_column" + }, + "uprating_from_period": "2025-09", + "uprating_to_period": 2025 + }, { "name": "voa.council_tax_stock.band_g", "ledger_selector": { @@ -9108,6 +9222,25 @@ "uprating_from_period": "2025-03", "uprating_to_period": 2025 }, + { + "name": "scotgov.council_tax_stock.band_g", + "ledger_selector": { + "source_name": "scotgov", + "source_measure_id": "band_g", + "geography_level": "country", + "geography_id": "S92000003" + }, + "entity": "household", + "measure": "voa/council_tax/SCOTLAND/band_g", + "family": "council_tax_stock", + "period": 2025, + "metadata": { + "contract_target_id": "scotgov.council_tax_stock.band_g", + "measure_kind": "prepared_column" + }, + "uprating_from_period": "2025-09", + "uprating_to_period": 2025 + }, { "name": "voa.council_tax_stock.band_h", "ledger_selector": { @@ -9127,6 +9260,25 @@ "uprating_from_period": "2025-03", "uprating_to_period": 2025 }, + { + "name": "scotgov.council_tax_stock.band_h", + "ledger_selector": { + "source_name": "scotgov", + "source_measure_id": "band_h", + "geography_level": "country", + "geography_id": "S92000003" + }, + "entity": "household", + "measure": "voa/council_tax/SCOTLAND/band_h", + "family": "council_tax_stock", + "period": 2025, + "metadata": { + "contract_target_id": "scotgov.council_tax_stock.band_h", + "measure_kind": "prepared_column" + }, + "uprating_from_period": "2025-09", + "uprating_to_period": 2025 + }, { "name": "voa.council_tax_stock.total", "ledger_selector": { @@ -9146,6 +9298,25 @@ "uprating_from_period": "2025-03", "uprating_to_period": 2025 }, + { + "name": "scotgov.council_tax_stock.total", + "ledger_selector": { + "source_name": "scotgov", + "source_measure_id": "total", + "geography_level": "country", + "geography_id": "S92000003" + }, + "entity": "household", + "measure": "voa/council_tax/SCOTLAND/total", + "family": "council_tax_stock", + "period": 2025, + "metadata": { + "contract_target_id": "scotgov.council_tax_stock.total", + "measure_kind": "prepared_column" + }, + "uprating_from_period": "2025-09", + "uprating_to_period": 2025 + }, { "name": "ons.savings_interest_income", "ledger_selector": { diff --git a/packages/microcosm-build/tests/test_country_spec.py b/packages/microcosm-build/tests/test_country_spec.py index e4be8693..6af8d265 100644 --- a/packages/microcosm-build/tests/test_country_spec.py +++ b/packages/microcosm-build/tests/test_country_spec.py @@ -393,7 +393,7 @@ def test_uk_target_references_accept_regenerated_contract_fields(self) -> None: spec = load_country_spec("uk") references = {reference.name: reference for reference in spec.target_references} - assert len(references) == 388 + assert len(references) == 397 assert references["obr.esa"].value_operation == "sum" assert references["dwp.uc.households"].value_operation == ( "calendar_year_average" diff --git a/packages/microcosm-build/tests/test_uk_national_calibration.py b/packages/microcosm-build/tests/test_uk_national_calibration.py index 12a9cddd..49445d4f 100644 --- a/packages/microcosm-build/tests/test_uk_national_calibration.py +++ b/packages/microcosm-build/tests/test_uk_national_calibration.py @@ -16,7 +16,7 @@ from microcosm.build.uk_runtime.national_frame import validate_uk_national_frame from microcosm.frame import EntitySchema, Frame, WeightKind, Weights -ACTIVE_REFERENCE_COUNT = 388 +ACTIVE_REFERENCE_COUNT = 397 def _uc_reference(**overrides) -> LedgerTargetReference: diff --git a/packages/microcosm-build/tests/test_uk_target_references.py b/packages/microcosm-build/tests/test_uk_target_references.py index 60e70fe8..4bd50e1a 100644 --- a/packages/microcosm-build/tests/test_uk_target_references.py +++ b/packages/microcosm-build/tests/test_uk_target_references.py @@ -33,7 +33,7 @@ _value_operation_by_target_id, ) -ACTIVE_REFERENCE_COUNT = 388 +ACTIVE_REFERENCE_COUNT = 397 UK_DATA_REPO = "policyengine-" + "uk-data" FIXTURE_REFERENCE_NAMES = { @@ -184,15 +184,67 @@ def test_ons_age_total_targets_pin_exact_age_dimension_set() -> None: ]["dimensions"] == ["age"] +def test_scotgov_council_tax_stock_pins_are_scotland_and_the_rule_is_scoped() -> None: + """The CTAXBASE stock facts are stamped S92000003 in Chronicle. + + The substring pin rule sees no "scotland" in "scotgov" and used to pin the + nine stock targets to the UK, so they could never match. The fix is scoped + to the stock family: every other Scotland pin still comes from the + substring rule, and the unrelated scotgov child-payment target keeps the + UK pin it had. + """ + contract = _load_uk_resource("uk_national_targets.json") + pins = _geography_pins(contract) + stock_ids = { + str(target["target_id"]) + for target in contract["targets"] + if str(target["target_id"]).startswith("scotgov.council_tax_stock.") + } + assert stock_ids == {f"scotgov.council_tax_stock.band_{band}" for band in "abcdefgh"} | { + "scotgov.council_tax_stock.total" + } + assert {pins[target_id]["geography_id"] for target_id in stock_ids} == {"S92000003"} + assert pins["scotgov.scottish_child_payment_spending"]["geography_id"] == "K02000001" + + def haystack(target: dict) -> str: + selector = target.get("ledger_selector") or {} + return " ".join( + ( + str(target["target_id"]).lower(), + str(selector.get("source_concept", "")).lower(), + str(selector.get("source_measure_id", "")).lower(), + ) + ) + + substring_scotland = { + str(target["target_id"]) + for target in contract["targets"] + if "scotland" in haystack(target) + and "northern" not in haystack(target) + and "domestic_rates" not in haystack(target) + } + scotland_pinned = { + target_id + for target_id, pin in pins.items() + if pin["geography_id"] == "S92000003" + } + assert scotland_pinned == stock_ids | substring_scotland + + membership = _load_uk_resource("target_reference_membership.json") + for target_id in stock_ids: + assert membership["geography_pins"][target_id]["geography_id"] == "S92000003" + assert membership["targets"][target_id]["status"] == "active" + + def test_uk_target_reference_membership_report_is_packaged() -> None: membership = _load_uk_resource("target_reference_membership.json") assert membership["target_period"] == 2025 assert membership["active_reference_count"] == ACTIVE_REFERENCE_COUNT assert membership["status_counts"] == { - "active": 388, + "active": 397, "multi_fact": 1, - "no_fact_at_or_before_period": 27, + "no_fact_at_or_before_period": 18, "signed_excluded": 1, } assert membership["genuine_sum_residue"] @@ -230,11 +282,12 @@ def test_uk_target_reference_membership_report_is_packaged() -> None: { "family": "council_tax_stock", "status": "active_declared_rows", - "active_reference_count": 9, + "active_reference_count": 18, "signed_rationale": ( - "VOA council-tax stock bands are declared as nine explicit " - "target rows, including total, and each resolves with its " - "country-level geography and band pin." + "VOA (England and Wales) and Scottish Government CTAXBASE " + "(Scotland) council-tax stock bands are declared as nine " + "explicit target rows each, including total, and each resolves " + "with its country-level geography and band pin." ), }, ] diff --git a/tools/generate_uk_target_references.py b/tools/generate_uk_target_references.py index af4da650..8ccc4e3d 100644 --- a/tools/generate_uk_target_references.py +++ b/tools/generate_uk_target_references.py @@ -160,8 +160,17 @@ def _geography_pins(contract: Mapping[str, Any]) -> dict[str, dict[str, str]]: } +SCOTGOV_COUNCIL_TAX_STOCK_PREFIX = "scotgov.council_tax_stock." + + def _geography_id_for_target(target: Mapping[str, Any]) -> str: target_id = str(target["target_id"]).lower() + if target_id.startswith(SCOTGOV_COUNCIL_TAX_STOCK_PREFIX): + # The Scottish Government CTAXBASE chargeable-dwelling facts are + # stamped S92000003 in Chronicle; the substring rule below sees no + # "scotland" in "scotgov" and would fall through to the UK pin, which + # never matches a Scotland-stamped fact. + return UK_GEOGRAPHY_IDS["scotland"] selector = target.get("ledger_selector") or {} concept = str(selector.get("source_concept", "")).lower() measure = str(selector.get("source_measure_id", "")).lower() @@ -314,7 +323,7 @@ def _add_uk_membership_accounting( 1 for reference in references if reference["metadata"]["contract_target_id"].startswith( - "voa.council_tax_stock." + ("voa.council_tax_stock.", SCOTGOV_COUNCIL_TAX_STOCK_PREFIX) ) ) report["fanout_family_outcomes"] = [ @@ -352,9 +361,10 @@ def _add_uk_membership_accounting( "status": "active_declared_rows", "active_reference_count": council_tax_count, "signed_rationale": ( - "VOA council-tax stock bands are declared as nine explicit " - "target rows, including total, and each resolves with its " - "country-level geography and band pin." + "VOA (England and Wales) and Scottish Government CTAXBASE " + "(Scotland) council-tax stock bands are declared as nine " + "explicit target rows each, including total, and each resolves " + "with its country-level geography and band pin." ), }, ]