diff --git a/changelog.d/nj-ssp-2026.added.md b/changelog.d/nj-ssp-2026.added.md new file mode 100644 index 00000000000..7a522b36c2a --- /dev/null +++ b/changelog.d/nj-ssp-2026.added.md @@ -0,0 +1 @@ +Add New Jersey state supplementary payments and the ineligible-spouse variation, verified for 2026. diff --git a/policyengine_us/parameters/gov/household/household_state_benefits.yaml b/policyengine_us/parameters/gov/household/household_state_benefits.yaml index d2cbd6ba2d4..4aa598b2d20 100644 --- a/policyengine_us/parameters/gov/household/household_state_benefits.yaml +++ b/policyengine_us/parameters/gov/household/household_state_benefits.yaml @@ -65,6 +65,8 @@ values: - ok_child_care_subsidies # South Carolina benefits - sc_child_care_subsidies + # New Jersey benefits + - nj_ssp # New Mexico benefits - nm_ssi_state_supplement # South Carolina benefits @@ -157,6 +159,8 @@ values: - nv_child_care_subsidies # Oklahoma benefits - ok_child_care_subsidies + # New Jersey benefits + - nj_ssp # New Mexico benefits - nm_ssi_state_supplement # South Carolina benefits @@ -259,6 +263,8 @@ values: - nv_child_care_subsidies # Oklahoma benefits - ok_child_care_subsidies + # New Jersey benefits + - nj_ssp # New Mexico benefits - nm_ssi_state_supplement # South Carolina benefits @@ -362,6 +368,8 @@ values: - nv_child_care_subsidies # Oklahoma benefits - ok_child_care_subsidies + # New Jersey benefits + - nj_ssp # New Mexico benefits - nm_ssi_state_supplement # South Carolina benefits @@ -401,6 +409,7 @@ values: - nj_property_tax_relief # New York benefits - ny_child_care_subsidies + metadata: unit: list period: year diff --git a/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml b/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml index 0df11213631..987c76494ce 100644 --- a/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/hud/annual_income/sources/unearned.yaml @@ -19,6 +19,7 @@ values: - strike_benefits - social_security - ssi + - nj_ssp - general_assistance - total_unemployment_compensation - child_support_received @@ -29,6 +30,7 @@ values: - disability_benefits - survivor_benefits - financial_assistance + metadata: unit: list period: year diff --git a/policyengine_us/parameters/gov/ssa/ssi/state_supplement/minimum_payment.yaml b/policyengine_us/parameters/gov/ssa/ssi/state_supplement/minimum_payment.yaml new file mode 100644 index 00000000000..1d3e6e2e6b6 --- /dev/null +++ b/policyengine_us/parameters/gov/ssa/ssi/state_supplement/minimum_payment.yaml @@ -0,0 +1,13 @@ +description: The Social Security Administration pays at least this monthly amount to each recipient of a positive federally administered optional state supplement. +values: + 2026-01-01: 1 + +metadata: + unit: currency-USD + period: month + label: SSI optional state supplement minimum payment + reference: + - title: 20 CFR 416.2020(c) - Minimum federally administered supplementary payment + href: https://www.ssa.gov/OP_Home/cfr20/416/416-2020.htm + - title: POMS SI 02001.005 A.2 and B.2 - Minimum benefit for individuals and members of couples + href: https://secure.ssa.gov/poms.nsf/lnx/0502001005 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ssp/amount/couple.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ssp/amount/couple.yaml new file mode 100644 index 00000000000..957485c6360 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ssp/amount/couple.yaml @@ -0,0 +1,36 @@ +description: New Jersey provides this amount as the monthly couple payment under the State Supplementary Payment program. + +metadata: + unit: currency-USD + period: month + label: New Jersey SSP couple payment rate + breakdown: + - nj_ssp_living_arrangement + reference: + - title: POMS SI 01415.058 J.2.b, New Jersey January 2026 couple payment levels + href: https://secure.ssa.gov/poms.nsf/lnx/0501415058#j2b + +LIVING_ALONE_OR_WITH_OTHERS: + 2026-01-01: 25.35 + +# SSA publishes no couple rate for code C (SI 01415.058 J.1). This placeholder +# repeats the B couple rate and never affects results: a claimant with an +# ineligible spouse is paid as an individual or, under deeming, at the higher +# individual rate (SI 01320.430 D.2.c). +LIVING_ONLY_WITH_INELIGIBLE_SPOUSE: + 2026-01-01: 25.35 + +CONGREGATE_CARE: + 2026-01-01: 618.35 + +RESIDENTIAL_HEALTH_CARE: + 2026-01-01: 738.35 + +HOUSEHOLD_OF_ANOTHER: + 2026-01-01: 93.08 + +MEDICAID_INSTITUTION: + 2026-01-01: 40 + +NONE: + 2026-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/ssp/amount/individual.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/ssp/amount/individual.yaml new file mode 100644 index 00000000000..214af0ffa08 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/ssp/amount/individual.yaml @@ -0,0 +1,32 @@ +description: New Jersey provides this amount as the monthly individual payment under the State Supplementary Payment program. + +metadata: + unit: currency-USD + period: month + label: New Jersey SSP individual payment rate + breakdown: + - nj_ssp_living_arrangement + reference: + - title: POMS SI 01415.058 J.2.a, New Jersey January 2026 individual payment levels + href: https://secure.ssa.gov/poms.nsf/lnx/0501415058#j2a + +LIVING_ALONE_OR_WITH_OTHERS: + 2026-01-01: 31.25 + +LIVING_ONLY_WITH_INELIGIBLE_SPOUSE: + 2026-01-01: 152.99 + +CONGREGATE_CARE: + 2026-01-01: 150.05 + +RESIDENTIAL_HEALTH_CARE: + 2026-01-01: 210.05 + +HOUSEHOLD_OF_ANOTHER: + 2026-01-01: 44.31 + +MEDICAID_INSTITUTION: + 2026-01-01: 20 + +NONE: + 2026-01-01: 0 diff --git a/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml index e9baee603e8..ea209473011 100644 --- a/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/usda/snap/income/sources/unearned.yaml @@ -46,6 +46,7 @@ values: - mn_msa_person - mo_ssp - ne_aabd + - nj_ssp - nm_ssi_state_supplement - sc_ssi_state_supplement - tx_ssi_state_supplement @@ -95,9 +96,7 @@ values: metadata: reference: - - title: 7 CFR 273.9(b)(2) - href: https://www.law.cornell.edu/cfr/text/7/273.9#b_2 - - title: 7 CFR 273.9(c)(1) - href: https://www.law.cornell.edu/cfr/text/7/273.9#c_1 + - title: 7 CFR 273.9(b)(2) and (c)(1) + href: https://www.law.cornell.edu/cfr/text/7/273.9 - title: POMS SI 01401.001 General Information about State Supplementation href: https://secure.ssa.gov/poms.nsf/lnx/0501401001 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 5250ab3aa89..85d9c243eac 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1093,6 +1093,17 @@ programs: tracks. Unmodeled paths: grandfathered medically-needy-in-medical- institution recipients per WAC 388-478-0055(2)(b); DDA-determined / PVL track per (2)(f); and foster child in BRS per (2)(g). + - state: NJ + status: partial + name: New Jersey SSP + full_name: New Jersey State Supplementary Payment + variable: nj_ssp + parameter_prefix: gov.states.nj.njdhs.ssp + verified_years: "2026" + notes: >- + Models 2026 New Jersey optional supplement rates by living + arrangement, including the ineligible-spouse variation. Mandatory + grandfathered supplementation is not modeled. - id: social_security name: Social Security diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ssp/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ssp/integration.yaml new file mode 100644 index 00000000000..025d58e702a --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ssp/integration.yaml @@ -0,0 +1,252 @@ +- name: Case 1, eligible couple rounds each half up. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 65 + person2: + age: 65 + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: &id001 [person1, person2] + households: + household: + members: *id001 + state_code: NJ + output: + nj_ssp: [12.68, 12.68] + +- name: Case 2, congregate care couple in a small household-scale facility. + period: 2026-01 + absolute_error_margin: 0.001 + # SI NY01415.025: couple status continues in a small Level 2 facility that + # is not an institution. + input: + people: + person1: + age: 65 + nj_ssp_care_setting: CONGREGATE_CARE + person2: + age: 65 + nj_ssp_care_setting: CONGREGATE_CARE + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: &id002 [person1, person2] + households: + household: + members: *id002 + state_code: NJ + output: + nj_ssp: [309.18, 309.18] + +- name: Case 3, special rate with only an ineligible spouse. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 65 + person2: + age: 40 + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: &id003 [person1, person2] + households: + household: + members: *id003 + state_code: NJ + output: + nj_ssp: [152.99, 0] + +- name: Case 4, deeming uses higher individual special rate. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 65 + person2: + age: 63 + social_security_retirement: 19_800 + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: &id004 [person1, person2] + households: + household: + members: *id004 + state_code: NJ + output: + # person2 is 63, below the SSI aged threshold of 65, and not blind or disabled. + is_ssi_ineligible_spouse: [false, true] + # Spouse income 19_800 per year > (1_491 - 994) * 12 = 5_964, so deeming applies. + is_ssi_spousal_deeming_applies: [true, false] + # Deemed: 19_800 / 12 = 1_650 - 20 general exclusion = 1_630 per month. + ssi_income_deemed_from_ineligible_spouse: [1_630, 0] + # person1 has no own income: 0 + 1_630 deemed = 1_630. + ssi_countable_income: [1_630, 0] + # Deeming uses the couple FBR for person1; person2's 994 is not used. + ssi_amount_if_eligible: [1_491, 994] + # 1_491 - 1_630 = -139, so no federal SSI. + uncapped_ssi: [-139, 0] + ssi: [0, 0] + # Only the ineligible spouse shares the household: code C. + nj_ssp_living_arrangement: [LIVING_ONLY_WITH_INELIGIBLE_SPOUSE, LIVING_ONLY_WITH_INELIGIBLE_SPOUSE] + # Deemed: max(25.35, 152.99) - (1_630 - 1_491) = 152.99 - 139 = 13.99. + # Own: 152.99 - max(0 - 994, 0) = 152.99; the lower amount, 13.99, is paid. + nj_ssp: [13.99, 0] + +- name: Case 5, special rate ends when a child shares the household. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 65 + person2: + age: 40 + person3: + age: 12 + is_tax_unit_dependent: true + marital_units: + couple: + members: [person1, person2] + child: + members: [person3] + tax_units: + unit: + members: &id005 [person1, person2, person3] + households: + household: + members: *id005 + state_code: NJ + output: + nj_ssp: [31.25, 0, 0] + +- name: Case 6, explicit ineligible spouse code for a couple living only with a foster child. + period: 2026-01 + absolute_error_margin: 0.001 + # SI NY01415.025 allows code C with foster children (effective 7/1/90); the + # state's household determination is entered directly. + input: + people: + person1: + age: 65 + nj_ssp_living_arrangement: LIVING_ONLY_WITH_INELIGIBLE_SPOUSE + person2: + age: 40 + person3: + age: 12 + is_tax_unit_dependent: true + marital_units: + couple: + members: [person1, person2] + child: + members: [person3] + tax_units: + unit: + members: &id006 [person1, person2, person3] + households: + household: + members: *id006 + state_code: NJ + output: + nj_ssp: [152.99, 0, 0] + +- name: Case 7, annual state benefits and SNAP income. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 65 + output: + nj_ssp: 375 + household_state_benefits: 375 + snap_unearned_income: 12_303 + hud_unearned_income: 12_303 + # SSI 994 * 12 = 11_928. SNAP: 298 - 245 = 53 a month, raised to New + # Jersey's 95 minimum, so 95 * 12 = 1_140. 11_928 + 375 + 1_140 = 13_443. + spm_unit_benefits: 13_443 + +- name: Case 8, congregate care spouses claim as individuals after the month of entry. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 65 + nj_ssp_care_setting: CONGREGATE_CARE + person2: + age: 65 + nj_ssp_care_setting: CONGREGATE_CARE + # SI NY01415.025: after the month of entry, spouses in a congregate care + # facility are treated as two individuals, entered as separate marital units. + marital_units: + unit1: + members: [person1] + unit2: + members: [person2] + tax_units: + unit: + members: &id008 [person1, person2] + households: + household: + members: *id008 + state_code: NJ + output: + ssi: [994, 994] + nj_ssp_living_arrangement: [CONGREGATE_CARE, CONGREGATE_CARE] + # J.2.a individual code A row: 150.05 each. + nj_ssp: [150.05, 150.05] + +- name: Case 9, deeming in the living alone or with others code uses the higher individual rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + person2: + age: 45 + # Full-time cashier (SOC 41-2011) at the New Jersey median wage, BLS + # OEWS May 2025: $16.63 an hour, published as $34,590 a year. + employment_income: 34_590 + person3: + age: 12 + is_tax_unit_dependent: true + marital_units: + couple: + members: [person1, person2] + child: + members: [person3] + tax_units: + unit: + members: &id009 [person1, person2, person3] + households: + household: + members: *id009 + state_code: NJ + output: + # 34_590 / 12 = 2_882.50 - 497 child allocation = 2_385.50 > 497, so + # deeming applies: (2_385.50 - 20 - 65) / 2 = 1_150.25 countable. + is_ssi_spousal_deeming_applies: [true, false, false] + ssi_countable_income: [1_150.25, 0, 0] + # 1_491 couple FBR - 1_150.25 = 340.75. + ssi: [340.75, 0, 0] + # A child shares the household, so code B. + nj_ssp_living_arrangement: [LIVING_ALONE_OR_WITH_OTHERS, LIVING_ALONE_OR_WITH_OTHERS, LIVING_ALONE_OR_WITH_OTHERS] + # Deemed: max(25.35, 31.25) - max(1_150.25 - 1_491, 0) = 31.25; own: 31.25. + # The lesser is 31.25; the couple rate would give 25.35 (SI 01320.430 D.2.c). + nj_ssp: [31.25, 0, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ssp/nj_ssp.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ssp/nj_ssp.yaml new file mode 100644 index 00000000000..8fb2fbe44fb --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ssp/nj_ssp.yaml @@ -0,0 +1,216 @@ +# Sources: POMS SI 01415.058 J and SI NY01415.025. +- name: Case 1, independent individual. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 65 + output: + nj_ssp: 31.25 + +- name: Case 2, certified congregate care. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 65 + nj_ssp_care_setting: CONGREGATE_CARE + output: + nj_ssp: 150.05 + +- name: Case 3, certified residential health care. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 65 + nj_ssp_care_setting: RESIDENTIAL_HEALTH_CARE + output: + nj_ssp: 210.05 + +- name: Case 4, excluded setting. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 65 + nj_ssp_care_setting: EXCLUDED + output: + nj_ssp: 0 + +- name: Case 5, Medicaid institutional payment. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 65 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + output: + ssi: 30 + nj_ssp: 20 + +- name: Case 6, non Medicaid medical institution. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 65 + ssi_lives_in_medical_treatment_facility: true + output: + nj_ssp: 0 + +- name: Case 7, household of another. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 65 + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + output: + nj_ssp: 44.31 + +- name: Case 8, state only payment. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 65 + social_security_retirement: 12_360 + output: + ssi: 0 + nj_ssp: 15.25 + +- name: Case 9, positive sub dollar amount receives minimum. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 65 + social_security_retirement: 12_540 + output: + # 12_540 / 12 = 1_045 - 20 = 1_025 countable, 31 above the 994 FBR. + # 31.25 - 31 = 0.25, raised to the 1 dollar minimum. + nj_ssp: 1 + +- name: Case 10, combined income cutoff. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 65 + social_security_retirement: 12_543 + output: + nj_ssp: 0 + +- name: Case 11, resource cutoff. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 65 + ssi_countable_resources: 2_001 + output: + nj_ssp: 0 + +- name: Case 12, no aged blind or disabled category. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 30 + output: + nj_ssp: 0 + +- name: Case 13, disabled child. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 12 + meets_ssi_disability_criteria: true + output: + nj_ssp: 31.25 + +- name: Case 14, out of state. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NY + age: 65 + output: + nj_ssp: 0 + +- name: Case 15, declining SSI application. + period: 2026-01 + absolute_error_margin: 0.01 + input: + state_code: NJ + age: 65 + takes_up_ssi_if_eligible: false + output: + nj_ssp: 0 + +- name: Case 16, couple with Social Security receives a state only payment. + period: 2026-01 + absolute_error_margin: 0.001 + input: + people: + person1: + age: 65 + social_security_retirement: 18_240 + person2: + age: 65 + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # 18_240 / 12 = 1_520 - 20 = 1_500 couple countable, 750 per spouse. + ssi_countable_income: [750, 750] + # 750 - 1_491 / 2 = 4.50 above each spouse's federal amount, so no SSI. + ssi: [0, 0] + # 25.35 / 2 = 12.675 - 4.50 = 8.175, rounded up to 8.18 per spouse. + nj_ssp: [8.18, 8.18] + +- name: Case 17, disabled child living with parents receives the living alone or with others rate. + period: 2026-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + own_children_in_household: 1 + person2: + age: 40 + own_children_in_household: 1 + person3: + age: 10 + meets_ssi_disability_criteria: true + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + # The parents are not aged, blind or disabled, so the child is in federal + # code C, which New Jersey pays as code B (SI 01415.058 J.1). + ssi_federal_living_arrangement: [OWN_HOUSEHOLD, OWN_HOUSEHOLD, CHILD_IN_PARENTAL_HOUSEHOLD] + nj_ssp_living_arrangement: [LIVING_ALONE_OR_WITH_OTHERS, LIVING_ALONE_OR_WITH_OTHERS, LIVING_ALONE_OR_WITH_OTHERS] + # The parents have no income, so nothing is deemed. + ssi: [0, 0, 994] + # J.2.a row C/B: 31.25. + nj_ssp: [0, 0, 31.25] diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ssp/nj_ssp_living_arrangement.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ssp/nj_ssp_living_arrangement.yaml new file mode 100644 index 00000000000..1211707cdd0 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/ssp/nj_ssp_living_arrangement.yaml @@ -0,0 +1,138 @@ +# Source: POMS SI NY01415.025. +- name: Case 1, independent individual is code B. + period: 2026-01 + input: + state_code: NJ + age: 65 + output: + nj_ssp_living_arrangement: LIVING_ALONE_OR_WITH_OTHERS + +- name: Case 2, couple with only an ineligible spouse is code C. + period: 2026-01 + input: + people: + person1: + age: 65 + person2: + age: 63 + marital_units: + couple: + members: [person1, person2] + tax_units: + unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NJ + output: + # person2 is under 65 and not blind or disabled; no one else lives there. + nj_ssp_living_arrangement: [LIVING_ONLY_WITH_INELIGIBLE_SPOUSE, LIVING_ONLY_WITH_INELIGIBLE_SPOUSE] + +- name: Case 3, certified congregate care is code A. + period: 2026-01 + input: + state_code: NJ + age: 65 + nj_ssp_care_setting: CONGREGATE_CARE + output: + nj_ssp_living_arrangement: CONGREGATE_CARE + +- name: Case 4, certified residential health care is code I. + period: 2026-01 + input: + state_code: NJ + age: 65 + nj_ssp_care_setting: RESIDENTIAL_HEALTH_CARE + output: + nj_ssp_living_arrangement: RESIDENTIAL_HEALTH_CARE + +- name: Case 5, household of another is code D. + period: 2026-01 + input: + state_code: NJ + age: 65 + ssi_lives_in_another_persons_household: true + ssi_receives_shelter_from_others_in_household: true + ssi_others_pay_all_meals: true + output: + nj_ssp_living_arrangement: HOUSEHOLD_OF_ANOTHER + +- name: Case 6, Medicaid institution is code G. + period: 2026-01 + input: + state_code: NJ + age: 65 + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + output: + nj_ssp_living_arrangement: MEDICAID_INSTITUTION + +- name: Case 7, excluded setting is code Z with no supplement. + period: 2026-01 + input: + state_code: NJ + age: 65 + nj_ssp_care_setting: EXCLUDED + output: + nj_ssp_living_arrangement: NONE + +- name: Case 8, medical institution without Medicaid majority is code Z. + period: 2026-01 + input: + state_code: NJ + age: 65 + ssi_lives_in_medical_treatment_facility: true + output: + nj_ssp_living_arrangement: NONE + +- name: Case 9, Medicaid institution takes precedence over congregate care. + period: 2026-01 + input: + state_code: NJ + age: 65 + nj_ssp_care_setting: CONGREGATE_CARE + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + output: + # The Medicaid institution branch is checked before certified care. + nj_ssp_living_arrangement: MEDICAID_INSTITUTION + +- name: Case 10, excluded setting takes precedence over a Medicaid institution. + period: 2026-01 + input: + state_code: NJ + age: 65 + nj_ssp_care_setting: EXCLUDED + ssi_lives_in_medical_treatment_facility: true + ssi_medicaid_pays_majority_of_care: true + output: + # The excluded setting branch is checked first. + nj_ssp_living_arrangement: NONE + +- name: Case 11, code C ends when a child shares the household. + period: 2026-01 + input: + people: + person1: + age: 65 + person2: + age: 63 + person3: + age: 12 + is_tax_unit_dependent: true + marital_units: + couple: + members: [person1, person2] + child: + members: [person3] + tax_units: + unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + # Three household members against a two-person marital unit. + nj_ssp_living_arrangement: [LIVING_ALONE_OR_WITH_OTHERS, LIVING_ALONE_OR_WITH_OTHERS, LIVING_ALONE_OR_WITH_OTHERS] diff --git a/policyengine_us/variables/gov/ssa/ssi/_ssi_state_supplement.py b/policyengine_us/variables/gov/ssa/ssi/_ssi_state_supplement.py new file mode 100644 index 00000000000..5e0c84da3f3 --- /dev/null +++ b/policyengine_us/variables/gov/ssa/ssi/_ssi_state_supplement.py @@ -0,0 +1,53 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.ssa.ssi.eligibility.status.ssi_federal_living_arrangement import ( + SSIFederalLivingArrangement, +) + + +def ssi_state_supplement( + person, period, parameters, individual_rate, couple_rate, federal_payment_rules=True +): + """Apply SSI-based supplement income, couple and spouse-deeming rules. + + Rates are state supplements, excluding federal SSI. Each member supplies + the same-category couple rate; averaging these rates implements mixed + arrangements where the state's published schedule supports that method. + Set federal_payment_rules only for SSA-administered payments; state + administrators do not inherit the federal rounding or minimum payment. + Sources: 20 CFR 416.2025; POMS SI 01320.430 D, SI 02005.030 G, + SI 02001.005 and SI 02001.010. Callers apply state-specific eligibility. + """ + joint = person("ssi_couple_computation_applies", period) + couple_total = person.marital_unit.sum(couple_rate / 2) + standard = where(joint, couple_total / 2, individual_rate) + countable = person("ssi_countable_income", period) + federal_amount = person("ssi_amount_if_eligible", period) + excess = max_(countable - federal_amount, 0) + payment = max_(standard - excess, 0) + + deeming = person("is_ssi_spousal_deeming_applies", period.this_year) + deemed = person("ssi_income_deemed_from_ineligible_spouse", period) + own_income = max_(countable - deemed, 0) + ssi = parameters(period).gov.ssa.ssi + federal_la = person("ssi_federal_living_arrangement", period) + own_federal_amount = ssi.amount.individual * where( + federal_la == SSIFederalLivingArrangement.ANOTHER_PERSONS_HOUSEHOLD, + 1 - ssi.amount.one_third_reduction_rate, + 1, + ) + own_payment = max_(individual_rate - max_(own_income - own_federal_amount, 0), 0) + # SI 01320.430 D.2: use the higher individual rate where it exceeds + # the couple rate (including New Jersey's ineligible-spouse variation). + deemed_payment = max_(max_(couple_rate, individual_rate) - excess, 0) + payment = where(deeming, min_(own_payment, deemed_payment), payment) + + eligible = person("is_ssi_eligible", period) & person( + "takes_up_ssi_if_eligible", period.this_year + ) + # Federal administration discards digits beyond the third decimal place, + # rounds up to cents, and pays at least one dollar for a positive amount. + rounded = np.ceil(np.floor(payment * 1_000) / 10) / 100 + federal_payment = where( + rounded > 0, max_(rounded, ssi.state_supplement.minimum_payment), 0 + ) + return eligible * where(federal_payment_rules, federal_payment, payment) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ssp/nj_ssp.py b/policyengine_us/variables/gov/states/nj/njdhs/ssp/nj_ssp.py new file mode 100644 index 00000000000..1dfdc8d0890 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ssp/nj_ssp.py @@ -0,0 +1,40 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.ssa.ssi._ssi_state_supplement import ( + ssi_state_supplement, +) + + +class nj_ssp(Variable): + value_type = float + entity = Person + label = "New Jersey State Supplementary Payment" + definition_period = MONTH + unit = USD + defined_for = StateCode.NJ + reference = ( + "https://secure.ssa.gov/poms.nsf/lnx/0501415058#j", + "https://secure.ssa.gov/poms.nsf/lnx/0501415025NY", + "https://secure.ssa.gov/poms.nsf/lnx/0501320430#d", + "https://www.ssa.gov/policy/docs/progdesc/ssi_st_asst/2011/nj.html", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.nj.njdhs.ssp.amount + # NOTE: The C rate uses the federal ineligible-spouse definition, which + # omits an aged, blind or disabled spouse who is ineligible for SSI or + # chooses not to apply (SI 01415.058 J.1); the model treats that claim + # as joint and pays half the couple rate instead. + arrangement = person("nj_ssp_living_arrangement", period) + # NOTE: The shared helper averages the couple rates of spouses in + # different arrangements. SSA treats spouses who enter an institution + # as two individuals after the month of change (SI NY01415.025), so + # such couples need explicit marital-unit inputs. + # NOTE: The individual rate exceeds the couple rate for codes B and C, + # so a claim with deemed spousal income uses the higher individual + # rate (SI 01320.430 D.2.c). + # NOTE: Every rate except the Medicaid-facility rate includes the + # state's Lifeline utility payment (SI 01415.058 J.1); issue 10230 + # tracks counting it net of the Lifeline in New Jersey LIHEAP. + return ssi_state_supplement( + person, period, parameters, p.individual[arrangement], p.couple[arrangement] + ) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ssp/nj_ssp_care_setting.py b/policyengine_us/variables/gov/states/nj/njdhs/ssp/nj_ssp_care_setting.py new file mode 100644 index 00000000000..63371e5ec2e --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ssp/nj_ssp_care_setting.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class NJSSPCareSetting(Enum): + CONGREGATE_CARE = "New Jersey certified congregate care" + RESIDENTIAL_HEALTH_CARE = "New Jersey certified residential health care" + EXCLUDED = "Setting excluded from New Jersey supplementation" + NONE = "No certified care setting" + + +class nj_ssp_care_setting(Variable): + value_type = Enum + entity = Person + label = "New Jersey SSP certified care setting" + definition_period = MONTH + possible_values = NJSSPCareSetting + default_value = NJSSPCareSetting.NONE + reference = "https://secure.ssa.gov/poms.nsf/lnx/0501415025NY" + documentation = """ + Certified settings require inclusion in New Jersey's Congregate Care + Directory. EXCLUDED includes publicly operated community residences, + emergency shelters and institutional children funded by private insurance. + Use the SSI claim and marital-unit inputs to represent separate individual + claims after institutionalization; this input does not change federal SSI. + """ diff --git a/policyengine_us/variables/gov/states/nj/njdhs/ssp/nj_ssp_living_arrangement.py b/policyengine_us/variables/gov/states/nj/njdhs/ssp/nj_ssp_living_arrangement.py new file mode 100644 index 00000000000..f652d78b1c9 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/ssp/nj_ssp_living_arrangement.py @@ -0,0 +1,67 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.states.nj.njdhs.ssp.nj_ssp_care_setting import ( + NJSSPCareSetting, +) +from policyengine_us.variables.gov.ssa.ssi.eligibility.status.ssi_federal_living_arrangement import ( + SSIFederalLivingArrangement, +) + + +class NJSSPLivingArrangement(Enum): + LIVING_ALONE_OR_WITH_OTHERS = "Living alone or with others" + LIVING_ONLY_WITH_INELIGIBLE_SPOUSE = "Living only with an ineligible spouse" + CONGREGATE_CARE = "Certified congregate care" + RESIDENTIAL_HEALTH_CARE = "Certified residential health care" + HOUSEHOLD_OF_ANOTHER = "Household of another" + MEDICAID_INSTITUTION = "Medicaid institution" + NONE = "No supplement" + + +class nj_ssp_living_arrangement(Variable): + value_type = Enum + entity = Person + label = "New Jersey SSP living arrangement" + definition_period = MONTH + defined_for = StateCode.NJ + possible_values = NJSSPLivingArrangement + default_value = NJSSPLivingArrangement.NONE + reference = ( + "https://secure.ssa.gov/poms.nsf/lnx/0501415058#j1", + "https://secure.ssa.gov/poms.nsf/lnx/0501415025NY", + ) + documentation = """ + A separately purchasing couple sharing an address with others, or a couple + living only with foster children, can set the ineligible-spouse variation + explicitly after the state's household determination. + """ + + def formula(person, period, parameters): + care = person("nj_ssp_care_setting", period) + federal = person("ssi_federal_living_arrangement", period) + medical = federal == SSIFederalLivingArrangement.MEDICAL_TREATMENT_FACILITY + other_medical = ( + person("ssi_lives_in_medical_treatment_facility", period) & ~medical + ) + ineligible_spouse = person.marital_unit.any( + person("is_ssi_ineligible_spouse", period.this_year) + ) + no_others = person.household.nb_persons() == person.marital_unit.nb_persons() + return select( + [ + (care == NJSSPCareSetting.EXCLUDED) | other_medical, + medical, + care == NJSSPCareSetting.CONGREGATE_CARE, + care == NJSSPCareSetting.RESIDENTIAL_HEALTH_CARE, + federal == SSIFederalLivingArrangement.ANOTHER_PERSONS_HOUSEHOLD, + ineligible_spouse & no_others, + ], + [ + NJSSPLivingArrangement.NONE, + NJSSPLivingArrangement.MEDICAID_INSTITUTION, + NJSSPLivingArrangement.CONGREGATE_CARE, + NJSSPLivingArrangement.RESIDENTIAL_HEALTH_CARE, + NJSSPLivingArrangement.HOUSEHOLD_OF_ANOTHER, + NJSSPLivingArrangement.LIVING_ONLY_WITH_INELIGIBLE_SPOUSE, + ], + default=NJSSPLivingArrangement.LIVING_ALONE_OR_WITH_OTHERS, + ) diff --git a/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py b/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py index a473c2b438d..a8eccf27b73 100644 --- a/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py +++ b/policyengine_us/variables/household/income/spm_unit/spm_unit_benefits.py @@ -22,6 +22,7 @@ def formula(spm_unit, period, parameters): "ky_ssp", # Kentucky benefits "de_ssp", # Delaware benefits "fl_oss", + "nj_ssp", # New Jersey benefits "ks_sspp", # Kansas benefits "hi_oss", "la_oss", # Louisiana benefits