diff --git a/changelog.d/ca-liheap-cooling.fixed.md b/changelog.d/ca-liheap-cooling.fixed.md new file mode 100644 index 00000000000..0b4368d5acd --- /dev/null +++ b/changelog.d/ca-liheap-cooling.fixed.md @@ -0,0 +1 @@ +Pay California's regular HEAP utility benefit to households with no heating that pay a gas or electric bill. diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 0f74596fd68..0b8f0204397 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1075,7 +1075,7 @@ programs: variable: ca_liheap_utility_heating parameter_prefix: gov.states.ca.csd.liheap verified_years: "2026" - notes: FY2026 regular utility heating on gas and electric accounts, Madera propane and fuel-oil heating, and statewide wood heating from an approved delivery cost; other liquid-fuel service areas and vendor-service supplements are not modeled. Crisis, cooling, weatherization and equipment assistance are out of scope. + notes: FY2026 regular utility benefit on gas and electric accounts, which also pays homes without heating on either bill, plus Madera propane and fuel-oil heating and statewide wood heating from an approved delivery cost; other liquid-fuel service areas and vendor-service supplements are not modeled. Crisis, weatherization and equipment assistance are out of scope. - state: CO status: partial name: Colorado LEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/csd/liheap/ca_liheap_utility_heating.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/csd/liheap/ca_liheap_utility_heating.yaml index 8d54dbb9977..8e2444a6588 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/csd/liheap/ca_liheap_utility_heating.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/csd/liheap/ca_liheap_utility_heating.yaml @@ -5254,7 +5254,8 @@ # bill. A wood home with an approved delivery takes that instead. Madera burden is # 2,040 / 12,000 = 17%, for 10 + 10 = 20 points: with a $12 propane bill WPO pays # 411 + 105 = 516; with no propane bill WPO pays nothing (contract 8.1.5.2, p. 364) -# and HEAP pays 702. NONE and UNSPECIFIED get $0 even with a utility bill. +# and HEAP pays 702. A home without heating takes HEAP on its electric bill +# (Alameda group 1, 484); UNSPECIFIED gets $0 even with a utility bill. - name: Case 15, another fuel takes the utility benefit only where no other component pays. period: 2026 absolute_error_margin: 0.01 @@ -5350,7 +5351,9 @@ state_code: CA county: ALAMEDA_COUNTY_CA output: - ca_liheap_utility_heating: [716, 716, 0, 0, 702, 0, 0] + # Was 0, now 484 for spm_unit6: the guide asks only for responsibility for + # energy costs (p. 193). + ca_liheap_utility_heating: [716, 716, 0, 0, 702, 484, 0] ca_liheap_wood_heating: [0, 0, 600, 0, 0, 0, 0] ca_liheap_covered_liquid_heating: [0, 0, 0, 516, 0, 0, 0] @@ -5430,3 +5433,54 @@ ca_liheap_energy_burden_group: [1, 4, 3, 0, 0] ca_liheap_madera_priority_points: [8, 20, 18, 0, 0] ca_liheap_utility_heating: [0, 702, 0, 702, 434] + +# Plan p. 55: HEAP payments on electric bills from July 1 to October 31 are +# cooling, paid from the same county table (pp. 182-184) with no bill cap. A +# desert home in Imperial County with no heating pays an electric bill for air +# conditioning. One adult with wages of $12,000 ($1,000 a month) is poverty +# group 1: Imperial pays $621. The guide has no cooling-cost condition, so the +# same home without a cooling cost also receives $621 on its electric bill. +- name: Case 17, a home without heating receives the county utility amount on its electric bill. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + employment_income_before_lsr: 12_000 + person2: + age: 40 + is_citizen_or_legal_immigrant: true + ssi: 0 + employment_income_before_lsr: 12_000 + spm_units: + spm_unit1: + members: [person1] + heating_type: NONE + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_200 + snap: 0 + tanf: 0 + ca_state_supplement: 0 + spm_unit2: + members: [person2] + heating_type: NONE + has_cooling_expense: false + pre_subsidy_electricity_expense: 1_200 + snap: 0 + tanf: 0 + ca_state_supplement: 0 + households: + household1: + members: [person1] + state_code: CA + county: IMPERIAL_COUNTY_CA + household2: + members: [person2] + state_code: CA + county: IMPERIAL_COUNTY_CA + output: + ca_liheap_income_group: [1, 1] + ca_liheap_utility_heating: [621, 621] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/csd/liheap/eligibility/ca_liheap_utility_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/csd/liheap/eligibility/ca_liheap_utility_eligible.yaml index 782cce03ab4..868d96e0fc4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/csd/liheap/eligibility/ca_liheap_utility_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/csd/liheap/eligibility/ca_liheap_utility_eligible.yaml @@ -213,7 +213,9 @@ - false # Guide p. 221: the applicant names the utility account that takes the benefit, so -# any known fuel qualifies on a gas or electric bill. NONE and UNSPECIFIED do not. +# any known fuel qualifies on a gas or electric bill. So does a home without heating, +# since the guide asks only for responsibility for energy costs (p. 193). UNSPECIFIED +# does not. # A wood home with an approved delivery takes that payment instead (contract # 8.1.2, p. 363). Heat in rent gives a propane home no utility account. - name: Case 3, a gas or electric bill opens the utility benefit to every known fuel. @@ -344,4 +346,77 @@ state_code: CA county: ALAMEDA_COUNTY_CA output: - ca_liheap_utility_eligible: [true, true, true, true, true, true, false, false, false, false] + # Was false, now true for spm_unit7: a home without heating qualifies on its + # electric bill. + ca_liheap_utility_eligible: [true, true, true, true, true, true, true, false, false, false] + +# Plan p. 55 reports HEAP payments on electric bills from July 1 to October 31 +# as cooling, within the one HEAP benefit a year (guide p. 193). A home without +# heating qualifies on an electric bill it pays for cooling, and on a gas bill +# alone without any cooling cost: the guide asks only that the household be +# responsible for energy costs (p. 193). UNSPECIFIED fuel still gets nothing. +# Wages of 40,500 exceed the 39,979.92 one-person limit (p. 184). +- name: Case 4, a home without heating qualifies on a gas or electric bill. + period: 2026 + input: + people: + person1: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0} + person2: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0} + person3: {age: 35, is_citizen_or_legal_immigrant: true, ssi: 0} + person4: + age: 35 + is_citizen_or_legal_immigrant: true + ssi: 0 + employment_income_before_lsr: 40_500 + spm_units: + spm_unit1: + members: [person1] + heating_type: NONE + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_200 + snap: 0 + tanf: 0 + ca_state_supplement: 0 + spm_unit2: + members: [person2] + heating_type: NONE + has_cooling_expense: false + gas_expense: 600 + snap: 0 + tanf: 0 + ca_state_supplement: 0 + spm_unit3: + members: [person3] + heating_type: UNSPECIFIED + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_200 + snap: 0 + tanf: 0 + ca_state_supplement: 0 + spm_unit4: + members: [person4] + heating_type: NONE + has_cooling_expense: true + pre_subsidy_electricity_expense: 1_200 + snap: 0 + tanf: 0 + ca_state_supplement: 0 + households: + household1: + members: [person1] + state_code: CA + county: IMPERIAL_COUNTY_CA + household2: + members: [person2] + state_code: CA + county: IMPERIAL_COUNTY_CA + household3: + members: [person3] + state_code: CA + county: IMPERIAL_COUNTY_CA + household4: + members: [person4] + state_code: CA + county: IMPERIAL_COUNTY_CA + output: + ca_liheap_utility_eligible: [true, true, false, false] diff --git a/policyengine_us/variables/gov/states/ca/csd/liheap/ca_liheap_utility_heating.py b/policyengine_us/variables/gov/states/ca/csd/liheap/ca_liheap_utility_heating.py index b996436f671..914987bca7f 100644 --- a/policyengine_us/variables/gov/states/ca/csd/liheap/ca_liheap_utility_heating.py +++ b/policyengine_us/variables/gov/states/ca/csd/liheap/ca_liheap_utility_heating.py @@ -6,7 +6,9 @@ class ca_liheap_utility_heating(Variable): entity = SPMUnit definition_period = YEAR unit = USD - label = "California LIHEAP regular gas or electric utility heating benefit" + label = ( + "California LIHEAP regular gas or electric utility heating or cooling benefit" + ) defined_for = "ca_liheap_utility_eligible" # PDF pages 182-184 reference = "https://www.csd.ca.gov/Shared%20Documents/2026-Final-LIHEAP-State-Plan.pdf#page=182" diff --git a/policyengine_us/variables/gov/states/ca/csd/liheap/eligibility/ca_liheap_utility_eligible.py b/policyengine_us/variables/gov/states/ca/csd/liheap/eligibility/ca_liheap_utility_eligible.py index 7b044a7b560..56d80b09073 100644 --- a/policyengine_us/variables/gov/states/ca/csd/liheap/eligibility/ca_liheap_utility_eligible.py +++ b/policyengine_us/variables/gov/states/ca/csd/liheap/eligibility/ca_liheap_utility_eligible.py @@ -5,10 +5,10 @@ class ca_liheap_utility_eligible(Variable): value_type = bool entity = SPMUnit definition_period = YEAR - label = "California LIHEAP utility heating eligibility" + label = "California LIHEAP utility heating or cooling eligibility" defined_for = StateCode.CA reference = ( - # PDF pages 9,182-184,193,202-203,205,219,221,264-265,279,363 + # PDF pages 9,55,182-184,193,202-203,205,219,221,264-265,279,363 "https://www.csd.ca.gov/Shared%20Documents/2026-Final-LIHEAP-State-Plan.pdf#page=9", # PDF pages 189,233-234 "https://maderacap.org/wp-content/uploads/2025/10/Agenda-and-Packet-for-October-9-2025-Updated.pdf#page=189", @@ -21,13 +21,17 @@ def formula(spm_unit, period, parameters): utility_heat = np.isin( heating_type.decode_to_str(), p.eligibility.utility_heating_fuels ) - known_fuel = (heating_type != types.NONE) & (heating_type != types.UNSPECIFIED) + # heating_type is a required input; UNSPECIFIED does not qualify. + heating_type_reported = heating_type != types.UNSPECIFIED utility_bills = add( spm_unit, period, ["pre_subsidy_electricity_expense", "gas_expense"] ) - # The applicant names the utility account that takes the benefit, so a - # home heated with another fuel qualifies on a gas or electric bill. - utility_account = utility_heat | (known_fuel & (utility_bills > 0)) + # The household must be responsible for energy costs (guide 1.1 and + # 1.6), and the applicant names the utility account that takes the + # benefit. So a home heated with another fuel, or without heating, + # qualifies on a gas or electric bill. HEAP payments on electric bills + # from July 1 to October 31 are reported as cooling. + utility_account = utility_heat | (heating_type_reported & (utility_bills > 0)) # A household receives one HEAP or WPO payment per program year. other_component = ( add(