Skip to content

Stop storing is_enhanced_disabled_for_benefits; map or flag AFIP #643

Open

Description

@MaxGhenis

What policyengine-uk-data stores

At policyengine-uk-data main (e1acdf96), add_disability_benefit_flags_from_reported_amounts (policyengine_uk_data/datasets/disability_benefits.py, line 216) stores:

person["is_enhanced_disabled_for_benefits"] = (
    (attendance_allowance >= aa_higher)
    | (dla_sc > dla_sc_higher)
    | (pip_dl >= pip_dl_enhanced)
)

Each threshold sits £1 a week below the top weekly rate (threshold_safety_gap, line 202). test_attendance_allowance_feeds_stronger_disability_flags (tests/test_disability_benefits.py, line 149) pins higher-rate attendance allowance as setting the flag.

The build maps FRS benefit codes to model inputs in BENEFIT_CODES (policyengine_uk_data/datasets/frs.py, line 1413): attendance allowance 12, DLA care 1, PIP daily living 96, the Armed Forces Compensation Scheme 8 and others. It maps no code to armed_forces_independence_payment, and nothing else in the repository writes that variable, so every record carries the model's default of £0.

What policyengine-uk does with them

policyengine-uk sets every dataset column that names a model variable as an input (policyengine_uk/simulation.py, the loop under "Load variable values for all years"), so in dataset runs the model uses the stored flag in place of is_enhanced_disabled_for_benefits's formula.

The fix for PolicyEngine/policyengine-uk#1971 (draft PolicyEngine/policyengine-uk#2808) turns the flag into a deprecated alias of receives_enhanced_disability_premium_qualifying_benefit. That variable reads the highest DLA care rate, the enhanced PIP daily living rate and AFIP from the stored award categories and armed_forces_independence_payment, following the Housing Benefit Regulations 2006 (Sch 3 para 15(1)). In that paragraph the Secretary of State lists limited capability for work-related activity, the highest DLA care rate, the enhanced PIP daily living rate, their Scottish equivalents and AFIP, but not attendance allowance. After the fix no premium formula reads the flag; the deprecated counts num_enhanced_disabled_adults and num_enhanced_disabled_children and outside callers still do.

The stored flag then differs from the model's own definition in three ways:

  • Higher-rate attendance allowance sets the stored flag but does not qualify a claimant for the enhanced disability premium.
  • The stored flag has no AFIP limb.
  • uk-data compares DLA care with a strict > where dla_sc_category uses >=; the two differ only when an award equals the threshold.

policyengine-uk reads AFIP in the severe disability premiums, the Housing Benefit child premiums, the Universal Credit and Housing Benefit benefit cap exemptions, Carer's Allowance's qualifying benefits, the Council Tax Reduction non-dependant exemption, the LHA shared accommodation exception and Pension Credit. A dataset run finds no AFIP recipient for any of them.

What to change

  1. Once uk-data's lock moves to the policyengine-uk release with the #1971 fix, stop writing is_enhanced_disabled_for_benefits, so the model derives it from the stored categories. Until then the model's premium formulas still read the flag. On policyengine-uk main (2da212abc), num_enhanced_disabled_claimants_or_partners_for_legacy_benefits and council_tax_reduction_premiums read it, and its formula counts only the highest DLA care rate, so if uk-data drops the column early, dataset runs move onto that narrower formula. Update the tests that pin the stored flag in tests/test_disability_benefits.py and tests/test_frs_only_imputation.py, and add a test that the saved person table has no such column. Draft PR Store the tax credit severe disability flag, not a mix of premium tests #494 edits the same function and test, so land this after it or with it.
  2. Confirm from the FRS 2024-25 benefits documentation whether any BENEFITS code identifies AFIP. In the description of Store the tax credit severe disability flag, not a mix of premium tests #494, its author reads the code frame as having none, with code 8 covering every Armed Forces Compensation Scheme and war disablement payment. If a code exists, map it to armed_forces_independence_payment. If none does, record AFIP as a known gap (every record £0) in the dataset documentation, or impute it from a published AFIP caseload and test the imputation against that source.
  3. Measure both changes with policyengine-uk runs on the new lock, and report how many people's flag changes. Under #1971's fix no premium formula reads the flag, so dropping the column should change no benefit amount.

PolicyEngine builds the default UK dataset in the policyengine.py bundle (microcosm_uk_2024_25) in PolicyEngine/microcosm. Its frs_disability.py (packages/microcosm-build/src/microcosm/build/uk_runtime/frs_disability.py, line 285, at 09a2fce5) stores the same flag with the same definition, and it writes no AFIP either. Port both changes there through the uk-data parity review in PolicyEngine/microcosm#1095.

Related: PolicyEngine/policyengine-uk#1971, #494, #481, #500.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions