diff --git a/changelog.d/ne-liheap-cooling.added.md b/changelog.d/ne-liheap-cooling.added.md new file mode 100644 index 00000000000..da690393444 --- /dev/null +++ b/changelog.d/ne-liheap-cooling.added.md @@ -0,0 +1 @@ +Add Nebraska LIHEAP regular cooling assistance. diff --git a/policyengine_us/parameters/gov/hhs/liheap/regular_payments.yaml b/policyengine_us/parameters/gov/hhs/liheap/regular_payments.yaml index e811bea6fbd..be081fcf297 100644 --- a/policyengine_us/parameters/gov/hhs/liheap/regular_payments.yaml +++ b/policyengine_us/parameters/gov/hhs/liheap/regular_payments.yaml @@ -33,6 +33,7 @@ values: - nc_lieap # North Carolina LIEAP - nd_liheap # North Dakota LIHEAP - ne_liheap # Nebraska LIHEAP + - ne_liheap_cooling # Nebraska LIHEAP cooling - nh_fap # New Hampshire FAP - nj_liheap # New Jersey LIHEAP - nm_liheap # New Mexico LIHEAP diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/liheap/cooling/adc_child_age_limit.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/cooling/adc_child_age_limit.yaml new file mode 100644 index 00000000000..73f48184790 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/cooling/adc_child_age_limit.yaml @@ -0,0 +1,12 @@ +description: Nebraska qualifies a household for cooling assistance when a member below this age receives Aid to Dependent Children under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: 6 +metadata: + unit: year + period: year + label: Nebraska LIHEAP cooling Aid to Dependent Children child age limit + reference: + - title: 476 NAC 2-003(A) Cooling Assistance (a household member who "is a child under age 6 who receives Aid to Dependent Children") + href: https://rules.nebraska.gov/api/fileStorage/GetAsByteArray/chapter-pdfs/476%20NAC%202%20(06-26-2022).pdf/1747#page=2 + - title: Nebraska FY2026 LIHEAP State Plan, section 3.3 + href: https://liheapch.acf.gov/docs/2026/state-plans/NE_Plan_2026.pdf#page=11 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/liheap/cooling/elderly_age.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/cooling/elderly_age.yaml new file mode 100644 index 00000000000..cfd68fa8f63 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/cooling/elderly_age.yaml @@ -0,0 +1,12 @@ +description: Nebraska qualifies a household for cooling assistance when a member is at least this age under the Low Income Home Energy Assistance Program. +values: + 2025-10-01: 70 +metadata: + unit: year + period: year + label: Nebraska LIHEAP cooling elderly member age + reference: + - title: 476 NAC 2-003(B) Cooling Assistance (a household member who "is age 70 or older") + href: https://rules.nebraska.gov/api/fileStorage/GetAsByteArray/chapter-pdfs/476%20NAC%202%20(06-26-2022).pdf/1747#page=2 + - title: Nebraska FY2026 LIHEAP State Plan, section 3.3 + href: https://liheapch.acf.gov/docs/2026/state-plans/NE_Plan_2026.pdf#page=11 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/liheap/cooling/multifamily.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/cooling/multifamily.yaml new file mode 100644 index 00000000000..062d0e418a6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/cooling/multifamily.yaml @@ -0,0 +1,32 @@ +description: Nebraska provides these regular multi-family cooling payments by countable income as a share of the federal poverty guideline under the Low Income Home Energy Assistance Program. +# The Guidance Document effective October 1, 2026 prints the same table for FY2027. +brackets: + - threshold: + 2025-10-01: -.inf + amount: + 2025-10-01: 385 + - threshold: + 2025-10-01: 0.7 + amount: + 2025-10-01: 335 + - threshold: + 2025-10-01: 1 + amount: + 2025-10-01: 300 + - threshold: + 2025-10-01: 1.3 + amount: + 2025-10-01: 273 +metadata: + type: single_amount + threshold_unit: /1 + amount_unit: currency-USD + period: year + label: Nebraska LIHEAP multi-family cooling payment + reference: + - title: Nebraska LIHEAP Guidance Document effective October 1, 2025, Cooling Payment Computation + href: https://dhhs.ne.gov/Documents/Low%20Income%20Home%20Energy%20Assistance%20Program%20%28LIHEAP%29%20Guidance%20Document%202026.pdf#page=3 + - title: Nebraska LIHEAP Guidance Document effective October 1, 2026, Cooling Payment Computation + href: https://dhhs.ne.gov/Guidance%20Docs/Low%20Income%20Home%20Energy%20Assistance%20Program%20%28LIHEAP%29%20Guidance%20Document.pdf#page=4 + - title: Nebraska FY2026 LIHEAP State Plan, section 3.6 (minimum $273, maximum $700) + href: https://liheapch.acf.gov/docs/2026/state-plans/NE_Plan_2026.pdf#page=12 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/liheap/cooling/single_family.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/cooling/single_family.yaml new file mode 100644 index 00000000000..a0938f9ff0a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/cooling/single_family.yaml @@ -0,0 +1,32 @@ +description: Nebraska provides these regular single-family cooling payments by countable income as a share of the federal poverty guideline under the Low Income Home Energy Assistance Program. +# The Guidance Document effective October 1, 2026 prints the same table for FY2027. +brackets: + - threshold: + 2025-10-01: -.inf + amount: + 2025-10-01: 700 + - threshold: + 2025-10-01: 0.7 + amount: + 2025-10-01: 595 + - threshold: + 2025-10-01: 1 + amount: + 2025-10-01: 525 + - threshold: + 2025-10-01: 1.3 + amount: + 2025-10-01: 478 +metadata: + type: single_amount + threshold_unit: /1 + amount_unit: currency-USD + period: year + label: Nebraska LIHEAP single-family cooling payment + reference: + - title: Nebraska LIHEAP Guidance Document effective October 1, 2025, Cooling Payment Computation + href: https://dhhs.ne.gov/Documents/Low%20Income%20Home%20Energy%20Assistance%20Program%20%28LIHEAP%29%20Guidance%20Document%202026.pdf#page=3 + - title: Nebraska LIHEAP Guidance Document effective October 1, 2026, Cooling Payment Computation + href: https://dhhs.ne.gov/Guidance%20Docs/Low%20Income%20Home%20Energy%20Assistance%20Program%20%28LIHEAP%29%20Guidance%20Document.pdf#page=4 + - title: Nebraska FY2026 LIHEAP State Plan, section 3.6 (minimum $273, maximum $700) + href: https://liheapch.acf.gov/docs/2026/state-plans/NE_Plan_2026.pdf#page=12 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/liheap/earned_income_disregard.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/earned_income_disregard.yaml index ccaea440e6a..151f7d987a7 100644 --- a/policyengine_us/parameters/gov/states/ne/dhhs/liheap/earned_income_disregard.yaml +++ b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/earned_income_disregard.yaml @@ -1,4 +1,4 @@ -description: Nebraska excludes this share of gross countable earned income when determining regular heating payments under the Low Income Home Energy Assistance Program. +description: Nebraska excludes this share of gross countable earned income when determining regular heating and cooling payments under the Low Income Home Energy Assistance Program. values: 2025-10-01: 0.2 metadata: @@ -6,5 +6,5 @@ metadata: period: year label: Nebraska LIHEAP earned income disregard reference: - - title: Nebraska LIHEAP Guidance Document effective October 1, 2025 + - title: "Nebraska LIHEAP Guidance Document effective October 1, 2025, Heating and Cooling Payment Computation #page 2-3" href: https://dhhs.ne.gov/Documents/Low%20Income%20Home%20Energy%20Assistance%20Program%20%28LIHEAP%29%20Guidance%20Document%202026.pdf#page=2 diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/liheap/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/fpg_year_lag.yaml index 6427304d368..bd3baf4d756 100644 --- a/policyengine_us/parameters/gov/states/ne/dhhs/liheap/fpg_year_lag.yaml +++ b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/fpg_year_lag.yaml @@ -1,4 +1,4 @@ -description: Nebraska uses federal poverty guidelines from this many years before the modeled heating-season ending year under the Low Income Home Energy Assistance Program. +description: Nebraska uses federal poverty guidelines from this many years before the modeled federal fiscal year, for heating and cooling, under the Low Income Home Energy Assistance Program. values: 2025-10-01: 1 metadata: diff --git a/policyengine_us/parameters/gov/states/ne/dhhs/liheap/payment_size_limit.yaml b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/payment_size_limit.yaml index c4fea5d14ee..bae8ac428ce 100644 --- a/policyengine_us/parameters/gov/states/ne/dhhs/liheap/payment_size_limit.yaml +++ b/policyengine_us/parameters/gov/states/ne/dhhs/liheap/payment_size_limit.yaml @@ -1,4 +1,4 @@ -description: Nebraska limits household size to this number when determining regular heating payment income bands under the Low Income Home Energy Assistance Program. +description: Nebraska limits household size to this number when determining regular heating and cooling payment income bands under the Low Income Home Energy Assistance Program. values: 2025-10-01: 6 metadata: @@ -6,5 +6,5 @@ metadata: period: year label: Nebraska LIHEAP payment band household size limit reference: - - title: Nebraska LIHEAP Guidance Document effective October 1, 2025 + - title: "Nebraska LIHEAP Guidance Document effective October 1, 2025, Heating and Cooling Payment Computation #page 2-3" href: https://dhhs.ne.gov/Documents/Low%20Income%20Home%20Energy%20Assistance%20Program%20%28LIHEAP%29%20Guidance%20Document%202026.pdf#page=2 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 6f704d520fb..01370320e45 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1301,7 +1301,15 @@ programs: variable: ne_liheap parameter_prefix: gov.states.ne.dhhs.liheap verified_years: "2026" - notes: FY2026 regular heating only, with the single-family and multifamily schedules and the earned-income disregard. Crisis, cooling and weatherization assistance are out of scope. + notes: FY2026 regular heating, with the single-family and multifamily schedules and the earned-income disregard. Cooling is a separate entry; crisis and weatherization assistance are out of scope. + - state: NE + status: partial + name: Nebraska LIHEAP cooling + full_name: Nebraska Low Income Home Energy Assistance Program Cooling Assistance + variable: ne_liheap_cooling + parameter_prefix: gov.states.ne.dhhs.liheap + verified_years: "2026-2027" + notes: FY2026-FY2027 cooling payment by dwelling type for households with a member age 70 or older or a child under 6 receiving ADC. The medical-statement and prior-air-conditioner routes, crisis assistance and air conditioner purchase or repair are out of scope. - state: NH status: partial name: New Hampshire FAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/liheap/cooling/ne_liheap_cooling.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/liheap/cooling/ne_liheap_cooling.yaml new file mode 100644 index 00000000000..fc98e2db17e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/liheap/cooling/ne_liheap_cooling.yaml @@ -0,0 +1,337 @@ +# Source: Nebraska FY2026 LIHEAP Guidance, Cooling Payment Computation (page 3). +# https://dhhs.ne.gov/Documents/Low%20Income%20Home%20Energy%20Assistance%20Program%20%28LIHEAP%29%20Guidance%20Document%202026.pdf#page=3 +# Tiers by payment income as a share of the 2025 guideline: at or below 70% / 100% / 130% / +# 150%. Single-family $700 / $595 / $525 / $478; multi-family $385 / $335 / $300 / $273. +# One-person tier tops: $10,955 / $15,650 / $20,345 / $23,475. + +- name: Case 1, single-family cooling payments at each closed tier boundary. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [NE, NE, NE, NE, NE, NE, NE, NE, NE] + ne_liheap_cooling_eligible: [true, true, true, true, true, true, true, true, true] + ne_liheap_household_size: [1, 1, 1, 1, 1, 1, 1, 1, 1] + ne_liheap_gross_income: [-100, 0, 10_955, 10_955.01, 15_650, 15_650.01, 20_345, 20_345.01, + 23_475] + ne_liheap_earned_income: [0, 0, 0, 0, 0, 0, 0, 0, 0] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, + NATURAL_GAS, NATURAL_GAS, NATURAL_GAS] + has_cooling_expense: [true, true, true, true, true, true, true, true, true] + output: + ne_liheap_cooling: [700, 700, 700, 595, 595, 525, 525, 478, 478] + +- name: Case 2, multi-family cooling payments at each closed tier boundary. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [NE, NE, NE, NE, NE, NE, NE, NE] + ne_liheap_cooling_eligible: [true, true, true, true, true, true, true, true] + ne_liheap_household_size: [1, 1, 1, 1, 1, 1, 1, 1] + ne_liheap_gross_income: [0, 10_955, 10_955.01, 15_650, 15_650.01, 20_345, 20_345.01, 23_475] + ne_liheap_earned_income: [0, 0, 0, 0, 0, 0, 0, 0] + ne_liheap_dwelling_type: [MULTI_FAMILY, MULTI_FAMILY, MULTI_FAMILY, MULTI_FAMILY, + MULTI_FAMILY, MULTI_FAMILY, MULTI_FAMILY, MULTI_FAMILY] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, + NATURAL_GAS, NATURAL_GAS] + has_cooling_expense: [true, true, true, true, true, true, true, true] + output: + ne_liheap_cooling: [385, 385, 335, 335, 300, 300, 273, 273] + +# A 72-year-old in a house with $1,200 a month of Social Security ($14,400 a year) and a +# $900 gas heating bill. 14,400 / 15,650 = 0.920, tier 2: cooling $595 (single-family) and, +# separately, heating $550 (natural gas column). The national LIHEAP total is $550 + $595. +- name: Case 3, a retiree receives both the heating and the cooling payment. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: NE + age: 72 + social_security_retirement: 14_400 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + tanf: 0 + heating_type: NATURAL_GAS + gas_expense: 900 + has_cooling_expense: true + output: + ne_liheap_cooling_eligible: true + ne_liheap: 550 + ne_liheap_cooling: 595 + liheap: 1_145 + +# A mother receiving ADC of about $5,920 a year with her 3-year-old in an apartment. +# 5,920 / 21,150 = 0.280, tier 1: multi-family $385. +- name: Case 4, an ADC household in an apartment receives the multi-family payment. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 28 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + person2: + age: 3 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + spm_units: + spm_unit: + members: [person1, person2] + tanf: 5_920 + heating_type: ELECTRICITY + has_cooling_expense: true + ne_liheap_dwelling_type: MULTI_FAMILY + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_liheap_cooling_eligible: true + ne_liheap_cooling: 385 + +# Case 3's retiree with no heating, then with the heating fuel left unspecified, and no +# heating bill. The cooling table has no fuel column, so both homes receive $595. Heating pays +# nothing in both. +- name: Case 5, a home without heating and a home with an unspecified heating fuel are both paid. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [NE, NE] + age: [72, 72] + social_security_retirement: [14_400, 14_400] + ssi: [0, 0] + ne_aabd: [0, 0] + general_assistance: [0, 0] + tanf: [0, 0] + heating_type: [NONE, UNSPECIFIED] + has_cooling_expense: [true, true] + output: + ne_liheap: [0, 0] + # Was [true, false] and [595, 0], now [true, true] and [595, 595]: the cooling payment + # adds no heating-fuel condition of its own. + ne_liheap_cooling_eligible: [true, true] + ne_liheap_cooling: [595, 595] + +# A 75-year-old with $2,000 a month of Social Security ($24,000 a year) exceeds the $23,475 +# one-person limit. +- name: Case 6, income above 150% of the guideline pays nothing. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: NE + age: 75 + social_security_retirement: 24_000 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + tanf: 0 + heating_type: NATURAL_GAS + has_cooling_expense: true + output: + ne_liheap_income_eligible: false + ne_liheap_cooling: 0 + +- name: Case 7, a household without a cooling cost receives no cooling payment. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: NE + age: 72 + social_security_retirement: 14_400 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + tanf: 0 + heating_type: NATURAL_GAS + has_cooling_expense: false + output: + ne_liheap_cooling: 0 + +# The Guidance Document effective October 1, 2026 (page 4) prints the FY2026 amounts +# on the 2026 guideline of $15,960 for one person: 14,400 / 15,960 = 0.902, tier 2: $595. +# The limit is 1.5 x 15,960 = $23,940. +- name: Case 8, the FY2027 cooling table repeats the FY2026 amounts. + period: 2027 + absolute_error_margin: 0.01 + input: + state_code: NE + age: 72 + social_security_retirement: 14_400 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + tanf: 0 + heating_type: NATURAL_GAS + has_cooling_expense: true + output: + ne_liheap_cooling: 595 + +# A 45-year-old earning $15 an hour for 20 hours a week ($15,600) lives with a 72-year-old +# parent receiving $1,100 a month of Social Security ($13,200). Gross $28,800 is under the +# $31,725 two-person limit. Payment income 28,800 - 0.2 x 15,600 = 25,680; 25,680 / 21,150 = +# 1.214, tier 3: $525. Without the disregard 28,800 / 21,150 = 1.362 would be tier 4 ($478). +- name: Case 9, the earned income disregard raises the cooling payment tier. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + employment_income_before_lsr: 15_600 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + person2: + age: 72 + social_security_retirement: 13_200 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + spm_units: + spm_unit: + members: [person1, person2] + tanf: 0 + heating_type: NATURAL_GAS + has_cooling_expense: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_liheap_cooling: 525 + +# A 72-year-old with $1,200 a month of Social Security ($14,400 a year) rents an apartment with +# heat in the rent and an unknown heating fuel. She pays her own electric bill for a window air +# conditioner and gets no housing assistance. 14,400 / 15,650 = 0.920, tier 2: multi-family +# heating $300 (as in integration Case 7) and multi-family cooling $335. +- name: Case 10, an apartment renter with heat in the rent and an unspecified fuel is paid cooling. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: NE + age: 72 + social_security_retirement: 14_400 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + tanf: 0 + ne_liheap_dwelling_type: MULTI_FAMILY + heat_expense_included_in_rent: true + heating_type: UNSPECIFIED + has_cooling_expense: true + receives_housing_assistance: false + output: + ne_liheap: 300 + ne_liheap_cooling_eligible: true + ne_liheap_cooling: 335 + +# The same retiree rents an apartment in Douglas County (Omaha) with all utilities in the rent, +# reports no separate cooling cost and gets no housing assistance. Her rent is the FY2026 HUD Fair +# Market Rent for a one-bedroom unit, $1,148 a month (x12 = 13,776). Plan section 3.3 requires a +# renter with utilities in rent to be responsible for a portion of the cooling utilities, read as +# heating reads the same sentence for heat in rent (ne_liheap_eligible Case 9). Tier 2: +# multi-family heating $300 and cooling $335. +- name: Case 11, an unsubsidized renter with utilities in the rent is paid cooling. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: NE + age: 72 + social_security_retirement: 14_400 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + tanf: 0 + ne_liheap_dwelling_type: MULTI_FAMILY + tenant_pays_utilities: false + rent: 13_776 + heat_expense_included_in_rent: true + heating_type: ELECTRICITY + has_cooling_expense: false + receives_housing_assistance: false + output: + ne_liheap: 300 + ne_liheap_cooling_eligible: true + ne_liheap_cooling: 335 + +# Case 11's renter with all utilities in the rent and no separate cooling cost, first with housing +# assistance and then in public housing. Each pays a subsidized rent of about 30% of her income, +# $360 a month (x12 = 4,320). A subsidized household must pay a portion of the cooling utilities +# itself, so neither is paid cooling; with no heating bill, neither is paid heating (as in +# ne_liheap_eligible Cases 6 and 7). +- name: Case 12, a subsidized renter with utilities in the rent and no cooling cost is not paid. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [NE, NE] + age: [72, 72] + social_security_retirement: [14_400, 14_400] + ssi: [0, 0] + ne_aabd: [0, 0] + general_assistance: [0, 0] + tanf: [0, 0] + ne_liheap_dwelling_type: [MULTI_FAMILY, MULTI_FAMILY] + tenant_pays_utilities: [false, false] + rent: [4_320, 4_320] + heat_expense_included_in_rent: [true, true] + heating_type: [ELECTRICITY, ELECTRICITY] + has_cooling_expense: [false, false] + receives_housing_assistance: [true, false] + is_in_public_housing: [false, true] + output: + ne_liheap: [0, 0] + ne_liheap_cooling_eligible: [false, false] + ne_liheap_cooling: [0, 0] + +# The same retiree lives rent-free in a relative's apartment, and the relative pays the +# utilities. With no rent she pays no portion of the cooling utilities, so she is not paid +# cooling. +- name: Case 13, utilities paid by someone else with no rent do not qualify the household. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: NE + age: 72 + social_security_retirement: 14_400 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + tanf: 0 + ne_liheap_dwelling_type: MULTI_FAMILY + tenant_pays_utilities: false + rent: 0 + heat_expense_included_in_rent: false + heating_type: ELECTRICITY + has_cooling_expense: false + receives_housing_assistance: false + output: + ne_liheap_cooling_eligible: false + ne_liheap_cooling: 0 + +# Case 11's retiree pays the same rent, but she pays her own utilities apart from the rent and +# reports no cooling cost. With the utilities outside the rent and no cooling cost, she is not +# paid cooling. +- name: Case 14, a renter who pays her own utilities and reports no cooling cost is not paid. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: NE + age: 72 + social_security_retirement: 14_400 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + tanf: 0 + ne_liheap_dwelling_type: MULTI_FAMILY + tenant_pays_utilities: true + rent: 13_776 + heat_expense_included_in_rent: false + heating_type: ELECTRICITY + has_cooling_expense: false + receives_housing_assistance: false + output: + ne_liheap_cooling_eligible: false + ne_liheap_cooling: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/liheap/cooling/ne_liheap_cooling_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/liheap/cooling/ne_liheap_cooling_eligible.yaml new file mode 100644 index 00000000000..0a0037f1ec8 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/liheap/cooling/ne_liheap_cooling_eligible.yaml @@ -0,0 +1,194 @@ +# Source: 476 NAC 2-003 Cooling Assistance and Nebraska FY2026 LIHEAP plan section 3.3. +# https://rules.nebraska.gov/api/fileStorage/GetAsByteArray/chapter-pdfs/476%20NAC%202%20(06-26-2022).pdf/1747#page=2 +# A household must qualify for LIHEAP, pay a cooling cost or rent unsubsidized housing with +# utilities in the rent, and include a member who is a child under 6 receiving Aid to Dependent +# Children or a member age 70 or older. The medical-statement and prior-air-conditioner routes +# have no existing inputs. + +# Retirees with $1,200 a month of Social Security ($14,400 a year), under the $23,475 +# one-person limit. Age 69 has no qualifying member; age 70 does. +- name: Case 1, a member age 70 qualifies the household and age 69 does not. + period: 2026 + input: + state_code: [NE, NE] + age: [69, 70] + social_security_retirement: [14_400, 14_400] + ssi: [0, 0] + ne_aabd: [0, 0] + general_assistance: [0, 0] + tanf: [0, 0] + heating_type: [NATURAL_GAS, NATURAL_GAS] + has_cooling_expense: [true, true] + output: + ne_liheap_income_eligible: [true, true] + ne_liheap_cooling_eligible: [false, true] + +# Two mothers receiving ADC of 55% x $897 = $493.35 a month, about $5,920 a year, for +# themselves and one child. The child aged 5 qualifies the household; the child aged 6 does not. +- name: Case 2, a child under 6 receiving ADC qualifies the household and a child aged 6 does not. + period: 2026 + input: + people: + person1: + age: 28 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + person2: + age: 5 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + person3: + age: 28 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + person4: + age: 6 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + spm_units: + spm_unit1: + members: [person1, person2] + tanf: 5_920 + heating_type: NATURAL_GAS + has_cooling_expense: true + spm_unit2: + members: [person3, person4] + tanf: 5_920 + heating_type: NATURAL_GAS + has_cooling_expense: true + households: + household1: + members: [person1, person2] + state_code: NE + household2: + members: [person3, person4] + state_code: NE + output: + ne_liheap_income_eligible: [true, true] + ne_liheap_cooling_eligible: [true, false] + +# A mother earning $15 an hour for 20 hours a week ($15,600 a year) with a 3-year-old who does +# not receive ADC. +- name: Case 3, a young child without ADC does not qualify the household. + period: 2026 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 15_600 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + person2: + age: 3 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + spm_units: + spm_unit: + members: [person1, person2] + tanf: 0 + heating_type: NATURAL_GAS + has_cooling_expense: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_liheap_income_eligible: true + ne_liheap_cooling_eligible: false + +# A 45-year-old receiving $1,200 a month of Social Security disability. 476 NAC 2-003 has no +# disability route; route (C) needs a medical statement of a heat-aggravated condition. +- name: Case 4, disability alone does not qualify the household. + period: 2026 + input: + state_code: NE + age: 45 + is_disabled: true + social_security_disability: 14_400 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + tanf: 0 + heating_type: NATURAL_GAS + has_cooling_expense: true + output: + ne_liheap_income_eligible: true + ne_liheap_cooling_eligible: false + +# A citizen earning $15,600 lives with an undocumented 74-year-old parent. 476 NAC 2-002.02 +# excludes the parent from the household, so no qualifying member remains. +- name: Case 5, an excluded noncitizen member cannot qualify the household. + period: 2026 + input: + people: + person1: + age: 45 + employment_income_before_lsr: 15_600 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + person2: + age: 74 + immigration_status: UNDOCUMENTED + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + spm_units: + spm_unit: + members: [person1, person2] + tanf: 0 + heating_type: NATURAL_GAS + has_cooling_expense: true + households: + household: + members: [person1, person2] + state_code: NE + output: + ne_liheap_household_size: 1 + ne_liheap_income_eligible: true + ne_liheap_cooling_eligible: false + +# A mother receiving ADC of about $5,920 a year (Case 2's two-person grant) lives with a citizen +# child aged 8 and an undocumented child aged 4, who is outside the grant. 476 NAC 2-002.02 +# excludes the 4-year-old from the household (size 2, limit 1.5 x 21,150 = 31,725), so no child +# under 6 can qualify it, and the child aged 8 is too old. +- name: Case 6, an excluded noncitizen child under 6 cannot qualify an ADC household. + period: 2026 + input: + people: + person1: + age: 28 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + person2: + age: 8 + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + person3: + age: 4 + immigration_status: UNDOCUMENTED + ssi: 0 + ne_aabd: 0 + general_assistance: 0 + spm_units: + spm_unit: + members: [person1, person2, person3] + tanf: 5_920 + heating_type: NATURAL_GAS + has_cooling_expense: true + households: + household: + members: [person1, person2, person3] + state_code: NE + output: + ne_liheap_household_size: 2 + ne_liheap_income_eligible: true + ne_liheap_cooling_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/liheap/ne_liheap_payment_fpg_ratio.yaml b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/liheap/ne_liheap_payment_fpg_ratio.yaml new file mode 100644 index 00000000000..2ebd7e42d84 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ne/dhhs/liheap/ne_liheap_payment_fpg_ratio.yaml @@ -0,0 +1,56 @@ +# Source: Nebraska FY2026 LIHEAP Guidance, heating and cooling payment computation (pages 2-3). +# Payment income is gross countable income less 20% of gross countable earned income, divided +# by the guideline for the household size capped at six. FY2026 uses the 2025 guidelines +# ($15,650 plus $5,500 per additional person). + +# 17,000 - 0.2 x 17,000 = 13,600; 13,600 / 15,650 = 0.86901. +- name: Case 1, the earned income disregard applies before the ratio. + period: 2026 + absolute_error_margin: 0.0001 + input: + state_code: NE + heating_type: NATURAL_GAS + ne_liheap_household_size: 1 + ne_liheap_gross_income: 17_000 + ne_liheap_earned_income: 17_000 + output: + ne_liheap_payment_fpg_ratio: 0.86901 + +# Seven people use the six-person guideline: 15,650 + 5 x 5,500 = 43,150; +# 31,000 / 43,150 = 0.71842. +- name: Case 2, households above six people use the six-person guideline. + period: 2026 + absolute_error_margin: 0.0001 + input: + state_code: NE + heating_type: NATURAL_GAS + ne_liheap_household_size: 7 + ne_liheap_gross_income: 31_000 + ne_liheap_earned_income: 0 + output: + ne_liheap_payment_fpg_ratio: 0.71842 + +- name: Case 3, negative income floors the ratio at zero. + period: 2026 + absolute_error_margin: 0.0001 + input: + state_code: NE + heating_type: NATURAL_GAS + ne_liheap_household_size: 1 + ne_liheap_gross_income: -100 + ne_liheap_earned_income: 0 + output: + ne_liheap_payment_fpg_ratio: 0 + +# FY2027 keeps the one-year lag: the 2026 guideline is $15,960, so 15,960 / 15,960 = 1. +- name: Case 4, FY2027 uses the 2026 guidelines. + period: 2027 + absolute_error_margin: 0.0001 + input: + state_code: NE + heating_type: NATURAL_GAS + ne_liheap_household_size: 1 + ne_liheap_gross_income: 15_960 + ne_liheap_earned_income: 0 + output: + ne_liheap_payment_fpg_ratio: 1 diff --git a/policyengine_us/variables/gov/states/ne/dhhs/liheap/cooling/ne_liheap_cooling.py b/policyengine_us/variables/gov/states/ne/dhhs/liheap/cooling/ne_liheap_cooling.py new file mode 100644 index 00000000000..e909c951c85 --- /dev/null +++ b/policyengine_us/variables/gov/states/ne/dhhs/liheap/cooling/ne_liheap_cooling.py @@ -0,0 +1,44 @@ +from policyengine_us.model_api import * + + +class ne_liheap_cooling(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Nebraska LIHEAP regular cooling assistance" + documentation = ( + "Verified for FY2026 and FY2027 (the June-August cooling seasons); the " + "FY2027 Guidance Document prints the FY2026 table again. FY2027 rests on " + "the October 1, 2026 print, which FY2027 plan section 3.5 makes subject to " + "update closer to the cooling season based on funding. Earlier years " + "use model parameter backfilling and are unverified historical " + "estimates. Later years carry the table forward until a new one is " + "added." + ) + defined_for = "ne_liheap_cooling_eligible" + reference = ( + "https://dhhs.ne.gov/Documents/Low%20Income%20Home%20Energy%20Assistance%20Program%20%28LIHEAP%29%20Guidance%20Document%202026.pdf#page=3", + "https://dhhs.ne.gov/Guidance%20Docs/Low%20Income%20Home%20Energy%20Assistance%20Program%20%28LIHEAP%29%20Guidance%20Document.pdf#page=4", + # 476 NAC 3-001 and 3-003.01, PDF pages 1-2 + "https://rules.nebraska.gov/api/fileStorage/GetAsByteArray/chapter-pdfs/476%20NAC%203%20(12-26-2020).pdf/1748#page=1", + "https://rules.nebraska.gov/api/fileStorage/GetAsByteArray/chapter-pdfs/476%20NAC%201%20(12-26-2020).pdf/1746#page=1", + "https://dhhs.ne.gov/Pages/Energy-Assistance.aspx", + # FY2027 plan section 3.5 + "https://liheapch.acf.gov/docs/2027/state-plans/NE_Plan_2027.pdf#page=12", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ne.dhhs.liheap.cooling + income_ratio = spm_unit("ne_liheap_payment_fpg_ratio", period) + dwelling = spm_unit("ne_liheap_dwelling_type", period) + multifamily = dwelling == dwelling.possible_values.MULTI_FAMILY + # The cooling season runs June 1 through August 31 (476 NAC 1-004.04), + # and DHHS pays "one time per cooling season" (Energy Assistance page). + # The FY2026 table has no fuel column. No FY2026 cooling supplement has + # been verified. + return where( + multifamily, + p.multifamily.calc(income_ratio, right=True), + p.single_family.calc(income_ratio, right=True), + ) diff --git a/policyengine_us/variables/gov/states/ne/dhhs/liheap/cooling/ne_liheap_cooling_eligible.py b/policyengine_us/variables/gov/states/ne/dhhs/liheap/cooling/ne_liheap_cooling_eligible.py new file mode 100644 index 00000000000..9ad1338c276 --- /dev/null +++ b/policyengine_us/variables/gov/states/ne/dhhs/liheap/cooling/ne_liheap_cooling_eligible.py @@ -0,0 +1,65 @@ +from policyengine_us.model_api import * + + +class ne_liheap_cooling_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Nebraska LIHEAP regular cooling assistance eligibility" + defined_for = StateCode.NE + reference = ( + # PDF pages 1-3 + "https://rules.nebraska.gov/api/fileStorage/GetAsByteArray/chapter-pdfs/476%20NAC%202%20(06-26-2022).pdf/1747#page=1", + # 476 NAC 3-002.02 + "https://rules.nebraska.gov/api/fileStorage/GetAsByteArray/chapter-pdfs/476%20NAC%203%20(12-26-2020).pdf/1748#page=1", + # PDF pages 9,11-12 + "https://liheapch.acf.gov/docs/2026/state-plans/NE_Plan_2026.pdf#page=9", + "https://dhhs.ne.gov/Documents/Low%20Income%20Home%20Energy%20Assistance%20Program%20%28LIHEAP%29%20Guidance%20Document%202026.pdf#page=4", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ne.dhhs.liheap.cooling + person = spm_unit.members + age = person("age", period) + # 476 NAC 2-002.02 excludes members who fail the citizenship and + # residency rules, so they cannot be the qualifying member. + included = person("is_snap_immigration_status_eligible", period.first_month) + # 2-003(A) requires a child under 6 who receives ADC. ADC receipt is + # known only for the whole unit, so a child under 6 in a unit that + # receives ADC qualifies even if that child is outside the grant. + receives_adc = spm_unit("tanf", period) > 0 + # 476 NAC 2-003(A) and (B). Routes (C), a severe illness aggravated by + # extreme heat verified on form IM-55, and (D), an air conditioner from + # the Department within four years, have no existing inputs, so + # households qualifying only through them are not paid. Disability is + # not one of the 2-003 routes. + young_child = spm_unit.any(included & (age < p.adc_child_age_limit)) + adc_child = young_child & receives_adc + elderly_member = spm_unit.any(included & (age >= p.elderly_age)) + # FY2026 plan section 3.3 requires subsidized households and renters + # with utilities in rent to be "responsible for a portion of the + # cooling utilities", the sentence section 2.3 sets for heating. It is + # read as ne_liheap_eligible reads section 2.3: an unsubsidized renter + # with utilities in the rent is responsible, since 476 NAC 3-002.02 + # lets the Department pay a household directly "if utilities are + # included in rent" for every 3-001 payment type, cooling included. A + # household receiving housing assistance or living in public housing + # needs a cooling cost of its own. + subsidized = spm_unit("receives_housing_assistance", period) | ( + spm_unit.household("is_in_public_housing", period) + ) + utilities_in_rent = ~spm_unit.household("tenant_pays_utilities", period) & ( + add(spm_unit, period, ["rent"]) > 0 + ) + # A cooling cost apart from rent (has_cooling_expense) is a PolicyEngine + # convention of the all-state cooling work; 476 NAC 2-003 names no air + # conditioner or separate cooling cost. + responsible = spm_unit("has_cooling_expense", period) | ( + utilities_in_rent & ~subsidized + ) + # The cooling table has no fuel column, so heating_type is not read. + return ( + spm_unit("ne_liheap_income_eligible", period) + & responsible + & (adc_child | elderly_member) + ) diff --git a/policyengine_us/variables/gov/states/ne/dhhs/liheap/ne_liheap.py b/policyengine_us/variables/gov/states/ne/dhhs/liheap/ne_liheap.py index 347b097900a..59949c16ae7 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/liheap/ne_liheap.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/liheap/ne_liheap.py @@ -1,5 +1,4 @@ from policyengine_us.model_api import * -from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg class ne_liheap(Variable): @@ -18,24 +17,7 @@ class ne_liheap(Variable): def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ne.dhhs.liheap - gross = spm_unit("ne_liheap_gross_income", period) - earned = spm_unit("ne_liheap_earned_income", period) - income = max_(gross - earned * p.earned_income_disregard, 0) - size = spm_unit("ne_liheap_household_size", period) - state_group = spm_unit.household("state_group_str", period) - # The payment bands stop growing at six people; eligibility does not. - # The Guidance footnote states the size-6+ tier cutoffs in "gross - # countable income", while the same page bases every payment on - # "income after the disregard is applied" with no size exception; the - # disregard is applied at every size here. - payment_fpg = fpg( - clip(size, 1, p.payment_size_limit), - state_group, - period, - parameters, - year_lag=p.fpg_year_lag, - ) - income_ratio = income / payment_fpg + income_ratio = spm_unit("ne_liheap_payment_fpg_ratio", period) fuel = spm_unit("heating_type", period) types = fuel.possible_values dwelling = spm_unit("ne_liheap_dwelling_type", period) diff --git a/policyengine_us/variables/gov/states/ne/dhhs/liheap/ne_liheap_fpg.py b/policyengine_us/variables/gov/states/ne/dhhs/liheap/ne_liheap_fpg.py index f9a45ebecdb..8065983f0d4 100644 --- a/policyengine_us/variables/gov/states/ne/dhhs/liheap/ne_liheap_fpg.py +++ b/policyengine_us/variables/gov/states/ne/dhhs/liheap/ne_liheap_fpg.py @@ -15,7 +15,8 @@ def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ne.dhhs.liheap size = spm_unit("ne_liheap_household_size", period) state_group = spm_unit.household("state_group_str", period) - # The annual period represents the heating season ending in that year. + # The annual period represents the federal fiscal year ending in that + # year, with its heating season and its June-August cooling season. # Household composition is current; only the federal guideline is lagged. amount = fpg( max_(size, 1), state_group, period, parameters, year_lag=p.fpg_year_lag diff --git a/policyengine_us/variables/gov/states/ne/dhhs/liheap/ne_liheap_payment_fpg_ratio.py b/policyengine_us/variables/gov/states/ne/dhhs/liheap/ne_liheap_payment_fpg_ratio.py new file mode 100644 index 00000000000..63f1f1df632 --- /dev/null +++ b/policyengine_us/variables/gov/states/ne/dhhs/liheap/ne_liheap_payment_fpg_ratio.py @@ -0,0 +1,34 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class ne_liheap_payment_fpg_ratio(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = "/1" + label = "Nebraska LIHEAP payment income as a share of the federal poverty guideline" + defined_for = StateCode.NE + # PDF pages 2-3 + reference = "https://dhhs.ne.gov/Documents/Low%20Income%20Home%20Energy%20Assistance%20Program%20%28LIHEAP%29%20Guidance%20Document%202026.pdf#page=2" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ne.dhhs.liheap + gross = spm_unit("ne_liheap_gross_income", period) + earned = spm_unit("ne_liheap_earned_income", period) + income = max_(gross - earned * p.earned_income_disregard, 0) + size = spm_unit("ne_liheap_household_size", period) + state_group = spm_unit.household("state_group_str", period) + # The heating and cooling payment bands stop growing at six people; + # eligibility does not. The Guidance footnotes state the size-6+ tier + # cutoffs in "gross countable income", while the same pages base every + # payment on "income after the disregard is applied" with no size + # exception; the disregard is applied at every size here. + payment_fpg = fpg( + clip(size, 1, p.payment_size_limit), + state_group, + period, + parameters, + year_lag=p.fpg_year_lag, + ) + return income / payment_fpg