diff --git a/app/scripts/build-parameter-dependency-map.py b/app/scripts/build-parameter-dependency-map.py index ddf72ccb4..470e54843 100644 --- a/app/scripts/build-parameter-dependency-map.py +++ b/app/scripts/build-parameter-dependency-map.py @@ -2,21 +2,30 @@ The flagship validation layer needs to know which model variables a reform touches, so it can look those variables up in the calibration dashboard and -the scorecard. Grepping formula source for parameter paths misses bracket, -scale, and vectorised accesses; the only exact record is what the model -actually reads at run time. This script runs policyengine-us with -policyengine-core's FullTracer over a subsample of the default microdata, -calculates every variable, and writes two edge sets: +the scorecard, and the report's household section uses the same map to +suggest the household inputs a reform reads. Grepping formula source for +parameter paths misses bracket, scale, and vectorised accesses; the only +exact record is what the model actually reads at run time. This script runs +a country model with policyengine-core's FullTracer, calculates every +variable, and writes two edge sets: readers[parameter_path] -> variables whose formula read that parameter consumers[variable] -> variables whose formula read that variable -Output: app/src/data/flagship/parameterDependencies.json (consumed by -app/src/libs/flagship/parameterDependencies.ts). +The US map traces policyengine-us over a subsample of its default microdata. +The UK map traces policyengine-uk over a generated population of households +(see uk_situation): the UK microdata is not public, and the formula reads do +not depend on which households run, only on which formulas run, so a +population varied enough to reach every program's eligible cases serves. -Run from a Python environment with policyengine-us installed: +Output (consumed by app/src/libs/flagship/parameterDependencies.ts): - python app/scripts/build-parameter-dependency-map.py [--households N] [--year YYYY] + us: app/src/data/flagship/parameterDependencies.json + uk: app/src/data/flagship/parameterDependencies.uk.json + +Run from a Python environment with the country's package installed: + + python app/scripts/build-parameter-dependency-map.py [--country us|uk] [--households N] [--year YYYY] Two core quirks are handled here rather than upstream: * core caches the yearly ParameterNodeAtInstant before its own tracing @@ -35,6 +44,7 @@ import argparse import json +import random import sys import time from collections import defaultdict @@ -42,13 +52,12 @@ from importlib.metadata import version from pathlib import Path -OUTPUT = ( - Path(__file__).resolve().parent.parent - / "src" - / "data" - / "flagship" - / "parameterDependencies.json" -) +DATA_DIRECTORY = Path(__file__).resolve().parent.parent / "src" / "data" / "flagship" +OUTPUTS = { + "us": DATA_DIRECTORY / "parameterDependencies.json", + "uk": DATA_DIRECTORY / "parameterDependencies.uk.json", +} +PACKAGES = {"us": "policyengine-us", "uk": "policyengine-uk"} # The simulation's tracer, once tracing is on (see patch_tracer). TRACING: dict = {} @@ -172,24 +181,110 @@ def walk(node) -> None: return readers, consumers +# The UK inputs the generated population varies, by how each is drawn. Enum +# inputs draw any of the model's own values, so the list never names a value +# the model does not have. +UK_PERSON_AMOUNTS = { + "employment_income": (0.6, 150_000), + "self_employment_income": (0.15, 80_000), + "private_pension_income": (0.2, 40_000), + "savings_interest_income": (0.4, 5_000), + "dividend_income": (0.15, 60_000), + "property_income": (0.1, 30_000), + "childcare_expenses": (0.15, 12_000), + "hours_worked": (0.6, 2_400), +} +UK_PERSON_FLAGS = {"is_disabled_for_benefits": 0.15, "is_blind": 0.03} +UK_PERSON_ENUMS = ("pip_dl_category", "pip_m_category", "dla_sc_category", "dla_m_category") +UK_HOUSEHOLD_AMOUNTS = {"rent": (0.4, 18_000)} +UK_HOUSEHOLD_ENUMS = ("region", "tenure_type", "council_tax_band") + + +def enum_names(system, variable_name: str) -> list[str]: + variable = system.variables[variable_name] + return [member.name for member in variable.possible_values] + + +def uk_situation(system, households: int, year: int, seed: int) -> dict: + """A varied UK population: singles, couples, children, pensioners, carers' cases, + every region, tenure and council tax band, and each income source, drawn with a + fixed seed so the map is reproducible.""" + draw = random.Random(seed) + period = str(year) + people: dict = {} + benunits: dict = {} + household_records: dict = {} + for household_index in range(households): + adult_count = draw.choice((1, 1, 2, 2, 2)) + child_count = draw.choice((0, 0, 1, 2, 3, 4)) + # Some households are of pension age, some of working age. + adult_age_range = draw.choice(((18, 30), (25, 64), (40, 66), (66, 95))) + members = [] + for adult_index in range(adult_count): + person_name = f"household {household_index} adult {adult_index}" + person = {"age": {period: draw.randint(*adult_age_range)}} + for variable_name, (share, ceiling) in UK_PERSON_AMOUNTS.items(): + if draw.random() < share: + person[variable_name] = {period: round(draw.uniform(0, ceiling))} + for variable_name, share in UK_PERSON_FLAGS.items(): + person[variable_name] = {period: draw.random() < share} + for variable_name in UK_PERSON_ENUMS: + if draw.random() < 0.15: + person[variable_name] = { + period: draw.choice(enum_names(system, variable_name)) + } + people[person_name] = person + members.append(person_name) + for child_index in range(child_count): + person_name = f"household {household_index} child {child_index}" + people[person_name] = {"age": {period: draw.randint(0, 19)}} + if draw.random() < 0.05: + people[person_name]["is_disabled_for_benefits"] = {period: True} + members.append(person_name) + benunits[f"household {household_index} benefit unit"] = {"members": members} + household = {"members": list(members)} + for variable_name, (share, ceiling) in UK_HOUSEHOLD_AMOUNTS.items(): + if draw.random() < share: + household[variable_name] = {period: round(draw.uniform(0, ceiling))} + for variable_name in UK_HOUSEHOLD_ENUMS: + household[variable_name] = {period: draw.choice(enum_names(system, variable_name))} + household_records[f"household {household_index}"] = household + return {"people": people, "benunits": benunits, "households": household_records} + + +def load_simulation(country: str, households: int, year: int): + """The traced simulation and the name of the data it runs on.""" + if country == "us": + from policyengine_us import Microsimulation + + simulation = Microsimulation() + # Subsampling rewraps the data as a plain dataframe; keep the real name. + dataset_name = getattr(simulation.dataset, "name", None) + simulation = simulation.subsample(n=households, seed=0) or simulation + return simulation, dataset_name + from policyengine_uk import CountryTaxBenefitSystem, Simulation + + situation = uk_situation(CountryTaxBenefitSystem(), households, year, seed=0) + simulation = Simulation(situation=situation, trace=True) + return simulation, "generated households (scripts/build-parameter-dependency-map.py)" + + def main() -> None: parser = argparse.ArgumentParser(description=__doc__.split("\n\n")[0]) - parser.add_argument("--households", type=int, default=2000) + parser.add_argument("--country", choices=sorted(OUTPUTS), default="us") + parser.add_argument("--households", type=int, default=None) parser.add_argument("--year", type=int, default=2026) - parser.add_argument("--output", type=Path, default=OUTPUT) + parser.add_argument("--output", type=Path, default=None) args = parser.parse_args() + households = args.households or (2000 if args.country == "us" else 400) + output = args.output or OUTPUTS[args.country] patch_tracer() - from policyengine_us import Microsimulation - started = time.time() - simulation = Microsimulation() - # Subsampling rewraps the data as a plain dataframe; keep the real name. - dataset_name = getattr(simulation.dataset, "name", None) - simulation = simulation.subsample(n=args.households, seed=0) or simulation + simulation, dataset_name = load_simulation(args.country, households, args.year) simulation.trace = True enable_parameter_tracing(simulation) - print(f"loaded microdata subsample in {time.time() - started:.0f}s", file=sys.stderr) + print(f"loaded {households} households in {time.time() - started:.0f}s", file=sys.stderr) started = time.time() outcomes = calculate_everything(simulation, args.year) @@ -202,11 +297,11 @@ def main() -> None: payload = { "generatedAt": datetime.now(timezone.utc).isoformat(timespec="seconds"), "model": { - "package": "policyengine-us", - "version": version("policyengine-us"), + "package": PACKAGES[args.country], + "version": version(PACKAGES[args.country]), "coreVersion": version("policyengine-core"), "dataset": dataset_name, - "households": args.households, + "households": households, "year": args.year, }, "variablesCalculated": outcomes["ok"], @@ -214,10 +309,10 @@ def main() -> None: "readers": {path: sorted(names) for path, names in sorted(readers.items())}, "consumers": {name: sorted(users) for name, users in sorted(consumers.items())}, } - args.output.parent.mkdir(parents=True, exist_ok=True) - args.output.write_text(json.dumps(payload, separators=(",", ":")) + "\n") + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(payload, separators=(",", ":")) + "\n") print( - f"wrote {args.output} — {len(readers)} parameter paths, {len(consumers)} consumed variables", + f"wrote {output} — {len(readers)} parameter paths, {len(consumers)} consumed variables", file=sys.stderr, ) diff --git a/app/src/components/flagship/ScorecardComparisons.tsx b/app/src/components/flagship/ScorecardComparisons.tsx index 8d805388f..b174de3ba 100644 --- a/app/src/components/flagship/ScorecardComparisons.tsx +++ b/app/src/components/flagship/ScorecardComparisons.tsx @@ -782,10 +782,11 @@ async function fetchScorecardComparisons( signal: AbortSignal ): Promise { let variables: string[] = []; - // The committed dependency map is US-only. Never use it for another country. + // The scorecard is the US model's: only the US dependency map is read, and + // never for another country. if (countryId === 'us') { try { - variables = variablesReachedByPaths(paths, await loadParameterDependencies()).map( + variables = variablesReachedByPaths(paths, await loadParameterDependencies('us')).map( (entry) => entry.variable ); } catch { diff --git a/app/src/components/flagship/ValidationPanel.tsx b/app/src/components/flagship/ValidationPanel.tsx index 46352562b..299744e41 100644 --- a/app/src/components/flagship/ValidationPanel.tsx +++ b/app/src/components/flagship/ValidationPanel.tsx @@ -258,8 +258,9 @@ export function trackRecordPrograms(trackRecord: ModelTrackRecord): string[] | n * at page level, not inside a tab panel, so the request runs in * parallel with the rest of the report instead of starting on tab * click (inactive tab panels are unmounted). The track record is the - * US model's (its dependency map and comparison table are US-only), so - * another country gets an empty one, and an unknown country waits. + * US model's (it reads the US dependency map, and its comparison table + * is US-only), so another country gets an empty one, and an unknown + * country waits. */ export function useModelTrackRecord( paths: string[], @@ -352,8 +353,9 @@ const NO_READERS: Record = {}; /** * The variables that read each reform path directly, from the traced - * dependency map: `undefined` while it loads. The map is US-only, so - * another country, or a map that fails to load, matches on the paths alone. + * dependency map: `undefined` while it loads. Only the US map is read here, + * as the validation data is the US model's, so another country, or a map + * that fails to load, matches on the paths alone. */ export function useReformReaders( countryId: string, @@ -368,7 +370,7 @@ export function useReformReaders( } const request = JSON.parse(requestKey) as { paths: string[] }; let cancelled = false; - loadParameterDependencies() + loadParameterDependencies('us') .then((map) => Object.fromEntries(request.paths.map((path) => [path, readersOfPath(path, map)])) ) diff --git a/app/src/components/flagship/report/household/HouseholdBreakdowns.tsx b/app/src/components/flagship/report/household/HouseholdBreakdowns.tsx index 24689e0ef..93ae4e0d0 100644 --- a/app/src/components/flagship/report/household/HouseholdBreakdowns.tsx +++ b/app/src/components/flagship/report/household/HouseholdBreakdowns.tsx @@ -169,8 +169,6 @@ export default function HouseholdBreakdowns({ reform, simulations, policies: policyQuery.policies, - // v3 households use national thresholds, so the footnote says nothing new. - hideSpmFootnote: true, renderLoading: () => ( ('summary'); const { netIncome, components, programs } = impact; @@ -393,6 +409,11 @@ export default function HouseholdImpactResult({ ) : ( )} + + {/* The variation views show their own calculation's methodology. */} + {methodology && (view === 'summary' || view === 'net-income') && ( + + )} ); } diff --git a/app/src/components/flagship/report/household/HouseholdImpactSection.tsx b/app/src/components/flagship/report/household/HouseholdImpactSection.tsx index a2ae81250..127d7e251 100644 --- a/app/src/components/flagship/report/household/HouseholdImpactSection.tsx +++ b/app/src/components/flagship/report/household/HouseholdImpactSection.tsx @@ -75,8 +75,9 @@ export function ukNationPlace(region: string | undefined): Record state.metadata); const inputs = useMemo( - () => new Set(getInputVariables(metadata).map((variable) => variable.name)), - [metadata] + () => + new Set( + getInputVariables(metadata) + .filter((variable) => describesAHousehold(variable, countryId)) + .map((variable) => variable.name) + ), + [metadata, countryId] ); const preferred = useMemo( () => new Set(commonHouseholdInputs(countryId).map((input) => input.name)), @@ -209,18 +217,11 @@ function useSuggestedInputs(paths: string[], countryId: string): string[] { setSuggested([]); return; } - loadParameterDependencies() + loadParameterDependencies(countryId) .then((map) => { if (!cancelled) { setSuggested( - suggestedHouseholdInputs( - pathsKey.split('\n'), - map, - inputs, - undefined, - preferred, - countryId - ) + suggestedHouseholdInputs(pathsKey.split('\n'), map, inputs, countryId, { preferred }) ); } }) @@ -578,8 +579,6 @@ function HouseholdCard({ setHousehold(household.withBuilderChildCount(year, count)) } disabled={running} - // National poverty thresholds, the model's default, without the choice. - hideSpmGeography layout="columns" suggestedVariables={suggestedVariables} suggestedLabel="Related to this reform" @@ -646,6 +645,11 @@ function HouseholdCard({ void; disabled?: boolean; isReadOnly?: boolean; - /** Leave out the SPM geography choice; the household keeps its own. */ - hideSpmGeography?: boolean; /** "columns" sets the sections side by side on a wide screen; stacked by default. */ layout?: 'stacked' | 'columns'; /** Variables to list first in the variable search, in order, under their own heading. */ @@ -259,7 +257,6 @@ export default function HouseholdBuilderForm({ onChange, onMaritalStatusChange, onNumChildrenChange, - hideSpmGeography = false, layout = 'stacked', suggestedVariables, suggestedLabel = 'Suggested', @@ -609,16 +606,14 @@ export default function HouseholdBuilderForm({ : undefined } > - {!hideSpmGeography && ( - - )} + {/* Floating notification when variable added to different entity */} {warningMessage && (
; + /** Display calculation receipts in the results, without claiming certification. */ export default function SPMMethodologyFootnote({ output, context = 'point', }: { - output: (HouseholdCalculationOutput | null)[]; + /** The baseline's calculation first, then the reform's (null when there is none). */ + output: (HouseholdCalculationOutput | SPMMethodologySource | null)[]; context?: 'point' | 'variation'; }) { const receipts = output diff --git a/app/src/data/flagship/parameterDependencies.uk.json b/app/src/data/flagship/parameterDependencies.uk.json new file mode 100644 index 000000000..a92ecf70b --- /dev/null +++ b/app/src/data/flagship/parameterDependencies.uk.json @@ -0,0 +1 @@ +{"generatedAt":"2026-10-21T22:01:00+00:00","model":{"package":"policyengine-uk","version":"2.130.1","coreVersion":"3.33.0","dataset":"generated households (scripts/build-parameter-dependency-map.py)","households":400,"year":2026},"variablesCalculated":1163,"variablesFailed":0,"readers":{"gov.boe.base_rate":["plan_1_interest_rate"],"gov.contrib.abolish_council_tax":["household_benefits","pre_budget_change_household_benefits"],"gov.contrib.benefit_uprating.all":["household_benefits","pre_budget_change_household_benefits"],"gov.contrib.benefit_uprating.non_sp":["household_benefits","pre_budget_change_household_benefits"],"gov.contrib.cec.non_primary_residence_wealth_tax":["non_primary_residence_wealth_tax"],"gov.contrib.disability_basic_income.amount":["disability_basic_income"],"gov.contrib.freeze_pension_credit":["in_receipt_of_guarantee_credit","in_receipt_of_savings_credit_only","pension_credit"],"gov.contrib.labour.private_school_vat":["private_school_vat"],"gov.contrib.policyengine.budget.consumer_incident_tax_change":["consumer_incident_tax_revenue_change"],"gov.contrib.policyengine.budget.corporate_incident_tax_change":["corporate_incident_tax_revenue_change"],"gov.contrib.policyengine.budget.education":["education_budget_change"],"gov.contrib.policyengine.budget.nhs":["nhs_budget_change"],"gov.contrib.policyengine.budget.other_public_spending":["other_public_spending_budget_change"],"gov.contrib.policyengine.economy.gdp_per_capita":["household_market_income"],"gov.contrib.policyengine.employer_ni.capital_incidence":["employer_ni_response_capital_incidence"],"gov.contrib.policyengine.employer_ni.consumer_incidence":["employer_ni_response_consumer_incidence"],"gov.contrib.policyengine.employer_ni.employee_incidence":["employer_ni_fixed_employer_cost_change","employer_ni_response_capital_incidence","employer_ni_response_consumer_incidence"],"gov.contrib.policyengine.employer_ni.exempt_employer_pension_contributions":["adjusted_employer_cost","employer_ni_fixed_employer_cost_change","ni_class_1_employer"],"gov.contrib.ubi_center.basic_income.amount.adult_age":["bi_maximum"],"gov.contrib.ubi_center.basic_income.amount.by_age.child":["bi_maximum"],"gov.contrib.ubi_center.basic_income.amount.by_age.senior":["bi_maximum"],"gov.contrib.ubi_center.basic_income.amount.by_age.working_age":["bi_maximum"],"gov.contrib.ubi_center.basic_income.amount.child_min_age":["bi_maximum"],"gov.contrib.ubi_center.basic_income.amount.flat":["bi_maximum"],"gov.contrib.ubi_center.basic_income.interactions.include_in_means_tests":["council_tax_reduction_applicable_income","housing_benefit_applicable_income","income_support_applicable_income","pension_credit_income","tax_credits_current_year_income","uc_income_tax_on_earnings","uc_income_tax_on_trade","uc_individual_earned_income_before_mif"],"gov.contrib.ubi_center.basic_income.interactions.include_in_taxable_income":["net_income"],"gov.contrib.ubi_center.basic_income.interactions.withdraw_cb":["child_benefit_respective_amount"],"gov.contrib.ubi_center.basic_income.phase_out.household.rate":["bi_household_phaseout"],"gov.contrib.ubi_center.basic_income.phase_out.household.threshold":["bi_household_phaseout"],"gov.contrib.ubi_center.basic_income.phase_out.individual.rate":["bi_individual_phaseout"],"gov.contrib.ubi_center.basic_income.phase_out.individual.threshold":["bi_individual_phaseout"],"gov.contrib.ubi_center.carbon_tax.consumer_incidence":["carbon_tax"],"gov.contrib.ubi_center.carbon_tax.rate":["carbon_tax"],"gov.contrib.ubi_center.land_value_tax.corporate_rate":["LVT"],"gov.contrib.ubi_center.land_value_tax.household_rate":["LVT"],"gov.contrib.ubi_center.land_value_tax.rate":["LVT"],"gov.contrib.ubi_center.wealth_tax":["wealth_tax"],"gov.dcms.bbc.tv_licence.colour":["free_tv_licence_value","tv_licence"],"gov.dcms.bbc.tv_licence.discount.blind.discount":["tv_licence_discount"],"gov.dfe.adult_dependants_grant.income_limit":["adult_dependants_grant_eligible"],"gov.dfe.adult_dependants_grant.other_adult_income_limit":["adult_dependants_grant_adult_eligible"],"gov.dfe.bursary_fund_16_to_19.age.minimum":["bursary_fund_16_to_19_age_eligible"],"gov.dfe.bursary_fund_16_to_19.age.standard_upper":["bursary_fund_16_to_19_age_eligible"],"gov.dfe.care_to_learn.age_limit":["care_to_learn_eligible"],"gov.dfe.childcare_funding_rate":["extended_childcare_entitlement_total_per_child","targeted_childcare_entitlement","universal_childcare_entitlement"],"gov.dfe.childcare_grant.eligible_child.max_age.special_educational_needs":["childcare_grant_child_eligible"],"gov.dfe.childcare_grant.eligible_child.max_age.standard":["childcare_grant_child_eligible"],"gov.dfe.childcare_grant.income_limit.one_child":["childcare_grant_eligible"],"gov.dfe.childcare_grant.income_limit.two_or_more_children":["childcare_grant_eligible"],"gov.dfe.compulsory_school_age":["extended_childcare_entitlement_qualifying_child","is_of_compulsory_school_age","uc_expected_hours"],"gov.dfe.extended_childcare_entitlement.disability_criteria":["extended_childcare_entitlement_limited_capability_or_specified_benefit"],"gov.dfe.extended_childcare_entitlement.exemption.income_limit_applies":["extended_childcare_entitlement_work_condition"],"gov.dfe.extended_childcare_entitlement.exemption.partner_exclusion_criteria":["extended_childcare_entitlement_work_condition"],"gov.dfe.extended_childcare_entitlement.hours":["extended_childcare_entitlement_total_per_child","is_child_receiving_extended_childcare"],"gov.dfe.extended_childcare_entitlement.income.countable_sources":["extended_childcare_entitlement_meets_income_requirements"],"gov.dfe.extended_childcare_entitlement.income.limit":["extended_childcare_entitlement_meets_income_requirements","extended_childcare_entitlement_work_condition"],"gov.dfe.extended_childcare_entitlement.minimum_weekly_hours":["extended_childcare_entitlement_meets_income_requirements"],"gov.dfe.extended_childcare_entitlement.young_child_minimum_age":["extended_childcare_entitlement_qualifying_child"],"gov.dfe.maintenance_loans.full_time.maximum.away_in_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.maximum.away_outside_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.maximum.living_with_parents":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.maximum_entitled_to_benefits.away_in_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.maximum_entitled_to_benefits.away_outside_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.maximum_entitled_to_benefits.living_with_parents":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.minimum_rate.entitled_to_benefits.away_in_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.minimum_rate.entitled_to_benefits.away_outside_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.minimum_rate.entitled_to_benefits.living_with_parents":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.minimum_rate.not_entitled.away_in_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.minimum_rate.not_entitled.away_outside_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.minimum_rate.not_entitled.living_with_parents":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.taper.entitled_to_benefits.first_stage.away_in_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.taper.entitled_to_benefits.first_stage.away_outside_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.taper.entitled_to_benefits.first_stage.living_with_parents":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.taper.entitled_to_benefits.second_stage.away_in_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.taper.entitled_to_benefits.second_stage.away_outside_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.taper.entitled_to_benefits.second_stage.living_with_parents":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.taper.not_entitled.away_in_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.taper.not_entitled.away_outside_london":["maintenance_loan"],"gov.dfe.maintenance_loans.full_time.taper.not_entitled.living_with_parents":["maintenance_loan"],"gov.dfe.maintenance_loans.household_income.higher_threshold":["maintenance_loan"],"gov.dfe.maintenance_loans.household_income.threshold":["maintenance_loan"],"gov.dfe.maintenance_loans.independent_student_age":["maintenance_loan_household_income"],"gov.dfe.maintenance_loans.over_60.max_amount":["maintenance_loan"],"gov.dfe.maintenance_loans.over_60.maximum_income":["maintenance_loan"],"gov.dfe.maintenance_loans.over_60.minimum_amount":["maintenance_loan"],"gov.dfe.maintenance_loans.over_60.reduction_per_pound":["maintenance_loan"],"gov.dfe.parents_learning_allowance.income_limit":["parents_learning_allowance_eligible"],"gov.dfe.targeted_childcare_entitlement.age_eligibility":["is_child_receiving_targeted_childcare","targeted_childcare_entitlement"],"gov.dfe.targeted_childcare_entitlement.hours_entitlement":["targeted_childcare_entitlement"],"gov.dfe.targeted_childcare_entitlement.income_limit.tax_credits":["meets_child_tax_credit_criteria_for_targeted_childcare_entitlement","meets_working_tax_credit_criteria_for_targeted_childcare_entitlement"],"gov.dfe.targeted_childcare_entitlement.income_limit.universal_credit":["meets_universal_credit_criteria_for_targeted_childcare_entitlement"],"gov.dfe.targeted_childcare_entitlement.qualifying_benefits":["targeted_childcare_entitlement_eligible"],"gov.dfe.targeted_childcare_entitlement.qualifying_criteria":["meets_tax_credit_criteria_for_targeted_childcare_entitlement","targeted_childcare_entitlement_eligible"],"gov.dfe.universal_childcare_entitlement.age.max":["is_child_receiving_universal_childcare","universal_childcare_entitlement_eligible"],"gov.dfe.universal_childcare_entitlement.age.min":["is_child_receiving_universal_childcare","universal_childcare_entitlement_eligible"],"gov.dfe.universal_childcare_entitlement.hours":["universal_childcare_entitlement"],"gov.dfe.weeks_per_year":["extended_childcare_entitlement_total_per_child","targeted_childcare_entitlement","universal_childcare_entitlement"],"gov.dft.bus.default_single_fare_share":["local_bus_single_fare_share"],"gov.dft.bus.fare_allocation_weight_by_age":["household_bus_fare_age_weight","person_bus_fare_spending"],"gov.dft.bus.fare_index":["person_bus_fare_spending"],"gov.dft.bus.prior_law_fare_index":["person_bus_fare_spending"],"gov.dft.bus.uncapped_single_fare":["local_bus_uncapped_single_fare"],"gov.dft.rail.fare_index":["rail_subsidy_spending"],"gov.dft.vehicle_excise_duty.alternative_fuel_discount":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.band_k_max_emissions":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.band_k_registration_cutoff":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.engine_size_threshold":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.expensive_car_supplement":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.expensive_car_threshold":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.first_year":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.first_year_diesel_non_rde2":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.graduated":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.graduated_registration_start":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.large_engine_rate":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.modern_registration_start":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.small_engine_rate":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.standard_rate":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.supplement_years":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.zero_emission_exempt":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.zero_emission_expensive_car_threshold":["car_vehicle_excise_duty"],"gov.dft.vehicle_excise_duty.zero_emission_supplement_registration_start":["car_vehicle_excise_duty"],"gov.dwp.ESA.exempt_work.higher_earnings_limit":["esa_income_claimant_remunerative_work"],"gov.dwp.ESA.exempt_work.hours_limit":["esa_income_claimant_remunerative_work"],"gov.dwp.ESA.exempt_work.lower_earnings_limit":["esa_income_claimant_remunerative_work"],"gov.dwp.ESA.income.capital.limit":["esa_income_eligible","is_on_income_related_esa"],"gov.dwp.ESA.income.capital.person_sources":["esa_income_assessable_capital"],"gov.dwp.ESA.income.capital.sources":["esa_income_assessable_capital"],"gov.dwp.ESA.income.capital.tariff_income.amount":["esa_income_tariff_income"],"gov.dwp.ESA.income.capital.tariff_income.step":["esa_income_tariff_income"],"gov.dwp.ESA.income.capital.tariff_income.threshold":["esa_income_tariff_income"],"gov.dwp.ESA.income.remunerative_work.partner_hours":["esa_income_eligible"],"gov.dwp.ESA.income.self_employment_class_2.above_lower_profits_threshold":["esa_exempt_work_earnings"],"gov.dwp.ESA.income.self_employment_class_2.deducted":["esa_exempt_work_earnings"],"gov.dwp.JSA.income.active":["benefit_cap_reduction","claimant_or_partner_jsa_income","income_support_eligible","is_on_income_based_jsa","jsa_income","legacy_benefits_closed"],"gov.dwp.JSA.income.capital.limit":["is_on_income_based_jsa","jsa_income_eligible"],"gov.dwp.JSA.income.capital.person_sources":["jsa_income_assessable_capital"],"gov.dwp.JSA.income.capital.sources":["jsa_income_assessable_capital"],"gov.dwp.JSA.income.capital.tariff_income.amount":["jsa_income_tariff_income"],"gov.dwp.JSA.income.capital.tariff_income.step":["jsa_income_tariff_income"],"gov.dwp.JSA.income.capital.tariff_income.threshold":["jsa_income_tariff_income"],"gov.dwp.JSA.remunerative_work.claimant_hours":["is_on_income_based_jsa","jsa_income_eligible"],"gov.dwp.JSA.remunerative_work.partner_hours":["jsa_income_eligible"],"gov.dwp.LHA.shared_accommodation_age_threshold":["is_housing_benefit_young_individual","is_lha_shared_accommodation_rate_specified_renter"],"gov.dwp.LHA.shared_accommodation_exception_benefits":["is_lha_shared_accommodation_rate_specified_renter"],"gov.dwp.attendance_allowance.higher":["attendance_allowance","is_severely_disabled_for_benefits"],"gov.dwp.attendance_allowance.lower":["attendance_allowance"],"gov.dwp.benefit_cap.non_single.in_london":["benefit_cap"],"gov.dwp.benefit_cap.non_single.outside_london":["benefit_cap"],"gov.dwp.benefit_cap.single.in_london":["benefit_cap"],"gov.dwp.benefit_cap.single.outside_london":["benefit_cap"],"gov.dwp.carer_premium.single":["carer_premium"],"gov.dwp.carers_allowance.earnings_limit":["is_gainfully_employed_for_carers_allowance"],"gov.dwp.carers_allowance.min_hours":["carers_allowance_pre_overlap","is_carer_for_benefits","partners_care_for_same_severely_disabled_person"],"gov.dwp.carers_allowance.qualifying_disability_benefits":["is_severely_disabled_for_carers_allowance"],"gov.dwp.carers_allowance.rate":["carers_allowance_pre_overlap","uc_unearned_carer_support_payment"],"gov.dwp.disability_premia.disability_couple":["disability_premium"],"gov.dwp.disability_premia.disability_single":["disability_premium"],"gov.dwp.disability_premia.enhanced_couple":["enhanced_disability_premium"],"gov.dwp.disability_premia.enhanced_single":["enhanced_disability_premium"],"gov.dwp.disability_premia.severe_couple":["severe_disability_premium"],"gov.dwp.disability_premia.severe_non_dependant_age":["has_non_dependant_for_severe_disability_premium"],"gov.dwp.disability_premia.severe_qualifying_benefits":["receives_severe_disability_premium_qualifying_benefit"],"gov.dwp.disability_premia.severe_qualifying_benefits_northern_ireland":["receives_severe_disability_premium_qualifying_benefit"],"gov.dwp.disability_premia.severe_single":["severe_disability_premium"],"gov.dwp.dla.mobility.higher":["dla_m"],"gov.dwp.dla.mobility.lower":["dla_m"],"gov.dwp.dla.self_care.higher":["dla_sc","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits"],"gov.dwp.dla.self_care.lower":["dla_sc"],"gov.dwp.dla.self_care.middle":["dla_sc"],"gov.dwp.housing_benefit.allowances.age_threshold.older":["council_tax_reduction_applicable_amount","housing_benefit_applicable_amount"],"gov.dwp.housing_benefit.allowances.age_threshold.younger":["council_tax_reduction_applicable_amount","housing_benefit_applicable_amount"],"gov.dwp.housing_benefit.allowances.couple.aged":["council_tax_reduction_applicable_amount","housing_benefit_applicable_amount"],"gov.dwp.housing_benefit.allowances.couple.older":["council_tax_reduction_applicable_amount","housing_benefit_applicable_amount"],"gov.dwp.housing_benefit.allowances.couple.younger":["council_tax_reduction_applicable_amount","housing_benefit_applicable_amount"],"gov.dwp.housing_benefit.allowances.lone_parent.aged":["council_tax_reduction_applicable_amount","housing_benefit_applicable_amount"],"gov.dwp.housing_benefit.allowances.lone_parent.older":["council_tax_reduction_applicable_amount","housing_benefit_applicable_amount"],"gov.dwp.housing_benefit.allowances.lone_parent.younger":["council_tax_reduction_applicable_amount","housing_benefit_applicable_amount"],"gov.dwp.housing_benefit.allowances.single.aged":["council_tax_reduction_applicable_amount","housing_benefit_applicable_amount"],"gov.dwp.housing_benefit.allowances.single.older":["council_tax_reduction_applicable_amount","housing_benefit_applicable_amount"],"gov.dwp.housing_benefit.allowances.single.younger":["council_tax_reduction_applicable_amount","housing_benefit_applicable_amount"],"gov.dwp.housing_benefit.ineligible_charges.meals.at_least_three_a_day.aged_16_or_over":["housing_benefit_meals_deduction"],"gov.dwp.housing_benefit.ineligible_charges.meals.at_least_three_a_day.under_16":["housing_benefit_meals_deduction"],"gov.dwp.housing_benefit.ineligible_charges.meals.breakfast_only":["housing_benefit_meals_deduction"],"gov.dwp.housing_benefit.ineligible_charges.meals.fewer_than_three_a_day.aged_16_or_over":["housing_benefit_meals_deduction"],"gov.dwp.housing_benefit.ineligible_charges.meals.fewer_than_three_a_day.under_16":["housing_benefit_meals_deduction"],"gov.dwp.housing_benefit.means_test.capital.pension_age.limit":["housing_benefit_eligible"],"gov.dwp.housing_benefit.means_test.capital.pension_age.tariff_income.amount":["housing_benefit_tariff_income"],"gov.dwp.housing_benefit.means_test.capital.pension_age.tariff_income.step":["housing_benefit_tariff_income"],"gov.dwp.housing_benefit.means_test.capital.pension_age.tariff_income.threshold":["housing_benefit_tariff_income"],"gov.dwp.housing_benefit.means_test.capital.person_sources":["housing_benefit_assessable_capital"],"gov.dwp.housing_benefit.means_test.capital.sources":["housing_benefit_assessable_capital"],"gov.dwp.housing_benefit.means_test.capital.working_age.limit":["housing_benefit_eligible"],"gov.dwp.housing_benefit.means_test.capital.working_age.tariff_income.amount":["housing_benefit_tariff_income"],"gov.dwp.housing_benefit.means_test.capital.working_age.tariff_income.step":["housing_benefit_tariff_income"],"gov.dwp.housing_benefit.means_test.capital.working_age.tariff_income.threshold":["housing_benefit_tariff_income"],"gov.dwp.housing_benefit.means_test.childcare.child_age_limit.disabled":["num_relevant_children_for_housing_benefit_childcare"],"gov.dwp.housing_benefit.means_test.childcare.child_age_limit.standard":["num_relevant_children_for_housing_benefit_childcare"],"gov.dwp.housing_benefit.means_test.income_disregard.couple":["housing_benefit_applicable_income_disregard"],"gov.dwp.housing_benefit.means_test.income_disregard.lone_parent":["housing_benefit_applicable_income_disregard"],"gov.dwp.housing_benefit.means_test.income_disregard.single":["housing_benefit_applicable_income_disregard"],"gov.dwp.housing_benefit.means_test.income_disregard.specified_or_temporary_accommodation.age_threshold.older":["housing_benefit_specified_or_temporary_accommodation_disregard"],"gov.dwp.housing_benefit.means_test.income_disregard.specified_or_temporary_accommodation.age_threshold.younger":["housing_benefit_specified_or_temporary_accommodation_disregard"],"gov.dwp.housing_benefit.means_test.income_disregard.specified_or_temporary_accommodation.couple.minors":["housing_benefit_specified_or_temporary_accommodation_disregard"],"gov.dwp.housing_benefit.means_test.income_disregard.specified_or_temporary_accommodation.couple.older":["housing_benefit_specified_or_temporary_accommodation_disregard"],"gov.dwp.housing_benefit.means_test.income_disregard.specified_or_temporary_accommodation.couple.younger":["housing_benefit_specified_or_temporary_accommodation_disregard"],"gov.dwp.housing_benefit.means_test.income_disregard.specified_or_temporary_accommodation.lone_parent.older":["housing_benefit_specified_or_temporary_accommodation_disregard"],"gov.dwp.housing_benefit.means_test.income_disregard.specified_or_temporary_accommodation.lone_parent.younger":["housing_benefit_specified_or_temporary_accommodation_disregard"],"gov.dwp.housing_benefit.means_test.income_disregard.specified_or_temporary_accommodation.single.older":["housing_benefit_specified_or_temporary_accommodation_disregard"],"gov.dwp.housing_benefit.means_test.income_disregard.specified_or_temporary_accommodation.single.younger":["housing_benefit_specified_or_temporary_accommodation_disregard"],"gov.dwp.housing_benefit.means_test.income_disregard.worker":["housing_benefit_applicable_income_disregard"],"gov.dwp.housing_benefit.means_test.income_disregard.worker_age":["meets_housing_benefit_additional_earnings_disregard_conditions"],"gov.dwp.housing_benefit.means_test.income_disregard.worker_hours":["meets_housing_benefit_additional_earnings_disregard_conditions"],"gov.dwp.housing_benefit.means_test.income_disregard.worker_hours_lower":["meets_housing_benefit_additional_earnings_disregard_conditions"],"gov.dwp.housing_benefit.means_test.pension_contribution_deduction_rate":["housing_benefit_net_earnings"],"gov.dwp.housing_benefit.means_test.universal_credit_passport.great_britain":["housing_benefit_on_passporting_benefit"],"gov.dwp.housing_benefit.means_test.universal_credit_passport.northern_ireland":["housing_benefit_on_passporting_benefit"],"gov.dwp.housing_benefit.means_test.withdrawal_rate":["housing_benefit_entitlement"],"gov.dwp.housing_benefit.non_dep_deduction.age_threshold":["housing_benefit_individual_non_dep_deduction_eligible"],"gov.dwp.housing_benefit.non_dep_deduction.amount":["household_benefits_individual_non_dep_deduction"],"gov.dwp.housing_benefit.severe_disability_premium.qualifying_benefits":["housing_benefit_severe_disability_premium_applies"],"gov.dwp.income_support.active":["income_support","is_on_income_support","legacy_benefits_closed"],"gov.dwp.income_support.amounts.age_threshold.older":["income_support_applicable_amount"],"gov.dwp.income_support.amounts.age_threshold.younger":["income_support_applicable_amount"],"gov.dwp.income_support.amounts.amount_16_24":["income_support_applicable_amount"],"gov.dwp.income_support.amounts.amount_couples_16_17":["income_support_applicable_amount"],"gov.dwp.income_support.amounts.amount_couples_age_gap":["income_support_applicable_amount"],"gov.dwp.income_support.amounts.amount_couples_over_18":["income_support_applicable_amount"],"gov.dwp.income_support.amounts.amount_lone_16_17":["income_support_applicable_amount"],"gov.dwp.income_support.amounts.amount_lone_over_18":["income_support_applicable_amount"],"gov.dwp.income_support.amounts.amount_over_25":["income_support_applicable_amount"],"gov.dwp.income_support.eligibility.lone_parent_youngest_child_age_limit":["income_support_eligible"],"gov.dwp.income_support.eligibility.remunerative_work.claimant_hours":["income_support_eligible"],"gov.dwp.income_support.eligibility.remunerative_work.partner_hours":["income_support_eligible"],"gov.dwp.income_support.means_test.capital.limit":["income_support_eligible"],"gov.dwp.income_support.means_test.capital.person_sources":["income_support_assessable_capital"],"gov.dwp.income_support.means_test.capital.sources":["income_support_assessable_capital"],"gov.dwp.income_support.means_test.capital.tariff_income.amount":["income_support_tariff_income"],"gov.dwp.income_support.means_test.capital.tariff_income.step":["income_support_tariff_income"],"gov.dwp.income_support.means_test.capital.tariff_income.threshold":["income_support_tariff_income"],"gov.dwp.income_support.means_test.income_disregard_couple":["income_support_applicable_income"],"gov.dwp.income_support.means_test.income_disregard_lone_parent":["income_support_applicable_income"],"gov.dwp.income_support.means_test.income_disregard_single":["income_support_applicable_income"],"gov.dwp.pension_credit.guarantee_credit.carer.addition":["carer_minimum_guarantee_addition"],"gov.dwp.pension_credit.guarantee_credit.child.addition":["child_minimum_guarantee_addition"],"gov.dwp.pension_credit.guarantee_credit.child.disability.addition":["child_minimum_guarantee_addition"],"gov.dwp.pension_credit.guarantee_credit.child.disability.eligibility":["child_minimum_guarantee_addition"],"gov.dwp.pension_credit.guarantee_credit.child.disability.severe.addition":["child_minimum_guarantee_addition"],"gov.dwp.pension_credit.guarantee_credit.child.disability.severe.eligibility":["child_minimum_guarantee_addition"],"gov.dwp.pension_credit.guarantee_credit.child.eligibility.child_age_limit":["is_child_for_pension_credit","meets_qualifying_young_person_age_condition_for_pension_credit"],"gov.dwp.pension_credit.guarantee_credit.child.eligibility.education_or_training_start_age_limit":["meets_qualifying_young_person_entry_condition_for_pension_credit"],"gov.dwp.pension_credit.guarantee_credit.child.eligibility.qualifying_young_person_age_limit":["meets_qualifying_young_person_age_condition_for_pension_credit"],"gov.dwp.pension_credit.guarantee_credit.child.first.addition":["child_minimum_guarantee_addition"],"gov.dwp.pension_credit.guarantee_credit.child.first.born_before":["child_minimum_guarantee_addition"],"gov.dwp.pension_credit.guarantee_credit.earnings_sources":["pension_credit_earnings"],"gov.dwp.pension_credit.guarantee_credit.income":["pension_credit_income"],"gov.dwp.pension_credit.guarantee_credit.minimum_guarantee":["standard_minimum_guarantee"],"gov.dwp.pension_credit.guarantee_credit.severe_disability.addition":["severe_disability_minimum_guarantee_addition"],"gov.dwp.pension_credit.guarantee_credit.severe_disability.other_resident_age_limit":["is_counted_resident_for_severe_disability_addition"],"gov.dwp.pension_credit.guarantee_credit.severe_disability.relevant_benefits":["receives_severe_disability_addition_qualifying_benefit"],"gov.dwp.pension_credit.income.capital.lower_threshold":["pension_credit_deemed_income"],"gov.dwp.pension_credit.income.capital.person_sources":["pension_credit_assessable_capital"],"gov.dwp.pension_credit.income.capital.sources":["pension_credit_assessable_capital"],"gov.dwp.pension_credit.income.capital.tariff_income.amount":["pension_credit_deemed_income"],"gov.dwp.pension_credit.income.capital.tariff_income.step":["pension_credit_deemed_income"],"gov.dwp.pension_credit.income.pension_contributions_deduction":["pension_credit_income"],"gov.dwp.pension_credit.mixed_age_couples.excluded":["meets_pension_credit_age_conditions"],"gov.dwp.pension_credit.mixed_age_couples.saving_latest_birth_date":["has_mixed_age_couple_pension_credit_saving"],"gov.dwp.pension_credit.savings_credit.cutoff_year":["meets_savings_credit_age_requirement"],"gov.dwp.pension_credit.savings_credit.excluded_income":["savings_credit_income"],"gov.dwp.pension_credit.savings_credit.minimum_age":["meets_savings_credit_age_requirement"],"gov.dwp.pension_credit.savings_credit.rate.phase_in":["savings_credit"],"gov.dwp.pension_credit.savings_credit.rate.phase_out":["savings_credit"],"gov.dwp.pension_credit.savings_credit.threshold":["is_savings_credit_eligible","savings_credit"],"gov.dwp.pip.daily_living.enhanced":["is_severely_disabled_for_benefits","pip_dl"],"gov.dwp.pip.daily_living.standard":["pip_dl"],"gov.dwp.pip.mobility.enhanced":["pip_m"],"gov.dwp.pip.mobility.standard":["pip_m"],"gov.dwp.sda.maximum":["sda"],"gov.dwp.ssmg.rate":["ssmg"],"gov.dwp.state_pension.age.age_by_birth_date":["state_pension_age","state_pension_credit_qualifying_age"],"gov.dwp.state_pension.age.day_by_birth_date":["state_pension_age","state_pension_credit_qualifying_age"],"gov.dwp.state_pension.age.male.age":["state_pension_age","state_pension_credit_qualifying_age"],"gov.dwp.state_pension.age.male.born_before":["state_pension_age"],"gov.dwp.tax_credits.active":["legacy_benefits_closed","tax_credit_award","tax_credits","tax_credits_applicable_income"],"gov.dwp.tax_credits.child_tax_credit.elements.child_element":["CTC_child_element"],"gov.dwp.tax_credits.child_tax_credit.elements.dis_child_element":["CTC_disabled_child_element"],"gov.dwp.tax_credits.child_tax_credit.eligibility.child_age_limit":["is_child_for_child_tax_credit","meets_qualifying_young_person_age_condition_for_child_tax_credit"],"gov.dwp.tax_credits.child_tax_credit.eligibility.education_or_training_start_age_limit":["meets_qualifying_young_person_entry_condition_for_child_tax_credit"],"gov.dwp.tax_credits.child_tax_credit.eligibility.qualifying_young_person_age_limit":["meets_qualifying_young_person_age_condition_for_child_tax_credit"],"gov.dwp.tax_credits.child_tax_credit.limit.born_before":["is_CTC_child_limit_exempt"],"gov.dwp.tax_credits.child_tax_credit.limit.child_count":["CTC_child_element","ctc_child_limit_affected"],"gov.dwp.tax_credits.means_test.income_reduction_rate":["tax_credits_reduction"],"gov.dwp.tax_credits.means_test.income_threshold":["tax_credits_reduction"],"gov.dwp.tax_credits.means_test.income_threshold_CTC_only":["tax_credits_reduction"],"gov.dwp.tax_credits.means_test.non_earned_disregard":["tax_credits_current_year_income"],"gov.dwp.tax_credits.means_test.pension_credit_passport":["tax_credits_applicable_income"],"gov.dwp.tax_credits.working_tax_credit.childcare_child_age_limit.disabled":["is_child_for_working_tax_credit_childcare_element"],"gov.dwp.tax_credits.working_tax_credit.childcare_child_age_limit.standard":["is_child_for_working_tax_credit_childcare_element"],"gov.dwp.tax_credits.working_tax_credit.elements.childcare_1":["housing_benefit_applicable_income_childcare_element"],"gov.dwp.tax_credits.working_tax_credit.elements.childcare_2":["housing_benefit_applicable_income_childcare_element"],"gov.dwp.tax_credits.working_tax_credit.elements.severely_disabled":["WTC_severely_disabled_element"],"gov.dwp.tax_credits.working_tax_credit.min_hours.couple_with_children":["is_WTC_eligible"],"gov.dwp.tax_credits.working_tax_credit.min_hours.default":["is_WTC_eligible"],"gov.dwp.tax_credits.working_tax_credit.min_hours.lower":["is_WTC_eligible"],"gov.dwp.tax_credits.working_tax_credit.min_hours.old_age":["is_WTC_eligible"],"gov.dwp.universal_credit.company_owner.intermediary_exclusion.chapters":["uc_company_intermediary_exclusion_applies"],"gov.dwp.universal_credit.company_owner.intermediary_exclusion.requires_main_employment":["uc_company_intermediary_exclusion_applies"],"gov.dwp.universal_credit.deductions.abolish.advance":["uc_deduction_rate"],"gov.dwp.universal_credit.deductions.abolish.government":["uc_deduction_rate"],"gov.dwp.universal_credit.deductions.abolish.third_party":["uc_deduction_rate"],"gov.dwp.universal_credit.deductions.cap":["uc_deduction_rate"],"gov.dwp.universal_credit.deductions.minimum_payable":["uc_deductions"],"gov.dwp.universal_credit.deductions.protected_floor":["universal_credit"],"gov.dwp.universal_credit.elements.child.amount":["two_child_limit_payment","uc_individual_child_element"],"gov.dwp.universal_credit.elements.child.disabled.amount":["uc_individual_disabled_child_element"],"gov.dwp.universal_credit.elements.child.eligibility.child_age_limit":["is_child_for_universal_credit","meets_qualifying_young_person_age_condition_for_universal_credit"],"gov.dwp.universal_credit.elements.child.eligibility.education_or_training_start_age_limit":["meets_qualifying_young_person_entry_condition_for_universal_credit"],"gov.dwp.universal_credit.elements.child.eligibility.qualifying_young_person_age_limit":["meets_qualifying_young_person_age_condition_for_universal_credit"],"gov.dwp.universal_credit.elements.child.eligibility.terminal_date_age_limit":["meets_qualifying_young_person_terminal_date_condition_for_universal_credit"],"gov.dwp.universal_credit.elements.child.first.higher_amount":["uc_individual_child_element"],"gov.dwp.universal_credit.elements.child.limit.born_before":["uc_is_child_born_before_child_limit"],"gov.dwp.universal_credit.elements.child.limit.child_count":["uc_individual_child_element"],"gov.dwp.universal_credit.elements.child.severely_disabled.amount":["uc_individual_severely_disabled_child_element"],"gov.dwp.universal_credit.elements.childcare.cap":["uc_maximum_childcare_element_amount"],"gov.dwp.universal_credit.elements.childcare.coverage_rate":["uc_childcare_element"],"gov.dwp.universal_credit.elements.housing.non_dep_deduction.age_threshold":["uc_individual_non_dep_deduction_eligible"],"gov.dwp.universal_credit.elements.housing.non_dep_deduction.amount":["uc_individual_non_dep_deduction"],"gov.dwp.universal_credit.eligibility.min_age":["meets_uc_minimum_age_condition"],"gov.dwp.universal_credit.eligibility.reduced_min_age":["meets_uc_minimum_age_condition"],"gov.dwp.universal_credit.means_test.capital.limit":["is_uc_eligible"],"gov.dwp.universal_credit.means_test.capital.person_sources":["uc_assessable_capital"],"gov.dwp.universal_credit.means_test.capital.sources":["uc_assessable_capital"],"gov.dwp.universal_credit.means_test.capital.tariff_income.amount":["uc_tariff_income"],"gov.dwp.universal_credit.means_test.capital.tariff_income.step":["uc_tariff_income"],"gov.dwp.universal_credit.means_test.capital.tariff_income.threshold":["uc_tariff_income"],"gov.dwp.universal_credit.means_test.income_definitions.unearned":["uc_unearned_income"],"gov.dwp.universal_credit.means_test.minimum_income_floor.ineligible_partner_hours":["uc_minimum_income_floor_gross"],"gov.dwp.universal_credit.means_test.minimum_income_floor.no_requirements_partner_hours":["uc_minimum_income_floor_gross"],"gov.dwp.universal_credit.means_test.minimum_income_floor.self_employed_national_insurance":["uc_minimum_income_floor_national_insurance"],"gov.dwp.universal_credit.means_test.reduction_rate":["uc_income_reduction"],"gov.dwp.universal_credit.means_test.work_allowance.with_housing":["uc_work_allowance"],"gov.dwp.universal_credit.means_test.work_allowance.without_housing":["uc_work_allowance"],"gov.dwp.universal_credit.standard_allowance.amount":["uc_standard_allowance"],"gov.dwp.universal_credit.standard_allowance.claimant_type.age_threshold":["uc_standard_allowance_claimant_type"],"gov.dwp.universal_credit.work_requirements.default_expected_hours":["uc_expected_hours"],"gov.dwp.universal_credit.work_requirements.interview_or_preparation_threshold_hours":["uc_minimum_income_floor_gross"],"gov.dwp.universal_credit.work_requirements.responsible_carer.child_age.interview_only":["uc_work_related_group_apart_from_earnings"],"gov.dwp.universal_credit.work_requirements.responsible_carer.child_age.no_requirements":["uc_work_related_group_apart_from_earnings"],"gov.dwp.universal_credit.work_requirements.responsible_carer.child_age.work_preparation":["uc_work_related_group_apart_from_earnings"],"gov.dwp.universal_credit.work_requirements.responsible_carer.expected_hours.below_compulsory_school_age":["uc_expected_hours"],"gov.dwp.universal_credit.work_requirements.responsible_carer.expected_hours.child_age_limit":["uc_expected_hours"],"gov.dwp.universal_credit.work_requirements.responsible_carer.expected_hours.compulsory_school_age":["uc_expected_hours"],"gov.dwp.winter_fuel_payment.amount.higher":["winter_fuel_payment"],"gov.dwp.winter_fuel_payment.amount.higher_shared_with_80_or_over":["winter_fuel_payment"],"gov.dwp.winter_fuel_payment.amount.higher_shared_with_under_80":["winter_fuel_payment"],"gov.dwp.winter_fuel_payment.amount.lower":["winter_fuel_payment"],"gov.dwp.winter_fuel_payment.amount.lower_shared":["winter_fuel_payment"],"gov.dwp.winter_fuel_payment.eligibility.countries":["winter_fuel_payment_eligible"],"gov.dwp.winter_fuel_payment.eligibility.higher_age_requirement":["winter_fuel_payment"],"gov.dwp.winter_fuel_payment.eligibility.minimum_tax_credit_award":["is_on_winter_fuel_payment_relevant_benefit","winter_fuel_payment_eligible"],"gov.dwp.winter_fuel_payment.eligibility.partner_receipt_counts":["is_on_winter_fuel_payment_relevant_benefit"],"gov.dwp.winter_fuel_payment.eligibility.relevant_benefits":["is_on_winter_fuel_payment_relevant_benefit","winter_fuel_payment_eligible"],"gov.dwp.winter_fuel_payment.eligibility.require_benefits":["winter_fuel_payment_eligible"],"gov.dwp.winter_fuel_payment.eligibility.state_pension_age_requirement":["winter_fuel_payment_eligible"],"gov.dwp.winter_fuel_payment.eligibility.taxable_income_test.maximum_taxable_income":["winter_fuel_payment_eligible"],"gov.dwp.winter_fuel_payment.eligibility.taxable_income_test.use_maximum_taxable_income":["winter_fuel_payment_eligible"],"gov.economic_assumptions.yoy_growth.obr.rpi":["plan_1_interest_rate","plan_2_interest_rate","plan_5_interest_rate","postgraduate_interest_rate"],"gov.hmrc.alcohol_duty.high_abv":["beer_duty","cider_duty","other_fermented_duty","sparkling_cider_duty","spirits_duty","wine_duty"],"gov.hmrc.alcohol_duty.sparkling_cider_abv":["sparkling_cider_duty"],"gov.hmrc.alcohol_duty.spirits_abv":["beer_duty","cider_duty","other_fermented_duty","sparkling_cider_duty","spirits_duty","wine_duty"],"gov.hmrc.alcohol_duty.standard_abv":["beer_duty","cider_duty","other_fermented_duty","sparkling_cider_duty","spirits_duty","wine_duty"],"gov.hmrc.alcohol_duty.taxable_abv":["beer_duty","cider_duty","other_fermented_duty","sparkling_cider_duty","spirits_duty","wine_duty"],"gov.hmrc.alcohol_duty.wine_easement_abv":["wine_duty"],"gov.hmrc.alcohol_duty.wine_easement_max_abv":["wine_duty"],"gov.hmrc.alcohol_duty.wine_easement_min_abv":["wine_duty"],"gov.hmrc.business_rates.statistics.revenue.ENGLAND":["baseline_business_rates","business_rates"],"gov.hmrc.business_rates.statistics.revenue.NORTHERN_IRELAND":["baseline_business_rates","business_rates"],"gov.hmrc.business_rates.statistics.revenue.SCOTLAND":["baseline_business_rates","business_rates"],"gov.hmrc.business_rates.statistics.revenue.WALES":["baseline_business_rates","business_rates"],"gov.hmrc.cgt.additional_rate":["capital_gains_tax"],"gov.hmrc.cgt.annual_exempt_amount":["capital_gains_tax"],"gov.hmrc.cgt.badr.lifetime_limit":["capital_gains_tax"],"gov.hmrc.cgt.badr.rate":["capital_gains_tax"],"gov.hmrc.cgt.basic_rate":["capital_gains_tax"],"gov.hmrc.cgt.carried_interest.additional_rate":["capital_gains_tax"],"gov.hmrc.cgt.carried_interest.basic_rate":["capital_gains_tax"],"gov.hmrc.cgt.carried_interest.higher_rate":["capital_gains_tax"],"gov.hmrc.cgt.higher_rate":["capital_gains_tax"],"gov.hmrc.cgt.residential_property.additional_rate":["capital_gains_tax"],"gov.hmrc.cgt.residential_property.basic_rate":["capital_gains_tax"],"gov.hmrc.cgt.residential_property.higher_rate":["capital_gains_tax"],"gov.hmrc.child_benefit.amount.additional":["child_benefit_respective_amount"],"gov.hmrc.child_benefit.amount.eldest":["child_benefit_respective_amount"],"gov.hmrc.child_benefit.eligibility.child_age_limit":["is_child_for_child_benefit","meets_qualifying_young_person_age_condition_for_child_benefit"],"gov.hmrc.child_benefit.eligibility.education_or_training_start_age_limit":["meets_qualifying_young_person_entry_condition_for_child_benefit"],"gov.hmrc.child_benefit.eligibility.qualifying_young_person_age_limit":["meets_qualifying_young_person_age_condition_for_child_benefit"],"gov.hmrc.child_benefit.opt_out_charge_share":["child_benefit"],"gov.hmrc.fuel_duty.lpg":["fuel_duty"],"gov.hmrc.fuel_duty.natural_gas":["fuel_duty"],"gov.hmrc.fuel_duty.petrol_and_diesel":["fuel_duty"],"gov.hmrc.fuel_duty.rural_fuel_duty_relief":["fuel_duty"],"gov.hmrc.income_tax.adjusted_net_income_components":["net_income","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"gov.hmrc.income_tax.allowances.annual_allowance.default":["pension_annual_allowance"],"gov.hmrc.income_tax.allowances.annual_allowance.minimum":["pension_annual_allowance"],"gov.hmrc.income_tax.allowances.annual_allowance.reduction_rate":["pension_annual_allowance"],"gov.hmrc.income_tax.allowances.annual_allowance.taper":["pension_annual_allowance"],"gov.hmrc.income_tax.allowances.dividend_allowance":["dividend_income_tax","taxed_dividend_income"],"gov.hmrc.income_tax.allowances.marriage_allowance.eligible_bands":["meets_marriage_allowance_income_conditions"],"gov.hmrc.income_tax.allowances.marriage_allowance.max":["marriage_allowance"],"gov.hmrc.income_tax.allowances.marriage_allowance.rounding_increment":["marriage_allowance"],"gov.hmrc.income_tax.allowances.married_couples_allowance.deduction_rate":["married_couples_allowance_deduction"],"gov.hmrc.income_tax.allowances.personal_allowance.amount":["carers_allowance_earnings","marriage_allowance","personal_allowance","savings_starter_rate_income","uc_minimum_income_floor_income_tax"],"gov.hmrc.income_tax.allowances.personal_allowance.maximum_ANI":["personal_allowance"],"gov.hmrc.income_tax.allowances.personal_allowance.reduction_rate":["personal_allowance"],"gov.hmrc.income_tax.allowances.personal_savings_allowance.additional":["savings_allowance"],"gov.hmrc.income_tax.allowances.personal_savings_allowance.basic":["savings_allowance"],"gov.hmrc.income_tax.allowances.personal_savings_allowance.higher":["savings_allowance"],"gov.hmrc.income_tax.allowances.property_allowance":["property_allowance_deduction_if_used","property_receipts_within_allowance"],"gov.hmrc.income_tax.allowances.trading_allowance":["trading_allowance_deduction"],"gov.hmrc.income_tax.bases.taxable_self_employment_income_deductions":["taxable_self_employment_income"],"gov.hmrc.income_tax.charges.CB_HITC.phase_out_end":["CB_HITC","child_benefit"],"gov.hmrc.income_tax.charges.CB_HITC.phase_out_start":["CB_HITC","child_benefit"],"gov.hmrc.income_tax.earned_taxable_income_exclusions":["earned_taxable_income","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"gov.hmrc.income_tax.income_tax_additions":["income_tax"],"gov.hmrc.income_tax.income_tax_subtractions":["income_tax","property_finance_cost_relief","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"gov.hmrc.income_tax.rates.dividends":["dividend_income_tax"],"gov.hmrc.income_tax.rates.property.additional":["property_income_tax"],"gov.hmrc.income_tax.rates.property.basic":["property_finance_cost_relief","property_income_tax"],"gov.hmrc.income_tax.rates.property.higher":["property_income_tax"],"gov.hmrc.income_tax.rates.savings.additional":["savings_income_tax"],"gov.hmrc.income_tax.rates.savings.basic":["savings_income_tax"],"gov.hmrc.income_tax.rates.savings.higher":["savings_income_tax"],"gov.hmrc.income_tax.rates.savings_starter_rate.allowance":["savings_starter_rate_income"],"gov.hmrc.income_tax.rates.savings_starter_rate.phase_out":["savings_starter_rate_income"],"gov.hmrc.income_tax.rates.scotland.rates":["carers_allowance_earnings","earned_income_tax","esa_exempt_work_earnings","property_income_tax","tax_band","uc_income_tax_on_earnings","uc_income_tax_on_trade","uc_minimum_income_floor_income_tax"],"gov.hmrc.income_tax.rates.uk":["add_rate_earned_income","add_rate_earned_income_tax","add_rate_savings_income","basic_rate_earned_income","basic_rate_earned_income_tax","basic_rate_savings_income","basic_rate_savings_income_pre_starter","capital_gains_tax","carers_allowance_earnings","earned_income_tax","esa_exempt_work_earnings","gift_aid_grossed_up","higher_rate_earned_income","higher_rate_earned_income_tax","higher_rate_savings_income","personal_pension_contributions_tax","property_income_tax","savings_allowance","tax_band","uc_income_tax_on_earnings","uc_income_tax_on_trade","uc_minimum_income_floor_income_tax"],"gov.hmrc.income_tax.reliefs.pension_contribution.basic_amount":["pension_contributions_relief"],"gov.hmrc.income_tax.reliefs.property_finance_costs.disallowed_share":["deductible_property_finance_costs","property_finance_costs_relievable"],"gov.hmrc.isa.lifetime.charge_free_age":["lifetime_isa_countable_capital"],"gov.hmrc.isa.lifetime.withdrawal_charge":["lifetime_isa_countable_capital"],"gov.hmrc.minimum_wage.apprentice":["minimum_wage"],"gov.hmrc.minimum_wage.non_apprentice":["minimum_wage","uc_minimum_income_floor_gross"],"gov.hmrc.national_insurance.class_1.rates.employee.additional":["esa_exempt_work_earnings","ni_class_1_employee_additional","salary_sacrifice_pension_ni_employee","uc_minimum_income_floor_national_insurance"],"gov.hmrc.national_insurance.class_1.rates.employee.main":["esa_exempt_work_earnings","ni_class_1_employee_primary","salary_sacrifice_pension_ni_employee","uc_minimum_income_floor_national_insurance"],"gov.hmrc.national_insurance.class_1.rates.employer":["adjusted_employer_cost","employer_ni_fixed_employer_cost_change","ni_class_1_employer","salary_sacrifice_pension_ni_employer"],"gov.hmrc.national_insurance.class_1.thresholds.primary_threshold":["esa_exempt_work_earnings","ni_class_1_employee_primary","uc_minimum_income_floor_national_insurance"],"gov.hmrc.national_insurance.class_1.thresholds.secondary_threshold":["adjusted_employer_cost","employer_ni_fixed_employer_cost_change","ni_class_1_employer"],"gov.hmrc.national_insurance.class_1.thresholds.upper_earnings_limit":["esa_exempt_work_earnings","ni_class_1_employee_additional","ni_class_1_employee_primary","salary_sacrifice_pension_ni_employee","uc_minimum_income_floor_national_insurance"],"gov.hmrc.national_insurance.class_2.flat_rate":["carers_allowance_earnings","esa_exempt_work_earnings","ni_class_2","ni_class_4_maximum","uc_minimum_income_floor_national_insurance"],"gov.hmrc.national_insurance.class_2.lower_profits_threshold":["carers_allowance_earnings","esa_exempt_work_earnings","ni_class_2","uc_minimum_income_floor_national_insurance"],"gov.hmrc.national_insurance.class_2.lower_profits_threshold_applies":["carers_allowance_earnings","ni_class_2","uc_minimum_income_floor_national_insurance"],"gov.hmrc.national_insurance.class_2.small_profits_threshold":["carers_allowance_earnings","esa_exempt_work_earnings","ni_class_2","uc_minimum_income_floor_national_insurance"],"gov.hmrc.national_insurance.class_4.annual_maximum.includes_class_2":["ni_class_4","ni_class_4_maximum"],"gov.hmrc.national_insurance.class_4.rates.additional":["ni_class_4","ni_class_4_maximum","uc_minimum_income_floor_national_insurance"],"gov.hmrc.national_insurance.class_4.rates.main":["carers_allowance_earnings","esa_exempt_work_earnings","ni_class_4","ni_class_4_main","ni_class_4_maximum","uc_minimum_income_floor_national_insurance"],"gov.hmrc.national_insurance.class_4.thresholds.lower_profits_limit":["carers_allowance_earnings","esa_exempt_work_earnings","ni_class_4","ni_class_4_main","ni_class_4_maximum","uc_minimum_income_floor_national_insurance"],"gov.hmrc.national_insurance.class_4.thresholds.upper_profits_limit":["carers_allowance_earnings","esa_exempt_work_earnings","ni_class_4","ni_class_4_main","ni_class_4_maximum","uc_minimum_income_floor_national_insurance"],"gov.hmrc.national_insurance.salary_sacrifice_pension_cap":["pension_contributions_via_salary_sacrifice_adjusted","salary_sacrifice_broad_base_haircut","salary_sacrifice_returned_to_income"],"gov.hmrc.pensions.pension_contributions_relief_age_limit":["pension_contributions_relief","uc_individual_earned_income_before_mif"],"gov.hmrc.stamp_duty.abolish":["expected_sdlt"],"gov.hmrc.stamp_duty.non_residential.purchase":["sdlt_on_non_residential_property_transactions"],"gov.hmrc.stamp_duty.non_residential.rent":["sdlt_on_non_residential_property_rent"],"gov.hmrc.stamp_duty.property_sale_rate":["expected_lbtt","expected_ltt","expected_sdlt"],"gov.hmrc.stamp_duty.residential.purchase.additional.min":["sdlt_on_residential_property_transactions"],"gov.hmrc.stamp_duty.residential.purchase.additional.rate":["sdlt_on_residential_property_transactions"],"gov.hmrc.stamp_duty.residential.purchase.main.first.max":["sdlt_on_residential_property_transactions"],"gov.hmrc.stamp_duty.residential.purchase.main.first.rate":["sdlt_on_residential_property_transactions"],"gov.hmrc.stamp_duty.residential.purchase.main.subsequent":["sdlt_on_residential_property_transactions"],"gov.hmrc.stamp_duty.residential.rent":["sdlt_on_residential_property_rent"],"gov.hmrc.stamp_duty.statistics.non_residential.corporate.revenue":["corporate_sdlt"],"gov.hmrc.stamp_duty.statistics.residential.corporate.revenue":["corporate_sdlt"],"gov.hmrc.student_loans.interest_rates.plan_1.boe_margin":["plan_1_interest_rate"],"gov.hmrc.student_loans.interest_rates.plan_2.additional_rate":["plan_2_interest_rate"],"gov.hmrc.student_loans.interest_rates.plan_2.upper_threshold":["plan_2_interest_rate"],"gov.hmrc.student_loans.interest_rates.postgraduate_additional_rate":["postgraduate_interest_rate"],"gov.hmrc.student_loans.postgraduate_repayment_rate":["student_loan_repayment_rate"],"gov.hmrc.student_loans.repayment_rate":["student_loan_repayment_rate"],"gov.hmrc.student_loans.thresholds.plan_1":["student_loan_repayment"],"gov.hmrc.student_loans.thresholds.plan_2":["plan_2_interest_rate","student_loan_repayment"],"gov.hmrc.student_loans.thresholds.plan_4":["student_loan_repayment"],"gov.hmrc.student_loans.thresholds.plan_5":["student_loan_repayment"],"gov.hmrc.student_loans.thresholds.postgraduate":["student_loan_repayment"],"gov.hmrc.tax_free_childcare.age.disability":["tax_free_childcare_child_age_eligible"],"gov.hmrc.tax_free_childcare.age.standard":["tax_free_childcare_child_age_eligible"],"gov.hmrc.tax_free_childcare.carers_leave_qualifies":["tax_free_childcare_regarded_as_in_paid_work"],"gov.hmrc.tax_free_childcare.caring_or_incapacity_benefits":["tax_free_childcare_caring_or_incapacity_benefit"],"gov.hmrc.tax_free_childcare.caring_or_incapacity_benefits_in_payment":["tax_free_childcare_regarded_as_in_paid_work"],"gov.hmrc.tax_free_childcare.contribution.disabled_child":["tax_free_childcare"],"gov.hmrc.tax_free_childcare.contribution.rate":["tax_free_childcare"],"gov.hmrc.tax_free_childcare.contribution.standard_child":["tax_free_childcare"],"gov.hmrc.tax_free_childcare.declaration_periods_per_year":["tax_free_childcare","tax_free_childcare_eligible_declaration_periods"],"gov.hmrc.tax_free_childcare.disqualifying_benefits":["tax_free_childcare_program_eligible"],"gov.hmrc.tax_free_childcare.income.countable_sources":["tax_free_childcare_expected_declaration_period_income"],"gov.hmrc.tax_free_childcare.income.declaration_period_weeks":["tax_free_childcare_expected_declaration_period_income","tax_free_childcare_meets_income_requirements"],"gov.hmrc.tax_free_childcare.income.income_limit":["tax_free_childcare_meets_income_requirements"],"gov.hmrc.tax_free_childcare.minimum_weekly_hours":["tax_free_childcare_meets_income_requirements"],"gov.hmrc.vat.reduced_rate":["baseline_vat","vat"],"gov.hmrc.vat.reduced_rate_share":["reduced_rate_vat_consumption"],"gov.hmrc.vat.standard_rate":["baseline_vat","vat"],"gov.local_authorities.england.council_tax_reduction.pensioners.earnings_disregard.additional":["council_tax_reduction_pensioner_earnings_disregard"],"gov.local_authorities.england.council_tax_reduction.pensioners.earnings_disregard.couple":["council_tax_reduction_pensioner_earnings_disregard"],"gov.local_authorities.england.council_tax_reduction.pensioners.earnings_disregard.lone_parent":["council_tax_reduction_pensioner_earnings_disregard"],"gov.local_authorities.england.council_tax_reduction.pensioners.earnings_disregard.single":["council_tax_reduction_pensioner_earnings_disregard"],"gov.local_authorities.england.council_tax_reduction.pensioners.maximum_support_rate":["simulated_council_tax_reduction_benunit"],"gov.local_authorities.england.council_tax_reduction.pensioners.means_test.capital_limit":["simulated_council_tax_reduction_benunit"],"gov.local_authorities.england.council_tax_reduction.pensioners.means_test.withdrawal_rate":["simulated_council_tax_reduction_benunit"],"gov.local_authorities.kingston_upon_thames.council_tax_reduction.maximum_support_rate":["kingston_upon_thames_council_tax_reduction"],"gov.local_authorities.kingston_upon_thames.council_tax_reduction.means_test.capital_limit":["kingston_upon_thames_council_tax_reduction"],"gov.local_authorities.kingston_upon_thames.council_tax_reduction.means_test.tariff_income_step":["kingston_upon_thames_council_tax_reduction"],"gov.local_authorities.kingston_upon_thames.council_tax_reduction.means_test.tariff_income_threshold":["kingston_upon_thames_council_tax_reduction"],"gov.local_authorities.kingston_upon_thames.council_tax_reduction.means_test.withdrawal_rate":["kingston_upon_thames_council_tax_reduction"],"gov.local_authorities.merton.council_tax_reduction.maximum_support_rate":["merton_council_tax_reduction"],"gov.local_authorities.merton.council_tax_reduction.means_test.capital_limit":["merton_council_tax_reduction"],"gov.local_authorities.merton.council_tax_reduction.means_test.withdrawal_rate":["merton_council_tax_reduction"],"gov.local_authorities.newham.council_tax_reduction.maximum_support_rate":["newham_council_tax_reduction"],"gov.local_authorities.newham.council_tax_reduction.means_test.capital_limit":["newham_council_tax_reduction"],"gov.local_authorities.newham.council_tax_reduction.means_test.withdrawal_rate":["newham_council_tax_reduction"],"gov.local_authorities.oxford.council_tax_reduction.income_band.maximum_support_rate":["oxford_council_tax_reduction"],"gov.local_authorities.oxford.council_tax_reduction.means_test.capital_limit":["oxford_council_tax_reduction"],"gov.local_authorities.oxford.council_tax_reduction.means_test.tariff_income_step":["oxford_council_tax_reduction"],"gov.local_authorities.oxford.council_tax_reduction.means_test.tariff_income_threshold":["oxford_council_tax_reduction"],"gov.local_authorities.scotland.council_tax_reduction.maximum_support_rate":["simulated_council_tax_reduction_benunit"],"gov.local_authorities.scotland.council_tax_reduction.means_test.capital_limit":["simulated_council_tax_reduction_benunit"],"gov.local_authorities.scotland.council_tax_reduction.means_test.withdrawal_rate":["simulated_council_tax_reduction_benunit"],"gov.local_authorities.scotland.council_tax_reduction.pensioners.earnings_disregard.additional":["council_tax_reduction_pensioner_earnings_disregard"],"gov.local_authorities.scotland.council_tax_reduction.pensioners.earnings_disregard.couple":["council_tax_reduction_pensioner_earnings_disregard"],"gov.local_authorities.scotland.council_tax_reduction.pensioners.earnings_disregard.lone_parent":["council_tax_reduction_pensioner_earnings_disregard"],"gov.local_authorities.scotland.council_tax_reduction.pensioners.earnings_disregard.single":["council_tax_reduction_pensioner_earnings_disregard"],"gov.local_authorities.scotland.council_tax_reduction.working_age.young_person_follows_universal_credit":["is_child_or_young_person_for_council_tax_reduction"],"gov.local_authorities.wales.council_tax_reduction.maximum_support_rate":["simulated_council_tax_reduction_benunit"],"gov.local_authorities.wales.council_tax_reduction.means_test.capital_limit":["simulated_council_tax_reduction_benunit"],"gov.local_authorities.wales.council_tax_reduction.means_test.withdrawal_rate":["simulated_council_tax_reduction_benunit"],"gov.local_authorities.wales.council_tax_reduction.pensioners.earnings_disregard.additional":["council_tax_reduction_pensioner_earnings_disregard"],"gov.local_authorities.wales.council_tax_reduction.pensioners.earnings_disregard.couple":["council_tax_reduction_pensioner_earnings_disregard"],"gov.local_authorities.wales.council_tax_reduction.pensioners.earnings_disregard.lone_parent":["council_tax_reduction_pensioner_earnings_disregard"],"gov.local_authorities.wales.council_tax_reduction.pensioners.earnings_disregard.single":["council_tax_reduction_pensioner_earnings_disregard"],"gov.local_authorities.westminster.council_tax_reduction.maximum_support_rate":["westminster_council_tax_reduction"],"gov.local_authorities.westminster.council_tax_reduction.means_test.capital_limit":["westminster_council_tax_reduction"],"gov.local_authorities.westminster.council_tax_reduction.means_test.tariff_income_step":["westminster_council_tax_reduction"],"gov.local_authorities.westminster.council_tax_reduction.means_test.tariff_income_threshold":["westminster_council_tax_reduction"],"gov.local_authorities.westminster.council_tax_reduction.means_test.withdrawal_rate":["westminster_council_tax_reduction"],"gov.revenue_scotland.lbtt.non_residential":["lbtt_on_non_residential_property_transactions"],"gov.revenue_scotland.lbtt.rent":["lbtt_on_non_residential_property_rent","lbtt_on_residential_property_rent"],"gov.revenue_scotland.lbtt.residential.additional_residence_surcharge":["lbtt_on_residential_property_transactions"],"gov.revenue_scotland.lbtt.residential.first_time_buyer_rate":["lbtt_on_residential_property_transactions"],"gov.revenue_scotland.lbtt.residential.rate":["lbtt_on_residential_property_transactions"],"gov.scottish_government.funded_early_learning_childcare.age.max":["scottish_funded_early_learning_childcare_eligible"],"gov.scottish_government.funded_early_learning_childcare.age.min":["scottish_funded_early_learning_childcare_eligible"],"gov.simulation.capital_gains_responses.badr_elasticity":["capital_gains_badr_elasticity"],"gov.simulation.capital_gains_responses.elasticity":["capital_gains_badr_behavioural_response","capital_gains_behavioural_response","capital_gains_elasticity"],"gov.simulation.capital_gains_responses.mtr_elasticity":["capital_gains_badr_behavioural_response","capital_gains_behavioural_response"],"gov.simulation.capital_gains_responses.separate_badr_elasticity":["capital_gains_badr_behavioural_response","capital_gains_badr_elasticity","capital_gains_behavioural_response"],"gov.simulation.labour_supply_responses.bounds.effective_wage_rate_change":["relative_wage_change"],"gov.simulation.labour_supply_responses.bounds.income_change":["relative_income_change"],"gov.simulation.labour_supply_responses.income_elasticity":["employment_income_behavioral_response","income_elasticity_lsr"],"gov.simulation.labour_supply_responses.substitution_elasticity":["employment_income_behavioral_response","substitution_elasticity_lsr"],"gov.simulation.marginal_tax_rate_adults":["cliff_evaluated","marginal_tax_rate","marginal_tax_rate_wrt_employer_cost"],"gov.simulation.marginal_tax_rate_delta":["cliff_gap","marginal_tax_rate","marginal_tax_rate_wrt_employer_cost"],"gov.simulation.microdata_vat_coverage":["baseline_vat","vat"],"gov.simulation.private_school_vat.private_school_fees":["private_school_vat"],"gov.simulation.private_school_vat.private_school_vat_basis":["private_school_vat"],"gov.simulation.uc_deductions.calibration_cap":["uc_deduction_rate"],"gov.simulation.uc_deductions.latent_rate_distribution.AT_10":["uc_has_deduction","uc_latent_deduction_rate"],"gov.simulation.uc_deductions.latent_rate_distribution.AT_15":["uc_has_deduction","uc_latent_deduction_rate"],"gov.simulation.uc_deductions.latent_rate_distribution.AT_20":["uc_has_deduction","uc_latent_deduction_rate"],"gov.simulation.uc_deductions.latent_rate_distribution.AT_25":["uc_has_deduction","uc_latent_deduction_rate"],"gov.simulation.uc_deductions.latent_rate_distribution.AT_5":["uc_has_deduction","uc_latent_deduction_rate"],"gov.simulation.uc_deductions.latent_rate_distribution.FIFTEEN_TO_20":["uc_has_deduction","uc_latent_deduction_rate"],"gov.simulation.uc_deductions.latent_rate_distribution.FIVE_TO_10":["uc_has_deduction","uc_latent_deduction_rate"],"gov.simulation.uc_deductions.latent_rate_distribution.OVER_25":["uc_has_deduction","uc_latent_deduction_rate"],"gov.simulation.uc_deductions.latent_rate_distribution.TEN_TO_15":["uc_has_deduction","uc_latent_deduction_rate"],"gov.simulation.uc_deductions.latent_rate_distribution.TWENTY_TO_25":["uc_has_deduction","uc_latent_deduction_rate"],"gov.simulation.uc_deductions.latent_rate_distribution.UNDER_5":["uc_has_deduction","uc_latent_deduction_rate"],"gov.simulation.uc_deductions.mean_monthly_amount_by_type.ADVANCE":["uc_deduction_rate"],"gov.simulation.uc_deductions.mean_monthly_amount_by_type.GOVERNMENT":["uc_deduction_rate"],"gov.simulation.uc_deductions.mean_monthly_amount_by_type.THIRD_PARTY":["uc_deduction_rate"],"gov.simulation.uc_deductions.region_incidence_factor":["uc_has_deduction","uc_latent_deduction_rate"],"gov.simulation.uc_deductions.type_combination.ADVANCE_AND_GOVERNMENT":["uc_deduction_combination"],"gov.simulation.uc_deductions.type_combination.ADVANCE_AND_THIRD_PARTY":["uc_deduction_combination"],"gov.simulation.uc_deductions.type_combination.ADVANCE_ONLY":["uc_deduction_combination"],"gov.simulation.uc_deductions.type_combination.ALL_THREE":["uc_deduction_combination"],"gov.simulation.uc_deductions.type_combination.GOVERNMENT_ONLY":["uc_deduction_combination"],"gov.simulation.uc_deductions.type_combination.THIRD_PARTY_AND_GOVERNMENT":["uc_deduction_combination"],"gov.simulation.uc_deductions.type_combination.THIRD_PARTY_ONLY":["uc_deduction_combination"],"gov.social_security_scotland.carer_support_payment.min_hours":["carer_support_payment_pre_overlap","partners_care_for_same_severely_disabled_person"],"gov.social_security_scotland.carer_support_payment.rate":["carer_support_payment_pre_overlap"],"gov.social_security_scotland.carer_support_payment.supplement":["scottish_carer_supplement"],"gov.social_security_scotland.pawhp.active":["pawhp_eligible"],"gov.social_security_scotland.pawhp.amount.higher":["pension_age_winter_heating_payment"],"gov.social_security_scotland.pawhp.amount.higher_shared_with_80_or_over":["pension_age_winter_heating_payment"],"gov.social_security_scotland.pawhp.amount.higher_shared_with_under_80":["pension_age_winter_heating_payment"],"gov.social_security_scotland.pawhp.amount.lower":["pension_age_winter_heating_payment"],"gov.social_security_scotland.pawhp.amount.lower_shared":["pension_age_winter_heating_payment"],"gov.social_security_scotland.pawhp.eligibility.higher_age_requirement":["pension_age_winter_heating_payment"],"gov.social_security_scotland.pawhp.eligibility.minimum_tax_credit_award":["is_on_pawhp_relevant_benefit","pawhp_eligible"],"gov.social_security_scotland.pawhp.eligibility.partner_receipt_counts":["is_on_pawhp_relevant_benefit"],"gov.social_security_scotland.pawhp.eligibility.relevant_benefits":["is_on_pawhp_relevant_benefit","pawhp_eligible"],"gov.social_security_scotland.pawhp.eligibility.require_benefits":["pawhp_eligible"],"gov.social_security_scotland.pawhp.eligibility.state_pension_age_requirement":["pawhp_eligible"],"gov.social_security_scotland.scottish_child_payment.amount":["is_scp_eligible","scottish_child_payment"],"gov.social_security_scotland.scottish_child_payment.max_age":["is_scp_eligible_child"],"gov.social_security_scotland.scottish_child_payment.qualifying_benefits.child_tax_credit":["is_scp_eligible"],"gov.social_security_scotland.scottish_child_payment.qualifying_benefits.esa_income":["is_scp_eligible"],"gov.social_security_scotland.scottish_child_payment.qualifying_benefits.income_support":["is_scp_eligible"],"gov.social_security_scotland.scottish_child_payment.qualifying_benefits.jsa_income":["is_scp_eligible"],"gov.social_security_scotland.scottish_child_payment.qualifying_benefits.pension_credit":["is_scp_eligible"],"gov.social_security_scotland.scottish_child_payment.qualifying_benefits.universal_credit":["is_scp_eligible"],"gov.social_security_scotland.scottish_child_payment.qualifying_benefits.working_tax_credit":["is_scp_eligible"],"gov.social_security_scotland.two_child_limit_payment.in_effect":["two_child_limit_payment"],"gov.treasury.cost_of_living_support.disabled.amount":["cost_of_living_support_payment"],"gov.treasury.cost_of_living_support.disabled.qualifying_benefits":["cost_of_living_support_payment"],"gov.treasury.cost_of_living_support.means_tested_households.amount":["cost_of_living_support_payment"],"gov.treasury.cost_of_living_support.means_tested_households.qualifying_benefits":["cost_of_living_support_payment"],"gov.treasury.cost_of_living_support.pensioners.amount":["cost_of_living_support_payment"],"gov.treasury.cost_of_living_support.pensioners.qualifying_benefits":["cost_of_living_support_payment"],"gov.treasury.energy_bills_rebate.council_tax_rebate.amount":["ebr_council_tax_rebate"],"gov.treasury.energy_bills_rebate.council_tax_rebate.bands":["ebr_council_tax_rebate"],"gov.treasury.energy_bills_rebate.energy_bills_credit":["ebr_energy_bills_credit"],"gov.treasury.energy_bills_rebate.energy_bills_credit_monthly":["monthly_ebr_energy_bills_credit"],"gov.treasury.energy_bills_rebate.energy_bills_credit_northern_ireland":["monthly_ebr_energy_bills_credit"],"gov.wra.land_transaction_tax.non_residential":["ltt_on_non_residential_property_transactions"],"gov.wra.land_transaction_tax.rent":["ltt_on_non_residential_property_rent","ltt_on_residential_property_rent"],"gov.wra.land_transaction_tax.residential.higher_rate":["ltt_on_residential_property_transactions"],"gov.wra.land_transaction_tax.residential.primary":["ltt_on_residential_property_transactions"],"household.consumption.alcohol.beer_abv":["beer_abv"],"household.consumption.alcohol.cider_abv":["cider_abv"],"household.consumption.alcohol.other_fermented_abv":["other_fermented_abv"],"household.consumption.alcohol.sparkling_cider_abv":["sparkling_cider_abv"],"household.consumption.alcohol.spirits_abv":["spirits_abv"],"household.consumption.alcohol.wine_abv":["wine_abv"],"household.consumption.carbon.emissions.alcohol_and_tobacco":["carbon_consumption"],"household.consumption.carbon.emissions.clothing_and_footwear":["carbon_consumption"],"household.consumption.carbon.emissions.communication":["carbon_consumption"],"household.consumption.carbon.emissions.education":["carbon_consumption"],"household.consumption.carbon.emissions.food_and_non_alcoholic_beverages":["carbon_consumption"],"household.consumption.carbon.emissions.health":["carbon_consumption"],"household.consumption.carbon.emissions.household_furnishings":["carbon_consumption"],"household.consumption.carbon.emissions.housing_water_and_electricity":["carbon_consumption"],"household.consumption.carbon.emissions.miscellaneous":["carbon_consumption"],"household.consumption.carbon.emissions.recreation":["carbon_consumption"],"household.consumption.carbon.emissions.restaurants_and_hotels":["carbon_consumption"],"household.consumption.carbon.emissions.transport":["carbon_consumption"],"household.consumption.fuel.prices.diesel":["diesel_price"],"household.consumption.fuel.prices.petrol":["petrol_price"],"household.consumption.tobacco.cigarettes_per_pack":["tobacco_duty"],"household.consumption.tobacco.price_per_pack":["cigarette_price_per_pack"],"household.consumption.total_by_category.alcohol_and_tobacco_consumption":["carbon_consumption"],"household.consumption.total_by_category.clothing_and_footwear_consumption":["carbon_consumption"],"household.consumption.total_by_category.communication_consumption":["carbon_consumption"],"household.consumption.total_by_category.education_consumption":["carbon_consumption"],"household.consumption.total_by_category.food_and_non_alcoholic_beverages_consumption":["carbon_consumption"],"household.consumption.total_by_category.health_consumption":["carbon_consumption"],"household.consumption.total_by_category.household_furnishings_consumption":["carbon_consumption"],"household.consumption.total_by_category.housing_water_and_electricity_consumption":["carbon_consumption"],"household.consumption.total_by_category.miscellaneous_consumption":["carbon_consumption"],"household.consumption.total_by_category.recreation_consumption":["carbon_consumption"],"household.consumption.total_by_category.restaurants_and_hotels_consumption":["carbon_consumption"],"household.consumption.total_by_category.transport_consumption":["carbon_consumption"],"household.demographic.benefit_unit.presumed_child.age_limit":["is_claimant_or_partner"],"household.demographic.benefit_unit.presumed_child.minimum_age_gap":["is_claimant_or_partner"],"household.demographic.equiv.ahc.child_over_14":["household_equivalisation_ahc"],"household.demographic.equiv.ahc.child_under_14":["household_equivalisation_ahc"],"household.demographic.equiv.ahc.first_adult":["household_equivalisation_ahc"],"household.demographic.equiv.ahc.second_adult":["household_equivalisation_ahc"],"household.demographic.equiv.bhc.child_over_14":["household_equivalisation_bhc"],"household.demographic.equiv.bhc.child_under_14":["household_equivalisation_bhc"],"household.demographic.equiv.bhc.first_adult":["household_equivalisation_bhc"],"household.demographic.equiv.bhc.second_adult":["household_equivalisation_bhc"],"household.demographic.equiv.child_age_threshold":["is_hbai_child_aged_14_or_over","is_hbai_child_under_14"],"household.demographic.hbai.dependent_child.age_limit":["is_hbai_dependent_child"],"household.demographic.hbai.dependent_child.young_person_age_limit":["is_hbai_dependent_child"],"household.poverty.absolute_poverty_threshold_ahc":["in_deep_poverty_ahc","poverty_line_ahc","poverty_threshold_ahc"],"household.poverty.absolute_poverty_threshold_bhc":["in_deep_poverty_bhc","poverty_line","poverty_line_bhc","poverty_threshold_bhc"],"household.poverty.exclude_non_hbai_income":["baseline_hbai_excluded_income"],"household.wealth.land.intensity.property_wealth_by_region.EAST_MIDLANDS":["household_land_value"],"household.wealth.land.intensity.property_wealth_by_region.EAST_OF_ENGLAND":["household_land_value"],"household.wealth.land.intensity.property_wealth_by_region.LONDON":["household_land_value"],"household.wealth.land.intensity.property_wealth_by_region.NORTHERN_IRELAND":["household_land_value"],"household.wealth.land.intensity.property_wealth_by_region.NORTH_EAST":["household_land_value"],"household.wealth.land.intensity.property_wealth_by_region.NORTH_WEST":["household_land_value"],"household.wealth.land.intensity.property_wealth_by_region.SCOTLAND":["household_land_value"],"household.wealth.land.intensity.property_wealth_by_region.SOUTH_EAST":["household_land_value"],"household.wealth.land.intensity.property_wealth_by_region.SOUTH_WEST":["household_land_value"],"household.wealth.land.intensity.property_wealth_by_region.UNKNOWN":["household_land_value"],"household.wealth.land.intensity.property_wealth_by_region.WALES":["household_land_value"],"household.wealth.land.intensity.property_wealth_by_region.WEST_MIDLANDS":["household_land_value"],"household.wealth.land.intensity.property_wealth_by_region.YORKSHIRE":["household_land_value"],"household.wealth.national_balance_sheet.household.financial_net_worth":["shareholding"]},"consumers":{"CB_HITC":["capped_mcad","child_benefit_less_tax_charge","income_tax"],"CTC_child_element":["CTC_maximum_rate"],"CTC_disabled_child_element":["CTC_maximum_rate"],"CTC_family_element":["CTC_maximum_rate"],"CTC_maximum_rate":["child_tax_credit_pre_minimum","tax_credits_reduction"],"CTC_severely_disabled_child_element":["CTC_maximum_rate"],"LHA_allowed_bedrooms":["LHA_category"],"LHA_cap":["housing_benefit_entitlement"],"LHA_category":["BRMA_LHA_rate","uc_LHA_cap","uncapped_BRMA_LHA_rate"],"LHA_eligible":["housing_benefit_eligible","housing_benefit_entitlement"],"LVT":["gov_tax","hbai_household_net_income","household_tax","pre_budget_change_household_tax"],"WTC_basic_element":["WTC_maximum_rate"],"WTC_childcare_element":["WTC_maximum_rate","childcare_grant_eligible"],"WTC_couple_element":["WTC_maximum_rate"],"WTC_disabled_element":["WTC_maximum_rate"],"WTC_lone_parent_element":["WTC_maximum_rate"],"WTC_maximum_rate":["child_tax_credit_pre_minimum","tax_credits_reduction","working_tax_credit_pre_minimum"],"WTC_severely_disabled_element":["WTC_maximum_rate"],"WTC_worker_element":["WTC_maximum_rate"],"aa_category":["attendance_allowance","is_severely_disabled_for_benefits"],"access_fund":["student_payments"],"add_rate_earned_income":["add_rate_earned_income_tax"],"add_rate_savings_income":["savings_income_tax","taxed_savings_income"],"additional_minimum_guarantee":["minimum_guarantee"],"additional_residential_property_purchased":["lbtt_on_residential_property_transactions","ltt_on_residential_property_transactions","sdlt_on_residential_property_transactions"],"additional_state_pension":["overlapping_state_pension","state_pension"],"adjusted_net_income":["CB_HITC","child_benefit","extended_childcare_entitlement_meets_income_requirements","extended_childcare_entitlement_work_condition","is_higher_earner","personal_allowance","tax_free_childcare_meets_income_requirements"],"adult_dependants_grant":["gov_spending","hbai_benefits","household_benefits"],"adult_dependants_grant_adult_eligible":["adult_dependants_grant_eligible"],"adult_dependants_grant_adult_receives_student_finance":["adult_dependants_grant_eligible"],"adult_dependants_grant_course_eligible":["adult_dependants_grant_eligible"],"adult_dependants_grant_eligible":["adult_dependants_grant"],"adult_dependants_grant_has_other_adult_dependant":["adult_dependants_grant_adult_eligible"],"adult_dependants_grant_household_income":["adult_dependants_grant_eligible"],"adult_dependants_grant_other_adult_income":["adult_dependants_grant_adult_eligible"],"adult_dependants_grant_receives_postgraduate_loan":["adult_dependants_grant_eligible"],"adult_ema":["student_payments"],"adult_index":["cliff_evaluated","maintenance_loan_has_sponsor","maintenance_loan_sponsor_income","marginal_tax_rate","marginal_tax_rate_wrt_employer_cost"],"adult_index_cg":["marginal_tax_rate_on_capital_gains"],"afcs":["gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","is_benefit_cap_exempt_health_disability","pre_budget_change_household_benefits"],"afcs_reported":["afcs"],"age":["LHA_allowed_bedrooms","adult_dependants_grant_adult_eligible","adult_index","age_18_64","age_over_64","age_under_18","bi_maximum","birth_year","bursary_fund_16_to_19_age_eligible","care_to_learn_eligible","child_benefit_child_index","child_index","child_minimum_guarantee_addition","childcare_grant_child_eligible","council_tax_reduction_individual_non_dep_deduction_eligible","council_tax_reduction_liable_person","current_education","date_of_birth","eldest_adult_age","eldest_child_age","eldest_claimant_or_partner_age","extended_childcare_entitlement_qualifying_child","extended_childcare_entitlement_total_per_child","has_attained_state_pension_credit_qualifying_age","has_mixed_age_couple_pension_credit_saving","has_non_dependant_for_severe_disability_premium","has_own_esa_award","household_bus_fare_age_weight","housing_benefit_LHA_allowed_bedrooms","housing_benefit_has_non_dependant","housing_benefit_individual_non_dep_deduction_eligible","housing_benefit_meals_deduction","housing_benefit_severe_disability_premium_applies","is_CTC_child_limit_exempt","is_WTC_eligible","is_adult","is_benefit_cap_exempt_health_disability","is_benunit_eldest_child","is_benunit_head","is_cared_for_by_carer_benefit_recipient","is_child","is_child_for_child_benefit","is_child_for_child_tax_credit","is_child_for_pension_credit","is_child_for_universal_credit","is_child_for_working_tax_credit_childcare_element","is_child_receiving_extended_childcare","is_child_receiving_targeted_childcare","is_child_receiving_universal_childcare","is_claimant_or_partner","is_counted_resident_for_severe_disability_addition","is_hbai_child_aged_14_or_over","is_hbai_child_under_14","is_hbai_dependent_child","is_higher_earner","is_household_head","is_lha_shared_accommodation_rate_specified_renter","is_of_compulsory_school_age","is_older_child","is_on_income_based_jsa","is_on_income_related_esa","is_on_income_support","is_on_pension_credit","is_resolved_household_head","is_responsible_for_child_or_young_person_for_uc_or_housing_benefit","is_scp_eligible_child","is_uc_assessed_claimant","is_young_child","lha_renter_has_non_dependant","lifetime_isa_countable_capital","maintenance_loan","maintenance_loan_eligible","maintenance_loan_has_sponsor","maintenance_loan_household_income","maintenance_loan_in_higher_education","maintenance_loan_sponsor_income","meets_housing_benefit_additional_earnings_disregard_conditions","meets_qualifying_young_person_age_condition_for_child_benefit","meets_qualifying_young_person_age_condition_for_child_tax_credit","meets_qualifying_young_person_age_condition_for_pension_credit","meets_qualifying_young_person_age_condition_for_universal_credit","meets_qualifying_young_person_entry_condition_for_child_benefit","meets_qualifying_young_person_entry_condition_for_child_tax_credit","meets_qualifying_young_person_entry_condition_for_pension_credit","meets_qualifying_young_person_entry_condition_for_universal_credit","meets_qualifying_young_person_terminal_date_condition_for_universal_credit","meets_savings_credit_age_requirement","meets_uc_minimum_age_condition","minimum_wage","minimum_wage_category","months_since_last_birthday","months_since_state_pension_age","num_relevant_children_for_housing_benefit_childcare","over_16","pawhp_eligible","pension_age_winter_heating_payment","pension_contributions_relief","person_bus_fare_spending","scottish_funded_early_learning_childcare_eligible","state_pension_age","state_pension_credit_qualifying_age","targeted_childcare_entitlement","tax_free_childcare_child_age_eligible","tv_licence_discount","uc_child_index","uc_individual_earned_income_before_mif","uc_individual_non_dep_deduction_eligible","uc_is_child_born_before_child_limit","uc_is_responsible_carer","uc_minimum_income_floor_gross","uc_standard_allowance_claimant_type","uc_youngest_child_age","universal_childcare_entitlement","universal_childcare_entitlement_eligible","winter_fuel_payment","winter_fuel_payment_eligible","youngest_adult_age","youngest_child_age","youngest_child_age_for_legacy_benefits","youngest_claimant_or_partner_age"],"age_started_or_accepted_current_education_or_training":["meets_qualifying_young_person_entry_condition_for_child_benefit","meets_qualifying_young_person_entry_condition_for_child_tax_credit","meets_qualifying_young_person_entry_condition_for_pension_credit","meets_qualifying_young_person_entry_condition_for_universal_credit"],"age_under_18":["adult_index","adult_index_cg","is_hbai_dependent_child"],"alcohol_and_tobacco_consumption":["carbon_consumption","consumption"],"alcohol_duty":["gov_tax","household_tax"],"allowances":["capital_gains_tax","non_savings_income_after_allowances","received_allowances_dividend_income","received_allowances_earned_income","received_allowances_savings_income","savings_allowance","tax_band"],"armed_forces_independence_payment":["cost_of_living_support_payment","council_tax_reduction_applicant_has_non_dep_exemption","housing_benefit_severe_disability_premium_applies","is_benefit_cap_exempt_health_disability","is_severely_disabled_for_benefits","is_severely_disabled_for_carers_allowance","maintenance_loan_entitled_to_benefits","receives_severe_disability_addition_qualifying_benefit","receives_severe_disability_premium_qualifying_benefit"],"attendance_allowance":["cost_of_living_support_payment","council_tax_reduction_applicant_has_non_dep_exemption","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","housing_benefit_severe_disability_premium_applies","is_benefit_cap_exempt_health_disability","is_lha_shared_accommodation_rate_specified_renter","is_severely_disabled_for_benefits","is_severely_disabled_for_carers_allowance","pre_budget_change_household_benefits","receives_severe_disability_addition_qualifying_benefit","receives_severe_disability_premium_qualifying_benefit","uc_non_dep_deduction_exempt"],"attends_private_school":["private_school_vat"],"baseline_hbai_excluded_income":["hbai_excluded_income_change"],"baseline_vat":["vat_change"],"basic_income":["council_tax_reduction_applicable_income","gov_spending","household_benefits","housing_benefit_applicable_income","pre_budget_change_household_benefits"],"basic_rate_earned_income":["basic_rate_earned_income_tax"],"basic_rate_savings_income":["savings_income_tax","taxed_savings_income"],"basic_rate_savings_income_pre_starter":["savings_starter_rate_income"],"basic_state_pension":["overlapping_state_pension","state_pension"],"beer_abv":["beer_duty"],"beer_draught_share":["beer_duty"],"beer_duty":["alcohol_duty"],"beer_litres":["beer_duty"],"benefit_cap":["benefit_cap_reduction"],"benefit_cap_reduction":["housing_benefit","uc_deductions","uc_has_deduction","universal_credit"],"benefits_premiums":["housing_benefit_applicable_amount"],"benunit_contains_household_head":["is_liable_for_household_rent","is_non_dependant_of_household_head","pays_rent_to_householder","personal_rent","share_of_household_rent","uc_non_dependants_counted"],"benunit_has_carer":["uc_carer_element"],"benunit_is_rent_liable":["housing_benefit_individual_non_dep_deduction_eligible","housing_benefit_shares_accommodation","is_non_dependant_of_household_head","uc_individual_non_dep_deduction_eligible","uc_non_dep_receives_pension_credit"],"benunit_is_renting":["LHA_eligible","maintenance_loan_household_income","maintenance_loan_living_arrangement"],"benunit_rent":["LHA_cap","benunit_is_rent_liable","housing_benefit_entitlement","uc_LHA_cap","uc_housing_costs_element"],"benunit_reported_capital":["pension_credit_reported_capital","uc_reported_capital"],"benunit_tenure_type":["benunit_is_renting","in_social_housing","uc_housing_costs_element"],"bi_household_phaseout":["bi_phaseout"],"bi_individual_phaseout":["bi_household_phaseout","bi_phaseout"],"bi_maximum":["basic_income","bi_household_phaseout","bi_individual_phaseout"],"bi_phaseout":["basic_income"],"blind_persons_allowance":["allowances","esa_exempt_work_earnings","property_finance_costs_relieved"],"brma":["BRMA_LHA_rate","housing_benefit_LHA_rate","uc_LHA_cap","uncapped_BRMA_LHA_rate"],"bsp":["gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","pre_budget_change_household_benefits"],"bsp_reported":["bsp"],"bursary_fund_16_to_19":["gov_spending","hbai_benefits","household_benefits"],"bursary_fund_16_to_19_age_eligible":["bursary_fund_16_to_19_vulnerable_group_eligible"],"bursary_fund_16_to_19_in_care_or_care_leaver":["bursary_fund_16_to_19_vulnerable_group_eligible"],"bursary_fund_16_to_19_in_qualifying_education":["bursary_fund_16_to_19_vulnerable_group_eligible"],"bursary_fund_16_to_19_receives_uc_or_esa_in_own_right":["bursary_fund_16_to_19_vulnerable_group_eligible"],"bursary_fund_16_to_19_receives_uc_or_is_in_own_right":["bursary_fund_16_to_19_vulnerable_group_eligible"],"bursary_fund_16_to_19_self_supporting":["bursary_fund_16_to_19_vulnerable_group_eligible"],"bursary_fund_16_to_19_vulnerable_group_eligible":["bursary_fund_16_to_19"],"bus_fare_spending_reported":["person_bus_fare_spending"],"bus_in_london_trips":["local_bus_trips"],"bus_subsidy_spending":["dft_subsidy_spending"],"business_rates":["corporate_tax_incidence","gov_tax","household_tax","pre_budget_change_household_tax"],"capital_allowances":["ni_class_4_profits_before_losses","taxable_self_employment_income","trading_allowance_deduction"],"capital_gains":["capital_gains_tax","household_market_income","marginal_tax_rate_on_capital_gains"],"capital_gains_badr":["capital_gains_tax"],"capital_gains_badr_behavioural_response":["capital_gains_tax","marginal_tax_rate_on_capital_gains"],"capital_gains_before_response":["adult_index_cg","capital_gains","capital_gains_tax","relative_capital_gains_mtr_change","relative_capital_gains_retention_rate_change","relative_income_change","relative_wage_change"],"capital_gains_behavioural_response":["capital_gains","capital_gains_tax","marginal_tax_rate_on_capital_gains"],"capital_gains_carried_interest":["capital_gains_tax"],"capital_gains_elasticity":["capital_gains_badr_elasticity"],"capital_gains_residential_property":["capital_gains_tax"],"capital_gains_tax":["gov_tax","household_tax","pre_budget_change_household_tax"],"capped_mcad":["income_tax","property_finance_cost_relief","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"car_co2_emissions":["car_vehicle_excise_duty"],"car_engine_size":["car_vehicle_excise_duty"],"car_first_registration_date":["car_vehicle_excise_duty"],"car_fuel_type":["car_vehicle_excise_duty"],"car_is_ved_exempt":["car_vehicle_excise_duty"],"car_list_price":["car_vehicle_excise_duty"],"car_vehicle_excise_duty":["vehicle_excise_duty"],"carbon_consumption":["carbon_tax"],"carbon_tax":["gov_tax","household_tax","pre_budget_change_household_tax"],"care_hours":["carer_support_payment_pre_overlap","carers_allowance_pre_overlap","is_carer_for_benefits","partners_care_for_same_severely_disabled_person"],"care_to_learn":["gov_spending","household_benefits"],"care_to_learn_eligible":["care_to_learn"],"care_to_learn_qualifying_child":["care_to_learn_eligible"],"carer_minimum_guarantee_addition":["additional_minimum_guarantee"],"carer_premium":["pension_age_benefits_premiums","working_age_benefits_premiums"],"carer_support_payment":["gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","housing_benefit_applicable_income","pension_credit_income","pre_budget_change_household_benefits","receives_carer_support_payment","scottish_carer_supplement","social_security_income","tax_free_childcare_regarded_as_in_paid_work","uc_unearned_carer_support_payment"],"carer_support_payment_overlapping_benefits":["carer_support_payment"],"carer_support_payment_pre_overlap":["carer_support_payment","council_tax_reduction_applicable_income","is_entitled_to_carer_benefit"],"carers_allowance":["council_tax_reduction_applicable_income","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","housing_benefit_applicable_income","pension_credit_income","pre_budget_change_household_benefits","receives_carers_allowance","social_security_income","tax_free_childcare_regarded_as_in_paid_work","uc_unearned_income"],"carers_allowance_earnings":["is_gainfully_employed_for_carers_allowance"],"carers_allowance_overlapping_benefits":["carers_allowance"],"carers_allowance_pre_overlap":["carers_allowance","is_entitled_to_carer_benefit"],"carers_allowance_reported":["carer_support_payment_pre_overlap","carers_allowance_pre_overlap","is_carer_for_benefits","partners_care_for_same_severely_disabled_person"],"charitable_investment_gifts":["allowances","property_finance_costs_relieved"],"child_benefit":["CB_HITC","benefit_cap_reduction","child_benefit_less_tax_charge","council_tax_reduction_applicable_income","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","housing_benefit_applicable_income","oxford_council_tax_reduction","pre_budget_change_household_benefits"],"child_benefit_child_index":["child_benefit_respective_amount"],"child_benefit_entitlement":["child_benefit"],"child_benefit_opts_out":["child_benefit"],"child_benefit_respective_amount":["child_benefit_entitlement"],"child_ema":["student_payments"],"child_index":["is_eldest_child"],"child_minimum_guarantee_addition":["additional_minimum_guarantee"],"child_tax_credit":["benefit_cap_reduction","ctc_child_limit_affected","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","is_scp_eligible","meets_child_tax_credit_criteria_for_targeted_childcare_entitlement","pre_budget_change_household_benefits","tax_free_childcare_program_eligible"],"child_tax_credit_pre_minimum":["ctc_entitlement"],"child_tax_credit_reported":["claims_all_entitled_benefits","claims_legacy_benefits","is_CTC_eligible","legacy_benefits_closed","pawhp_eligible","tax_credit_award","winter_fuel_payment_eligible","would_claim_CTC"],"childcare_expenses":["housing_benefit_applicable_income_childcare_element","tax_free_childcare","uc_childcare_element","weekly_childcare_expenses"],"childcare_grant":["gov_spending","hbai_benefits","household_benefits"],"childcare_grant_child_eligible":["childcare_grant_eligible_children"],"childcare_grant_child_has_special_educational_needs":["childcare_grant_child_eligible"],"childcare_grant_eligible":["childcare_grant"],"childcare_grant_eligible_children":["childcare_grant_eligible"],"childcare_grant_full_time_student":["childcare_grant_eligible"],"childcare_grant_household_income":["childcare_grant_eligible"],"childcare_grant_provider_is_nanny":["childcare_grant_uses_qualifying_provider"],"childcare_grant_receives_nhs_childcare_support":["childcare_grant_eligible"],"childcare_grant_receives_postgraduate_loan":["childcare_grant_eligible"],"childcare_grant_student_finance_eligible":["childcare_grant_eligible"],"childcare_grant_uses_qualifying_provider":["childcare_grant_eligible"],"cider_abv":["cider_duty"],"cider_draught_share":["cider_duty"],"cider_duty":["alcohol_duty"],"cider_litres":["cider_duty"],"cigarette_price_per_pack":["tobacco_duty"],"cigarettes_per_week":["tobacco_duty"],"cigars_grams_per_week":["tobacco_duty"],"claimant_or_partner_esa_income":["council_tax_reduction_applicable_income","council_tax_reduction_relevant_income_based_benefit","extended_childcare_entitlement_limited_capability_or_specified_benefit","housing_benefit_applicable_income","in_receipt_of_income_support_jsa_ib_or_esa_ir","is_on_income_related_esa","is_scp_eligible","targeted_childcare_entitlement_eligible","tax_credits_applicable_income"],"claimant_or_partner_jsa_income":["council_tax_reduction_applicable_income","council_tax_reduction_relevant_income_based_benefit","housing_benefit_applicable_income","in_receipt_of_income_support_jsa_ib_or_esa_ir","is_on_income_based_jsa","is_scp_eligible","targeted_childcare_entitlement_eligible","tax_credits_applicable_income"],"claims_all_entitled_benefits":["would_claim_CTC","would_claim_IS","would_claim_WTC","would_claim_council_tax_reduction","would_claim_housing_benefit"],"claims_legacy_benefits":["is_benefit_cap_exempt_health_disability","is_benefit_cap_single_claimant_rate","is_lha_shared_accommodation_rate_specified_renter"],"claims_uc_at_legacy_closure":["claims_universal_credit","council_tax_reduction_pensioner","is_uc_eligible","left_pension_route_at_legacy_closure"],"claims_universal_credit":["housing_benefit_eligible","is_CTC_eligible","is_benefit_cap_exempt_health_disability","is_benefit_cap_single_claimant_rate","is_lha_shared_accommodation_rate_specified_renter","uc_has_deduction","uc_non_dependants_counted","universal_credit","universal_credit_pre_benefit_cap"],"cliff_gap":["is_on_cliff"],"clothing_and_footwear_consumption":["carbon_consumption","consumption"],"communication_consumption":["carbon_consumption","consumption"],"consumer_debt":["net_wealth"],"consumer_incident_tax_revenue_change":["gov_tax","household_tax"],"consumption":["consumer_incident_tax_revenue_change","consumption_shareholding","full_rate_vat_consumption","reduced_rate_vat_consumption"],"corporate_incident_tax_revenue_change":["gov_tax","household_tax"],"corporate_land_value":["LVT","land_value"],"corporate_sdlt":["corporate_tax_incidence","expected_sdlt","gov_tax","household_tax","pre_budget_change_household_tax"],"corporate_sector_wealth":["corporate_land_value","shareholding"],"corporate_tax_incidence":["hbai_excluded_income"],"corporate_wealth":["corporate_sector_wealth","esa_income_assessable_capital","household_uc_pool_company_holdings","housing_benefit_assessable_capital","income_support_assessable_capital","jsa_income_assessable_capital","pension_credit_assessable_capital","total_wealth","uc_assessable_capital"],"cost_of_living_support_payment":["gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","pre_budget_change_household_benefits"],"council_tax":["council_tax_less_benefit","council_tax_reduction_maximum_eligible_liability","gov_tax","hbai_household_net_income","household_tax","pre_budget_change_household_tax"],"council_tax_band":["ebr_council_tax_rebate"],"council_tax_benefit":["council_tax_reduction","gov_spending","hbai_household_net_income","household_benefits","pre_budget_change_household_benefits"],"council_tax_benefit_reported":["council_tax_benefit","would_claim_council_tax_reduction"],"council_tax_reduction":["council_tax_less_benefit"],"council_tax_reduction_applicable_amount":["kingston_upon_thames_council_tax_reduction","merton_council_tax_reduction","newham_council_tax_reduction","simulated_council_tax_reduction_benunit","westminster_council_tax_reduction"],"council_tax_reduction_applicable_income":["kingston_upon_thames_council_tax_reduction","merton_council_tax_reduction","newham_council_tax_reduction","oxford_council_tax_reduction","simulated_council_tax_reduction_benunit","westminster_council_tax_reduction"],"council_tax_reduction_applicant_has_non_dep_exemption":["kingston_upon_thames_council_tax_reduction_non_dep_deductions","merton_council_tax_reduction_non_dep_deductions","newham_council_tax_reduction_non_dep_deductions","oxford_council_tax_reduction_non_dep_deductions","westminster_council_tax_reduction_non_dep_deductions"],"council_tax_reduction_assessable_capital":["simulated_council_tax_reduction_benunit"],"council_tax_reduction_claimant_benunit":["council_tax_benefit","council_tax_reduction_household_has_simulated_claim","council_tax_reduction_individual_non_dep_deduction_eligible","kingston_upon_thames_council_tax_reduction","merton_council_tax_reduction","newham_council_tax_reduction","oxford_council_tax_reduction","simulated_council_tax_reduction_benunit","westminster_council_tax_reduction"],"council_tax_reduction_claims_are_joint":["council_tax_reduction_claimant_benunit"],"council_tax_reduction_head_applies_alone":["council_tax_reduction_pensioner","is_council_tax_reduction_applicant_or_partner"],"council_tax_reduction_household_has_simulated_claim":["council_tax_benefit"],"council_tax_reduction_individual_non_dep_deduction":["council_tax_reduction_non_dep_deductions"],"council_tax_reduction_individual_non_dep_deduction_eligible":["council_tax_reduction_individual_non_dep_deduction","kingston_upon_thames_council_tax_reduction_individual_non_dep_deduction","merton_council_tax_reduction_individual_non_dep_deduction","newham_council_tax_reduction_individual_non_dep_deduction","oxford_council_tax_reduction_individual_non_dep_deduction","westminster_council_tax_reduction_individual_non_dep_deduction"],"council_tax_reduction_joint_liability_share":["council_tax_benefit","council_tax_reduction_non_dep_deductions","kingston_upon_thames_council_tax_reduction","kingston_upon_thames_council_tax_reduction_non_dep_deductions","merton_council_tax_reduction","merton_council_tax_reduction_non_dep_deductions","newham_council_tax_reduction","newham_council_tax_reduction_non_dep_deductions","oxford_council_tax_reduction","oxford_council_tax_reduction_non_dep_deductions","simulated_council_tax_reduction_benunit","westminster_council_tax_reduction","westminster_council_tax_reduction_non_dep_deductions"],"council_tax_reduction_liable_person":["council_tax_benefit","council_tax_reduction_claimant_benunit","council_tax_reduction_head_applies_alone","council_tax_reduction_joint_liability_share","is_council_tax_reduction_applicant_or_partner"],"council_tax_reduction_maximum_eligible_liability":["council_tax_benefit","kingston_upon_thames_council_tax_reduction","merton_council_tax_reduction","newham_council_tax_reduction","oxford_council_tax_reduction","simulated_council_tax_reduction_benunit","westminster_council_tax_reduction"],"council_tax_reduction_non_dep_deductions":["simulated_council_tax_reduction_benunit"],"council_tax_reduction_pensioner":["council_tax_reduction_applicable_amount","council_tax_reduction_pensioner_earnings_disregard","council_tax_reduction_scheme_supported","is_child_or_young_person_for_council_tax_reduction","kingston_upon_thames_council_tax_reduction","merton_council_tax_reduction","newham_council_tax_reduction","oxford_council_tax_reduction","simulated_council_tax_reduction_benunit","westminster_council_tax_reduction"],"council_tax_reduction_pensioner_earnings_disregard":["council_tax_reduction_applicable_income"],"council_tax_reduction_relevant_income_based_benefit":["council_tax_reduction_pensioner","housing_benefit_pension_age_regulations_apply","kingston_upon_thames_council_tax_reduction","merton_council_tax_reduction","newham_council_tax_reduction","oxford_council_tax_reduction","westminster_council_tax_reduction"],"council_tax_reduction_scheme_supported":["council_tax_benefit","council_tax_reduction_household_has_simulated_claim"],"country":["adult_dependants_grant_eligible","bursary_fund_16_to_19_vulnerable_group_eligible","care_to_learn_eligible","carer_support_payment_pre_overlap","carers_allowance_pre_overlap","childcare_grant_eligible","council_tax_reduction_pensioner","council_tax_reduction_pensioner_earnings_disregard","council_tax_reduction_scheme_supported","extended_childcare_entitlement_qualifying_child","housing_benefit_on_passporting_benefit","is_child_or_young_person_for_council_tax_reduction","is_scp_eligible","kingston_upon_thames_council_tax_reduction","lbtt_liable","ltt_liable","maintenance_loan_in_england_system","merton_council_tax_reduction","monthly_ebr_energy_bills_credit","newham_council_tax_reduction","oxford_council_tax_reduction","parents_learning_allowance_eligible","partners_care_for_same_severely_disabled_person","pawhp_eligible","pays_scottish_income_tax","receives_severe_disability_premium_qualifying_benefit","scottish_funded_early_learning_childcare_eligible","sdlt_liable","simulated_council_tax_reduction_benunit","targeted_childcare_entitlement_eligible","travel_grant_eligible","two_child_limit_payment","universal_childcare_entitlement_eligible","westminster_council_tax_reduction","winter_fuel_payment_eligible"],"covenanted_payments":["allowances"],"ctc_entitlement":["child_tax_credit"],"cumulative_non_residential_rent":["lbtt_on_non_residential_property_rent","ltt_on_non_residential_property_rent","sdlt_on_non_residential_property_rent"],"cumulative_residential_rent":["lbtt_on_residential_property_rent","ltt_on_residential_property_rent","sdlt_on_residential_property_rent"],"current_education":["bursary_fund_16_to_19_in_qualifying_education","care_to_learn_eligible","council_tax_benefit","is_in_non_advanced_education","maintenance_loan_in_higher_education"],"date_of_birth":["birth_year","child_minimum_guarantee_addition","has_attained_state_pension_credit_qualifying_age","has_mixed_age_couple_pension_credit_saving","is_CTC_child_limit_exempt","meets_savings_credit_age_requirement","months_since_state_pension_age","state_pension_age","state_pension_credit_qualifying_age","uc_child_index","uc_is_child_born_before_child_limit"],"deductible_property_finance_costs":["property_allowance_deduction_if_used","taxable_property_income","uses_property_allowance"],"deep_poverty_gap":["in_deep_poverty"],"deep_poverty_line":["deep_poverty_gap"],"deficiency_relief":["taxable_dividend_income"],"dfe_education_spending":["gov_spending","household_benefits"],"dft_subsidy_spending":["gov_spending","household_benefits"],"diesel_litres":["fuel_duty"],"diesel_price":["diesel_litres"],"diesel_spending":["diesel_litres"],"disability_basic_income":["gov_spending","household_benefits","pre_budget_change_household_benefits"],"disability_premium":["maintenance_loan_entitled_to_benefits","working_age_benefits_premiums"],"disabled_students_allowance":["gov_spending","hbai_benefits","household_benefits"],"disabled_students_allowance_course_eligible":["disabled_students_allowance_eligible"],"disabled_students_allowance_eligible":["disabled_students_allowance"],"disabled_students_allowance_eligible_expenses":["disabled_students_allowance_eligible"],"disabled_students_allowance_has_qualifying_condition":["disabled_students_allowance_eligible"],"disabled_students_allowance_receives_equivalent_support":["disabled_students_allowance_eligible"],"dividend_income":["capital_income","hbai_household_net_income","household_market_income","housing_benefit_net_earnings","market_income","tax_credits_current_year_income","taxable_dividend_income","total_income"],"dividend_income_tax":["income_tax","income_tax_pre_charges"],"dla":["bursary_fund_16_to_19_vulnerable_group_eligible","child_minimum_guarantee_addition","cost_of_living_support_payment","disability_basic_income","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","is_benefit_cap_exempt_health_disability","pre_budget_change_household_benefits"],"dla_m":["dla","maintenance_loan_entitled_to_benefits"],"dla_m_category":["dla_m"],"dla_sc":["council_tax_reduction_applicant_has_non_dep_exemption","dla","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","maintenance_loan_entitled_to_benefits"],"dla_sc_category":["dla_sc","dla_sc_middle_plus","receives_highest_dla_sc"],"dla_sc_middle_plus":["housing_benefit_severe_disability_premium_applies","is_lha_shared_accommodation_rate_specified_renter","is_severely_disabled_for_carers_allowance","receives_severe_disability_addition_qualifying_benefit","receives_severe_disability_premium_qualifying_benefit","uc_non_dep_deduction_exempt"],"domestic_energy_consumption":["monthly_domestic_energy_consumption"],"domestic_rates":["gov_tax","hbai_household_net_income","household_tax","pre_budget_change_household_tax"],"earned_income_tax":["income_tax","income_tax_pre_charges"],"earned_taxable_income":["add_rate_earned_income","basic_rate_earned_income","earned_income_tax","higher_rate_earned_income","non_savings_taxable_income","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"ebr_council_tax_rebate":["energy_bills_rebate"],"ebr_energy_bills_credit":["energy_bills_rebate"],"ebr_energy_bills_credit_eligible":["monthly_ebr_energy_bills_credit"],"education_consumption":["carbon_consumption","consumption"],"education_grants":["student_payments"],"eldest_child_age":["is_benunit_eldest_child"],"eldest_claimant_or_partner_age":["council_tax_reduction_applicable_amount","housing_benefit_applicable_amount","housing_benefit_specified_or_temporary_accommodation_disregard","income_support_applicable_amount","is_WTC_eligible","is_housing_benefit_young_individual"],"employee_pension_contributions":["carers_allowance_earnings","esa_exempt_work_earnings","hbai_household_net_income","pension_contributions","pension_contributions_for_annual_allowance"],"employee_pension_contributions_reported":["employee_pension_contributions"],"employer_cost":["marginal_tax_rate_wrt_employer_cost"],"employer_ni_fixed_employer_cost_change":["employment_income"],"employer_ni_response_capital_incidence":["household_tax"],"employer_ni_response_consumer_incidence":["household_tax"],"employer_pension_contributions":["adjusted_employer_cost","baseline_employer_cost","employer_cost","employer_ni_fixed_employer_cost_change","pension_contributions_for_annual_allowance"],"employment_benefits":["housing_benefit_net_earnings","housing_benefit_specified_or_temporary_accommodation_disregard","taxable_employment_income"],"employment_deductions":["esa_exempt_work_earnings","taxable_employment_income"],"employment_expenses":["employment_deductions"],"employment_income":["adjusted_employer_cost","carers_allowance_earnings","council_tax_reduction_applicable_income","earned_income","employer_cost","esa_exempt_work_earnings","extended_childcare_entitlement_meets_income_requirements","hbai_household_net_income","household_market_income","housing_benefit_applicable_income","housing_benefit_net_earnings","housing_benefit_specified_or_temporary_accommodation_disregard","in_work","income_support_applicable_income","marginal_tax_rate","marginal_tax_rate_wrt_employer_cost","market_income","ni_class_1_income","pension_contributions_relief","pension_credit_earnings","salary_sacrifice_pension_ni_employee","tax_credits_current_year_income","tax_free_childcare_expected_declaration_period_income","taxable_employment_income","total_income","uc_individual_earned_income_before_mif"],"employment_income_before_lsr":["baseline_employer_cost","employer_ni_fixed_employer_cost_change","employment_income","income_elasticity_lsr","pension_contributions_via_salary_sacrifice_from_pay","substitution_elasticity_lsr"],"employment_income_behavioral_response":["baseline_employer_cost","employer_ni_fixed_employer_cost_change","employment_income"],"energy_bills_rebate":["gov_spending","household_benefits","pre_budget_change_household_benefits"],"enhanced_disability_premium":["working_age_benefits_premiums"],"epg_subsidy":["gov_spending","household_benefits","pre_budget_change_household_benefits"],"equiv_hbai_household_net_income":["household_income_decile","in_deep_poverty_bhc","in_poverty_bhc","in_relative_poverty_bhc"],"equiv_hbai_household_net_income_ahc":["in_deep_poverty_ahc","in_poverty_ahc","in_relative_poverty_ahc"],"esa_contrib":["benefit_cap_reduction","carer_support_payment_overlapping_benefits","carers_allowance_overlapping_benefits","council_tax_reduction_applicable_income","esa","extended_childcare_entitlement_limited_capability_or_specified_benefit","gov_spending","has_own_esa_award","hbai_benefits","hbai_household_net_income","household_benefits","housing_benefit_applicable_income","income_support_eligible","is_benefit_cap_exempt_health_disability","pension_credit_income","pre_budget_change_household_benefits","savings_credit_income","tax_free_childcare_caring_or_incapacity_benefit","tax_free_childcare_regarded_as_in_paid_work","uc_unearned_income"],"esa_contrib_reported":["bursary_fund_16_to_19_receives_uc_or_esa_in_own_right","esa_contrib","social_security_income"],"esa_exempt_work_earnings":["esa_income_claimant_remunerative_work"],"esa_includes_support_component":["is_benefit_cap_exempt_health_disability","uc_limited_capability_for_WRA"],"esa_income":["benefit_cap_reduction","claimant_or_partner_esa_income","cost_of_living_support_payment","esa","gov_spending","has_own_esa_award","hbai_benefits","hbai_household_net_income","household_benefits","income_support_eligible","is_benefit_cap_exempt_health_disability","is_on_income_related_esa","pre_budget_change_household_benefits"],"esa_income_assessable_capital":["esa_income_eligible","esa_income_tariff_income","is_on_income_related_esa"],"esa_income_claimant_remunerative_work":["esa_income_eligible","is_on_income_related_esa"],"esa_income_eligible":["benefit_cap_reduction","claimant_or_partner_esa_income","esa_income","income_support_eligible","is_benefit_cap_exempt_health_disability","is_on_income_related_esa"],"esa_income_remunerative_work_hours":["esa_income_claimant_remunerative_work","esa_income_eligible"],"esa_income_reported":["benefit_cap_reduction","bursary_fund_16_to_19_receives_uc_or_esa_in_own_right","claimant_or_partner_esa_income","claims_all_entitled_benefits","claims_legacy_benefits","esa_income","esa_income_assessable_capital","esa_income_eligible","has_mixed_age_couple_pension_credit_saving","has_own_esa_award","income_support_eligible","is_benefit_cap_exempt_health_disability","is_on_income_related_esa","pawhp_eligible","winter_fuel_payment_eligible"],"esa_income_tariff_income":["benefit_cap_reduction","claimant_or_partner_esa_income","esa_income","income_support_eligible","is_benefit_cap_exempt_health_disability","is_on_income_related_esa"],"expected_lbtt":["gov_tax","household_tax","pre_budget_change_household_tax"],"expected_ltt":["gov_tax","household_tax","pre_budget_change_household_tax"],"expected_sdlt":["gov_tax","household_tax","pre_budget_change_household_tax"],"extended_childcare_entitlement":["gov_spending","household_benefits","is_child_receiving_extended_childcare"],"extended_childcare_entitlement_eligible":["extended_childcare_entitlement","extended_childcare_entitlement_per_child","extended_childcare_entitlement_total_per_child"],"extended_childcare_entitlement_limited_capability_or_specified_benefit":["extended_childcare_entitlement_work_condition"],"extended_childcare_entitlement_meets_income_requirements":["extended_childcare_entitlement_work_condition"],"extended_childcare_entitlement_per_child":["extended_childcare_entitlement","is_child_receiving_extended_childcare"],"extended_childcare_entitlement_qualifying_child":["extended_childcare_entitlement_eligible","extended_childcare_entitlement_total_per_child","is_child_receiving_extended_childcare"],"extended_childcare_entitlement_total_per_child":["extended_childcare_entitlement_per_child","targeted_childcare_entitlement","universal_childcare_entitlement"],"extended_childcare_entitlement_work_condition":["extended_childcare_entitlement_eligible"],"external_child_payments":["hbai_household_net_income"],"food_and_non_alcoholic_beverages_consumption":["carbon_consumption","consumption"],"free_school_fruit_veg":["hbai_household_net_income"],"free_school_meals":["hbai_household_net_income"],"free_school_milk":["hbai_household_net_income"],"free_tv_licence_value":["hbai_household_net_income"],"fuel_duty":["gov_tax","household_tax","pre_budget_change_household_tax"],"full_rate_vat_consumption":["baseline_vat","vat"],"full_rate_vat_expenditure_rate":["full_rate_vat_consumption"],"gender":["is_female","is_male"],"gift_aid":["gift_aid_grossed_up"],"gift_aid_grossed_up":["add_rate_earned_income","add_rate_savings_income","adjusted_net_income","basic_rate_earned_income","basic_rate_savings_income","basic_rate_savings_income_pre_starter","capital_gains_tax","dividend_income_tax","earned_income_tax","higher_rate_earned_income","higher_rate_savings_income","property_income_tax","savings_allowance","tax_band","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"gov_spending":["gov_balance"],"gov_tax":["gov_balance"],"guarantee_credit":["in_receipt_of_guarantee_credit","in_receipt_of_savings_credit_only","pension_credit_entitlement","targeted_childcare_entitlement_eligible"],"hand_rolling_tobacco_grams_per_week":["tobacco_duty"],"has_attained_state_pension_credit_qualifying_age":["council_tax_reduction_pensioner","has_mixed_age_couple_pension_credit_saving","housing_benefit_pension_age_regulations_apply","income_support_eligible","is_mixed_age_couple","is_on_pension_credit","is_uc_eligible","meets_pension_credit_age_conditions","pension_age_severe_disability_premium","pension_credit_assessable_capital","uc_member_of_couple_claims_as_single_person","uc_work_related_group_apart_from_earnings","winter_fuel_payment_eligible"],"has_mixed_age_couple_pension_credit_saving":["meets_pension_credit_age_conditions"],"has_non_dependant_for_severe_disability_premium":["severe_disability_premium"],"has_own_esa_award":["esa_includes_support_component","uc_limited_capability_for_WRA"],"hbai_excluded_income":["baseline_hbai_excluded_income","hbai_excluded_income_change"],"hbai_household_net_income":["deep_poverty_gap","equiv_hbai_household_net_income","hbai_household_net_income_ahc","poverty_gap","poverty_gap_bhc","real_hbai_household_net_income"],"hbai_household_net_income_ahc":["equiv_hbai_household_net_income_ahc","poverty_gap_ahc","real_hbai_household_net_income_ahc"],"health_consumption":["carbon_consumption","consumption"],"healthy_start_vouchers":["gov_spending","hbai_benefits","hbai_household_net_income","household_benefits"],"heated_tobacco_grams_per_week":["tobacco_duty"],"high_value_council_tax_surcharge":["gov_tax","household_tax"],"higher_rate_earned_income":["higher_rate_earned_income_tax"],"higher_rate_savings_income":["savings_income_tax","taxed_savings_income"],"hours_worked":["in_work","uc_is_responsible_carer","weekly_hours"],"household_benefits":["household_gross_income","household_net_income","household_net_income_ahc"],"household_benefits_individual_non_dep_deduction":["housing_benefit_non_dep_deductions"],"household_bus_fare_age_weight":["person_bus_fare_spending"],"household_count_people":["household_income_decile","household_wealth_decile","in_relative_poverty_ahc","in_relative_poverty_bhc"],"household_equivalisation_ahc":["equiv_hbai_household_net_income_ahc","poverty_line_ahc"],"household_equivalisation_bhc":["equiv_hbai_household_net_income","equiv_household_net_income","poverty_line","poverty_line_bhc","pre_budget_change_ons_household_income_decile"],"household_furnishings_consumption":["carbon_consumption","consumption"],"household_income_decile":["income_decile"],"household_land_value":["LVT","land_value"],"household_market_income":["household_gross_income","household_net_income","household_net_income_ahc","pre_budget_change_household_net_income"],"household_net_income":["equiv_household_net_income","marginal_tax_rate","marginal_tax_rate_on_capital_gains","marginal_tax_rate_wrt_employer_cost","real_household_net_income","relative_income_change"],"household_net_income_ahc":["real_household_net_income_ahc"],"household_owns_tv":["free_tv_licence_value","tv_licence"],"household_tax":["household_net_income","household_net_income_ahc"],"household_uc_pool_company_holdings":["uc_assessable_capital"],"household_uc_reported_capital":["uc_assessable_capital"],"household_uc_unreported_claimants":["uc_assessable_capital"],"household_weight":["carbon_tax","corporate_land_value","household_income_decile","household_wealth_decile","in_relative_poverty_ahc","in_relative_poverty_bhc","person_weight","pre_budget_change_ons_household_income_decile"],"housing_benefit":["cost_of_living_support_payment","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","pre_budget_change_household_benefits"],"housing_benefit_LHA_allowed_bedrooms":["housing_benefit_LHA_category"],"housing_benefit_LHA_category":["housing_benefit_LHA_rate"],"housing_benefit_LHA_rate":["LHA_cap"],"housing_benefit_applicable_amount":["housing_benefit_entitlement"],"housing_benefit_applicable_income":["housing_benefit_entitlement"],"housing_benefit_applicable_income_childcare_element":["housing_benefit_applicable_income","housing_benefit_applicable_income_disregard","housing_benefit_savings_credit_only_income"],"housing_benefit_applicable_income_disregard":["housing_benefit_applicable_income","housing_benefit_savings_credit_only_income"],"housing_benefit_assessable_capital":["housing_benefit_eligible","housing_benefit_tariff_income"],"housing_benefit_board_and_attendance_determination":["LHA_cap"],"housing_benefit_eligible":["housing_benefit_applicable_amount","housing_benefit_pre_benefit_cap"],"housing_benefit_entitlement":["housing_benefit_pre_benefit_cap"],"housing_benefit_has_non_dependant":["housing_benefit_LHA_category"],"housing_benefit_individual_non_dep_deduction_eligible":["household_benefits_individual_non_dep_deduction"],"housing_benefit_meals_deduction":["LHA_cap","housing_benefit_entitlement"],"housing_benefit_net_earnings":["council_tax_reduction_pensioner_earnings_disregard","housing_benefit_applicable_income_disregard"],"housing_benefit_non_dep_deductions":["housing_benefit_entitlement"],"housing_benefit_on_passporting_benefit":["housing_benefit_applicable_income","housing_benefit_applicable_income_disregard","housing_benefit_assessable_capital"],"housing_benefit_pension_age_regulations_apply":["benefits_premiums","housing_benefit_applicable_amount","housing_benefit_applicable_income","housing_benefit_assessable_capital","housing_benefit_eligible","housing_benefit_specified_or_temporary_accommodation_disregard","housing_benefit_tariff_income","is_benefit_cap_exempt_other"],"housing_benefit_pre_benefit_cap":["benefit_cap_reduction","housing_benefit"],"housing_benefit_reported":["claims_all_entitled_benefits","claims_legacy_benefits","has_mixed_age_couple_pension_credit_saving","housing_benefit_eligible","would_claim_housing_benefit"],"housing_benefit_savings_credit_only_income":["housing_benefit_applicable_income"],"housing_benefit_severe_disability_premium_applies":["housing_benefit_LHA_category"],"housing_benefit_shares_accommodation":["housing_benefit_LHA_category"],"housing_benefit_specified_or_temporary_accommodation_disregard":["housing_benefit_applicable_income_disregard"],"housing_benefit_tariff_income":["housing_benefit_applicable_income"],"housing_costs":["household_net_income_ahc"],"housing_water_and_electricity_consumption":["carbon_consumption","consumption"],"iidb":["gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","is_benefit_cap_exempt_health_disability","pre_budget_change_household_benefits","uc_unearned_income"],"iidb_reported":["iidb"],"in_FE":["council_tax_benefit"],"in_HE":["council_tax_benefit","council_tax_reduction_claimant_benunit","council_tax_reduction_joint_liability_share","maintenance_loan_has_sponsor","maintenance_loan_in_higher_education","maintenance_loan_sponsor_income"],"in_receipt_of_guarantee_credit":["council_tax_reduction_applicable_income","council_tax_reduction_assessable_capital","housing_benefit_applicable_income","housing_benefit_assessable_capital","housing_benefit_tariff_income"],"in_receipt_of_income_support_jsa_ib_or_esa_ir":["housing_benefit_on_passporting_benefit"],"in_receipt_of_savings_credit_only":["council_tax_reduction_applicable_income","council_tax_reduction_assessable_capital","housing_benefit_applicable_income","housing_benefit_assessable_capital","housing_benefit_tariff_income"],"in_rural_fuel_duty_relief_area":["fuel_duty"],"in_social_housing":["LHA_eligible","housing_benefit_eligible"],"in_specified_or_temporary_accommodation":["housing_benefit_specified_or_temporary_accommodation_disregard"],"in_work":["extended_childcare_entitlement_work_condition","tax_free_childcare_treated_as_in_work","uc_childcare_work_condition"],"incapacity_benefit":["benefit_cap_reduction","carer_support_payment_overlapping_benefits","carers_allowance_overlapping_benefits","extended_childcare_entitlement_limited_capability_or_specified_benefit","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","pre_budget_change_household_benefits","social_security_income","tax_free_childcare_caring_or_incapacity_benefit","tax_free_childcare_regarded_as_in_paid_work"],"incapacity_benefit_reported":["incapacity_benefit"],"income_support":["benefit_cap_reduction","cost_of_living_support_payment","council_tax_reduction_applicable_income","council_tax_reduction_relevant_income_based_benefit","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","housing_benefit_applicable_income","in_receipt_of_income_support_jsa_ib_or_esa_ir","is_on_income_support","is_scp_eligible","pre_budget_change_household_benefits","targeted_childcare_entitlement_eligible","tax_credits_applicable_income"],"income_support_applicable_amount":["income_support_entitlement"],"income_support_applicable_income":["income_support_entitlement"],"income_support_assessable_capital":["income_support_eligible","income_support_tariff_income"],"income_support_eligible":["income_support_entitlement"],"income_support_remunerative_work_hours":["income_support_eligible"],"income_support_reported":["bursary_fund_16_to_19_receives_uc_or_is_in_own_right","claims_all_entitled_benefits","claims_legacy_benefits","has_mixed_age_couple_pension_credit_saving","income_support_eligible","is_on_income_support","legacy_benefits_closed","pawhp_eligible","winter_fuel_payment_eligible","would_claim_IS"],"income_support_tariff_income":["income_support_applicable_income"],"income_tax":["council_tax_reduction_applicable_income","gov_tax","hbai_household_net_income","household_tax","housing_benefit_applicable_income","housing_benefit_net_earnings","income_support_applicable_income","pension_credit_income","post_tax_income","pre_budget_change_household_tax","tax"],"income_tax_pre_charges":["capped_mcad","property_finance_cost_relief"],"individual_savings_account_interest_income":["tax_free_savings_income"],"inflation_adjustment":["real_hbai_household_net_income","real_hbai_household_net_income_ahc","real_household_net_income","real_household_net_income_ahc"],"is_CTC_child_limit_exempt":["CTC_child_element","ctc_child_limit_affected"],"is_CTC_eligible":["CTC_disabled_child_element","CTC_family_element","CTC_severely_disabled_child_element","ctc_entitlement"],"is_SP_age":["additional_state_pension","bi_maximum","is_WA_adult","is_hbai_pensioner","is_hbai_working_age_adult","ni_liable","pawhp_eligible","state_pension_type","winter_fuel_payment_eligible"],"is_WTC_eligible":["WTC_basic_element","WTC_childcare_element","WTC_couple_element","WTC_disabled_element","WTC_lone_parent_element","WTC_severely_disabled_element","WTC_worker_element","wtc_entitlement"],"is_adult":["benunit_count_adults","eldest_adult_age","family_type","is_WA_adult","num_adults","num_disabled_adults","num_enhanced_disabled_adults","num_severely_disabled_adults","youngest_adult_age"],"is_apprentice":["bursary_fund_16_to_19_in_qualifying_education","care_to_learn_eligible","is_in_non_advanced_education","minimum_wage","minimum_wage_category"],"is_before_universal_credit_qualifying_young_person_terminal_date":["meets_qualifying_young_person_terminal_date_condition_for_universal_credit"],"is_benefit_cap_exempt":["benefit_cap"],"is_benefit_cap_exempt_earnings":["is_benefit_cap_exempt"],"is_benefit_cap_exempt_health_disability":["is_benefit_cap_exempt"],"is_benefit_cap_exempt_other":["is_benefit_cap_exempt"],"is_benefit_cap_single_claimant_rate":["benefit_cap"],"is_benunit_head":["council_tax_benefit","council_tax_reduction","has_own_esa_award","household_num_benunits","household_uc_reported_capital","is_benefit_cap_exempt_health_disability","is_claimant_or_partner","is_hbai_dependent_child","is_on_income_based_jsa","is_on_income_related_esa","is_on_income_support","is_on_pension_credit","kingston_upon_thames_council_tax_reduction_non_dep_deductions","merton_council_tax_reduction_non_dep_deductions","newham_council_tax_reduction_non_dep_deductions","oxford_council_tax_reduction_non_dep_deductions","pawhp_eligible","personal_rent","westminster_council_tax_reduction_non_dep_deductions","winter_fuel_payment_eligible"],"is_blind":["council_tax_reduction_applicant_has_non_dep_exemption","disabled_students_allowance_has_qualifying_condition","has_non_dependant_for_severe_disability_premium","housing_benefit_severe_disability_premium_applies","is_child_for_working_tax_credit_childcare_element","is_counted_resident_for_severe_disability_addition","num_relevant_children_for_housing_benefit_childcare","severe_disability_minimum_guarantee_addition","severe_disability_premium","tax_free_childcare","tax_free_childcare_child_age_eligible","tv_licence_discount"],"is_cared_for_by_carer_benefit_recipient":["severe_disability_minimum_guarantee_addition","severe_disability_premium"],"is_carer_for_benefits":["esa_income_eligible","income_support_eligible","is_benefit_cap_exempt_health_disability","meets_uc_minimum_age_condition","num_carers","receives_uc_carer_element","uc_unable_to_provide_childcare","uc_work_related_group_apart_from_earnings"],"is_child":["benunit_count_children","child_index","eldest_child_age","family_type","is_benunit_eldest_child","num_children","num_disabled_children","num_enhanced_disabled_children","num_severely_disabled_children","youngest_child_age"],"is_child_for_child_benefit":["income_support_eligible","is_child_or_qualifying_young_person_for_child_benefit","youngest_child_age_for_legacy_benefits"],"is_child_for_child_tax_credit":["is_child_or_qualifying_young_person_for_child_tax_credit"],"is_child_for_pension_credit":["is_child_or_qualifying_young_person_for_pension_credit"],"is_child_for_universal_credit":["is_child_or_qualifying_young_person_for_universal_credit","meets_uc_minimum_age_condition","uc_youngest_child_age"],"is_child_or_qualifying_young_person_for_child_benefit":["care_to_learn_qualifying_child","child_benefit_child_index","child_benefit_respective_amount","has_non_dependant_for_severe_disability_premium","is_child_or_young_person_for_legacy_benefits"],"is_child_or_qualifying_young_person_for_child_tax_credit":["CTC_child_element","CTC_disabled_child_element","ctc_child_limit_affected","is_CTC_eligible","is_responsible_for_child_or_qualifying_young_person_for_child_tax_credit","tax_credits_current_year_income"],"is_child_or_qualifying_young_person_for_pension_credit":["child_minimum_guarantee_addition"],"is_child_or_qualifying_young_person_for_universal_credit":["is_benefit_cap_exempt_health_disability","is_child_or_young_person_for_council_tax_reduction","is_responsible_for_child_or_qualifying_young_person_for_universal_credit","lha_renter_has_non_dependant","uc_child_index","uc_individual_disabled_child_element","uc_individual_severely_disabled_child_element","uc_is_child_born_before_child_limit","uc_is_child_limit_affected"],"is_child_or_young_person_for_council_tax_reduction":["council_tax_reduction_applicable_income","is_responsible_for_child_or_young_person_for_council_tax_reduction"],"is_child_or_young_person_for_legacy_benefits":["council_tax_reduction_applicable_income","housing_benefit_applicable_income","housing_benefit_has_non_dependant","housing_benefit_severe_disability_premium_applies","income_support_applicable_income","is_benefit_cap_exempt_health_disability","is_child_or_young_person_for_council_tax_reduction","is_responsible_for_child_or_young_person_for_legacy_benefits","lha_renter_has_non_dependant","meets_housing_benefit_additional_earnings_disregard_conditions","num_relevant_children_for_housing_benefit_childcare","youngest_child_age_for_legacy_benefits"],"is_claimant_or_partner":["WTC_severely_disabled_element","benefit_cap_reduction","carer_minimum_guarantee_addition","carer_premium","claimant_or_partner_esa_income","claimant_or_partner_jsa_income","council_tax_reduction_applicable_income","council_tax_reduction_head_applies_alone","council_tax_reduction_liable_person","eldest_claimant_or_partner_age","esa_income_assessable_capital","esa_income_eligible","extended_childcare_entitlement_eligible","extended_childcare_entitlement_work_condition","has_mixed_age_couple_pension_credit_saving","has_non_dependant_for_severe_disability_premium","has_own_esa_award","housing_benefit_LHA_allowed_bedrooms","housing_benefit_applicable_income","housing_benefit_assessable_capital","housing_benefit_has_non_dependant","housing_benefit_net_earnings","housing_benefit_pension_age_regulations_apply","housing_benefit_severe_disability_premium_applies","housing_benefit_specified_or_temporary_accommodation_disregard","income_support_applicable_income","income_support_assessable_capital","income_support_eligible","is_WTC_eligible","is_benefit_cap_exempt_health_disability","is_benefit_cap_single_claimant_rate","is_cared_for_by_carer_benefit_recipient","is_child_for_working_tax_credit_childcare_element","is_child_or_qualifying_young_person_for_child_benefit","is_child_or_qualifying_young_person_for_child_tax_credit","is_child_or_qualifying_young_person_for_pension_credit","is_child_or_young_person_for_council_tax_reduction","is_child_or_young_person_for_legacy_benefits","is_council_tax_reduction_applicant_or_partner","is_dependent_child_for_student_support","is_lha_shared_accommodation_rate_specified_renter","is_liable_for_household_rent","is_mixed_age_couple","is_on_income_based_jsa","is_on_income_related_esa","is_on_income_support","is_on_pawhp_relevant_benefit","is_on_pension_credit","is_on_universal_credit","is_on_winter_fuel_payment_relevant_benefit","is_responsible_for_child_or_qualifying_young_person_for_child_tax_credit","is_responsible_for_child_or_young_person_for_uc_or_housing_benefit","is_savings_credit_eligible","is_uc_claimant","jsa_income_assessable_capital","jsa_income_eligible","lha_renter_has_non_dependant","maintenance_loan_entitled_to_benefits","marital_status","marriage_allowance","meets_housing_benefit_additional_earnings_disregard_conditions","meets_pension_credit_age_conditions","meets_severe_disability_addition_residence_condition","num_disabled_claimants_or_partners_for_legacy_benefits","num_enhanced_disabled_claimants_or_partners_for_legacy_benefits","partners_care_for_same_severely_disabled_person","partners_unused_personal_allowance","pawhp_eligible","pension_age_severe_disability_premium","pension_age_winter_heating_payment","pension_credit_assessable_capital","pension_credit_earnings","pension_credit_income","relation_type","savings_credit_income","severe_disability_minimum_guarantee_addition","severe_disability_premium","tax_credit_award","tax_credits_current_year_income","tax_free_childcare_regarded_as_in_paid_work","tax_free_childcare_work_condition","winter_fuel_payment","winter_fuel_payment_eligible","would_claim_IS","youngest_claimant_or_partner_age"],"is_council_tax_reduction_applicant_or_partner":["council_tax_reduction_applicable_income","council_tax_reduction_applicant_has_non_dep_exemption","council_tax_reduction_pensioner"],"is_council_tax_reduction_lone_parent":["council_tax_reduction_applicable_amount"],"is_counted_resident_for_severe_disability_addition":["meets_severe_disability_addition_residence_condition"],"is_couple":["adult_dependants_grant_adult_eligible","council_tax_reduction_applicable_amount","council_tax_reduction_pensioner_earnings_disregard","disability_premium","enhanced_disability_premium","housing_benefit_applicable_amount","housing_benefit_applicable_income_disregard","housing_benefit_specified_or_temporary_accommodation_disregard","income_support_applicable_income","is_WTC_eligible","is_benefit_cap_single_claimant_rate","is_lha_shared_accommodation_rate_specified_renter","is_married","maintenance_loan_household_income","maintenance_loan_living_arrangement","meets_housing_benefit_additional_earnings_disregard_conditions","severe_disability_minimum_guarantee_addition","severe_disability_premium"],"is_dependent_child_for_student_support":["childcare_grant_child_eligible","parents_learning_allowance_dependent_children"],"is_disabled_for_benefits":["CTC_disabled_child_element","disabled_students_allowance_has_qualifying_condition","is_WTC_eligible","is_child_for_working_tax_credit_childcare_element","meets_housing_benefit_additional_earnings_disregard_conditions","num_disabled_adults","num_disabled_children","num_disabled_claimants_or_partners_for_legacy_benefits","num_relevant_children_for_housing_benefit_childcare","tax_free_childcare","tax_free_childcare_child_age_eligible","uc_individual_disabled_child_element","uc_limited_capability_for_WRA","uc_limited_capability_for_work"],"is_engaged_in_owned_company_trade":["uc_company_capital"],"is_enhanced_disabled_for_benefits":["num_enhanced_disabled_adults","num_enhanced_disabled_children","num_enhanced_disabled_claimants_or_partners_for_legacy_benefits"],"is_entitled_to_carer_benefit":["carer_minimum_guarantee_addition","carer_premium","extended_childcare_entitlement_limited_capability_or_specified_benefit","is_benefit_cap_exempt_health_disability","is_carer_for_benefits","partners_care_for_same_severely_disabled_person","tax_free_childcare_caring_or_incapacity_benefit"],"is_gainfully_employed_for_carers_allowance":["carers_allowance_pre_overlap"],"is_guarantee_credit_eligible":["guarantee_credit","is_pension_credit_eligible"],"is_hbai_adult":["household_equivalisation_ahc","household_equivalisation_bhc","is_claimant_or_partner","is_hbai_pensioner","is_hbai_working_age_adult"],"is_hbai_child_aged_14_or_over":["household_equivalisation_ahc","household_equivalisation_bhc"],"is_hbai_child_under_14":["household_equivalisation_ahc","household_equivalisation_bhc"],"is_hbai_dependent_child":["hbai_person_type","is_hbai_adult","is_hbai_child_aged_14_or_over","is_hbai_child_under_14"],"is_hbai_working_age_adult":["hbai_person_type"],"is_higher_earner":["CB_HITC"],"is_household_head":["is_resolved_household_head"],"is_housing_benefit_young_individual":["housing_benefit_LHA_category"],"is_in_approved_training":["is_hbai_dependent_child","meets_qualifying_young_person_education_or_training_condition_for_child_benefit","meets_qualifying_young_person_education_or_training_condition_for_child_tax_credit","meets_qualifying_young_person_education_or_training_condition_for_pension_credit","meets_qualifying_young_person_education_or_training_condition_for_universal_credit"],"is_in_non_advanced_education":["is_hbai_dependent_child","meets_qualifying_young_person_education_or_training_condition_for_child_benefit","meets_qualifying_young_person_education_or_training_condition_for_child_tax_credit","meets_qualifying_young_person_education_or_training_condition_for_pension_credit","meets_qualifying_young_person_education_or_training_condition_for_universal_credit"],"is_lha_shared_accommodation_rate_specified_renter":["LHA_category"],"is_liable_for_household_rent":["housing_benefit_LHA_allowed_bedrooms","housing_benefit_has_non_dependant","housing_benefit_severe_disability_premium_applies","share_of_household_rent","uc_non_dependants_counted"],"is_lone_parent":["council_tax_reduction_pensioner_earnings_disregard","housing_benefit_applicable_amount","housing_benefit_applicable_income_disregard","housing_benefit_specified_or_temporary_accommodation_disregard","income_support_applicable_income","income_support_eligible","meets_housing_benefit_additional_earnings_disregard_conditions"],"is_looked_after_by_local_authority":["extended_childcare_entitlement_qualifying_child","income_support_eligible","is_benefit_cap_exempt_health_disability","is_child_for_working_tax_credit_childcare_element","is_child_or_qualifying_young_person_for_child_tax_credit","is_child_or_qualifying_young_person_for_pension_credit","is_child_or_qualifying_young_person_for_universal_credit","is_child_or_young_person_for_legacy_benefits","tax_free_childcare_qualifying_child","uc_youngest_child_age"],"is_male":["LHA_allowed_bedrooms","housing_benefit_LHA_allowed_bedrooms","state_pension_age"],"is_married":["marital_status"],"is_mixed_age_couple":["has_mixed_age_couple_pension_credit_saving","legacy_benefits_closed","meets_pension_credit_age_conditions"],"is_non_dependant_of_household_head":["LHA_allowed_bedrooms","housing_benefit_has_non_dependant","housing_benefit_non_dep_deductions","housing_benefit_severe_disability_premium_applies","lha_renter_has_non_dependant","uc_non_dep_deductions"],"is_of_compulsory_school_age":["universal_childcare_entitlement_eligible"],"is_on_income_based_jsa":["is_on_pawhp_relevant_benefit","is_on_winter_fuel_payment_relevant_benefit","pawhp_eligible","winter_fuel_payment_eligible"],"is_on_income_related_esa":["is_on_pawhp_relevant_benefit","is_on_winter_fuel_payment_relevant_benefit","maintenance_loan_entitled_to_benefits","pawhp_eligible","winter_fuel_payment_eligible"],"is_on_income_support":["is_on_pawhp_relevant_benefit","is_on_winter_fuel_payment_relevant_benefit","pawhp_eligible","winter_fuel_payment_eligible"],"is_on_pawhp_relevant_benefit":["pawhp_eligible","pension_age_winter_heating_payment"],"is_on_pension_credit":["is_on_pawhp_relevant_benefit","is_on_winter_fuel_payment_relevant_benefit","pawhp_eligible","winter_fuel_payment_eligible"],"is_on_universal_credit":["is_on_pawhp_relevant_benefit","is_on_winter_fuel_payment_relevant_benefit","pawhp_eligible","winter_fuel_payment_eligible"],"is_on_winter_fuel_payment_relevant_benefit":["winter_fuel_payment","winter_fuel_payment_eligible"],"is_parent":["care_to_learn_eligible","care_to_learn_qualifying_child","childcare_grant_eligible","is_claimant_or_partner","is_hbai_dependent_child","maintenance_loan_entitled_to_benefits","maintenance_loan_household_income","maintenance_loan_living_arrangement","parents_learning_allowance_eligible","tax_free_childcare_eligible","tax_free_childcare_qualifying_child"],"is_pension_credit_eligible":["guarantee_credit","in_receipt_of_guarantee_credit","in_receipt_of_savings_credit_only","pension_credit_entitlement"],"is_qualifying_young_person_for_child_benefit":["is_benefit_cap_exempt_health_disability","is_child_or_qualifying_young_person_for_child_benefit"],"is_qualifying_young_person_for_child_tax_credit":["is_child_or_qualifying_young_person_for_child_tax_credit"],"is_qualifying_young_person_for_pension_credit":["is_child_or_qualifying_young_person_for_pension_credit","is_counted_resident_for_severe_disability_addition"],"is_qualifying_young_person_for_universal_credit":["is_benefit_cap_exempt_health_disability","is_child_or_qualifying_young_person_for_universal_credit"],"is_resolved_household_head":["benunit_contains_household_head","council_tax_reduction_head_applies_alone","council_tax_reduction_liable_person","is_council_tax_reduction_applicant_or_partner","maintenance_loan_household_income","maintenance_loan_living_arrangement","personal_rent"],"is_responsible_for_child_or_qualifying_young_person_for_child_tax_credit":["is_WTC_eligible"],"is_responsible_for_child_or_qualifying_young_person_for_universal_credit":["is_responsible_for_child_or_young_person_for_uc_or_housing_benefit","is_uc_work_allowance_eligible"],"is_responsible_for_child_or_young_person_for_council_tax_reduction":["is_council_tax_reduction_lone_parent"],"is_responsible_for_child_or_young_person_for_legacy_benefits":["income_support_applicable_amount","is_lone_parent","is_responsible_for_child_or_young_person_for_uc_or_housing_benefit","is_single_person"],"is_responsible_for_child_or_young_person_for_uc_or_housing_benefit":["is_benefit_cap_single_claimant_rate","is_lha_shared_accommodation_rate_specified_renter"],"is_savings_credit_eligible":["is_pension_credit_eligible","savings_credit"],"is_scp_eligible":["scottish_child_payment"],"is_scp_eligible_child":["is_scp_eligible"],"is_severely_disabled_for_benefits":["WTC_severely_disabled_element","num_severely_disabled_adults","num_severely_disabled_children","uc_individual_severely_disabled_child_element"],"is_severely_disabled_for_carers_allowance":["is_cared_for_by_carer_benefit_recipient"],"is_shared_accommodation":["housing_benefit_shares_accommodation"],"is_single":["disability_premium","enhanced_disability_premium","income_support_applicable_amount","income_support_eligible","is_WTC_eligible","is_council_tax_reduction_lone_parent","is_lone_parent","is_single_person"],"is_single_person":["housing_benefit_applicable_amount","income_support_applicable_income","is_housing_benefit_young_individual"],"is_uc_assessed_claimant":["benefit_cap_reduction","is_benefit_cap_exempt_earnings","is_benefit_cap_exempt_health_disability","is_benefit_cap_single_claimant_rate","is_uc_single_or_joint_claimant","uc_childcare_work_condition","uc_earned_income","uc_individual_earned_income","uc_is_ineligible_partner","uc_is_responsible_carer","uc_member_of_couple_claims_as_single_person","uc_minimum_income_floor_gross","uc_unearned_income","uc_work_related_group_apart_from_earnings","uc_youngest_child_age"],"is_uc_claimant":["household_uc_pool_company_holdings","household_uc_unreported_claimants","is_responsible_for_child_or_qualifying_young_person_for_universal_credit","is_uc_assessed_claimant","meets_uc_minimum_age_condition","uc_assessable_capital","uc_child_index","uc_individual_disabled_child_element","uc_individual_severely_disabled_child_element","uc_is_child_limit_affected"],"is_uc_eligible":["uc_income_reduction","uc_maximum_amount","uc_non_dependants_counted","uc_tariff_income"],"is_uc_entitled":["council_tax_reduction_pensioner","housing_benefit_on_passporting_benefit","housing_benefit_pension_age_regulations_apply","left_pension_route_at_legacy_closure"],"is_uc_single_or_joint_claimant":["is_uc_eligible","uc_childcare_work_condition","uc_member_of_couple_claims_as_single_person","uc_standard_allowance_claimant_type"],"is_uc_work_allowance_eligible":["uc_work_allowance"],"jsa_contrib":["benefit_cap_reduction","carer_support_payment_overlapping_benefits","carers_allowance_overlapping_benefits","council_tax_reduction_applicable_income","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","housing_benefit_applicable_income","income_support_eligible","jsa","pension_credit_income","pre_budget_change_household_benefits","savings_credit_income","uc_unearned_income"],"jsa_contrib_reported":["jsa_contrib","social_security_income"],"jsa_income":["benefit_cap_reduction","claimant_or_partner_jsa_income","cost_of_living_support_payment","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","income_support_eligible","is_on_income_based_jsa","jsa","pre_budget_change_household_benefits"],"jsa_income_assessable_capital":["is_on_income_based_jsa","jsa_income_eligible","jsa_income_tariff_income"],"jsa_income_eligible":["is_on_income_based_jsa"],"jsa_income_reported":["benefit_cap_reduction","claimant_or_partner_jsa_income","claims_all_entitled_benefits","claims_legacy_benefits","has_mixed_age_couple_pension_credit_saving","income_support_eligible","is_on_income_based_jsa","jsa_income_assessable_capital","jsa_income_eligible","legacy_benefits_closed","pawhp_eligible","winter_fuel_payment_eligible"],"jsa_income_tariff_income":["is_on_income_based_jsa"],"jsa_remunerative_work_hours":["is_on_income_based_jsa","jsa_income_eligible"],"kingston_upon_thames_council_tax_reduction":["simulated_council_tax_reduction_benunit"],"kingston_upon_thames_council_tax_reduction_individual_non_dep_deduction":["kingston_upon_thames_council_tax_reduction_non_dep_deductions"],"kingston_upon_thames_council_tax_reduction_non_dep_deductions":["kingston_upon_thames_council_tax_reduction"],"land_and_buildings_transaction_tax":["expected_lbtt"],"land_transaction_tax":["expected_ltt"],"land_value":["LVT"],"lbtt_liable":["land_and_buildings_transaction_tax"],"lbtt_on_non_residential_property_rent":["lbtt_on_rent"],"lbtt_on_non_residential_property_transactions":["lbtt_on_transactions"],"lbtt_on_rent":["land_and_buildings_transaction_tax"],"lbtt_on_residential_property_rent":["lbtt_on_rent"],"lbtt_on_residential_property_transactions":["lbtt_on_transactions"],"lbtt_on_transactions":["land_and_buildings_transaction_tax"],"left_pension_route_at_legacy_closure":["housing_benefit_eligible","is_pension_credit_eligible"],"legacy_benefits_closed":["claims_uc_at_legacy_closure","esa_income_eligible","housing_benefit_eligible","is_CTC_eligible","is_WTC_eligible","is_on_income_based_jsa","is_on_income_related_esa","jsa_income_eligible","left_pension_route_at_legacy_closure"],"lha_renter_has_non_dependant":["is_lha_shared_accommodation_rate_specified_renter"],"liable_for_share_of_household_rent":["council_tax_reduction_claims_are_joint","council_tax_reduction_individual_non_dep_deduction_eligible","council_tax_reduction_liable_person","housing_benefit_shares_accommodation","is_liable_for_household_rent"],"lifetime_isa_balance":["has_lifetime_isa","household_lifetime_isa_balance","lifetime_isa_countable_capital"],"lifetime_isa_countable_capital":["esa_income_assessable_capital","housing_benefit_assessable_capital","income_support_assessable_capital","jsa_income_assessable_capital","pension_credit_assessable_capital","uc_assessable_capital"],"local_authority":["council_tax_reduction_scheme_supported","kingston_upon_thames_council_tax_reduction","merton_council_tax_reduction","newham_council_tax_reduction","oxford_council_tax_reduction","westminster_council_tax_reduction"],"loss_relief":["taxable_self_employment_income"],"lpg_kg":["fuel_duty"],"ltt_liable":["land_transaction_tax","ltt_on_non_residential_property_transactions"],"ltt_on_non_residential_property_rent":["ltt_on_rent"],"ltt_on_non_residential_property_transactions":["ltt_on_transactions"],"ltt_on_rent":["land_transaction_tax"],"ltt_on_residential_property_rent":["ltt_on_rent"],"ltt_on_residential_property_transactions":["ltt_on_transactions"],"ltt_on_transactions":["land_transaction_tax"],"main_residence_value":["main_residential_property_purchased","non_primary_residence_wealth_tax","residential_property_value"],"main_residential_property_purchased":["lbtt_on_residential_property_transactions","ltt_on_residential_property_transactions","sdlt_on_residential_property_transactions"],"main_residential_property_purchased_is_first_home":["lbtt_on_residential_property_transactions","sdlt_on_residential_property_transactions"],"maintenance_expenses":["hbai_household_net_income","market_income"],"maintenance_income":["hbai_household_net_income","household_market_income","market_income"],"maintenance_loan_candidate_benunit_income":["maintenance_loan_sponsor_income"],"maintenance_loan_eligible":["childcare_grant_student_finance_eligible","maintenance_loan","travel_grant_income_assessed_support"],"maintenance_loan_entitled_to_benefits":["maintenance_loan"],"maintenance_loan_has_sponsor":["maintenance_loan_household_income","maintenance_loan_living_arrangement"],"maintenance_loan_household_income":["adult_dependants_grant_household_income","childcare_grant_household_income","maintenance_loan","parents_learning_allowance_household_income","travel_grant_household_income"],"maintenance_loan_in_england_system":["disabled_students_allowance_eligible","maintenance_loan_eligible"],"maintenance_loan_in_higher_education":["adult_dependants_grant_adult_receives_student_finance","adult_dependants_grant_course_eligible","disabled_students_allowance_course_eligible","maintenance_loan_eligible","maintenance_loan_has_sponsor","maintenance_loan_household_income","maintenance_loan_living_arrangement","maintenance_loan_sponsor_income","parents_learning_allowance_course_eligible"],"maintenance_loan_living_arrangement":["maintenance_loan"],"maintenance_loan_sponsor_income":["maintenance_loan_household_income"],"marginal_tax_rate":["cliff_gap","relative_wage_change"],"marginal_tax_rate_on_capital_gains":["relative_capital_gains_mtr_change","relative_capital_gains_retention_rate_change"],"marital_status":["marriage_allowance"],"marriage_allowance":["earned_taxable_income"],"married_couples_allowance":["married_couples_allowance_deduction"],"married_couples_allowance_deduction":["capped_mcad","esa_exempt_work_earnings"],"maternity_allowance":["carer_support_payment_overlapping_benefits","carers_allowance_overlapping_benefits","council_tax_reduction_applicable_income","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","housing_benefit_applicable_income","pre_budget_change_household_benefits","tax_free_childcare_treated_as_in_work","uc_childcare_treated_as_in_paid_work","uc_unearned_income"],"maternity_allowance_reported":["maternity_allowance"],"max_free_entitlement_hours_used":["extended_childcare_entitlement_total_per_child","targeted_childcare_entitlement","universal_childcare_entitlement"],"maximum_extended_childcare_hours_usage":["extended_childcare_entitlement_total_per_child"],"meals_included_in_rent":["housing_benefit_meals_deduction"],"meets_housing_benefit_additional_earnings_disregard_conditions":["council_tax_reduction_pensioner_earnings_disregard","housing_benefit_applicable_income_disregard"],"meets_marriage_allowance_income_conditions":["marriage_allowance"],"meets_pension_credit_age_conditions":["housing_benefit_eligible","income_support_eligible","is_pension_credit_eligible","is_uc_eligible","left_pension_route_at_legacy_closure","legacy_benefits_closed"],"meets_qualifying_young_person_age_condition_for_child_benefit":["is_qualifying_young_person_for_child_benefit"],"meets_qualifying_young_person_age_condition_for_child_tax_credit":["is_qualifying_young_person_for_child_tax_credit"],"meets_qualifying_young_person_age_condition_for_pension_credit":["is_qualifying_young_person_for_pension_credit"],"meets_qualifying_young_person_age_condition_for_universal_credit":["is_qualifying_young_person_for_universal_credit"],"meets_qualifying_young_person_education_or_training_condition_for_child_benefit":["is_qualifying_young_person_for_child_benefit"],"meets_qualifying_young_person_education_or_training_condition_for_child_tax_credit":["is_qualifying_young_person_for_child_tax_credit"],"meets_qualifying_young_person_education_or_training_condition_for_pension_credit":["is_qualifying_young_person_for_pension_credit"],"meets_qualifying_young_person_education_or_training_condition_for_universal_credit":["is_qualifying_young_person_for_universal_credit"],"meets_qualifying_young_person_entry_condition_for_child_benefit":["is_qualifying_young_person_for_child_benefit"],"meets_qualifying_young_person_entry_condition_for_child_tax_credit":["is_qualifying_young_person_for_child_tax_credit"],"meets_qualifying_young_person_entry_condition_for_pension_credit":["is_qualifying_young_person_for_pension_credit"],"meets_qualifying_young_person_entry_condition_for_universal_credit":["is_qualifying_young_person_for_universal_credit"],"meets_qualifying_young_person_terminal_date_condition_for_universal_credit":["is_qualifying_young_person_for_universal_credit"],"meets_savings_credit_age_requirement":["is_savings_credit_eligible"],"meets_severe_disability_addition_residence_condition":["severe_disability_minimum_guarantee_addition"],"meets_uc_minimum_age_condition":["is_uc_eligible","uc_is_ineligible_partner","uc_member_of_couple_claims_as_single_person"],"meets_universal_credit_criteria_for_targeted_childcare_entitlement":["targeted_childcare_entitlement_eligible"],"merton_council_tax_reduction":["simulated_council_tax_reduction_benunit"],"merton_council_tax_reduction_individual_non_dep_deduction":["merton_council_tax_reduction_non_dep_deductions"],"merton_council_tax_reduction_non_dep_deductions":["merton_council_tax_reduction"],"minimum_guarantee":["guarantee_credit","is_guarantee_credit_eligible","savings_credit"],"minimum_wage":["extended_childcare_entitlement_meets_income_requirements","tax_free_childcare_meets_income_requirements"],"miscellaneous_consumption":["carbon_consumption","consumption"],"miscellaneous_income":["hbai_household_net_income","household_market_income","market_income","tax_credits_current_year_income","taxable_miscellaneous_income"],"monthly_domestic_energy_consumption":["monthly_epg_consumption_level","monthly_epg_subsidy"],"monthly_ebr_energy_bills_credit":["ebr_energy_bills_credit"],"monthly_epg_consumption_level":["monthly_epg_subsidy"],"monthly_epg_subsidy":["epg_subsidy"],"months_since_last_birthday":["birth_year","child_minimum_guarantee_addition","date_of_birth","has_attained_state_pension_credit_qualifying_age","has_mixed_age_couple_pension_credit_saving","is_CTC_child_limit_exempt","meets_savings_credit_age_requirement","months_since_state_pension_age","state_pension_age","state_pension_credit_qualifying_age","uc_child_index","uc_is_child_born_before_child_limit"],"months_since_state_pension_age":["is_SP_age","meets_savings_credit_age_requirement","ni_class_4_liable","state_pension_type"],"mortgage":["housing_costs"],"mortgage_capital_repayment":["mortgage"],"mortgage_debt":["net_wealth"],"mortgage_interest_repayment":["hbai_household_net_income_ahc","mortgage"],"national_insurance":["council_tax_reduction_applicable_income","gov_tax","hbai_household_net_income","household_tax","housing_benefit_applicable_income","income_support_applicable_income","pension_credit_income","post_tax_income","pre_budget_change_household_tax","tax","total_national_insurance"],"natural_gas_kg":["fuel_duty"],"net_income":["adjusted_net_income","capital_gains_tax","earned_taxable_income","maintenance_loan_candidate_benunit_income","maintenance_loan_household_income","non_savings_income_after_allowances","pension_annual_allowance","plan_2_interest_rate","property_finance_costs_relieved","received_allowances_earned_income","savings_allowance","student_loan_repayment","tax_band","uc_income_tax_on_earnings","uc_income_tax_on_trade","unused_personal_allowance"],"new_state_pension":["overlapping_state_pension","state_pension"],"newham_council_tax_reduction":["simulated_council_tax_reduction_benunit"],"newham_council_tax_reduction_individual_non_dep_deduction":["newham_council_tax_reduction_non_dep_deductions"],"newham_council_tax_reduction_non_dep_deductions":["newham_council_tax_reduction"],"nhs_a_and_e_spending":["nhs_spending"],"nhs_admitted_patient_spending":["nhs_spending"],"nhs_outpatient_spending":["nhs_spending"],"nhs_spending":["gov_spending","household_benefits"],"ni_class_1_employee":["carers_allowance_earnings","housing_benefit_net_earnings","national_insurance","ni_class_4","ni_employee","uc_national_insurance_on_earnings"],"ni_class_1_employee_additional":["ni_class_1_employee"],"ni_class_1_employee_primary":["ni_class_1_employee","ni_class_4_maximum"],"ni_class_1_employer":["ni_employer","total_national_insurance"],"ni_class_1_income":["ni_class_1_employee_additional","ni_class_1_employee_primary","ni_class_1_employer"],"ni_class_1_secondary_liable":["ni_class_1_employer"],"ni_class_2":["housing_benefit_net_earnings","national_insurance","ni_class_4","ni_class_4_maximum","ni_self_employed","uc_national_insurance_on_earnings","uc_national_insurance_on_trade"],"ni_class_3":["national_insurance"],"ni_class_4":["housing_benefit_net_earnings","national_insurance","ni_self_employed","uc_national_insurance_on_earnings","uc_national_insurance_on_trade"],"ni_class_4_liable":["esa_exempt_work_earnings","ni_class_4","ni_class_4_main","uc_minimum_income_floor_national_insurance"],"ni_class_4_loss_relief":["ni_class_4_losses_carried_forward","ni_class_4_profits"],"ni_class_4_losses_brought_forward":["ni_class_4_loss_relief","ni_class_4_losses_carried_forward"],"ni_class_4_maximum":["ni_class_4"],"ni_class_4_profits":["ni_class_2","ni_class_4","ni_class_4_main","ni_class_4_maximum"],"ni_class_4_profits_before_losses":["ni_class_4_loss_relief","ni_class_4_profits"],"ni_class_4_trading_loss":["ni_class_4_loss_relief","ni_class_4_losses_carried_forward"],"ni_employer":["employer_cost","gov_tax"],"ni_liable":["esa_exempt_work_earnings","ni_class_1_employee","ni_class_2","uc_minimum_income_floor_national_insurance"],"non_primary_residence_wealth_tax":["gov_tax","household_tax","pre_budget_change_household_tax"],"non_residential_property_purchased":["lbtt_on_non_residential_property_transactions","ltt_on_non_residential_property_transactions","sdlt_on_non_residential_property_transactions"],"non_residential_property_value":["esa_income_assessable_capital","housing_benefit_assessable_capital","income_support_assessable_capital","jsa_income_assessable_capital","pension_credit_assessable_capital","property_wealth","uc_assessable_capital"],"non_residential_rent":["lbtt_on_non_residential_property_rent","ltt_on_non_residential_property_rent","sdlt_on_non_residential_property_rent"],"non_savings_income_after_allowances":["property_income_tax","taxable_property_income_after_allowances"],"non_savings_taxable_income":["add_rate_savings_income","basic_rate_savings_income","basic_rate_savings_income_pre_starter","dividend_income_tax","higher_rate_savings_income","savings_starter_rate_income","taxed_income"],"num_carers":["benunit_has_carer"],"num_disabled_claimants_or_partners_for_legacy_benefits":["disability_premium"],"num_enhanced_disabled_claimants_or_partners_for_legacy_benefits":["enhanced_disability_premium"],"num_relevant_children_for_housing_benefit_childcare":["housing_benefit_applicable_income_childcare_element"],"num_vehicles":["owns_vehicle"],"other_deductions":["allowances","property_finance_costs_relieved"],"other_fermented_abv":["other_fermented_duty"],"other_fermented_draught_share":["other_fermented_duty"],"other_fermented_duty":["alcohol_duty"],"other_fermented_litres":["other_fermented_duty"],"other_investment_income":["taxable_savings_interest_income"],"other_local_bus_trips":["local_bus_trips"],"other_public_spending_budget_change":["gov_spending"],"other_residential_property_value":["additional_residential_property_purchased","esa_income_assessable_capital","housing_benefit_assessable_capital","income_support_assessable_capital","jsa_income_assessable_capital","pension_credit_assessable_capital","residential_property_value","uc_assessable_capital"],"other_tax_credits":["income_tax","property_finance_cost_relief","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"other_tobacco_grams_per_week":["tobacco_duty"],"over_16":["ni_class_1_secondary_liable","ni_class_4_liable","ni_liable","tax_free_childcare_work_condition"],"overlapping_state_pension":["carer_support_payment_overlapping_benefits","carers_allowance_overlapping_benefits"],"owned_company_capital":["uc_company_capital"],"owned_company_carries_on_property_business":["uc_company_owner_treatment_applies"],"owned_company_carries_on_trade":["uc_company_capital","uc_company_gainful_self_employment","uc_company_owner_treatment_applies","uc_company_self_employed_earnings"],"owned_company_holding_value":["uc_company_holding_disregard"],"owned_company_income_share":["uc_company_self_employed_earnings"],"owned_company_intermediary_earnings_chapter":["uc_company_intermediary_exclusion_applies"],"owned_company_intermediary_earnings_from_main_employment":["uc_company_intermediary_exclusion_applies"],"owned_company_is_main_employment":["uc_company_capital","uc_company_gainful_self_employment"],"owned_company_trade_assets":["uc_company_capital"],"owned_land":["esa_income_assessable_capital","household_land_value","housing_benefit_assessable_capital","income_support_assessable_capital","jsa_income_assessable_capital","pension_credit_assessable_capital"],"oxford_council_tax_reduction":["simulated_council_tax_reduction_benunit"],"oxford_council_tax_reduction_individual_non_dep_deduction":["oxford_council_tax_reduction_non_dep_deductions"],"oxford_council_tax_reduction_non_dep_deductions":["oxford_council_tax_reduction"],"parents_learning_allowance":["gov_spending","hbai_benefits","household_benefits"],"parents_learning_allowance_course_eligible":["parents_learning_allowance_eligible"],"parents_learning_allowance_dependent_children":["parents_learning_allowance_eligible"],"parents_learning_allowance_eligible":["parents_learning_allowance"],"parents_learning_allowance_household_income":["parents_learning_allowance_eligible"],"partners_care_for_same_severely_disabled_person":["carer_premium"],"partners_unused_personal_allowance":["marriage_allowance"],"pawhp":["gov_spending","hbai_benefits","hbai_household_net_income","household_benefits"],"pawhp_eligible":["pension_age_winter_heating_payment"],"pays_rent_to_householder":["benunit_tenure_type","council_tax_reduction_individual_non_dep_deduction_eligible","housing_benefit_shares_accommodation"],"pays_scottish_income_tax":["carers_allowance_earnings","earned_income_tax","esa_exempt_work_earnings","property_income_tax","tax_band","uc_income_tax_on_earnings","uc_income_tax_on_trade","uc_minimum_income_floor_income_tax"],"pension_age_benefits_premiums":["benefits_premiums","council_tax_reduction_applicable_amount"],"pension_age_severe_disability_premium":["pension_age_benefits_premiums"],"pension_age_winter_heating_payment":["pawhp"],"pension_annual_allowance":["pension_contributions_relief","personal_pension_contributions_tax"],"pension_contributions":["carers_allowance_earnings","council_tax_reduction_applicable_income","household_net_income","housing_benefit_applicable_income","housing_benefit_net_earnings","income_support_applicable_income","pension_contributions_relief","pension_credit_income","uc_individual_earned_income_before_mif"],"pension_contributions_for_annual_allowance":["personal_pension_contributions_tax"],"pension_contributions_relief":["allowances","capital_gains_tax"],"pension_contributions_via_salary_sacrifice":["pension_contributions_via_salary_sacrifice_from_pay"],"pension_contributions_via_salary_sacrifice_adjusted":["pension_contributions_for_annual_allowance"],"pension_contributions_via_salary_sacrifice_from_pay":["pension_contributions_via_salary_sacrifice_adjusted","salary_sacrifice_returned_to_income"],"pension_credit":["cost_of_living_support_payment","council_tax_reduction_applicable_income","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","housing_benefit_savings_credit_only_income","in_receipt_of_savings_credit_only","is_on_pension_credit","is_scp_eligible","pre_budget_change_household_benefits","tax_credits_applicable_income","tv_licence_discount","uc_non_dep_receives_pension_credit"],"pension_credit_assessable_capital":["council_tax_reduction_assessable_capital","housing_benefit_assessable_capital","pension_credit_deemed_income"],"pension_credit_deemed_income":["pension_credit_income"],"pension_credit_earnings":["pension_credit_income"],"pension_credit_entitlement":["pension_credit"],"pension_credit_income":["council_tax_reduction_applicable_income","guarantee_credit","housing_benefit_savings_credit_only_income","is_guarantee_credit_eligible","savings_credit","savings_credit_income"],"pension_credit_reported":["has_mixed_age_couple_pension_credit_saving","is_on_pension_credit","legacy_benefits_closed","pawhp_eligible","winter_fuel_payment_eligible"],"pension_credit_reported_capital":["pension_credit_assessable_capital"],"person_bus_fare_spending":["bus_fare_spending"],"person_id":["is_benunit_eldest_child"],"person_weight":["benunit_weight"],"personal_allowance":["allowances","esa_exempt_work_earnings","property_finance_costs_relieved","unused_personal_allowance"],"personal_pension_contributions":["capital_gains_tax","esa_exempt_work_earnings","hbai_household_net_income","pension_contributions","pension_contributions_for_annual_allowance"],"personal_pension_contributions_tax":["income_tax"],"personal_rent":["benunit_rent","family_rent"],"petrol_litres":["fuel_duty"],"petrol_price":["petrol_litres"],"petrol_spending":["petrol_litres"],"pip":["bursary_fund_16_to_19_vulnerable_group_eligible","child_minimum_guarantee_addition","cost_of_living_support_payment","disability_basic_income","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","is_benefit_cap_exempt_health_disability","pre_budget_change_household_benefits"],"pip_dl":["council_tax_reduction_applicant_has_non_dep_exemption","housing_benefit_severe_disability_premium_applies","is_lha_shared_accommodation_rate_specified_renter","is_severely_disabled_for_benefits","is_severely_disabled_for_carers_allowance","maintenance_loan_entitled_to_benefits","pip","receives_severe_disability_addition_qualifying_benefit","receives_severe_disability_premium_qualifying_benefit","uc_non_dep_deduction_exempt"],"pip_dl_category":["pip_dl","receives_enhanced_pip_dl"],"pip_m":["maintenance_loan_entitled_to_benefits","pip"],"pip_m_category":["pip_m"],"plan_1_interest_rate":["plan_4_interest_rate","student_loan_interest_rate"],"plan_2_interest_rate":["student_loan_interest_rate"],"plan_4_interest_rate":["student_loan_interest_rate"],"plan_5_interest_rate":["student_loan_interest_rate"],"postgraduate_interest_rate":["student_loan_interest_rate"],"poverty_gap":["in_poverty"],"poverty_line":["deep_poverty_line","poverty_gap"],"poverty_line_ahc":["poverty_gap_ahc"],"poverty_line_bhc":["poverty_gap_bhc"],"poverty_threshold_ahc":["in_poverty_ahc"],"poverty_threshold_bhc":["in_poverty_bhc"],"pre_budget_change_household_benefits":["pre_budget_change_household_net_income"],"pre_budget_change_household_net_income":["pre_budget_change_ons_household_income_decile"],"pre_budget_change_household_tax":["pre_budget_change_household_net_income"],"private_pension_income":["council_tax_reduction_applicable_income","earned_income","hbai_household_net_income","household_market_income","housing_benefit_applicable_income","housing_benefit_net_earnings","income_support_applicable_income","market_income","pension_credit_income","tax_credits_current_year_income","taxable_pension_income","total_income","total_pension_income","uc_unearned_income"],"private_pension_wealth":["corporate_sector_wealth","total_wealth"],"private_school_vat":["gov_tax","household_tax"],"private_transfer_income":["hbai_household_net_income","household_market_income","market_income"],"property_allowable_expenses":["property_allowance_deduction_if_used"],"property_allowance_deduction":["taxable_property_income"],"property_allowance_deduction_if_used":["property_allowance_deduction","uses_property_allowance"],"property_finance_cost_relief":["income_tax","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"property_finance_costs":["deductible_property_finance_costs","property_finance_costs_relievable","property_income_after_finance_costs"],"property_finance_costs_brought_forward":["property_finance_costs_carried_forward","property_finance_costs_relievable"],"property_finance_costs_relievable":["property_finance_costs_carried_forward","property_finance_costs_relieved","uses_property_allowance"],"property_finance_costs_relieved":["property_finance_cost_relief","property_finance_costs_carried_forward"],"property_income":["hbai_household_net_income","household_market_income","housing_benefit_net_earnings","market_income","property_allowable_expenses","property_allowance_deduction_if_used","property_income_after_finance_costs","property_receipts_within_allowance","taxable_property_income","total_income","uses_property_allowance"],"property_income_after_finance_costs":["council_tax_reduction_applicable_income","housing_benefit_applicable_income","income_support_applicable_income","pension_credit_income","tax_credits_current_year_income"],"property_income_tax":["income_tax","income_tax_pre_charges","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"property_purchased":["additional_residential_property_purchased","main_residential_property_purchased","non_residential_property_purchased"],"property_receipts_within_allowance":["property_allowance_deduction_if_used"],"property_rental_income":["property_allowable_expenses","property_allowance_deduction_if_used","property_receipts_within_allowance"],"property_wealth":["household_land_value","total_wealth"],"rail_subsidy_spending":["dft_subsidy_spending"],"rail_usage":["rail_subsidy_spending"],"received_allowances_dividend_income":["dividend_income_tax","received_allowances","taxed_dividend_income"],"received_allowances_earned_income":["earned_taxable_income","received_allowances","received_allowances_dividend_income","received_allowances_savings_income"],"received_allowances_savings_income":["add_rate_savings_income","basic_rate_savings_income","basic_rate_savings_income_pre_starter","dividend_income_tax","higher_rate_savings_income","received_allowances","received_allowances_dividend_income","savings_starter_rate_income"],"receives_benefits_in_own_right":["is_benefit_cap_exempt_health_disability","is_qualifying_young_person_for_child_benefit","is_qualifying_young_person_for_child_tax_credit","is_qualifying_young_person_for_pension_credit","is_qualifying_young_person_for_universal_credit"],"receives_carer_benefit":["is_cared_for_by_carer_benefit_recipient","is_carer_for_benefits","is_entitled_to_carer_benefit","tax_free_childcare_regarded_as_in_paid_work","uc_non_dep_deduction_exempt"],"receives_carer_support_payment":["receives_carer_benefit"],"receives_carers_allowance":["receives_carer_benefit"],"receives_enhanced_pip_dl":["child_minimum_guarantee_addition"],"receives_highest_dla_sc":["child_minimum_guarantee_addition"],"receives_limited_capability_for_work_credits":["extended_childcare_entitlement_limited_capability_or_specified_benefit","tax_free_childcare_caring_or_incapacity_benefit","tax_free_childcare_regarded_as_in_paid_work"],"receives_severe_disability_addition_qualifying_benefit":["is_counted_resident_for_severe_disability_addition","severe_disability_minimum_guarantee_addition"],"receives_severe_disability_premium_qualifying_benefit":["has_non_dependant_for_severe_disability_premium","severe_disability_premium"],"receives_uc_carer_element":["extended_childcare_entitlement_limited_capability_or_specified_benefit"],"recreation_consumption":["carbon_consumption","consumption"],"reduced_rate_vat_consumption":["baseline_vat","vat"],"region":["benefit_cap","benunit_region","country","household_land_value","maintenance_loan_living_arrangement","uc_has_deduction","uc_latent_deduction_rate"],"relation_type":["is_couple","is_savings_credit_eligible","is_single","savings_credit","standard_minimum_guarantee"],"relative_income_change":["income_elasticity_lsr"],"relative_wage_change":["substitution_elasticity_lsr"],"rent":["hbai_household_net_income_ahc","housing_costs","lbtt_on_residential_property_rent","ltt_on_residential_property_rent","personal_rent","sdlt_on_residential_property_rent"],"rent_paid_as_boarder":["pays_rent_to_householder","personal_rent"],"rent_paid_as_lodger":["pays_rent_to_householder","personal_rent"],"residential_property_value":["property_wealth"],"restaurants_and_hotels_consumption":["carbon_consumption","consumption"],"salary_sacrifice_broad_base_haircut":["employment_income"],"salary_sacrifice_returned_to_income":["employee_pension_contributions","employment_income","salary_sacrifice_pension_ni_employee","salary_sacrifice_pension_ni_employer"],"savings":["council_tax_reduction_assessable_capital","esa_income_assessable_capital","housing_benefit_assessable_capital","income_support_assessable_capital","jsa_income_assessable_capital","kingston_upon_thames_council_tax_reduction","merton_council_tax_reduction","newham_council_tax_reduction","oxford_council_tax_reduction","pension_credit_assessable_capital","total_wealth","uc_assessable_capital","westminster_council_tax_reduction"],"savings_allowance":["add_rate_savings_income","basic_rate_savings_income","higher_rate_savings_income"],"savings_credit":["in_receipt_of_savings_credit_only","pension_credit_entitlement"],"savings_credit_income":["is_savings_credit_eligible","savings_credit"],"savings_income_tax":["income_tax","income_tax_pre_charges"],"savings_interest_income":["capital_income","hbai_household_net_income","household_market_income","housing_benefit_net_earnings","market_income","tax_credits_current_year_income","taxable_savings_interest_income","total_income"],"savings_starter_rate_income":["add_rate_savings_income","basic_rate_savings_income","higher_rate_savings_income"],"scottish_carer_supplement":["gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","pre_budget_change_household_benefits","social_security_income"],"scottish_child_payment":["gov_spending","hbai_household_net_income","household_benefits"],"scottish_funded_early_learning_childcare_start_date_reached":["scottish_funded_early_learning_childcare_eligible"],"sda":["benefit_cap_reduction","carer_support_payment_overlapping_benefits","carers_allowance_overlapping_benefits","extended_childcare_entitlement_limited_capability_or_specified_benefit","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","pre_budget_change_household_benefits","tax_free_childcare_caring_or_incapacity_benefit","tax_free_childcare_regarded_as_in_paid_work"],"sda_reported":["sda"],"sdlt_liable":["stamp_duty_land_tax"],"sdlt_on_non_residential_property_rent":["sdlt_on_rent"],"sdlt_on_non_residential_property_transactions":["sdlt_on_transactions"],"sdlt_on_rent":["stamp_duty_land_tax"],"sdlt_on_residential_property_rent":["sdlt_on_rent"],"sdlt_on_residential_property_transactions":["sdlt_on_transactions"],"sdlt_on_transactions":["stamp_duty_land_tax"],"self_employment_gross_receipts":["trading_allowance_deduction"],"self_employment_income":["carers_allowance_earnings","council_tax_reduction_applicable_income","earned_income","esa_exempt_work_earnings","extended_childcare_entitlement_meets_income_requirements","hbai_household_net_income","household_market_income","housing_benefit_applicable_income","housing_benefit_net_earnings","housing_benefit_specified_or_temporary_accommodation_disregard","in_work","income_support_applicable_income","market_income","ni_class_4_profits_before_losses","pension_contributions_relief","pension_credit_earnings","tax_credits_current_year_income","tax_free_childcare_expected_declaration_period_income","taxable_self_employment_income","total_income","trading_allowance_deduction","uc_individual_earned_income_before_mif","uc_is_in_gainful_self_employment"],"severe_disability_minimum_guarantee_addition":["additional_minimum_guarantee"],"severe_disability_premium":["maintenance_loan_entitled_to_benefits","pension_age_severe_disability_premium","working_age_benefits_premiums"],"share_of_household_rent":["housing_benefit_non_dep_deductions","personal_rent"],"shareholding":["baseline_business_rates","business_rates","carbon_tax","corporate_incident_tax_revenue_change","corporate_sdlt"],"simulated_council_tax_reduction_benunit":["council_tax_benefit"],"social_security_income":["housing_benefit_net_earnings","income_support_applicable_income","tax_credits_current_year_income","taxable_social_security_income","total_income"],"sparkling_cider_abv":["sparkling_cider_duty"],"sparkling_cider_draught_share":["sparkling_cider_duty"],"sparkling_cider_duty":["alcohol_duty"],"sparkling_cider_litres":["sparkling_cider_duty"],"spirits_abv":["spirits_duty"],"spirits_draught_share":["spirits_duty"],"spirits_duty":["alcohol_duty"],"spirits_litres":["spirits_duty"],"ssmg":["council_tax_reduction_applicable_income","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","housing_benefit_applicable_income","pre_budget_change_household_benefits"],"ssmg_reported":["ssmg"],"stamp_duty_land_tax":["expected_sdlt"],"standard_minimum_guarantee":["minimum_guarantee","savings_credit"],"stands_as_sole_owner_or_partner_of_company":["uc_company_owner_treatment_applies"],"state_pension":["council_tax_reduction_applicable_income","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","housing_benefit_applicable_income","overlapping_state_pension","pension_credit_income","pre_budget_change_household_benefits","social_security_income","total_pension_income","uc_unearned_income"],"state_pension_age":["months_since_state_pension_age"],"state_pension_credit_qualifying_age":["has_attained_state_pension_credit_qualifying_age"],"state_pension_reported":["additional_state_pension","basic_state_pension","new_state_pension"],"state_pension_type":["additional_state_pension","basic_state_pension","new_state_pension","overlapping_state_pension"],"statutory_maternity_pay":["adjusted_employer_cost","baseline_employer_cost","council_tax_reduction_applicable_income","employer_cost","employer_ni_fixed_employer_cost_change","employment_benefits","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","housing_benefit_applicable_income","ni_class_1_income","pre_budget_change_household_benefits","tax_free_childcare_treated_as_in_work","uc_childcare_treated_as_in_paid_work","uc_individual_earned_income_before_mif"],"statutory_paternity_pay":["adjusted_employer_cost","baseline_employer_cost","employer_cost","employer_ni_fixed_employer_cost_change","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","ni_class_1_income","tax_free_childcare_treated_as_in_work","uc_childcare_treated_as_in_paid_work","uc_individual_earned_income_before_mif"],"statutory_sick_pay":["adjusted_employer_cost","baseline_employer_cost","council_tax_reduction_applicable_income","employer_cost","employer_ni_fixed_employer_cost_change","employment_benefits","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","housing_benefit_applicable_income","ni_class_1_income","pre_budget_change_household_benefits","tax_free_childcare_treated_as_in_work","uc_childcare_treated_as_in_paid_work","uc_individual_earned_income_before_mif"],"structural_insurance_payments":["hbai_household_net_income_ahc"],"student_loan_balance":["net_wealth","student_loan_repayment"],"student_loan_plan":["has_student_loan","student_loan_interest_rate","student_loan_repayment","student_loan_repayment_rate"],"student_loan_repayment":["student_loan_repayments"],"student_loan_repayment_rate":["student_loan_repayment"],"student_loan_repayments":["gov_tax","hbai_household_net_income","household_tax"],"targeted_childcare_entitlement":["extended_childcare_entitlement_per_child","gov_spending","household_benefits","is_child_receiving_targeted_childcare"],"targeted_childcare_entitlement_eligible":["targeted_childcare_entitlement"],"tax":["benunit_tax","tax_modelling"],"tax_band":["meets_marriage_allowance_income_conditions"],"tax_credit_award":["is_on_pawhp_relevant_benefit","is_on_winter_fuel_payment_relevant_benefit","pawhp_eligible","winter_fuel_payment_eligible"],"tax_credits":["council_tax_reduction_applicable_income","ctc_entitlement","housing_benefit_applicable_income","tax_credit_award"],"tax_credits_applicable_income":["tax_credits_reduction"],"tax_credits_current_year_income":["meets_child_tax_credit_criteria_for_targeted_childcare_entitlement","meets_working_tax_credit_criteria_for_targeted_childcare_entitlement","tax_credits_applicable_income"],"tax_credits_reduction":["child_tax_credit_pre_minimum","working_tax_credit_pre_minimum"],"tax_free_childcare":["childcare_grant_eligible","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","is_child_receiving_tax_free_childcare"],"tax_free_childcare_caring_or_incapacity_benefit":["tax_free_childcare_regarded_as_in_paid_work"],"tax_free_childcare_child_age_eligible":["tax_free_childcare_qualifying_child"],"tax_free_childcare_eligible":["tax_free_childcare","tax_free_childcare_eligible_declaration_periods"],"tax_free_childcare_eligible_declaration_periods":["tax_free_childcare"],"tax_free_childcare_expected_declaration_period_income":["tax_free_childcare_meets_income_requirements"],"tax_free_childcare_meets_income_requirements":["tax_free_childcare_eligible"],"tax_free_childcare_meets_uk_connection":["tax_free_childcare_program_eligible"],"tax_free_childcare_on_adoption_leave":["tax_free_childcare_treated_as_in_work"],"tax_free_childcare_on_carers_leave":["tax_free_childcare_regarded_as_in_paid_work"],"tax_free_childcare_on_qualifying_leave":["tax_free_childcare_treated_as_in_work"],"tax_free_childcare_on_shared_parental_leave":["tax_free_childcare_treated_as_in_work"],"tax_free_childcare_program_eligible":["tax_free_childcare_eligible"],"tax_free_childcare_qualifying_child":["is_child_receiving_tax_free_childcare","tax_free_childcare","tax_free_childcare_eligible"],"tax_free_childcare_regarded_as_in_paid_work":["tax_free_childcare_meets_income_requirements","tax_free_childcare_work_condition"],"tax_free_childcare_self_employment_start_up_period":["tax_free_childcare_meets_income_requirements"],"tax_free_childcare_spend_routed_share":["tax_free_childcare"],"tax_free_childcare_treated_as_in_work":["tax_free_childcare_regarded_as_in_paid_work","tax_free_childcare_work_condition"],"tax_free_childcare_uses_qualifying_provider":["tax_free_childcare"],"tax_free_childcare_work_condition":["tax_free_childcare_eligible"],"tax_free_savings_income":["taxable_savings_interest_income"],"tax_reported":["tax_modelling"],"taxable_dividend_income":["dividend_income_tax","earned_taxable_income","net_income","non_savings_income_after_allowances","property_finance_costs_relieved","received_allowances_dividend_income","received_allowances_earned_income","taxed_dividend_income","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"taxable_employment_income":["net_income","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"taxable_miscellaneous_income":["housing_benefit_net_earnings","net_income","total_income","uc_income_tax_on_earnings","uc_income_tax_on_trade","uc_individual_earned_income_before_mif"],"taxable_pension_income":["net_income"],"taxable_property_income":["earned_taxable_income","net_income","property_finance_costs_relieved","taxable_property_income_after_allowances","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"taxable_property_income_after_allowances":["non_savings_taxable_income","property_income_tax"],"taxable_savings_interest_income":["add_rate_savings_income","basic_rate_savings_income","basic_rate_savings_income_pre_starter","dividend_income_tax","earned_taxable_income","higher_rate_savings_income","net_income","non_savings_income_after_allowances","property_finance_costs_relieved","received_allowances_earned_income","received_allowances_savings_income","savings_starter_rate_income","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"taxable_self_employment_income":["net_income","uc_income_tax_on_earnings","uc_income_tax_on_trade"],"taxable_social_security_income":["net_income"],"taxed_dividend_income":["taxed_income"],"taxed_income":["personal_pension_contributions_tax"],"taxed_savings_income":["taxed_income"],"tenure_type":["benunit_tenure_type","is_renting","ons_tenure_type"],"tobacco_duty":["gov_tax","household_tax"],"total_income":["bi_household_phaseout","bi_individual_phaseout","household_benefits_individual_non_dep_deduction","housing_benefit_net_earnings","post_tax_income","winter_fuel_payment_eligible"],"total_wealth":["household_wealth_decile","net_wealth","non_primary_residence_wealth_tax","wealth_tax"],"trading_allowance_deduction":["ni_class_4_profits_before_losses","taxable_self_employment_income"],"trading_loss":["loss_relief"],"transport_consumption":["carbon_consumption","consumption"],"travel_grant":["gov_spending","hbai_benefits","household_benefits"],"travel_grant_abroad_placement":["travel_grant_eligible"],"travel_grant_clinical_placement":["travel_grant_eligible"],"travel_grant_eligible":["travel_grant"],"travel_grant_eligible_expenses":["travel_grant_eligible"],"travel_grant_income_assessed_support":["travel_grant_eligible"],"travel_grant_receives_means_tested_nhs_bursary":["travel_grant_eligible"],"tv_licence":["gov_tax","household_tax","pre_budget_change_household_tax"],"tv_licence_discount":["free_tv_licence_value","tv_licence"],"two_child_limit_payment":["gov_spending","household_benefits"],"uc_LCWRA_element":["is_benefit_cap_exempt_health_disability","uc_disability_elements"],"uc_LHA_cap":["uc_housing_costs_element"],"uc_assessable_capital":["is_uc_eligible","kingston_upon_thames_council_tax_reduction","merton_council_tax_reduction","newham_council_tax_reduction","uc_tariff_income","westminster_council_tax_reduction"],"uc_carer_element":["is_benefit_cap_exempt_health_disability","receives_uc_carer_element","uc_maximum_amount"],"uc_child_element":["uc_maximum_amount"],"uc_child_index":["uc_individual_child_element"],"uc_childcare_element":["childcare_grant_eligible","uc_maximum_amount"],"uc_childcare_element_claimed":["uc_childcare_element"],"uc_childcare_element_eligible_children":["uc_maximum_childcare_element_amount"],"uc_childcare_treated_as_in_paid_work":["uc_childcare_work_condition"],"uc_childcare_work_condition":["uc_childcare_element_claimed"],"uc_company_capital":["uc_assessable_capital"],"uc_company_gainful_self_employment":["uc_is_in_gainful_self_employment"],"uc_company_holding_disregard":["household_uc_pool_company_holdings","uc_assessable_capital"],"uc_company_intermediary_exclusion_applies":["uc_company_owner_treatment_applies"],"uc_company_owner_treatment_applies":["uc_company_capital","uc_company_gainful_self_employment","uc_company_holding_disregard","uc_company_self_employed_earnings"],"uc_company_self_employed_earnings":["uc_individual_earned_income_before_mif"],"uc_deduction_combination":["uc_deduction_rate"],"uc_deduction_random_draw":["uc_has_deduction","uc_latent_deduction_rate"],"uc_deduction_rate":["uc_deductions"],"uc_deduction_type_random_draw":["uc_deduction_combination"],"uc_deductions":["universal_credit"],"uc_disability_elements":["uc_maximum_amount"],"uc_earned_income":["kingston_upon_thames_council_tax_reduction","meets_universal_credit_criteria_for_targeted_childcare_entitlement","merton_council_tax_reduction","newham_council_tax_reduction","uc_income_reduction","westminster_council_tax_reduction"],"uc_expected_hours":["uc_minimum_income_floor_gross"],"uc_has_deduction":["uc_deduction_combination","uc_latent_deduction_rate"],"uc_has_offer_of_paid_work_starting_by_end_of_next_assessment_period":["uc_childcare_work_condition"],"uc_housing_costs_element":["uc_maximum_amount","uc_work_allowance"],"uc_income_reduction":["universal_credit_pre_benefit_cap"],"uc_income_tax_on_earnings":["uc_income_tax_on_trade","uc_individual_earned_income_before_mif"],"uc_income_tax_on_trade":["uc_individual_earned_income_before_mif"],"uc_individual_child_element":["uc_child_element","uc_childcare_element_eligible_children","uc_is_child_limit_affected"],"uc_individual_disabled_child_element":["uc_disability_elements"],"uc_individual_earned_income":["uc_earned_income"],"uc_individual_earned_income_before_mif":["is_benefit_cap_exempt_earnings","uc_individual_earned_income"],"uc_individual_non_dep_deduction":["uc_non_dep_deductions"],"uc_individual_non_dep_deduction_eligible":["uc_individual_non_dep_deduction"],"uc_individual_severely_disabled_child_element":["uc_disability_elements"],"uc_is_adopter_in_first_year":["uc_work_related_group_apart_from_earnings"],"uc_is_child_born_before_child_limit":["uc_individual_child_element"],"uc_is_child_limit_affected":["two_child_limit_payment"],"uc_is_foster_parent_or_new_friend_or_family_carer":["uc_work_related_group_apart_from_earnings"],"uc_is_in_gainful_self_employment":["uc_mif_applies"],"uc_is_in_pregnancy_or_post_confinement_period":["uc_work_related_group_apart_from_earnings"],"uc_is_in_startup_period":["uc_mif_applies"],"uc_is_ineligible_partner":["is_benefit_cap_exempt_health_disability","is_lha_shared_accommodation_rate_specified_renter","is_on_universal_credit","is_uc_single_or_joint_claimant","uc_is_responsible_carer","uc_member_of_couple_claims_as_single_person","uc_minimum_income_floor_gross","uc_work_related_group_apart_from_earnings"],"uc_is_responsible_carer":["uc_expected_hours","uc_work_related_group_apart_from_earnings"],"uc_is_responsible_foster_parent_of_child_under_one":["uc_work_related_group_apart_from_earnings"],"uc_is_student_with_no_work_related_requirements":["uc_work_related_group_apart_from_earnings"],"uc_is_temporarily_absent_from_claimant_household":["uc_unable_to_provide_childcare"],"uc_latent_deduction_rate":["uc_deduction_rate"],"uc_limited_capability_for_WRA":["disability_basic_income","extended_childcare_entitlement_limited_capability_or_specified_benefit","is_benefit_cap_exempt_health_disability","uc_limited_capability_for_work","uc_work_related_group_apart_from_earnings"],"uc_limited_capability_for_work":["is_uc_work_allowance_eligible","meets_uc_minimum_age_condition","uc_unable_to_provide_childcare","uc_work_related_group_apart_from_earnings"],"uc_maximum_amount":["kingston_upon_thames_council_tax_reduction","merton_council_tax_reduction","newham_council_tax_reduction","uc_income_reduction","universal_credit_pre_benefit_cap","westminster_council_tax_reduction"],"uc_maximum_childcare_element_amount":["uc_childcare_element"],"uc_member_of_couple_claims_as_single_person":["is_benefit_cap_exempt_health_disability","is_benefit_cap_single_claimant_rate","is_lha_shared_accommodation_rate_specified_renter"],"uc_mif_applies":["uc_individual_earned_income"],"uc_minimum_income_floor":["uc_individual_earned_income"],"uc_minimum_income_floor_gross":["uc_minimum_income_floor","uc_minimum_income_floor_income_tax","uc_minimum_income_floor_national_insurance"],"uc_minimum_income_floor_income_tax":["uc_minimum_income_floor"],"uc_minimum_income_floor_national_insurance":["uc_minimum_income_floor"],"uc_national_insurance_on_earnings":["uc_individual_earned_income_before_mif","uc_national_insurance_on_trade"],"uc_national_insurance_on_trade":["uc_individual_earned_income_before_mif"],"uc_non_dep_deduction_exempt":["uc_individual_non_dep_deduction_eligible"],"uc_non_dep_deductions":["uc_housing_costs_element"],"uc_non_dep_receives_pension_credit":["uc_non_dep_deduction_exempt"],"uc_non_dependants_counted":["LHA_allowed_bedrooms","lha_renter_has_non_dependant","uc_non_dep_deductions"],"uc_reported_capital":["household_uc_pool_company_holdings","household_uc_reported_capital","household_uc_unreported_claimants","uc_assessable_capital"],"uc_standard_allowance":["uc_deductions","uc_maximum_amount","universal_credit"],"uc_standard_allowance_claimant_type":["uc_standard_allowance"],"uc_tariff_income":["uc_unearned_income"],"uc_unable_to_provide_childcare":["uc_childcare_work_condition"],"uc_unearned_carer_support_payment":["uc_unearned_income"],"uc_unearned_income":["kingston_upon_thames_council_tax_reduction","merton_council_tax_reduction","newham_council_tax_reduction","uc_income_reduction","westminster_council_tax_reduction"],"uc_work_allowance":["uc_earned_income"],"uc_work_related_group_apart_from_earnings":["uc_mif_applies","uc_minimum_income_floor_gross"],"uc_youngest_child_age":["uc_expected_hours","uc_is_responsible_carer","uc_work_related_group_apart_from_earnings"],"universal_childcare_entitlement":["extended_childcare_entitlement_per_child","gov_spending","household_benefits","is_child_receiving_universal_childcare"],"universal_childcare_entitlement_eligible":["universal_childcare_entitlement"],"universal_credit":["cost_of_living_support_payment","council_tax_reduction_applicable_income","disability_basic_income","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","is_on_universal_credit","is_scp_eligible","kingston_upon_thames_council_tax_reduction","kingston_upon_thames_council_tax_reduction_non_dep_deductions","meets_universal_credit_criteria_for_targeted_childcare_entitlement","merton_council_tax_reduction","merton_council_tax_reduction_non_dep_deductions","newham_council_tax_reduction","oxford_council_tax_reduction","pre_budget_change_household_benefits","receives_uc_carer_element","uc_is_child_limit_affected","westminster_council_tax_reduction"],"universal_credit_pre_benefit_cap":["benefit_cap_reduction","is_benefit_cap_exempt_health_disability","is_benefit_cap_single_claimant_rate","is_uc_entitled","tax_free_childcare_program_eligible","uc_deductions","uc_has_deduction","universal_credit"],"universal_credit_reported":["bursary_fund_16_to_19_receives_uc_or_esa_in_own_right","bursary_fund_16_to_19_receives_uc_or_is_in_own_right","claims_all_entitled_benefits","has_mixed_age_couple_pension_credit_saving","is_on_universal_credit","meets_pension_credit_age_conditions","pawhp_eligible","winter_fuel_payment_eligible"],"unused_personal_allowance":["partners_unused_personal_allowance"],"uses_property_allowance":["property_allowance_deduction","property_finance_costs_carried_forward","property_finance_costs_relieved"],"vat":["gov_tax","vat_change"],"vat_change":["household_tax","pre_budget_change_household_tax"],"vehicle_excise_duty":["gov_tax","household_tax"],"water_and_sewerage_charges":["hbai_household_net_income_ahc","housing_costs"],"wealth_tax":["gov_tax","household_tax","pre_budget_change_household_tax"],"weekly_hours":["benunit_weekly_hours","esa_income_remunerative_work_hours","income_support_remunerative_work_hours","is_WTC_eligible","jsa_remunerative_work_hours","meets_housing_benefit_additional_earnings_disregard_conditions"],"westminster_council_tax_reduction":["simulated_council_tax_reduction_benunit"],"westminster_council_tax_reduction_individual_non_dep_deduction":["westminster_council_tax_reduction_non_dep_deductions"],"westminster_council_tax_reduction_non_dep_deductions":["westminster_council_tax_reduction"],"wine_abv":["wine_duty"],"wine_draught_share":["wine_duty"],"wine_duty":["alcohol_duty"],"wine_litres":["wine_duty"],"winter_fuel_allowance":["cost_of_living_support_payment","gov_spending","hbai_benefits","hbai_household_net_income","household_benefits"],"winter_fuel_payment":["winter_fuel_allowance"],"winter_fuel_payment_eligible":["winter_fuel_payment"],"working_age_benefits_premiums":["benefits_premiums","council_tax_reduction_applicable_amount","income_support_applicable_amount"],"working_tax_credit":["gov_spending","hbai_benefits","hbai_household_net_income","household_benefits","is_benefit_cap_exempt_health_disability","is_scp_eligible","meets_child_tax_credit_criteria_for_targeted_childcare_entitlement","meets_working_tax_credit_criteria_for_targeted_childcare_entitlement","pension_credit_income","pre_budget_change_household_benefits","tax_free_childcare_program_eligible"],"working_tax_credit_reported":["claims_all_entitled_benefits","claims_legacy_benefits","council_tax_reduction_pensioner","is_WTC_eligible","is_uc_eligible","legacy_benefits_closed","pawhp_eligible","tax_credit_award","winter_fuel_payment_eligible","would_claim_WTC"],"would_claim_CTC":["child_tax_credit","child_tax_credit_pre_minimum"],"would_claim_IS":["income_support","income_support_assessable_capital"],"would_claim_WTC":["working_tax_credit","working_tax_credit_pre_minimum"],"would_claim_adult_dependants_grant":["adult_dependants_grant_eligible"],"would_claim_bursary_fund_16_to_19":["bursary_fund_16_to_19_vulnerable_group_eligible"],"would_claim_care_to_learn":["care_to_learn_eligible"],"would_claim_carers_allowance":["carer_support_payment_pre_overlap","carers_allowance_pre_overlap","is_carer_for_benefits","partners_care_for_same_severely_disabled_person"],"would_claim_child_benefit":["child_benefit"],"would_claim_childcare_grant":["childcare_grant_eligible"],"would_claim_council_tax_reduction":["kingston_upon_thames_council_tax_reduction","merton_council_tax_reduction","newham_council_tax_reduction","oxford_council_tax_reduction","simulated_council_tax_reduction_benunit","westminster_council_tax_reduction"],"would_claim_disabled_students_allowance":["disabled_students_allowance_eligible"],"would_claim_extended_childcare":["extended_childcare_entitlement_eligible"],"would_claim_housing_benefit":["housing_benefit","housing_benefit_pre_benefit_cap"],"would_claim_marriage_allowance":["marriage_allowance"],"would_claim_parents_learning_allowance":["parents_learning_allowance_eligible"],"would_claim_pc":["in_receipt_of_guarantee_credit","in_receipt_of_savings_credit_only","income_support_eligible","pension_credit"],"would_claim_scp":["scottish_child_payment"],"would_claim_targeted_childcare":["targeted_childcare_entitlement"],"would_claim_tfc":["tax_free_childcare_eligible"],"would_claim_travel_grant":["travel_grant_eligible"],"would_claim_uc":["claims_universal_credit"],"would_claim_uc_at_legacy_closure":["claims_uc_at_legacy_closure"],"would_claim_uc_childcare":["uc_childcare_element_claimed"],"would_claim_universal_childcare":["universal_childcare_entitlement"],"would_evade_tv_licence_fee":["free_tv_licence_value","tv_licence"],"wtc_entitlement":["working_tax_credit"],"youngest_child_age_for_legacy_benefits":["income_support_eligible"],"youngest_claimant_or_partner_age":["income_support_applicable_amount","is_WTC_eligible"]}} diff --git a/app/src/libs/flagship/calibrationMatching.ts b/app/src/libs/flagship/calibrationMatching.ts index 128713617..de34d5969 100644 --- a/app/src/libs/flagship/calibrationMatching.ts +++ b/app/src/libs/flagship/calibrationMatching.ts @@ -555,7 +555,7 @@ export async function calibrationMatchesForPaths( ): Promise { let map; try { - map = await loadParameterDependencies(); + map = await loadParameterDependencies('us'); } catch { return null; } diff --git a/app/src/libs/flagship/householdRun.ts b/app/src/libs/flagship/householdRun.ts index f8e4a407f..e68cc805e 100644 --- a/app/src/libs/flagship/householdRun.ts +++ b/app/src/libs/flagship/householdRun.ts @@ -1,127 +1,25 @@ -import { STATE_NAMES } from '@/api/billFeed'; import { createHousehold } from '@/api/household'; -import { fetchHouseholdCalculation } from '@/api/householdCalculation'; +import { + fetchHouseholdCalculationWithBundle, + type HouseholdCalculationResult, +} from '@/api/householdCalculation'; +import type { PolicyEngineBundle } from '@/api/societyWideCalculation'; import type { CountryId } from '@/libs/countries'; -import { Household } from '@/models/Household'; import type { V1HouseholdCreateEnvelope } from '@/models/household/v1Types'; import type { HouseholdCalculationData } from '@/types/calculation/household'; -import { formatCurrency } from '@/utils/formatters'; +import type { SPMProvenance, SPMSelection } from '@/types/spm'; /** - * A household run for the flagship report: one family, described in a - * few fields, run under the report's baseline and reform policies for - * the report's year through the same v1 household endpoints the v2 - * household flow uses — create the household, then calculate it under - * each policy. + * A household run for the flagship report: a household built in the + * household builder, run under the report's baseline and reform policies + * for the report's year, in the household's own country, through the + * Public API's v1 household routes, as the older household flow uses + * them: create the household, then calculate it under each policy. */ -/** The household as the report's form describes it. US only for now. */ -export interface FlagshipHouseholdInput { - /** Two-letter state code, e.g. "CA". */ - state: string; - married: boolean; - /** One age per child, each 0–17. */ - childAges: number[]; - /** The head's annual employment income. */ - earnings: number; - /** The partner's annual employment income; read only when married. */ - partnerEarnings: number; -} - -export const MAX_CHILDREN = 6; -export const MAX_CHILD_AGE = 17; -export const DEFAULT_CHILD_AGE = 10; -const DEFAULT_STATE = 'CA'; -const DEFAULT_EARNINGS = 50000; -/** A change smaller than a dollar reads as no change. */ +/** A change smaller than a dollar (or a pound) reads as no change. */ const NEGLIGIBLE = 1; -/** - * The form's starting household: single, no children, $50,000 a year, in - * the report's state — a state or district report's own state, else - * California, the model's default. - */ -export function defaultHouseholdInput(region?: string): FlagshipHouseholdInput { - return { - state: stateFromRegion(region) ?? DEFAULT_STATE, - married: false, - childAges: [], - earnings: DEFAULT_EARNINGS, - partnerEarnings: 0, - }; -} - -/** "state/ny" → "NY", "congressional_district/TX-07" → "TX"; nothing for the country. */ -export function stateFromRegion(region?: string): string | undefined { - const match = region?.match(/^(?:state\/([a-z]{2})|congressional_district\/([a-z]{2})-)/i); - const code = (match?.[1] ?? match?.[2])?.toUpperCase(); - return code && STATE_NAMES[code] ? code : undefined; -} - -const isAmount = (value: number) => Number.isFinite(value) && value >= 0; -const isChildAge = (age: number) => Number.isInteger(age) && age >= 0 && age <= MAX_CHILD_AGE; - -/** Whether the household can run: a known state, amounts of zero or more, children's ages. */ -export function isValidHouseholdInput(input: FlagshipHouseholdInput): boolean { - return ( - !!STATE_NAMES[input.state] && - isAmount(input.earnings) && - (!input.married || isAmount(input.partnerEarnings)) && - input.childAges.length <= MAX_CHILDREN && - input.childAges.every(isChildAge) - ); -} - -/** - * The v1 household for the input, built with the v2 builder's own model - * so the API reads it as it reads a v2 household: the head is "you", and - * the API takes the year to calculate from "you"'s age. - */ -export function buildHouseholdPayload( - input: FlagshipHouseholdInput, - year: string -): V1HouseholdCreateEnvelope { - let household = Household.starter('us', year) - .withBuilderMaritalStatus(year, input.married ? 'married' : 'single') - .withBuilderChildCount(year, input.childAges.length); - const { primaryPersonKey, partnerKey, childKeys } = household.deriveBuilderComposition(year); - if (primaryPersonKey) { - household = household.setPersonVariableAtYear( - primaryPersonKey, - 'employment_income', - year, - input.earnings - ); - } - if (partnerKey) { - household = household.setPersonVariableAtYear( - partnerKey, - 'employment_income', - year, - input.partnerEarnings - ); - } - childKeys.forEach((childKey, index) => { - household = household.setPersonVariableAtYear( - childKey, - 'age', - year, - input.childAges[index] ?? DEFAULT_CHILD_AGE - ); - }); - const householdKey = Object.keys(household.householdData.households ?? {})[0]; - if (householdKey) { - household = household.setGroupVariableAtYear( - 'households', - householdKey, - 'state_name', - year, - input.state - ); - } - return household.toV1CreationPayload(); -} - type EntityPlural = 'people' | 'households' | 'tax_units' | 'spm_units' | 'benunits'; /** The app's camel-case keys, for results already in the app's shape. */ @@ -306,7 +204,7 @@ function benefitLine(variable: string, label: string, entity: EntityPlural): Lin return { id: variable, label, sign: 1, sources: [{ entity, variable }] }; } -/** Each country's parts of net income and programs; a country without its own reads the US's. */ +/** Each country's parts of net income and programs: the countries v3 runs households for. */ const LINES: Partial< Record > = { @@ -314,8 +212,17 @@ const LINES: Partial< uk: { components: UK_COMPONENTS, programs: UK_PROGRAMS }, }; +/** + * The rows a country's result lists (its `LINES` entry: parts of net + * income and programs). A country without an entry has none, and is never + * read as the US. + */ function linesFor(countryId: string) { - return LINES[countryId as CountryId] ?? LINES.us!; + const lines = LINES[countryId as CountryId]; + if (!lines) { + throw new Error(`Household results are not available for ${countryId}.`); + } + return lines; } export interface HouseholdLineChange { @@ -382,7 +289,7 @@ export function compareHouseholds( baseline: HouseholdCalculationData, reform: HouseholdCalculationData, year: string, - countryId: string = 'us' + countryId: string ): FlagshipHouseholdImpact { const lines = linesFor(countryId); const before = readHouseholdTotal(baseline, 'households', 'household_net_income', year); @@ -414,13 +321,6 @@ export function compareHouseholds( }; } -export interface RunFlagshipHouseholdArgs { - year: string; - input: FlagshipHouseholdInput; - baselinePolicyId: string; - reformPolicyId: string; -} - export interface FlagshipHouseholdRun extends FlagshipHouseholdImpact { householdId: string; /** @@ -429,6 +329,31 @@ export interface FlagshipHouseholdRun extends FlagshipHouseholdImpact { */ baseline: HouseholdCalculationData; reform: HouseholdCalculationData; + /** + * How each policy's calculation was made, as its response says. The + * SPM methodology footnote reads the SPM settings and receipt; the .py + * bundle is kept so Reproduce in Python can name the versions that + * calculated the result, which v3 does not offer yet. + */ + provenance: { baseline: HouseholdCalculationProvenance; reform: HouseholdCalculationProvenance }; +} + +/** What one calculation response says about how it was made. */ +export interface HouseholdCalculationProvenance { + /** The .py bundle that calculated it; null when the response names none. */ + policyengineBundle: PolicyEngineBundle | null; + /** The SPM settings the calculation used (US households only). */ + spmConfig?: SPMSelection; + /** The SPM forecast and thresholds the calculation read (US households only). */ + spmProvenance?: SPMProvenance; +} + +function provenanceOf(response: HouseholdCalculationResult): HouseholdCalculationProvenance { + return { + policyengineBundle: response.policyengine_bundle ?? null, + ...(response.spm_config ? { spmConfig: response.spm_config } : {}), + ...(response.spm_provenance ? { spmProvenance: response.spm_provenance } : {}), + }; } /** @@ -452,12 +377,16 @@ export function plainHouseholdError(error: unknown): Error { * the API keeps calculating and caches the result, so the second ask * usually returns it at once. */ -async function calculateOnce(countryId: string, householdId: string, policyId: string) { +async function calculateOnce( + countryId: string, + householdId: string, + policyId: string +): Promise { try { - return await fetchHouseholdCalculation(countryId, householdId, policyId); + return await fetchHouseholdCalculationWithBundle(countryId, householdId, policyId); } catch (error) { if (error instanceof Error && /timed out/i.test(error.message)) { - return fetchHouseholdCalculation(countryId, householdId, policyId); + return fetchHouseholdCalculationWithBundle(countryId, householdId, policyId); } throw error; } @@ -486,27 +415,10 @@ async function calculateHousehold( } /** - * Creates the household and calculates it under the baseline and the - * reform at once. The API stores a new household on every call, even for - * identical inputs, so each run gets its own household ID. - */ -export async function runFlagshipHousehold({ - year, - input, - baselinePolicyId, - reformPolicyId, -}: RunFlagshipHouseholdArgs): Promise { - return runFlagshipHouseholdPayload({ - year, - payload: buildHouseholdPayload(input, year), - baselinePolicyId, - reformPolicyId, - }); -} - -/** - * The same run for a household built in full (the household builder's - * own model, any of its inputs), sent as the builder sends it. + * Creates the household, as the household builder sends it, and + * calculates it under the baseline and the reform at once, in the + * payload's own country. The API stores a new household on every call, + * even for identical inputs, so each run gets its own household ID. */ export async function runFlagshipHouseholdPayload({ year, @@ -526,25 +438,9 @@ export async function runFlagshipHouseholdPayload({ ); return { householdId, - baseline, - reform, - ...compareHouseholds(baseline, reform, year, payload.country_id), + baseline: baseline.result, + reform: reform.result, + provenance: { baseline: provenanceOf(baseline), reform: provenanceOf(reform) }, + ...compareHouseholds(baseline.result, reform.result, year, payload.country_id), }; } - -/** "Single · 2 children · $50,000 · California": the household a result is for. */ -export function describeHouseholdInput( - input: FlagshipHouseholdInput, - countryId: CountryId = 'us' -): string { - const money = (value: number) => formatCurrency(value, countryId, { maximumFractionDigits: 0 }); - const children = input.childAges.length; - return [ - input.married ? 'Married' : 'Single', - children === 0 ? 'no children' : children === 1 ? '1 child' : `${children} children`, - input.married - ? `${money(input.earnings)} and ${money(input.partnerEarnings)} earnings` - : `${money(input.earnings)} earnings`, - STATE_NAMES[input.state] ?? input.state, - ].join(' · '); -} diff --git a/app/src/libs/flagship/householdSuggestions.ts b/app/src/libs/flagship/householdSuggestions.ts index 8d5731e4a..184a482ef 100644 --- a/app/src/libs/flagship/householdSuggestions.ts +++ b/app/src/libs/flagship/householdSuggestions.ts @@ -37,10 +37,16 @@ export function suggestedHouseholdInputs( paths: string[], map: ParameterDependencyMap, inputs: Set, - limit: number = DEFAULT_LIMIT, - /** Inputs a household commonly has, listed ahead of the rest at any distance. */ - preferred: ReadonlySet = new Set(), - countryId: string = 'us' + /** The household's country: a US state program's own input is left out only in the US. */ + countryId: string, + { + limit = DEFAULT_LIMIT, + preferred = new Set(), + }: { + limit?: number; + /** Inputs a household commonly has, listed ahead of the rest at any distance. */ + preferred?: ReadonlySet; + } = {} ): string[] { // The variables the parameters feed, and the ones one step on. const start = variablesReachedByPaths(paths, map, 1).map((entry) => entry.variable); diff --git a/app/src/libs/flagship/householdVariableGroups.ts b/app/src/libs/flagship/householdVariableGroups.ts index 329b3705f..a875a2d43 100644 --- a/app/src/libs/flagship/householdVariableGroups.ts +++ b/app/src/libs/flagship/householdVariableGroups.ts @@ -181,7 +181,7 @@ const UK_DATASET_INPUTS = new RegExp( * microdata sets (ids, weights, take-up draws), inputs only the UK * dataset supplies, and inputs the model keeps only for old API callers. */ -export function describesAHousehold(variable: VariableInfo, countryId: string = 'us'): boolean { +export function describesAHousehold(variable: VariableInfo, countryId: string): boolean { const module = variable.moduleName ?? ''; return !( /^deprecated/i.test(variable.documentation ?? '') || diff --git a/app/src/libs/flagship/modelValidation.ts b/app/src/libs/flagship/modelValidation.ts index 012ec5e2d..b7d5208f5 100644 --- a/app/src/libs/flagship/modelValidation.ts +++ b/app/src/libs/flagship/modelValidation.ts @@ -203,7 +203,7 @@ export async function scorecardMatchesForPaths( ): Promise { let map; try { - map = await loadParameterDependencies(); + map = await loadParameterDependencies('us'); } catch { return null; } diff --git a/app/src/libs/flagship/parameterDependencies.ts b/app/src/libs/flagship/parameterDependencies.ts index 2fed365bb..2217b835c 100644 --- a/app/src/libs/flagship/parameterDependencies.ts +++ b/app/src/libs/flagship/parameterDependencies.ts @@ -1,16 +1,18 @@ /** * Parameter → variable dependency map, traced from the model. * - * `app/scripts/build-parameter-dependency-map.py` runs policyengine-us with - * core's FullTracer and records which variables read each parameter path - * and which variables consume each variable. This module answers the - * question the validation layer needs: given a reform's parameter paths, - * which model variables does it move, and how far downstream? Depth is the - * validation "ring": 0–1 is the primary variable, 2–4 the mechanism it - * feeds, deeper is incidental. + * `app/scripts/build-parameter-dependency-map.py` runs a country model + * (policyengine-us, or policyengine-uk) with core's FullTracer and records + * which variables read each parameter path and which variables consume + * each variable. This module answers the question the validation layer + * needs: given a reform's parameter paths, which model variables does it + * move, and how far downstream? Depth is the validation "ring": 0–1 is the + * primary variable, 2–4 the mechanism it feeds, deeper is incidental. The + * household section reads the same map upstream, for the inputs a reform + * makes worth filling in. * - * The JSON is loaded lazily — it is a few hundred kilobytes and only the - * validation surfaces need it. + * Each country's JSON is loaded lazily: the US map is over a megabyte and + * only the validation and household surfaces need one. */ export interface ParameterDependencyMap { @@ -124,26 +126,41 @@ export function variablesReachedByPaths( ); } +/** The countries with a traced map, each loaded only when first asked for. */ +const MAP_LOADERS: Record Promise<{ default: unknown }>> = { + us: () => import('@/data/flagship/parameterDependencies.json'), + uk: () => import('@/data/flagship/parameterDependencies.uk.json'), +}; + /** - * Whether a country has a traced map. The map is traced from - * policyengine-us only, so another country's reform paths would match - * US variables: such a country gets no map at all. + * Whether a country has a traced map. Each map is traced from its own + * country's model, so another country's reform paths never match it: a + * country without its own map gets none at all. */ export function hasParameterDependencies(countryId: string): boolean { - return countryId === 'us'; + return Object.hasOwn(MAP_LOADERS, countryId); } -let cached: Promise | null = null; +const cached = new Map>(); -/** The traced map for policyengine-us, loaded once per session. */ -export function loadParameterDependencies(): Promise { - if (!cached) { - cached = import('@/data/flagship/parameterDependencies.json').then( - (module) => module.default as ParameterDependencyMap - ); - cached.catch(() => { - cached = null; +/** + * A country's traced map, loaded once per session. Every caller names its + * country, so none is given the US map by default: the validation surfaces + * (calibration, scorecard, track record) ask for the US map, as their data + * is the US model's. + */ +export function loadParameterDependencies(countryId: string): Promise { + if (!hasParameterDependencies(countryId)) { + return Promise.reject(new Error(`No traced parameter map for ${countryId}.`)); + } + const loader = MAP_LOADERS[countryId]; + let map = cached.get(countryId); + if (!map) { + map = loader().then((module) => module.default as ParameterDependencyMap); + cached.set(countryId, map); + map.catch(() => { + cached.delete(countryId); }); } - return cached; + return map; } diff --git a/app/src/pages/report-output/earnings-variation/EarningsVariationSubPage.tsx b/app/src/pages/report-output/earnings-variation/EarningsVariationSubPage.tsx index 797ea45ae..f393941f7 100644 --- a/app/src/pages/report-output/earnings-variation/EarningsVariationSubPage.tsx +++ b/app/src/pages/report-output/earnings-variation/EarningsVariationSubPage.tsx @@ -40,8 +40,6 @@ interface Props { reformVariation?: HouseholdCalculationOutput | null; /** What shows while the variation calculates; a spinner and a line by default. */ renderLoading?: () => ReactNode; - /** Leave out the SPM methodology footnote under the chart; shown by default. */ - hideSpmFootnote?: boolean; } /** @@ -59,7 +57,6 @@ export default function EarningsVariationSubPage({ baselineVariation: providedBaselineVariation = null, reformVariation: providedReformVariation = null, renderLoading, - hideSpmFootnote = false, }: Props) { const [selectedVariable, setSelectedVariable] = useState('household_net_income'); const [searchOpen, setSearchOpen] = useState(false); @@ -387,12 +384,10 @@ export default function EarningsVariationSubPage({ year={normalizedReportYear} /> )} - {!hideSpmFootnote && ( - - )} + ); } diff --git a/app/src/pages/report-output/marginal-tax-rates/MarginalTaxRatesSubPage.tsx b/app/src/pages/report-output/marginal-tax-rates/MarginalTaxRatesSubPage.tsx index 867b6ac30..626ed2d1e 100644 --- a/app/src/pages/report-output/marginal-tax-rates/MarginalTaxRatesSubPage.tsx +++ b/app/src/pages/report-output/marginal-tax-rates/MarginalTaxRatesSubPage.tsx @@ -57,8 +57,6 @@ interface Props { reformVariation?: HouseholdCalculationOutput | null; /** What shows while the variation calculates; a spinner and a line by default. */ renderLoading?: () => ReactNode; - /** Leave out the SPM methodology footnote under the chart; shown by default. */ - hideSpmFootnote?: boolean; /** Name the country's currency in the explainer ("next pound" in the UK); "dollar" by default. */ currencyAwareText?: boolean; } @@ -110,7 +108,6 @@ export default function MarginalTaxRatesSubPage({ baselineVariation: providedBaselineVariation = null, reformVariation: providedReformVariation = null, renderLoading, - hideSpmFootnote = false, currencyAwareText = false, }: Props) { const [viewMode, setViewMode] = useState('both'); @@ -514,12 +511,10 @@ export default function MarginalTaxRatesSubPage({ {renderChart()}
- {!hideSpmFootnote && ( - - )} + ); } diff --git a/app/src/tests/fixtures/components/flagship/report/householdSuggestionMocks.ts b/app/src/tests/fixtures/components/flagship/report/householdSuggestionMocks.ts new file mode 100644 index 000000000..871ef7f68 --- /dev/null +++ b/app/src/tests/fixtures/components/flagship/report/householdSuggestionMocks.ts @@ -0,0 +1,46 @@ +import type { VariableInfo } from '@/utils/VariableResolver'; + +/** Universal Credit's child element: a UK reform's parameter. */ +export const UK_CHILD_ELEMENT_PATH = 'gov.dwp.universal_credit.elements.child.amount'; + +/** The Child Tax Credit's base amount: a US reform's parameter. */ +export const US_CTC_BASE_PATH = 'gov.irs.credits.ctc.amount.base'; + +function ukInput(name: string, entity: string, documentation?: string): VariableInfo { + return { + name, + label: name.replaceAll('_', ' '), + entity, + valueType: 'float', + defaultValue: 0, + isInputVariable: true, + hiddenInput: false, + // The UK model files no input under a module. + moduleName: '', + documentation, + }; +} + +/** + * UK inputs as the model's metadata lists them: some a reader describes a + * household with, and one only the microdata sets (a public-spending + * imputation), which the household section never suggests. + */ +export const UK_INPUT_VARIABLES: VariableInfo[] = [ + ukInput('age', 'person'), + ukInput('employment_income', 'person'), + ukInput('childcare_expenses', 'person'), + ukInput('is_disabled_for_benefits', 'person'), + ukInput('rent', 'household'), + ukInput('region', 'household'), + ukInput('dfe_education_spending', 'person'), +]; + +export const UK_HOUSEHOLD_INPUT_NAMES = new Set( + UK_INPUT_VARIABLES.filter((variable) => variable.name !== 'dfe_education_spending').map( + (variable) => variable.name + ) +); + +/** An input only the microdata sets, which the UK map reaches from the child element. */ +export const UK_MICRODATA_ONLY_INPUT = 'dfe_education_spending'; diff --git a/app/src/tests/fixtures/libs/flagship/householdRunMocks.ts b/app/src/tests/fixtures/libs/flagship/householdRunMocks.ts index 8be39f781..1a8c0d8cf 100644 --- a/app/src/tests/fixtures/libs/flagship/householdRunMocks.ts +++ b/app/src/tests/fixtures/libs/flagship/householdRunMocks.ts @@ -1,5 +1,8 @@ -import type { FlagshipHouseholdInput } from '@/libs/flagship/householdRun'; +import type { HouseholdCalculationResult } from '@/api/householdCalculation'; +import type { PolicyEngineBundle } from '@/api/societyWideCalculation'; +import { Household } from '@/models/Household'; import type { HouseholdCalculationData } from '@/types/calculation/household'; +import type { SPMSelection } from '@/types/spm'; export const HOUSEHOLD_YEAR = '2026'; export const BASELINE_POLICY_ID = '2'; @@ -8,13 +11,36 @@ export const CUSTOM_BASELINE_POLICY_ID = '45678'; export const REFORM_POLICY_ID = '98765'; export const CREATED_HOUSEHOLD_ID = 54321; -export const MARRIED_TWO_CHILDREN: FlagshipHouseholdInput = { - state: 'NY', - married: true, - childAges: [4, 12], - earnings: 60000, - partnerEarnings: 25000, +/** The .py bundle a calculation response names (synthetic versions, never published pins). */ +export const BASELINE_RUN_BUNDLE: PolicyEngineBundle = { + policyengine_version: '9.1.0', + model_version: '8.1.0', + data_version: null, + dataset: null, }; +export const REFORM_RUN_BUNDLE: PolicyEngineBundle = { + ...BASELINE_RUN_BUNDLE, + model_version: '8.2.0', +}; +/** The SPM settings a US calculation response echoes. */ +export const NATIONAL_SPM_CONFIG: SPMSelection = { geography_kind: 'national' }; + +/** One policy's calculation as the Public API's v1 household route answers it: the result and how it was made. */ +export function calculationResponse( + result: HouseholdCalculationData, + provenance: Omit = {} +): HouseholdCalculationResult { + return { result, policyengine_bundle: null, ...provenance }; +} + +/** A country whose household results v3 does not list (no rows of taxes and benefits). */ +export const COUNTRY_WITHOUT_HOUSEHOLD_RESULT_ROWS = 'ca'; + +/** A married couple with two children, as the household builder sends it to the Public API. */ +export const US_COUPLE_WITH_CHILDREN_PAYLOAD = Household.starter('us', HOUSEHOLD_YEAR) + .withBuilderMaritalStatus(HOUSEHOLD_YEAR, 'married') + .withBuilderChildCount(HOUSEHOLD_YEAR, 2) + .toV1CreationPayload(); interface ResultValues { netIncome: number; @@ -232,3 +258,44 @@ export const UK_FAMILY_REFORM_RESULT = ukHouseholdResult({ universalCredit: 20511.06, childBenefit: 2337.4, }); + +/** + * Issue #358's UK household, in the report's year: an adult earning £100 + * and a dependant aged 10 earning £10, in one benefit unit, with a BRMA, + * region and local authority that name different places. The Public API + * once failed to calculate it; policyengine-uk 2.130.1 calculates it. + */ +export const ISSUE_358_HOUSEHOLD = Household.fromV1CreationPayload({ + country_id: 'uk', + data: { + people: { + you: { age: at(40), employment_income: at(100) }, + 'your first dependent': { age: at(10), employment_income: at(10) }, + }, + benunits: { 'your benefit unit': { members: ['you', 'your first dependent'] } }, + households: { + 'your household': { + members: ['you', 'your first dependent'], + brma: at('AYLESBURY'), + region: at('NORTH_EAST'), + local_authority: at('ABERDEENSHIRE'), + }, + }, + }, +}); + +/** + * Issue #562's UK household: a couple and a child, built with the + * household builder's own controls, with an input set on the benefit unit + * (it opts out of Child Benefit) rather than on a person or the household. + */ +export const UK_COUPLE_WITH_BENEFIT_UNIT_INPUT = Household.starter('uk', HOUSEHOLD_YEAR) + .withBuilderMaritalStatus(HOUSEHOLD_YEAR, 'married') + .withBuilderChildCount(HOUSEHOLD_YEAR, 1) + .setGroupVariableAtYear( + 'benunits', + 'your benefit unit', + 'child_benefit_opts_out', + HOUSEHOLD_YEAR, + true + ); diff --git a/app/src/tests/unit/components/flagship/report/HouseholdImpactAnalytics.test.tsx b/app/src/tests/unit/components/flagship/report/HouseholdImpactAnalytics.test.tsx index ff313b57c..16799eed6 100644 --- a/app/src/tests/unit/components/flagship/report/HouseholdImpactAnalytics.test.tsx +++ b/app/src/tests/unit/components/flagship/report/HouseholdImpactAnalytics.test.tsx @@ -9,6 +9,7 @@ import { Household } from '@/models/Household'; import { BASELINE_POLICY_ID, BASELINE_RESULT, + calculationResponse, CREATED_HOUSEHOLD_ID, HOUSEHOLD_YEAR, REFORM_POLICY_ID, @@ -22,7 +23,8 @@ vi.mock('@/api/household', () => ({ createHousehold: (...args: unknown[]) => mockCreateHousehold(...args), })); vi.mock('@/api/householdCalculation', () => ({ - fetchHouseholdCalculation: (...args: unknown[]) => mockFetchHouseholdCalculation(...args), + fetchHouseholdCalculationWithBundle: async (...args: unknown[]) => + calculationResponse(await mockFetchHouseholdCalculation(...args)), })); /** An input value no event may carry. */ diff --git a/app/src/tests/unit/components/flagship/report/HouseholdImpactResult.test.tsx b/app/src/tests/unit/components/flagship/report/HouseholdImpactResult.test.tsx new file mode 100644 index 000000000..a5b626b75 --- /dev/null +++ b/app/src/tests/unit/components/flagship/report/HouseholdImpactResult.test.tsx @@ -0,0 +1,102 @@ +import type { ComponentProps } from 'react'; +import { render, screen, userEvent } from '@test-utils'; +import { describe, expect, test, vi } from 'vitest'; +import HouseholdImpactResult from '@/components/flagship/report/household/HouseholdImpactResult'; +import { compareHouseholds } from '@/libs/flagship/householdRun'; +import { + BASELINE_POLICY_ID, + BASELINE_RESULT, + CREATED_HOUSEHOLD_ID, + HOUSEHOLD_YEAR, + NATIONAL_SPM_CONFIG, + REFORM_POLICY_ID, + REFORM_RESULT, + UK_BASELINE_RESULT, + UK_REFORM_RESULT, +} from '@/tests/fixtures/libs/flagship/householdRunMocks'; +import { SPM_RECEIPT } from '@/tests/fixtures/spm/spmMocks'; + +// The v2 breakdowns, tested on their own: a stand-in names the one shown. +vi.mock('@/components/flagship/report/household/HouseholdBreakdowns', async (importOriginal) => ({ + ...(await importOriginal< + typeof import('@/components/flagship/report/household/HouseholdBreakdowns') + >()), + default: ({ view }: { view: string }) =>
{view}
, +})); + +const UK_IMPACT = compareHouseholds(UK_BASELINE_RESULT, UK_REFORM_RESULT, HOUSEHOLD_YEAR, 'uk'); +const UK_SUMMARY = 'Single · no children · £30,000 earnings · 2026'; +const US_IMPACT = compareHouseholds(BASELINE_RESULT, REFORM_RESULT, HOUSEHOLD_YEAR, 'us'); +const NATIONAL_THRESHOLDS_PROVENANCE = { + policyengineBundle: null, + spmConfig: NATIONAL_SPM_CONFIG, + spmProvenance: SPM_RECEIPT, +}; + +function renderUSResultWithMethodology() { + render( + + ); +} + +const pointMethodology = () => + screen.queryByRole('region', { name: 'SPM point calculation methodology' }); + +describe('HouseholdImpactResult', () => { + test('given no country then the props do not type-check, so no result reads as the US', () => { + // @ts-expect-error The household's country is required: it sets the currency. + const propsWithoutCountry: ComponentProps = { + impact: UK_IMPACT, + summary: UK_SUMMARY, + }; + + expect(propsWithoutCountry).not.toHaveProperty('countryId'); + }); + + test('given a UK household then its change in net income reads in pounds', () => { + render(); + + expect(screen.getByRole('group', { name: 'Change in annual net income' })).toHaveTextContent( + '£' + ); + }); + + test('given SPM provenance then the methodology shows under the summary and the net income breakdown', async () => { + const user = userEvent.setup(); + renderUSResultWithMethodology(); + + expect(pointMethodology()).toBeInTheDocument(); + await user.click(screen.getByRole('tab', { name: 'Net income' })); + expect(pointMethodology()).toBeInTheDocument(); + }); + + test.each(['Varying earnings', 'Marginal tax rates'])( + 'given SPM provenance then %s shows its own variation methodology, not the point calculation', + async (tabName) => { + const user = userEvent.setup(); + renderUSResultWithMethodology(); + + await user.click(screen.getByRole('tab', { name: tabName })); + + expect(pointMethodology()).not.toBeInTheDocument(); + } + ); +}); diff --git a/app/src/tests/unit/components/flagship/report/HouseholdImpactSection.test.tsx b/app/src/tests/unit/components/flagship/report/HouseholdImpactSection.test.tsx index a38c05f03..b970d4ad3 100644 --- a/app/src/tests/unit/components/flagship/report/HouseholdImpactSection.test.tsx +++ b/app/src/tests/unit/components/flagship/report/HouseholdImpactSection.test.tsx @@ -10,16 +10,19 @@ import HouseholdImpactSection from '@/components/flagship/report/household/House import { BASELINE_POLICY_ID, BASELINE_RESULT, + calculationResponse, CREATED_HOUSEHOLD_ID, HOUSEHOLD_YEAR, LOW_EARNER_BASELINE_RESULT, LOW_EARNER_REFORM_RESULT, + NATIONAL_SPM_CONFIG, REFORM_POLICY_ID, REFORM_RESULT, REFORM_RESULT_LOSS, UK_BASELINE_RESULT, UK_REFORM_RESULT, } from '@/tests/fixtures/libs/flagship/householdRunMocks'; +import { SPM_RECEIPT } from '@/tests/fixtures/spm/spmMocks'; const mockCreateHousehold = vi.fn(); const mockFetchHouseholdCalculation = vi.fn(); @@ -27,8 +30,14 @@ const mockFetchHouseholdCalculation = vi.fn(); vi.mock('@/api/household', () => ({ createHousehold: (...args: unknown[]) => mockCreateHousehold(...args), })); +/** How each policy's calculation was made, as its response says it: nothing unless a test sets it. */ +const mockCalculationProvenance = vi.fn(); vi.mock('@/api/householdCalculation', () => ({ - fetchHouseholdCalculation: (...args: unknown[]) => mockFetchHouseholdCalculation(...args), + fetchHouseholdCalculationWithBundle: async (...args: unknown[]) => + calculationResponse( + await mockFetchHouseholdCalculation(...args), + mockCalculationProvenance(...args) + ), })); // Saving a calculated household to the user is tested on its own: here only @@ -41,19 +50,40 @@ vi.mock('@/hooks/useFlagshipHousehold', async (importOriginal) => ({ // The household builder is the v2 builder, tested on its own: here a stand-in // makes the same calls it makes, so the section's own work is what is tested. -vi.mock('@/components/household/HouseholdBuilderForm', () => ({ - default: ({ - household, - year, - maritalStatus, - numChildren, - onChange, - onMaritalStatusChange, - onNumChildrenChange, - variablePickerCommon, - personDisplayNameOf, - labelInputs, - }: any) => ( +vi.mock('@/components/household/HouseholdBuilderForm', async () => { + const { default: SPMGeographyChoice } = await import('@/components/household/SPMGeographyChoice'); + const { RESOLVED_CANONICAL_METADATA } = await import('@/tests/fixtures/spm/spmMocks'); + return { + default: (props: any) => ( + + ), + }; +}); + +/** The builder's stand-in: the real SPM choice, as the builder shows it, and the builder's own calls. */ +function HouseholdBuilderStandIn({ + household, + year, + maritalStatus, + numChildren, + onChange, + onMaritalStatusChange, + onNumChildrenChange, + variablePickerCommon, + personDisplayNameOf, + labelInputs, + SPMGeographyChoice, + spmMetadata, +}: any) { + return (
input.name).join(' ')} @@ -67,6 +97,12 @@ vi.mock('@/components/household/HouseholdBuilderForm', () => ({ ) .join(' ')} > + {`${maritalStatus} · ${numChildren}`} {String( @@ -90,8 +126,8 @@ vi.mock('@/components/household/HouseholdBuilderForm', () => ({ Partner earns 20000
- ), -})); + ); +} // The v2 breakdowns, tested on their own: a stand-in shows what each is given. vi.mock('@/components/flagship/report/household/HouseholdBreakdowns', async (importOriginal) => ({ ...(await importOriginal< @@ -119,7 +155,8 @@ function renderSection({ region, countryId = 'us', added = true, -}: { region?: string; countryId?: string; added?: boolean } = {}) { + reformPolicyId = REFORM_POLICY_ID, +}: { region?: string; countryId?: string; added?: boolean; reformPolicyId?: string } = {}) { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }); const view = render( @@ -128,7 +165,7 @@ function renderSection({ year={HOUSEHOLD_YEAR} region={region} baselinePolicyId={BASELINE_POLICY_ID} - reformPolicyId={REFORM_POLICY_ID} + reformPolicyId={reformPolicyId} /> ); @@ -150,6 +187,7 @@ function calculateWith(reformResult: typeof REFORM_RESULT) { describe('HouseholdImpactSection', () => { beforeEach(() => { vi.clearAllMocks(); + mockCalculationProvenance.mockReset(); mockCreateHousehold.mockResolvedValue({ result: { household_id: CREATED_HOUSEHOLD_ID } }); calculateWith(REFORM_RESULT); // Radix Select scrolls its options and captures the pointer, which jsdom lacks. @@ -247,6 +285,81 @@ describe('HouseholdImpactSection', () => { expect(JSON.stringify(sent)).toContain('national'); }); + test('given a US household then the SPM geography choice shows, on national thresholds', () => { + renderSection(); + + expect( + screen.getByRole('combobox', { name: 'Supplemental Poverty Measure geography' }) + ).toHaveValue('national'); + }); + + test('given local thresholds and a county then the household is sent with them', async () => { + const user = userEvent.setup(); + renderSection(); + + await user.selectOptions( + screen.getByRole('combobox', { name: 'Supplemental Poverty Measure geography' }), + 'county' + ); + await user.type(screen.getByRole('textbox', { name: /County FIPS code/ }), '06037'); + await user.click(screen.getByRole('button', { name: 'Calculate' })); + + await waitFor(() => expect(mockCreateHousehold).toHaveBeenCalledTimes(1)); + const sent = mockCreateHousehold.mock.calls[0][0]; + expect(sent.spm).toEqual({ geography_kind: 'county' }); + expect(sent.data.households['your household'].county_fips).toEqual({ + [HOUSEHOLD_YEAR]: '06037', + }); + }); + + test('given a calculation with SPM provenance then its methodology shows under the result', async () => { + const user = userEvent.setup(); + mockCalculationProvenance.mockReturnValue({ + spm_config: NATIONAL_SPM_CONFIG, + spm_provenance: SPM_RECEIPT, + }); + renderSection(); + + await user.click(screen.getByRole('button', { name: 'Calculate' })); + + const result = await screen.findByRole('region', { name: 'Household impact' }); + const methodology = within(result).getByRole('region', { + name: 'SPM point calculation methodology', + }); + expect(methodology).toHaveTextContent('Baseline · Point calculation · National thresholds'); + expect(methodology).toHaveTextContent('Reform · Point calculation · National thresholds'); + }); + + test('given the same policy as baseline and reform then its one calculation shows its methodology once', async () => { + const user = userEvent.setup(); + mockCalculationProvenance.mockReturnValue({ + spm_config: NATIONAL_SPM_CONFIG, + spm_provenance: SPM_RECEIPT, + }); + renderSection({ reformPolicyId: BASELINE_POLICY_ID }); + + await user.click(screen.getByRole('button', { name: 'Calculate' })); + + const result = await screen.findByRole('region', { name: 'Household impact' }); + const methodology = within(result).getByRole('region', { + name: 'SPM point calculation methodology', + }); + expect(methodology).toHaveTextContent('Baseline · Point calculation · National thresholds'); + expect(methodology).not.toHaveTextContent('Reform ·'); + }); + + test('given a calculation without SPM provenance then no methodology shows', async () => { + const user = userEvent.setup(); + renderSection(); + + await user.click(screen.getByRole('button', { name: 'Calculate' })); + + const result = await screen.findByRole('region', { name: 'Household impact' }); + expect( + within(result).queryByRole('region', { name: 'SPM point calculation methodology' }) + ).not.toBeInTheDocument(); + }); + test('given Calculate then the run shows its progress, then the change in net income', async () => { const user = userEvent.setup(); let finish!: () => void; @@ -590,6 +703,14 @@ describe('HouseholdImpactSection', () => { expect(result).not.toHaveTextContent('$'); }); + test('then no SPM geography choice shows', () => { + renderSection({ countryId: 'uk' }); + + expect( + screen.queryByRole('combobox', { name: 'Supplemental Poverty Measure geography' }) + ).not.toBeInTheDocument(); + }); + test("then the picker features the UK's inputs", () => { renderSection({ countryId: 'uk' }); const featured = screen diff --git a/app/src/tests/unit/components/flagship/report/HouseholdImpactSuggestions.test.tsx b/app/src/tests/unit/components/flagship/report/HouseholdImpactSuggestions.test.tsx new file mode 100644 index 000000000..f89ad425d --- /dev/null +++ b/app/src/tests/unit/components/flagship/report/HouseholdImpactSuggestions.test.tsx @@ -0,0 +1,76 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { render, screen, userEvent, waitFor } from '@test-utils'; +import { beforeEach, describe, expect, test, vi } from 'vitest'; +import HouseholdImpactSection from '@/components/flagship/report/household/HouseholdImpactSection'; +import { + UK_CHILD_ELEMENT_PATH, + UK_INPUT_VARIABLES, + UK_MICRODATA_ONLY_INPUT, +} from '@/tests/fixtures/components/flagship/report/householdSuggestionMocks'; +import { + BASELINE_POLICY_ID, + HOUSEHOLD_YEAR, + REFORM_POLICY_ID, +} from '@/tests/fixtures/libs/flagship/householdRunMocks'; + +// The model's inputs, as its metadata lists them. +vi.mock('@/utils/VariableResolver', async (importOriginal) => ({ + ...(await importOriginal()), + getInputVariables: () => UK_INPUT_VARIABLES, +})); +// The household builder, tested on its own: a stand-in shows the inputs it is asked to lead with. +vi.mock('@/components/household/HouseholdBuilderForm', () => ({ + default: ({ suggestedVariables }: { suggestedVariables?: string[] }) => ( +
+ ), +})); +vi.mock('@/utils/HouseholdValidation', () => ({ + HouseholdValidation: { isReadyForSimulation: () => ({ isValid: true, errors: [] }) }, +})); + +function renderSection(countryId: string, reformPaths: string[]) { + const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }); + return render( + + + , + countryId + ); +} + +const suggestedInputs = () => + (screen.getByRole('generic', { name: 'Household builder' }).getAttribute('data-suggested') ?? '') + .split(' ') + .filter(Boolean); + +describe('HouseholdImpactSection suggestions', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + test("given a UK reform to Universal Credit's child element then the inputs it reads are suggested", async () => { + const user = userEvent.setup(); + renderSection('uk', [UK_CHILD_ELEMENT_PATH]); + + await user.click(screen.getByRole('button', { name: 'Add a household' })); + + await waitFor(() => expect(suggestedInputs()).toContain('childcare_expenses')); + expect(suggestedInputs()).toContain('age'); + }); + + test('given a UK reform then an input only the microdata sets is never suggested', async () => { + const user = userEvent.setup(); + renderSection('uk', [UK_CHILD_ELEMENT_PATH]); + + await user.click(screen.getByRole('button', { name: 'Add a household' })); + + await waitFor(() => expect(suggestedInputs()).toContain('age')); + expect(suggestedInputs()).not.toContain(UK_MICRODATA_ONLY_INPUT); + }); +}); diff --git a/app/src/tests/unit/components/flagship/report/ReportViewHousehold.test.tsx b/app/src/tests/unit/components/flagship/report/ReportViewHousehold.test.tsx index 3bbf9ab9a..3fbf087fe 100644 --- a/app/src/tests/unit/components/flagship/report/ReportViewHousehold.test.tsx +++ b/app/src/tests/unit/components/flagship/report/ReportViewHousehold.test.tsx @@ -4,6 +4,7 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; import ReportView from '@/components/flagship/report/ReportView'; import { BASELINE_RESULT, + calculationResponse, CREATED_HOUSEHOLD_ID, CUSTOM_BASELINE_POLICY_ID, HOUSEHOLD_YEAR, @@ -21,7 +22,8 @@ vi.mock('@/api/household', () => ({ createHousehold: (...args: unknown[]) => mockCreateHousehold(...args), })); vi.mock('@/api/householdCalculation', () => ({ - fetchHouseholdCalculation: (...args: unknown[]) => mockFetchHouseholdCalculation(...args), + fetchHouseholdCalculationWithBundle: async (...args: unknown[]) => + calculationResponse(await mockFetchHouseholdCalculation(...args)), })); // The v2 household builder, tested on its own, stands in by its state. vi.mock('@/components/household/HouseholdBuilderForm', () => ({ diff --git a/app/src/tests/unit/components/flagship/report/UKHouseholdAcceptance.test.tsx b/app/src/tests/unit/components/flagship/report/UKHouseholdAcceptance.test.tsx new file mode 100644 index 000000000..025b66f39 --- /dev/null +++ b/app/src/tests/unit/components/flagship/report/UKHouseholdAcceptance.test.tsx @@ -0,0 +1,141 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { render, screen, userEvent, waitFor, within } from '@test-utils'; +import { beforeEach, describe, expect, test, vi } from 'vitest'; +import HouseholdImpactSection from '@/components/flagship/report/household/HouseholdImpactSection'; +import type { Household } from '@/models/Household'; +import { + BASELINE_POLICY_ID, + calculationResponse, + CREATED_HOUSEHOLD_ID, + HOUSEHOLD_YEAR, + ISSUE_358_HOUSEHOLD, + REFORM_POLICY_ID, + UK_BASELINE_RESULT, + UK_COUPLE_WITH_BENEFIT_UNIT_INPUT, + UK_REFORM_RESULT, +} from '@/tests/fixtures/libs/flagship/householdRunMocks'; + +/** + * Acceptance checks for UK households in v3's report section, from issues + * #358 (a UK household the Public API once failed to calculate) and #562 (the + * UK household checklist: several people, an input on the benefit unit, + * the report's policies, the whole run). Saving and reusing a household + * (#562's second item) belongs to the standalone household report. + */ + +const mockCreateHousehold = vi.fn(); +const mockFetchHouseholdCalculation = vi.fn(); + +vi.mock('@/api/household', () => ({ + createHousehold: (...args: unknown[]) => mockCreateHousehold(...args), +})); +vi.mock('@/api/householdCalculation', () => ({ + fetchHouseholdCalculationWithBundle: async (...args: unknown[]) => + calculationResponse(await mockFetchHouseholdCalculation(...args)), +})); +// The household builder, tested on its own: a stand-in hands the section a +// household the builder can make, as its onChange does. +vi.mock('@/components/household/HouseholdBuilderForm', async () => { + const fixtures = await import('@/tests/fixtures/libs/flagship/householdRunMocks'); + return { + default: ({ onChange }: { onChange: (household: Household) => void }) => ( +
+ + +
+ ), + }; +}); +vi.mock('@/utils/HouseholdValidation', () => ({ + HouseholdValidation: { isReadyForSimulation: () => ({ isValid: true, errors: [] }) }, +})); + +async function calculateUKHousehold(describe: string) { + const user = userEvent.setup(); + const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }); + render( + + + , + 'uk' + ); + await user.click(screen.getByRole('button', { name: 'Add a household' })); + await user.click(screen.getByRole('button', { name: describe })); + await user.click(screen.getByRole('button', { name: 'Calculate' })); + await waitFor(() => expect(mockCreateHousehold).toHaveBeenCalledTimes(1)); + return mockCreateHousehold.mock.calls[0][0]; +} + +describe('UK households in the report section (issues #358 and #562)', () => { + beforeEach(() => { + vi.clearAllMocks(); + mockCreateHousehold.mockResolvedValue({ result: { household_id: CREATED_HOUSEHOLD_ID } }); + mockFetchHouseholdCalculation.mockImplementation( + async (_country: string, _household: string, policyId: string) => + policyId === BASELINE_POLICY_ID ? UK_BASELINE_RESULT : UK_REFORM_RESULT + ); + }); + + test("given issue 358's household then it is sent as described, and its result shows", async () => { + const sent = await calculateUKHousehold("Describe issue 358's household"); + + expect(sent).toEqual(ISSUE_358_HOUSEHOLD.toV1CreationPayload()); + expect(sent.data.benunits['your benefit unit'].members).toEqual([ + 'you', + 'your first dependent', + ]); + expect(sent.data.households['your household']).toMatchObject({ + brma: { [HOUSEHOLD_YEAR]: 'AYLESBURY' }, + region: { [HOUSEHOLD_YEAR]: 'NORTH_EAST' }, + local_authority: { [HOUSEHOLD_YEAR]: 'ABERDEENSHIRE' }, + }); + const result = await screen.findByRole('region', { name: 'Household impact' }); + expect( + within(result).getByRole('group', { name: 'Change in annual net income' }) + ).toHaveTextContent('+£500'); + }); + + test('given a couple and a child then all three share one benefit unit and one household', async () => { + const sent = await calculateUKHousehold('Describe a couple with a child'); + + const everyone = ['you', 'your partner', 'your first dependent']; + expect(Object.keys(sent.data.people)).toEqual(everyone); + expect(sent.data.benunits['your benefit unit'].members).toEqual(everyone); + expect(sent.data.households['your household'].members).toEqual(everyone); + }); + + test('given an input on the benefit unit then it is sent on the benefit unit', async () => { + const sent = await calculateUKHousehold('Describe a couple with a child'); + + expect(sent).toEqual(UK_COUPLE_WITH_BENEFIT_UNIT_INPUT.toV1CreationPayload()); + expect(sent.data.benunits['your benefit unit'].child_benefit_opts_out).toEqual({ + [HOUSEHOLD_YEAR]: true, + }); + expect(sent.data.households['your household'].child_benefit_opts_out).toBeUndefined(); + }); + + test("given a UK household then it runs under the report's two policies, in pounds", async () => { + await calculateUKHousehold('Describe a couple with a child'); + + await waitFor(() => + expect(mockFetchHouseholdCalculation.mock.calls).toEqual([ + ['uk', String(CREATED_HOUSEHOLD_ID), BASELINE_POLICY_ID], + ['uk', String(CREATED_HOUSEHOLD_ID), REFORM_POLICY_ID], + ]) + ); + const result = await screen.findByRole('region', { name: 'Household impact' }); + expect(within(result).getByRole('table', { name: 'Taxes and benefits' })).toHaveTextContent( + 'Income Tax' + ); + expect(result).not.toHaveTextContent('$'); + }); +}); diff --git a/app/src/tests/unit/components/household/HouseholdBuilderForm.test.tsx b/app/src/tests/unit/components/household/HouseholdBuilderForm.test.tsx index 50d7a7a6a..4f75ea5f9 100644 --- a/app/src/tests/unit/components/household/HouseholdBuilderForm.test.tsx +++ b/app/src/tests/unit/components/household/HouseholdBuilderForm.test.tsx @@ -40,11 +40,11 @@ describe('HouseholdBuilderForm', () => { expect(screen.getByRole('separator', { hidden: true })).toBeInTheDocument(); }); - test('given hideSpmGeography then the SPM choice is left out', () => { + test('given a request to hide the SPM choice then there is no such option, and the choice shows', () => { + // @ts-expect-error Every builder shows the SPM choice; it cannot be hidden. renderForm({ hideSpmGeography: true }); - expect(screen.queryByText('Supplemental Poverty Measure geography')).not.toBeInTheDocument(); - expect(screen.getByText('Marital status')).toBeInTheDocument(); + expect(screen.getByText('Supplemental Poverty Measure geography')).toBeInTheDocument(); }); test('given the columns layout then the number of children is typed, any whole number to 10', () => { diff --git a/app/src/tests/unit/libs/flagship/householdRun.test.ts b/app/src/tests/unit/libs/flagship/householdRun.test.ts index 95898cdaf..1161627ad 100644 --- a/app/src/tests/unit/libs/flagship/householdRun.test.ts +++ b/app/src/tests/unit/libs/flagship/householdRun.test.ts @@ -1,35 +1,35 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; import { - buildHouseholdPayload, compareHouseholds, - defaultHouseholdInput, - describeHouseholdInput, - isValidHouseholdInput, plainHouseholdError, readHouseholdTotal, - runFlagshipHousehold, runFlagshipHouseholdPayload, - stateFromRegion, } from '@/libs/flagship/householdRun'; import { Household } from '@/models/Household'; import { BASELINE_POLICY_ID, BASELINE_RESULT, + BASELINE_RUN_BUNDLE, + calculationResponse, + COUNTRY_WITHOUT_HOUSEHOLD_RESULT_ROWS, CREATED_HOUSEHOLD_ID, HOUSEHOLD_YEAR, householdResult, LOW_EARNER_BASELINE_RESULT, LOW_EARNER_REFORM_RESULT, - MARRIED_TWO_CHILDREN, + NATIONAL_SPM_CONFIG, REFORM_POLICY_ID, REFORM_RESULT, REFORM_RESULT_LOSS, REFORM_RESULT_WITH_REMAINDER, + REFORM_RUN_BUNDLE, UK_BASELINE_RESULT, UK_FAMILY_BASELINE_RESULT, UK_FAMILY_REFORM_RESULT, UK_REFORM_RESULT, + US_COUPLE_WITH_CHILDREN_PAYLOAD, } from '@/tests/fixtures/libs/flagship/householdRunMocks'; +import { SPM_RECEIPT } from '@/tests/fixtures/spm/spmMocks'; const mockCreateHousehold = vi.fn(); const mockFetchHouseholdCalculation = vi.fn(); @@ -37,89 +37,16 @@ const mockFetchHouseholdCalculation = vi.fn(); vi.mock('@/api/household', () => ({ createHousehold: (...args: unknown[]) => mockCreateHousehold(...args), })); +/** How each policy's calculation was made, as its response says it: nothing unless a test sets it. */ +const mockCalculationProvenance = vi.fn(); vi.mock('@/api/householdCalculation', () => ({ - fetchHouseholdCalculation: (...args: unknown[]) => mockFetchHouseholdCalculation(...args), + fetchHouseholdCalculationWithBundle: async (...args: unknown[]) => + calculationResponse( + await mockFetchHouseholdCalculation(...args), + mockCalculationProvenance(...args) + ), })); -describe('defaultHouseholdInput', () => { - test('given a nationwide report then the household is single, childless, in California', () => { - expect(defaultHouseholdInput()).toEqual({ - state: 'CA', - married: false, - childAges: [], - earnings: 50000, - partnerEarnings: 0, - }); - }); - - test("given a state or district report then the household starts in that report's state", () => { - expect(defaultHouseholdInput('state/ny').state).toBe('NY'); - expect(defaultHouseholdInput('congressional_district/TX-07').state).toBe('TX'); - }); - - test('given a region that is not a state then no state is read from it', () => { - expect(stateFromRegion('us')).toBeUndefined(); - expect(stateFromRegion('state/zz')).toBeUndefined(); - }); -}); - -describe('isValidHouseholdInput', () => { - test('given the default household then it can run', () => { - expect(isValidHouseholdInput(defaultHouseholdInput())).toBe(true); - }); - - test('given negative or missing earnings or an adult child then it cannot run', () => { - const base = defaultHouseholdInput(); - expect(isValidHouseholdInput({ ...base, earnings: -1 })).toBe(false); - expect(isValidHouseholdInput({ ...base, earnings: Number.NaN })).toBe(false); - expect(isValidHouseholdInput({ ...base, childAges: [18] })).toBe(false); - expect(isValidHouseholdInput({ ...base, childAges: [2.5] })).toBe(false); - }); - - test("given a single household then the partner's earnings are not read", () => { - expect(isValidHouseholdInput({ ...defaultHouseholdInput(), partnerEarnings: Number.NaN })).toBe( - true - ); - }); -}); - -describe('buildHouseholdPayload', () => { - test('given a married couple with two children then every person carries the year', () => { - const payload = buildHouseholdPayload(MARRIED_TWO_CHILDREN, HOUSEHOLD_YEAR); - const people = payload.data.people; - - expect(payload.country_id).toBe('us'); - // The API reads the year to calculate from "you"'s age. - expect(people.you.age).toEqual({ [HOUSEHOLD_YEAR]: 30 }); - expect(people.you.employment_income).toEqual({ [HOUSEHOLD_YEAR]: 60000 }); - expect(people['your partner'].employment_income).toEqual({ [HOUSEHOLD_YEAR]: 25000 }); - expect(people['your first dependent'].age).toEqual({ [HOUSEHOLD_YEAR]: 4 }); - expect(people['your second dependent'].age).toEqual({ [HOUSEHOLD_YEAR]: 12 }); - expect(people['your second dependent'].is_tax_unit_dependent).toEqual({ - [HOUSEHOLD_YEAR]: true, - }); - }); - - test('given a state then the household lives there', () => { - const payload = buildHouseholdPayload(MARRIED_TWO_CHILDREN, HOUSEHOLD_YEAR); - - expect(payload.data.households?.['your household'].state_name).toEqual({ - [HOUSEHOLD_YEAR]: 'NY', - }); - expect(payload.data.marital_units?.['your marital unit'].members).toEqual([ - 'you', - 'your partner', - ]); - }); - - test('given a single adult then the household has one person', () => { - const payload = buildHouseholdPayload(defaultHouseholdInput(), HOUSEHOLD_YEAR); - - expect(Object.keys(payload.data.people)).toEqual(['you']); - expect(payload.data.tax_units?.['your tax unit'].members).toEqual(['you']); - }); -}); - describe('readHouseholdTotal', () => { test('given a variable in the API result then its year value is read', () => { expect(readHouseholdTotal(BASELINE_RESULT, 'tax_units', 'income_tax', HOUSEHOLD_YEAR)).toBe( @@ -138,7 +65,7 @@ describe('readHouseholdTotal', () => { describe('compareHouseholds', () => { test('given a federal tax cut then net income and the tax line both show it', () => { - const impact = compareHouseholds(BASELINE_RESULT, REFORM_RESULT, HOUSEHOLD_YEAR); + const impact = compareHouseholds(BASELINE_RESULT, REFORM_RESULT, HOUSEHOLD_YEAR, 'us'); expect(impact.netIncome).toEqual({ baseline: 72000, reform: 73000, change: 1000 }); expect(impact.components).toEqual([ @@ -154,7 +81,7 @@ describe('compareHouseholds', () => { }); test('given a bigger Child Tax Credit then the credit is listed and unchanged ones are not', () => { - const impact = compareHouseholds(BASELINE_RESULT, REFORM_RESULT, HOUSEHOLD_YEAR); + const impact = compareHouseholds(BASELINE_RESULT, REFORM_RESULT, HOUSEHOLD_YEAR, 'us'); expect(impact.programs.map((line) => [line.label, line.change])).toEqual([ ['Child Tax Credit', 1000], @@ -165,7 +92,8 @@ describe('compareHouseholds', () => { const impact = compareHouseholds( LOW_EARNER_BASELINE_RESULT, LOW_EARNER_REFORM_RESULT, - HOUSEHOLD_YEAR + HOUSEHOLD_YEAR, + 'us' ); expect(impact.netIncome.change).toBe(0); @@ -182,7 +110,8 @@ describe('compareHouseholds', () => { ctcValue: 1500, grossCtc: 6000, }), - HOUSEHOLD_YEAR + HOUSEHOLD_YEAR, + 'us' ); expect(impact.programs).toEqual([ @@ -198,7 +127,12 @@ describe('compareHouseholds', () => { }); test('given net income moving beyond the listed parts then the rest is "Other"', () => { - const impact = compareHouseholds(BASELINE_RESULT, REFORM_RESULT_WITH_REMAINDER, HOUSEHOLD_YEAR); + const impact = compareHouseholds( + BASELINE_RESULT, + REFORM_RESULT_WITH_REMAINDER, + HOUSEHOLD_YEAR, + 'us' + ); expect(impact.components.at(-1)).toEqual({ id: 'other', @@ -211,7 +145,7 @@ describe('compareHouseholds', () => { }); test('given a tax rise and a benefit cut then both read as losses', () => { - const impact = compareHouseholds(BASELINE_RESULT, REFORM_RESULT_LOSS, HOUSEHOLD_YEAR); + const impact = compareHouseholds(BASELINE_RESULT, REFORM_RESULT_LOSS, HOUSEHOLD_YEAR, 'us'); expect(impact.netIncome.change).toBe(-900); expect(impact.components.map((line) => [line.id, line.effect])).toEqual([ @@ -222,7 +156,7 @@ describe('compareHouseholds', () => { }); test('given the same result twice then nothing changes', () => { - const impact = compareHouseholds(BASELINE_RESULT, BASELINE_RESULT, HOUSEHOLD_YEAR); + const impact = compareHouseholds(BASELINE_RESULT, BASELINE_RESULT, HOUSEHOLD_YEAR, 'us'); expect(impact.netIncome.change).toBe(0); expect(impact.components).toEqual([]); @@ -234,10 +168,21 @@ describe('compareHouseholds', () => { delete (missing.households as Record>)['your household'] .household_net_income; - expect(() => compareHouseholds(BASELINE_RESULT, missing, HOUSEHOLD_YEAR)).toThrow( + expect(() => compareHouseholds(BASELINE_RESULT, missing, HOUSEHOLD_YEAR, 'us')).toThrow( `The result has no net income for ${HOUSEHOLD_YEAR}.` ); - expect(() => compareHouseholds(missing, BASELINE_RESULT, HOUSEHOLD_YEAR)).toThrow(); + expect(() => compareHouseholds(missing, BASELINE_RESULT, HOUSEHOLD_YEAR, 'us')).toThrow(); + }); + + test('given a country without household result rows then the comparison fails, not reads as the US', () => { + expect(() => + compareHouseholds( + BASELINE_RESULT, + REFORM_RESULT, + HOUSEHOLD_YEAR, + COUNTRY_WITHOUT_HOUSEHOLD_RESULT_ROWS + ) + ).toThrow(`Household results are not available for ${COUNTRY_WITHOUT_HOUSEHOLD_RESULT_ROWS}.`); }); }); @@ -321,9 +266,17 @@ describe('runFlagshipHouseholdPayload for the UK', () => { }); }); -describe('runFlagshipHousehold', () => { +describe('runFlagshipHouseholdPayload', () => { + const runArgs = { + year: HOUSEHOLD_YEAR, + payload: US_COUPLE_WITH_CHILDREN_PAYLOAD, + baselinePolicyId: BASELINE_POLICY_ID, + reformPolicyId: REFORM_POLICY_ID, + }; + beforeEach(() => { vi.clearAllMocks(); + mockCalculationProvenance.mockReset(); mockCreateHousehold.mockResolvedValue({ result: { household_id: CREATED_HOUSEHOLD_ID } }); mockFetchHouseholdCalculation.mockImplementation( async (_country: string, _household: string, policyId: string) => @@ -332,16 +285,9 @@ describe('runFlagshipHousehold', () => { }); test('given a household then it is created once and calculated under both policies', async () => { - const run = await runFlagshipHousehold({ - year: HOUSEHOLD_YEAR, - input: MARRIED_TWO_CHILDREN, - baselinePolicyId: BASELINE_POLICY_ID, - reformPolicyId: REFORM_POLICY_ID, - }); + const run = await runFlagshipHouseholdPayload(runArgs); - expect(mockCreateHousehold).toHaveBeenCalledWith( - buildHouseholdPayload(MARRIED_TWO_CHILDREN, HOUSEHOLD_YEAR) - ); + expect(mockCreateHousehold).toHaveBeenCalledWith(US_COUPLE_WITH_CHILDREN_PAYLOAD); expect(mockFetchHouseholdCalculation.mock.calls).toEqual([ ['us', String(CREATED_HOUSEHOLD_ID), BASELINE_POLICY_ID], ['us', String(CREATED_HOUSEHOLD_ID), REFORM_POLICY_ID], @@ -354,10 +300,8 @@ describe('runFlagshipHousehold', () => { }); test('given the same policy as baseline and reform then it is calculated once', async () => { - const run = await runFlagshipHousehold({ - year: HOUSEHOLD_YEAR, - input: MARRIED_TWO_CHILDREN, - baselinePolicyId: BASELINE_POLICY_ID, + const run = await runFlagshipHouseholdPayload({ + ...runArgs, reformPolicyId: BASELINE_POLICY_ID, }); @@ -365,33 +309,69 @@ describe('runFlagshipHousehold', () => { expect(run.netIncome.change).toBe(0); }); + test('given each response names its .py bundle and SPM provenance then the run keeps them per policy', async () => { + mockCalculationProvenance.mockImplementation( + (_country: string, _household: string, policyId: string) => ({ + policyengine_bundle: + policyId === BASELINE_POLICY_ID ? BASELINE_RUN_BUNDLE : REFORM_RUN_BUNDLE, + spm_config: NATIONAL_SPM_CONFIG, + spm_provenance: SPM_RECEIPT, + }) + ); + + const run = await runFlagshipHouseholdPayload(runArgs); + + expect(run.provenance).toEqual({ + baseline: { + policyengineBundle: BASELINE_RUN_BUNDLE, + spmConfig: NATIONAL_SPM_CONFIG, + spmProvenance: SPM_RECEIPT, + }, + reform: { + policyengineBundle: REFORM_RUN_BUNDLE, + spmConfig: NATIONAL_SPM_CONFIG, + spmProvenance: SPM_RECEIPT, + }, + }); + }); + + test('given one calculation for both policies then the reform reads its provenance', async () => { + mockCalculationProvenance.mockReturnValue({ policyengine_bundle: BASELINE_RUN_BUNDLE }); + + const run = await runFlagshipHouseholdPayload({ + ...runArgs, + reformPolicyId: BASELINE_POLICY_ID, + }); + + expect(run.provenance.reform).toEqual(run.provenance.baseline); + expect(run.provenance.reform.policyengineBundle).toEqual(BASELINE_RUN_BUNDLE); + }); + + test('given responses without a bundle or SPM provenance then the run says none, not a guess', async () => { + const run = await runFlagshipHouseholdPayload(runArgs); + + expect(run.provenance.baseline).toEqual({ policyengineBundle: null }); + expect(run.provenance.reform).toEqual({ policyengineBundle: null }); + }); + test('given a calculation failure then the run fails with it', async () => { mockFetchHouseholdCalculation.mockRejectedValue(new Error('Household calculation failed')); - await expect( - runFlagshipHousehold({ - year: HOUSEHOLD_YEAR, - input: MARRIED_TWO_CHILDREN, - baselinePolicyId: BASELINE_POLICY_ID, - reformPolicyId: REFORM_POLICY_ID, - }) - ).rejects.toThrow('Household calculation failed'); + await expect(runFlagshipHouseholdPayload(runArgs)).rejects.toThrow( + 'Household calculation failed' + ); }); test('given a timeout or a network failure then the run fails in plain words', async () => { - const args = { - year: HOUSEHOLD_YEAR, - input: MARRIED_TWO_CHILDREN, - baselinePolicyId: BASELINE_POLICY_ID, - reformPolicyId: REFORM_POLICY_ID, - }; mockFetchHouseholdCalculation.mockRejectedValue( new Error('Household calculation timed out after 50 seconds (client-side timeout)') ); - await expect(runFlagshipHousehold(args)).rejects.toThrow('The calculation took too long.'); + await expect(runFlagshipHouseholdPayload(runArgs)).rejects.toThrow( + 'The calculation took too long.' + ); mockCreateHousehold.mockRejectedValue(new TypeError('Failed to fetch')); - await expect(runFlagshipHousehold(args)).rejects.toThrow( + await expect(runFlagshipHouseholdPayload(runArgs)).rejects.toThrow( 'Could not reach PolicyEngine. Check your connection.' ); }); @@ -410,20 +390,3 @@ describe('plainHouseholdError', () => { expect(plainHouseholdError(error).cause).toBe(error); }); }); - -describe('describeHouseholdInput', () => { - test('given a household then it reads as one short line', () => { - expect(describeHouseholdInput(MARRIED_TWO_CHILDREN)).toBe( - 'Married · 2 children · $60,000 and $25,000 earnings · New York' - ); - expect(describeHouseholdInput(defaultHouseholdInput())).toBe( - 'Single · no children · $50,000 earnings · California' - ); - }); - - test('given the UK then amounts read in pounds', () => { - expect(describeHouseholdInput(MARRIED_TWO_CHILDREN, 'uk')).toContain( - '£60,000 and £25,000 earnings' - ); - }); -}); diff --git a/app/src/tests/unit/libs/flagship/householdSuggestions.test.ts b/app/src/tests/unit/libs/flagship/householdSuggestions.test.ts index 15cc1f033..ce2edb100 100644 --- a/app/src/tests/unit/libs/flagship/householdSuggestions.test.ts +++ b/app/src/tests/unit/libs/flagship/householdSuggestions.test.ts @@ -1,6 +1,13 @@ import { describe, expect, test } from 'vitest'; import { suggestedHouseholdInputs } from '@/libs/flagship/householdSuggestions'; -import type { ParameterDependencyMap } from '@/libs/flagship/parameterDependencies'; +import { + loadParameterDependencies, + type ParameterDependencyMap, +} from '@/libs/flagship/parameterDependencies'; +import { + UK_CHILD_ELEMENT_PATH, + UK_HOUSEHOLD_INPUT_NAMES, +} from '@/tests/fixtures/components/flagship/report/householdSuggestionMocks'; const MAP = { generatedAt: '', @@ -38,13 +45,13 @@ const INPUTS = new Set([ describe('suggestedHouseholdInputs', () => { test('given a SNAP parameter then the inputs SNAP reads lead, nearest first', () => { expect( - suggestedHouseholdInputs(['gov.usda.snap.emergency_allotment.allowed'], MAP, INPUTS) + suggestedHouseholdInputs(['gov.usda.snap.emergency_allotment.allowed'], MAP, INPUTS, 'us') ).toEqual(['childcare_expenses', 'employment_income', 'rent']); }); test('given inputs only downstream of the change then they are not suggested', () => { expect( - suggestedHouseholdInputs(['gov.usda.snap.emergency_allotment.allowed'], MAP, INPUTS) + suggestedHouseholdInputs(['gov.usda.snap.emergency_allotment.allowed'], MAP, INPUTS, 'us') ).not.toContain('capital_gains'); }); @@ -52,7 +59,8 @@ describe('suggestedHouseholdInputs', () => { const suggested = suggestedHouseholdInputs( ['gov.usda.snap.emergency_allotment.allowed'], MAP, - INPUTS + INPUTS, + 'us' ); expect(suggested).not.toContain('household_weight'); expect(suggested).not.toContain('snap_reported'); @@ -60,7 +68,7 @@ describe('suggestedHouseholdInputs', () => { }); test('given a parameter the map does not trace then nothing is suggested', () => { - expect(suggestedHouseholdInputs(['gov.irs.unknown'], MAP, INPUTS)).toEqual([]); + expect(suggestedHouseholdInputs(['gov.irs.unknown'], MAP, INPUTS, 'us')).toEqual([]); }); test('given a state prefix then it is a US state program only in the US', () => { @@ -71,15 +79,40 @@ describe('suggestedHouseholdInputs', () => { const inputs = new Set([...INPUTS, 'in_FE']); const paths = ['gov.usda.snap.emergency_allotment.allowed']; - expect(suggestedHouseholdInputs(paths, map, inputs)).not.toContain('in_FE'); - expect(suggestedHouseholdInputs(paths, map, inputs, undefined, new Set(), 'uk')).toContain( - 'in_FE' - ); + expect(suggestedHouseholdInputs(paths, map, inputs, 'us')).not.toContain('in_FE'); + expect(suggestedHouseholdInputs(paths, map, inputs, 'uk')).toContain('in_FE'); }); test('given a limit then only that many are suggested', () => { expect( - suggestedHouseholdInputs(['gov.usda.snap.emergency_allotment.allowed'], MAP, INPUTS, 1) + suggestedHouseholdInputs(['gov.usda.snap.emergency_allotment.allowed'], MAP, INPUTS, 'us', { + limit: 1, + }) ).toEqual(['childcare_expenses']); }); }); + +describe('suggestedHouseholdInputs without a country', () => { + test('given no country then the call does not type-check, so no country is read as the US', () => { + expect( + // @ts-expect-error Every caller names the household's country. + suggestedHouseholdInputs(['gov.usda.snap.emergency_allotment.allowed'], MAP, INPUTS) + ).toBeDefined(); + }); +}); + +describe('suggestedHouseholdInputs for the UK', () => { + test("given a change to Universal Credit's child element then a child's age and childcare lead", async () => { + const map = await loadParameterDependencies('uk'); + + const suggested = suggestedHouseholdInputs( + [UK_CHILD_ELEMENT_PATH], + map, + UK_HOUSEHOLD_INPUT_NAMES, + 'uk' + ); + + expect(suggested).toContain('age'); + expect(suggested).toContain('childcare_expenses'); + }); +}); diff --git a/app/src/tests/unit/libs/flagship/householdVariableGroups.test.ts b/app/src/tests/unit/libs/flagship/householdVariableGroups.test.ts index 3429a1e8b..6f12d2cc5 100644 --- a/app/src/tests/unit/libs/flagship/householdVariableGroups.test.ts +++ b/app/src/tests/unit/libs/flagship/householdVariableGroups.test.ts @@ -78,37 +78,50 @@ describe('describesAHousehold', () => { const input = (name: string, moduleName: string, documentation?: string) => ({ name, label: name, moduleName, documentation }) as VariableInfo; + test('given no country then the call does not type-check, so no country is read as the US', () => { + // @ts-expect-error Every caller names the household's country. + expect(describesAHousehold(input('rent', 'household.expense.housing.rent'))).toBe(true); + }); + test('given survey totals, incidence inputs or deprecated inputs then they are left out', () => { expect( - describesAHousehold(input('spm_unit_snap', 'household.income.spm_unit.spm_unit_snap')) + describesAHousehold(input('spm_unit_snap', 'household.income.spm_unit.spm_unit_snap'), 'us') ).toBe(false); expect( - describesAHousehold(input('cbo_excise_tax', 'household.income.household.cbo_excise_tax')) + describesAHousehold( + input('cbo_excise_tax', 'household.income.household.cbo_excise_tax'), + 'us' + ) + ).toBe(false); + expect( + describesAHousehold(input('ssi_reported', 'household.income.person.ssi_reported'), 'us') ).toBe(false); - expect(describesAHousehold(input('ssi_reported', 'household.income.person.ssi_reported'))).toBe( - false - ); expect( describesAHousehold( - input('use_reported_ssi', 'household.income.person.use_reported_ssi', 'Deprecated: …') + input('use_reported_ssi', 'household.income.person.use_reported_ssi', 'Deprecated: …'), + 'us' ) ).toBe(false); }); test('given what a household is described by then it is kept', () => { - expect(describesAHousehold(input('rent', 'household.expense.housing.rent'))).toBe(true); - expect(describesAHousehold(input('tip_income', 'household.income.person.tip_income'))).toBe( - true - ); + expect(describesAHousehold(input('rent', 'household.expense.housing.rent'), 'us')).toBe(true); + expect( + describesAHousehold(input('tip_income', 'household.income.person.tip_income'), 'us') + ).toBe(true); }); test('given US ids and weights then they are left out, and the US inputs beside them kept', () => { expect( - describesAHousehold(input('tax_unit_id', 'household.demographic.identifiers.tax_unit_id')) + describesAHousehold( + input('tax_unit_id', 'household.demographic.identifiers.tax_unit_id'), + 'us' + ) ).toBe(false); expect( describesAHousehold( - input('household_weight', 'household.demographic.weights.household_weight') + input('household_weight', 'household.demographic.weights.household_weight'), + 'us' ) ).toBe(false); for (const [name, moduleName] of [ @@ -118,7 +131,7 @@ describe('describesAHousehold', () => { ['state_name', 'household.demographic.geographic.state.state_name'], ['pension_income', 'household.income.person.pension_income'], ]) { - expect(describesAHousehold(input(name, moduleName))).toBe(true); + expect(describesAHousehold(input(name, moduleName), 'us')).toBe(true); } }); diff --git a/app/src/tests/unit/libs/flagship/parameterDependencies.test.ts b/app/src/tests/unit/libs/flagship/parameterDependencies.test.ts index a045746d4..700809ed2 100644 --- a/app/src/tests/unit/libs/flagship/parameterDependencies.test.ts +++ b/app/src/tests/unit/libs/flagship/parameterDependencies.test.ts @@ -1,5 +1,7 @@ import { describe, expect, test } from 'vitest'; import { + hasParameterDependencies, + loadParameterDependencies, normalizeParameterPath, ParameterDependencyMap, readersOfPath, @@ -86,3 +88,40 @@ describe('variablesReachedByPaths', () => { expect(variablesReachedByPaths([STANDARD_DEDUCTION_PATH], map)).toEqual([]); }); }); + +describe('each country has its own traced map', () => { + test.each(['us', 'uk'])('given %s then it has a traced map', (countryId) => { + expect(hasParameterDependencies(countryId)).toBe(true); + }); + + test('given a country without a traced model then it has none', () => { + expect(hasParameterDependencies('ca')).toBe(false); + }); + + test("given a name an object inherits then it is not a country's map", async () => { + expect(hasParameterDependencies('constructor')).toBe(false); + await expect(loadParameterDependencies('constructor')).rejects.toThrow( + 'No traced parameter map for constructor.' + ); + }); + + test("given the UK then the map is traced from policyengine-uk, with the UK's parameters", async () => { + const map = await loadParameterDependencies('uk'); + + expect(map.model.package).toBe('policyengine-uk'); + expect(readersOfPath('gov.dwp.universal_credit.elements.child.amount', map)).toContain( + 'uc_individual_child_element' + ); + }); + + test('given the US then the map is traced from policyengine-us, as the validation surfaces read it', async () => { + expect((await loadParameterDependencies('us')).model.package).toBe('policyengine-us'); + }); + + test('given no country then no map loads, so no caller is given the US map by default', async () => { + // @ts-expect-error Every caller names its country. + await expect(loadParameterDependencies()).rejects.toThrow( + 'No traced parameter map for undefined.' + ); + }); +});