diff --git a/changelog.d/added/ssa-disability-screen.md b/changelog.d/added/ssa-disability-screen.md new file mode 100644 index 00000000000..d2465484ea3 --- /dev/null +++ b/changelog.d/added/ssa-disability-screen.md @@ -0,0 +1 @@ +Added an SSA disability-screen variable for data-backed SSI disability modeling. diff --git a/changelog.d/fixed/ssi-disability-sga.md b/changelog.d/fixed/ssi-disability-sga.md index 97ad51f0902..c03e667fd88 100644 --- a/changelog.d/fixed/ssi-disability-sga.md +++ b/changelog.d/fixed/ssi-disability-sga.md @@ -1 +1 @@ -Keep the SSI substantial gainful activity screen separate from the data-backed SSI disability criteria variable. +Keep the SSI substantial gainful activity screen separate from the data-backed SSI disability criteria variable and preserve data-backed SSI disability criteria across future analysis years. diff --git a/policyengine_us/tests/core/test_ssi_disability_criteria_inputs.py b/policyengine_us/tests/core/test_ssi_disability_criteria_inputs.py new file mode 100644 index 00000000000..5676db14721 --- /dev/null +++ b/policyengine_us/tests/core/test_ssi_disability_criteria_inputs.py @@ -0,0 +1,36 @@ +from policyengine_us import Simulation + + +def test_data_provided_ssi_disability_criteria_carries_to_future_years(): + simulation = Simulation( + situation={ + "people": { + "person1": { + "is_disabled": {2024: False, 2026: False}, + "meets_ssi_disability_criteria": {2024: True}, + } + } + } + ) + + result = simulation.calculate("meets_ssi_disability_criteria", 2026) + + assert result[0] + + +def test_formula_derived_ssi_disability_criteria_allows_later_disabled_input(): + simulation = Simulation( + situation={ + "people": { + "person1": { + "is_disabled": {2024: False, 2026: True}, + } + } + } + ) + + assert not simulation.calculate("meets_ssi_disability_criteria", 2024)[0] + + result = simulation.calculate("meets_ssi_disability_criteria", 2026) + + assert result[0] diff --git a/policyengine_us/tests/policy/baseline/gov/ssa/ssi/meets_ssi_disability_criteria.yaml b/policyengine_us/tests/policy/baseline/gov/ssa/ssi/meets_ssi_disability_criteria.yaml index 16e917dc867..9db8d084b44 100644 --- a/policyengine_us/tests/policy/baseline/gov/ssa/ssi/meets_ssi_disability_criteria.yaml +++ b/policyengine_us/tests/policy/baseline/gov/ssa/ssi/meets_ssi_disability_criteria.yaml @@ -21,3 +21,19 @@ ssi_engaged_in_sga: false output: meets_ssi_disability_criteria: false + +- name: Data-provided SSI disability criteria can override broad disability + period: 2024 + input: + meets_ssi_disability_criteria: true + is_disabled: false + output: + meets_ssi_disability_criteria: true + +- name: Data-provided SSI disability criteria can exclude broad disability + period: 2024 + input: + meets_ssi_disability_criteria: false + is_disabled: true + output: + meets_ssi_disability_criteria: false diff --git a/policyengine_us/variables/gov/ssa/ssi/eligibility/status/meets_ssi_disability_criteria.py b/policyengine_us/variables/gov/ssa/ssi/eligibility/status/meets_ssi_disability_criteria.py index e8dc5b2ec28..bfebb585fc6 100644 --- a/policyengine_us/variables/gov/ssa/ssi/eligibility/status/meets_ssi_disability_criteria.py +++ b/policyengine_us/variables/gov/ssa/ssi/eligibility/status/meets_ssi_disability_criteria.py @@ -13,4 +13,23 @@ class meets_ssi_disability_criteria(Variable): reference = "https://www.law.cornell.edu/uscode/text/42/1382c#a_3_A" def formula(person, period, parameters): + holder = person.simulation.get_holder("meets_ssi_disability_criteria") + prior_periods = [ + known_period + for known_period in holder.get_known_periods() + if known_period.unit == YEAR and known_period.start < period.start + ] + if prior_periods: + latest_period = max( + prior_periods, key=lambda known_period: known_period.start + ) + latest_value = holder.get_array( + latest_period, person.simulation.branch_name + ) + latest_broad_disability = person("is_disabled", latest_period) + # Data-backed overrides should persist across analysis years; pure + # formula caches should not shadow later is_disabled inputs. + if not np.array_equal(latest_value, latest_broad_disability): + return None + return person("is_disabled", period)