diff --git a/changelog.d/ok-liheap-cooling.added.md b/changelog.d/ok-liheap-cooling.added.md new file mode 100644 index 00000000000..971601f7af4 --- /dev/null +++ b/changelog.d/ok-liheap-cooling.added.md @@ -0,0 +1 @@ +Add Oklahoma LIHEAP regular summer cooling assistance, the Appendix C-7-A flat payment by household size and net monthly income. diff --git a/policyengine_us/parameters/gov/hhs/liheap/regular_payments.yaml b/policyengine_us/parameters/gov/hhs/liheap/regular_payments.yaml index e811bea6fbd..8ba968c0efb 100644 --- a/policyengine_us/parameters/gov/hhs/liheap/regular_payments.yaml +++ b/policyengine_us/parameters/gov/hhs/liheap/regular_payments.yaml @@ -40,6 +40,7 @@ values: - ny_heap # New York HEAP - oh_liheap # Ohio HEAP - ok_liheap # Oklahoma LIHEAP + - ok_liheap_cooling # Oklahoma LIHEAP cooling - or_liheap # Oregon LIHEAP - pa_liheap # Pennsylvania LIHEAP - ri_liheap # Rhode Island LIHEAP diff --git a/policyengine_us/parameters/gov/states/ok/dhs/liheap/cooling/amount.yaml b/policyengine_us/parameters/gov/states/ok/dhs/liheap/cooling/amount.yaml new file mode 100644 index 00000000000..1514229d3d7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/dhs/liheap/cooling/amount.yaml @@ -0,0 +1,47 @@ +description: Oklahoma provides this summer cooling payment by net monthly income band and household size group under the Low Income Home Energy Assistance Program. +# The same amount applies to every cooling energy source and to renters, +# roomers and boarders with utilities included in their rent (OAC +# 340:20-1-20(d)(1)). The FY2026 and FY2027 plans' $650 maximum is the +# largest cell; their $150 minimum is the cooling equipment reimbursement cap. + +# Net monthly income band 1: $0 - $700. +1: + # Household size 1. + 1: + 2021-10-01: 500 + # Household size 2 or more. + 2: + 2021-10-01: 650 +# Net monthly income band 2: $701 to the income limit. +2: + 1: + 2021-10-01: 385 + 2: + 2021-10-01: 425 + +metadata: + unit: currency-USD + period: year + label: Oklahoma LIHEAP summer cooling payment + propagate_metadata_to_children: true + breakdown: + - range(1, 3) + - range(1, 3) + breakdown_labels: + - Net monthly income band + - Household size group + reference: + - title: OKDHS Appendix C-7-A, Summer Cooling Program + href: https://oklahoma.gov/content/dam/ok/en/okdhs/documents/searchcenter/okdhsformresults/c-7-a.pdf#page=2 + - title: Oklahoma FY2026 Benefits Matrix + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/OK_BenefitMatrix_2026.docx + - title: Oklahoma FY2025 State Plan, Sections 3.5-3.7 + href: https://liheapch.acf.gov/docs/2025/state-plans/OK_Plan_2025.pdf#page=12 + - title: Oklahoma FY2026 State Plan, Sections 3.5-3.7 + href: https://liheapch.acf.gov/docs/2026/state-plans/OK_Plan_2026.pdf#page=12 + - title: Oklahoma FY2027 State Plan, Sections 3.5-3.7 + href: https://liheapch.acf.gov/docs/2027/state-plans/OK_Plan_2027.pdf#page=16 + - title: OAC 340:20-1-10(i)(2) and 340:20-1-20(d), as amended effective 9-15-26 + href: https://prod-ok-administrativerules.tecuity.com/api/BlobStorageGetFile?storageContainer=TitleHtml&name=Title_340.html + - title: OAC 340:20-1-20(d), September 2025 permanent adoption + href: https://oklahoma.gov/content/dam/ok/en/omma/content/rulemaking-process/rules/Register_Volume-42_Issue-20.pdf#page=588 diff --git a/policyengine_us/parameters/gov/states/ok/dhs/liheap/cooling/household_size_group.yaml b/policyengine_us/parameters/gov/states/ok/dhs/liheap/cooling/household_size_group.yaml new file mode 100644 index 00000000000..96a1e4c0af2 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/dhs/liheap/cooling/household_size_group.yaml @@ -0,0 +1,23 @@ +description: Oklahoma uses this household-size group for the summer cooling payment under the Low Income Home Energy Assistance Program. +# Appendix C-7-A prints one row for household size 1 and one for "2 or more". +brackets: + - threshold: + 2021-10-01: 0 + amount: + 2021-10-01: 1 + - threshold: + 2021-10-01: 2 + amount: + 2021-10-01: 2 + +metadata: + type: single_amount + threshold_unit: person + amount_unit: /1 + period: year + label: Oklahoma LIHEAP summer cooling household size group + reference: + - title: OKDHS Appendix C-7-A, Summer Cooling Program + href: https://oklahoma.gov/content/dam/ok/en/okdhs/documents/searchcenter/okdhsformresults/c-7-a.pdf#page=2 + - title: Oklahoma FY2026 Benefits Matrix + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/OK_BenefitMatrix_2026.docx diff --git a/policyengine_us/parameters/gov/states/ok/dhs/liheap/cooling/income_band.yaml b/policyengine_us/parameters/gov/states/ok/dhs/liheap/cooling/income_band.yaml new file mode 100644 index 00000000000..99612f133d7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/dhs/liheap/cooling/income_band.yaml @@ -0,0 +1,25 @@ +description: Oklahoma uses this net monthly income band for the summer cooling payment under the Low Income Home Energy Assistance Program. +# Appendix C-7-A prints "$0 - $700" and "$701 - ineligible"; the printed lower +# bounds are inclusive. Monthly net income is rounded half up to the nearest +# dollar before the lookup (OAC 340:20-1-11(a)). +brackets: + - threshold: + 2021-10-01: 0 + amount: + 2021-10-01: 1 + - threshold: + 2021-10-01: 701 + amount: + 2021-10-01: 2 + +metadata: + type: single_amount + threshold_unit: currency-USD + amount_unit: /1 + period: month + label: Oklahoma LIHEAP summer cooling net monthly income band + reference: + - title: OKDHS Appendix C-7-A, Summer Cooling Program + href: https://oklahoma.gov/content/dam/ok/en/okdhs/documents/searchcenter/okdhsformresults/c-7-a.pdf#page=2 + - title: Oklahoma FY2026 Benefits Matrix + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/OK_BenefitMatrix_2026.docx diff --git a/policyengine_us/parameters/gov/states/ok/dhs/liheap/income/limit/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/ok/dhs/liheap/income/limit/fpg_year_lag.yaml index 3bdb3084c7e..2e110ebb1a1 100644 --- a/policyengine_us/parameters/gov/states/ok/dhs/liheap/income/limit/fpg_year_lag.yaml +++ b/policyengine_us/parameters/gov/states/ok/dhs/liheap/income/limit/fpg_year_lag.yaml @@ -1,4 +1,4 @@ -description: Oklahoma uses the federal poverty guideline from this many years before the heating benefit year under the Low Income Home Energy Assistance Program. +description: Oklahoma uses the federal poverty guideline from this many years before the benefit year under the Low Income Home Energy Assistance Program. # HHS makes each January's poverty guidelines mandatory for LIHEAP from the # next October 1 (LIHEAP IM 2024-02, IM 2025-02 and IM 2026-01), so FY2025 # uses the 2024 guidelines, FY2026 the 2025 and FY2027 the 2026. Plan item diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 6f704d520fb..89537adbb0d 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1123,7 +1123,15 @@ programs: variable: ok_liheap parameter_prefix: gov.states.ok.dhs.liheap verified_years: "2025-2027" - notes: FY2025-FY2027 regular winter heating only, using the Appendix C-7-A payment matrix. Crisis, cooling, weatherization and equipment assistance are out of scope. + notes: FY2025-FY2027 regular winter heating only, using the Appendix C-7-A payment matrix. Summer cooling is listed separately; crisis, weatherization and equipment assistance are out of scope. + - state: OK + status: partial + name: Oklahoma LIHEAP cooling + full_name: Oklahoma Low Income Home Energy Assistance Program summer cooling + variable: ok_liheap_cooling + parameter_prefix: gov.states.ok.dhs.liheap.cooling + verified_years: "2025-2027" + notes: FY2025-FY2027 regular summer cooling payment from the Appendix C-7-A flat amounts by household size and net monthly income, for households with cooling costs. The cooling equipment reimbursement, crisis and weatherization assistance are out of scope. - state: PA status: partial name: Pennsylvania LIHEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling.yaml new file mode 100644 index 00000000000..bb92b3ed358 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling.yaml @@ -0,0 +1,305 @@ +# Oklahoma LIHEAP summer cooling cases. +# OKDHS Appendix C-7-A page 2, Summer Cooling Program: household size 1 receives 500 at +# net monthly income $0 - $700 and 385 at $701 - ineligible; size 2 or more receives +# 650 and 425. OAC 340:20-1-11(a) rounds monthly income half up to the nearest dollar. +# Appendix C-7 deducts up to 240 a month (2,880 a year) of each worker's earnings +# before the net income band. Wages of 15,080 are full-time work at the 7.25 +# Oklahoma minimum wage (7.25 x 40 x 52); 9,425 is 25 hours a week at that wage. +# The cooling amount uses no bill, so cases carry only the bills a heating +# comparison needs. + +- name: Case 1, zero net income from a business loss receives the size-one amount for the lowest band. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + self_employment_income: -5_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + has_cooling_expense: true + households: + household: + members: [person1] + state_code: OK + output: + # max(-5,000, 0) = 0 gross and net income -> $0 - $700, size 1 + ok_liheap_net_income: 0 + ok_liheap_cooling: 500 + +- name: Case 2, net monthly income of exactly 700 stays in the higher band and 701 moves to the lower one. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [OK, OK] + age: [40, 40] + employment_income_before_lsr: [11_280, 11_292] + heating_type: [ELECTRICITY, ELECTRICITY] + has_cooling_expense: [true, true] + output: + # 11,280 - 2,880 = 8,400 -> 700 a month; 11,292 - 2,880 = 8,412 -> 701. + ok_liheap_net_income: [8_400, 8_412] + ok_liheap_cooling: [500, 385] + +- name: Case 3, a parent and child with low net income receive the larger-household amount for the lowest band. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 9_425 + person2: + age: 8 + spm_units: + spm_unit: + members: [person1, person2] + # Not receiving TANF or Child Care Subsidy. + tanf: 0 + ok_child_care_subsidies: 0 + heating_type: ELECTRICITY + has_cooling_expense: true + households: + household: + members: [person1, person2] + state_code: OK + output: + # Gross 9,425 / 12 = 785 <= 2,292 (size 2). Net 9,425 - 2,880 = 6,545 + # -> 545 a month: $0 - $700, size 2 or more + ok_liheap_cooling: 650 + +- name: Case 4, a parent and child in a home with no heating receive the cooling payment only. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 15_080 + person2: + age: 8 + spm_units: + spm_unit: + members: [person1, person2] + tanf: 0 + ok_child_care_subsidies: 0 + heating_type: NONE + has_cooling_expense: true + households: + household: + members: [person1, person2] + state_code: OK + output: + # Winter heating requires a heating fuel. + ok_liheap: 0 + # Net 15,080 - 2,880 = 12,200 -> 1,017 a month: $701 - ineligible, size 2 + # or more + ok_liheap_cooling: 425 + # The national LIHEAP total is the cooling payment alone: 0 + 425. + liheap: 425 + +- name: Case 5, a household without cooling costs receives no cooling payment. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income_before_lsr: 15_080 + spm_units: + spm_unit: + members: [person1] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + has_cooling_expense: false + households: + household: + members: [person1] + state_code: OK + output: + # The electric bill qualifies the household for winter heating: net 1,017 + # a month, C-7-A page 1 natural gas, electricity, wood or coal, size 1-3, + # $701 - ineligible. + ok_liheap: 235 + ok_liheap_cooling: 0 + +- name: Case 6, gross income above the size-one limit receives no cooling payment. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income_before_lsr: 21_000 + spm_units: + spm_unit: + members: [person1] + heating_type: ELECTRICITY + has_cooling_expense: true + households: + household: + members: [person1] + state_code: OK + output: + # 21,000 / 12 = 1,750 > 1,696, the FY2026 size-one limit. + ok_liheap_cooling: 0 + +- name: Case 7, the FY2025 summer cooling payment uses the same amounts. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income_before_lsr: 15_080 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + has_cooling_expense: true + households: + household: + members: [person1] + state_code: OK + output: + # Gross 1,257 <= 1,632 (FY2025 size one). Net 12,200 -> 1,017 a month: + # $701 - ineligible, size 1 + ok_liheap_cooling: 385 + +- name: Case 8, the FY2027 summer cooling payment uses the same amounts. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 9_425 + person2: + age: 8 + spm_units: + spm_unit: + members: [person1, person2] + tanf: 0 + ok_child_care_subsidies: 0 + heating_type: NATURAL_GAS + has_cooling_expense: true + households: + household: + members: [person1, person2] + state_code: OK + output: + # Gross 785 <= 2,345 (FY2027 size 2). Net 545 a month: $0 - $700, size 2 or + # more + ok_liheap_cooling: 650 + +- name: Case 9, an unspecified heating fuel receives the same cooling payment as a home with no heating. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 15_080 + person2: + age: 8 + spm_units: + spm_unit: + members: [person1, person2] + tanf: 0 + ok_child_care_subsidies: 0 + heating_type: UNSPECIFIED + has_cooling_expense: true + households: + household: + members: [person1, person2] + state_code: OK + output: + # Otherwise identical to Case 4, which pays 425 with heating_type NONE. + # Was 0, now 425: the cooling payment adds no heating-fuel condition. + ok_liheap_cooling: 425 + +- name: Case 10, net monthly income of 700.42 rounds to the higher band and 700.50 rounds up to the lower one. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [OK, OK] + age: [40, 40] + employment_income_before_lsr: [11_285, 11_286] + heating_type: [ELECTRICITY, ELECTRICITY] + has_cooling_expense: [true, true] + output: + # Gross 940 and 941 a month <= 1,696. 11,285 - 2,880 = 8,405 -> 700.42 a + # month -> 700; 11,286 - 2,880 = 8,406 -> 700.50 -> 701. Unrounded, 700.50 + # is below 701 and would pay 500. + ok_liheap_net_income: [8_405, 8_406] + ok_liheap_cooling: [500, 385] + +- name: Case 11, a household with heating and cooling costs receives both payments in one year. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + employment_income_before_lsr: 15_080 + spm_units: + spm_unit: + members: [person1] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_200 + has_cooling_expense: true + households: + household: + members: [person1] + state_code: OK + output: + # Case 5 with a cooling cost. Net 1,017 a month: winter heating pays 235 + # (natural gas, electricity, wood or coal, size 1-3, $701 - ineligible) and + # summer cooling pays 385 (size 1, $701 - ineligible). OAC 340:20-1-10(c)(4) + # allows one authorization per application-based assistance period. + ok_liheap: 235 + ok_liheap_cooling: 385 + # The national LIHEAP total is 235 + 385. + liheap: 620 + +- name: Case 12, a roomer household of four with utilities in the rent receives the full cooling amount. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 15_080 + person2: + age: 30 + person3: + age: 6 + person4: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + tanf: 0 + ok_child_care_subsidies: 0 + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + ok_liheap_dwelling_type: ROOMER + # Utility surcharge on the rent receipt: $50 a month in six winter months. + gas_expense: 300 + # The verified utility surcharge on the rent stands for the cooling cost. + has_cooling_expense: true + households: + household: + members: [person1, person2, person3, person4] + state_code: OK + output: + # Gross 15,080 / 12 = 1,257 <= 3,483 (size 4). Net 12,200 -> 1,017 a month. + # The winter roomer schedule pays 0 at size 4 or more; summer cooling pays + # roomers the same amount as other households: $701 - ineligible, size 2 or + # more. + ok_liheap_eligible: true + ok_liheap: 0 + ok_liheap_cooling: 425 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling_eligible.yaml new file mode 100644 index 00000000000..f91585de71d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling_eligible.yaml @@ -0,0 +1,87 @@ +# Oklahoma LIHEAP summer cooling eligibility. +# OAC 340:20-1-10(h): responsibility for home energy costs, gross income at or below +# Appendix C-7 (130% of the poverty guideline, the limit winter heating uses), and at +# least one eligible member. Monthly size-one limits: FY2025 1,632, FY2026 1,696 +# (also printed in the July 14, 2026 summer cooling release), FY2027 1,729. Wages of +# 15,080 are full-time work at the 7.25 Oklahoma minimum wage (7.25 x 40 x 52). + +- name: Case 1, a home with no heating is cooling eligible like a home with a known heating fuel. + period: 2026 + input: + state_code: [OK, OK] + age: [40, 40] + employment_income_before_lsr: [15_080, 15_080] + heating_type: [NONE, NATURAL_GAS] + gas_expense: [0, 600] + has_cooling_expense: [true, true] + output: + # Winter heating needs a heating fuel; summer cooling does not. + ok_liheap_eligible: [false, true] + ok_liheap_cooling_eligible: [true, true] + +- name: Case 2, the FY2026 limit admits gross income of 1,667 a month but not 1,700. + period: 2026 + input: + state_code: [OK, OK] + age: [40, 40] + employment_income_before_lsr: [20_000, 20_400] + heating_type: [ELECTRICITY, ELECTRICITY] + has_cooling_expense: [true, true] + output: + # 20,000 / 12 = 1,666.67 -> 1,667 <= 1,696; 20,400 / 12 = 1,700 > 1,696. + ok_liheap_cooling_eligible: [true, false] + +- name: Case 3, the lower FY2025 limit excludes gross income of 1,667 a month. + period: 2025 + input: + state_code: [OK] + age: [40] + employment_income_before_lsr: [20_000] + heating_type: [ELECTRICITY] + has_cooling_expense: [true] + output: + # 1,667 > 1,632. + ok_liheap_cooling_eligible: [false] + +- name: Case 4, the higher FY2027 limit admits gross income of 1,700 a month. + period: 2027 + input: + state_code: [OK] + age: [40] + employment_income_before_lsr: [20_400] + heating_type: [ELECTRICITY] + has_cooling_expense: [true] + output: + # 1,700 <= 1,729. + ok_liheap_cooling_eligible: [true] + +- name: Case 5, a household with no eligible member is ineligible. + period: 2026 + input: + state_code: [OK] + age: [40] + immigration_status: [UNDOCUMENTED] + employment_income_before_lsr: [15_080] + heating_type: [ELECTRICITY] + has_cooling_expense: [true] + output: + # The undocumented member is excluded from household size, and the deemed + # income of 15,080 - 2,880 - 398 x 12 = 7,424 (619 a month) exceeds the + # size-0 limit of 0. + ok_liheap_cooling_eligible: [false] + +- name: Case 6, a household with no eligible member is ineligible even when it passes the income test. + period: 2026 + input: + state_code: [OK] + age: [40] + immigration_status: [UNDOCUMENTED] + employment_income_before_lsr: [7_000] + heating_type: [ELECTRICITY] + has_cooling_expense: [true] + output: + # Deemed income max(7,000 - 2,880 - 398 x 12, 0) = 0 meets the size-0 limit + # of 0, so the household size of 0 alone makes the household ineligible. + ok_liheap_income_eligible: [true] + ok_liheap_cooling_eligible: [false] + ok_liheap_cooling: [0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/dhs/liheap/eligibility/ok_liheap_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/dhs/liheap/eligibility/ok_liheap_income_eligible.yaml new file mode 100644 index 00000000000..dabf4eb4662 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/dhs/liheap/eligibility/ok_liheap_income_eligible.yaml @@ -0,0 +1,14 @@ +# Oklahoma LIHEAP gross income test shared by winter heating and summer cooling. +# OAC 340:20-1-10(h)(2), 340:20-1-11(a); FY2026 Appendix C-7 size-one limit 1,696 a +# month (20,352 a year), inclusive, after rounding monthly gross income half up: +# 20,352 / 12 = 1,696.00; 20,357 / 12 = 1,696.42 -> 1,696; 20,358 / 12 = 1,696.50 +# -> 1,697. + +- name: Case 1, the gross limit is inclusive after rounding monthly income half up. + period: 2026 + input: + state_code: [OK, OK, OK] + age: [40, 40, 40] + ok_liheap_gross_income: [20_352, 20_357, 20_358] + output: + ok_liheap_income_eligible: [true, true, false] diff --git a/policyengine_us/variables/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling.py b/policyengine_us/variables/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling.py new file mode 100644 index 00000000000..75d70dd4a50 --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling.py @@ -0,0 +1,32 @@ +from policyengine_us.model_api import * + + +class ok_liheap_cooling(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Oklahoma LIHEAP regular summer cooling assistance" + defined_for = "ok_liheap_cooling_eligible" + # OAC 340:20-1-10(i)(2): "summer cooling is based on household size and + # net income"; 340:20-1-20(d) refers to Appendix C-7-A for the amounts. + reference = ( + "https://prod-ok-administrativerules.tecuity.com/api/BlobStorageGetFile?storageContainer=TitleHtml&name=Title_340.html", + "https://oklahoma.gov/content/dam/ok/en/okdhs/documents/searchcenter/okdhsformresults/c-7-a.pdf#page=2", + # PDF pages 4, 12 + "https://liheapch.acf.gov/docs/2026/state-plans/OK_Plan_2026.pdf#page=4", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ok.dhs.liheap.cooling + size = spm_unit("ok_liheap_household_size", period) + # OAC 340:20-1-11(a) rounds monthly income to the nearest dollar, and + # Appendix C-7-A prints whole-dollar bands, so round half up first. + net_income = spm_unit("ok_liheap_net_income", period) + monthly_income = np.floor(net_income / MONTHS_IN_YEAR + 0.5) + band = p.income_band.calc(monthly_income).astype(int) + size_group = p.household_size_group.calc(size).astype(int) + # One payment per household each year, the same for every cooling + # energy source and dwelling, with no bill cap. The equipment + # reimbursement, which replaces the bill payment, is not modeled. + return p.amount[band][size_group] diff --git a/policyengine_us/variables/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling_eligible.py b/policyengine_us/variables/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling_eligible.py new file mode 100644 index 00000000000..5df74413cea --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling_eligible.py @@ -0,0 +1,32 @@ +from policyengine_us.model_api import * + + +class ok_liheap_cooling_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Eligible for Oklahoma LIHEAP summer cooling assistance" + defined_for = StateCode.OK + # OAC 340:20-1-10(b)(2), (e) and (h), 340:20-1-20(d): eligible size, the + # gross income test heating uses, and responsibility for cooling costs. + reference = ( + "https://prod-ok-administrativerules.tecuity.com/api/BlobStorageGetFile?storageContainer=TitleHtml&name=Title_340.html", + # PDF pages 574-576, 588-589 + "https://oklahoma.gov/content/dam/ok/en/omma/content/rulemaking-process/rules/Register_Volume-42_Issue-20.pdf#page=574", + # PDF pages 11-12 + "https://liheapch.acf.gov/docs/2026/state-plans/OK_Plan_2026.pdf#page=11", + ) + + def formula(spm_unit, period, parameters): + size = spm_unit("ok_liheap_household_size", period) + income_eligible = spm_unit("ok_liheap_income_eligible", period) + # OAC 340:20-1-10(h)(1) requires total or partial responsibility for + # home energy costs, here the cooling cost; a renter with utilities in + # the rent qualifies through a verified surcharge (340:20-1-20(d)). + responsible = spm_unit("has_cooling_expense", period) + # The main cooling energy source is approved during the summer period + # (340:20-1-10(b)(2)) and the amount depends only on household size + # and net income (340:20-1-10(i)(2)), so the heating fuel is not read. + # Pre-authorization, roomer relatedness and tribal LIHEAP receipt have + # no existing inputs. + return (size > 0) & income_eligible & responsible diff --git a/policyengine_us/variables/gov/states/ok/dhs/liheap/eligibility/ok_liheap_eligible.py b/policyengine_us/variables/gov/states/ok/dhs/liheap/eligibility/ok_liheap_eligible.py index 1816468d7be..28f5d273e24 100644 --- a/policyengine_us/variables/gov/states/ok/dhs/liheap/eligibility/ok_liheap_eligible.py +++ b/policyengine_us/variables/gov/states/ok/dhs/liheap/eligibility/ok_liheap_eligible.py @@ -27,13 +27,7 @@ class ok_liheap_eligible(Variable): def formula(spm_unit, period, parameters): size = spm_unit("ok_liheap_household_size", period) - # OAC 340:20-1-11(a) converts income to a monthly amount and rounds it - # to the nearest dollar; Appendix C-7 prints whole-dollar monthly - # limits. Rounding the monthly total half up approximates the - # per-source rounding. - income = spm_unit("ok_liheap_gross_income", period) - monthly_income = np.floor(income / MONTHS_IN_YEAR + 0.5) - monthly_limit = spm_unit("ok_liheap_income_limit", period) / MONTHS_IN_YEAR + income_eligible = spm_unit("ok_liheap_income_eligible", period) fuel = spm_unit("heating_type", period) heat_in_rent = spm_unit("heat_expense_included_in_rent", period) # OAC 340:20-1-19(d)(1) pays "renters, roomers, and boarders who pay a @@ -66,7 +60,7 @@ def formula(spm_unit, period, parameters): # LIHEAP receipt are not available as existing inputs. return ( (size > 0) - & (monthly_income <= monthly_limit) + & income_eligible & (fuel != fuel.possible_values.NONE) & (has_bill | pays_directly) ) diff --git a/policyengine_us/variables/gov/states/ok/dhs/liheap/eligibility/ok_liheap_income_eligible.py b/policyengine_us/variables/gov/states/ok/dhs/liheap/eligibility/ok_liheap_income_eligible.py new file mode 100644 index 00000000000..b2f94c92531 --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/dhs/liheap/eligibility/ok_liheap_income_eligible.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class ok_liheap_income_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Oklahoma LIHEAP income eligible" + defined_for = StateCode.OK + # OAC 340:20-1-10(h)(2), 340:20-1-11(a): gross income including deemed + # contributions at or below the Appendix C-7 standard, which winter + # heating and summer cooling share (plan items 2.1 and 3.1). + reference = ( + "https://prod-ok-administrativerules.tecuity.com/api/BlobStorageGetFile?storageContainer=TitleHtml&name=Title_340.html", + "https://oklahoma.gov/content/dam/ok/en/okdhs/documents/searchcenter/okdhsformresults/c-7.pdf", + # PDF pages 9, 11 + "https://liheapch.acf.gov/docs/2026/state-plans/OK_Plan_2026.pdf#page=9", + ) + + def formula(spm_unit, period, parameters): + # OAC 340:20-1-11(a) converts income to a monthly amount and rounds it + # to the nearest dollar; Appendix C-7 prints whole-dollar monthly + # limits. Rounding the monthly total half up approximates the + # per-source rounding. + income = spm_unit("ok_liheap_gross_income", period) + monthly_income = np.floor(income / MONTHS_IN_YEAR + 0.5) + monthly_limit = spm_unit("ok_liheap_income_limit", period) / MONTHS_IN_YEAR + return monthly_income <= monthly_limit diff --git a/policyengine_us/variables/gov/states/ok/dhs/liheap/income/ok_liheap_net_income.py b/policyengine_us/variables/gov/states/ok/dhs/liheap/income/ok_liheap_net_income.py index a6ab9e7712d..7ca0a843a80 100644 --- a/policyengine_us/variables/gov/states/ok/dhs/liheap/income/ok_liheap_net_income.py +++ b/policyengine_us/variables/gov/states/ok/dhs/liheap/income/ok_liheap_net_income.py @@ -6,7 +6,7 @@ class ok_liheap_net_income(Variable): entity = SPMUnit definition_period = YEAR unit = USD - label = "Oklahoma LIHEAP net income for regular heating assistance" + label = "Oklahoma LIHEAP net income for regular heating and cooling assistance" defined_for = StateCode.OK reference = ( # OAC 340:20-1-11(a)(4), (c): do not repeat deductions already diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 352bbc3a578..cbfdf8d0c63 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -9248,6 +9248,41 @@ candidates: note: 'PE-US follows the regulation: earnings are excluded only for a tax-unit dependent under the age limit who attends K-12 school, with tax dependency standing in for parental control (ok_liheap_countable_earned_income.py, income/student_earned_income_age_limit.yaml). Verify whether the broader plan checkbox reflects actual practice.' +- id: us-ok:liheap-cooling-income-boundary + program: liheap + years: + from: 2025 + to: 2027 + type: federal-fiscal + question: Does net monthly income of exactly $700 receive Oklahoma's larger summer cooling payment, as Appendix + C-7-A's "$0 - $700" band says, although the state plan grants the larger benefit to incomes "under $700"? + sources: + - kind: regulation + citation: OAC 340:20-1-20(d) and OKDHS Appendix C-7-A, page 2 (Summer Cooling Program) + url: https://oklahoma.gov/content/dam/ok/en/okdhs/documents/searchcenter/okdhsformresults/c-7-a.pdf#page=2 + - kind: plan + citation: FY2026 Oklahoma LIHEAP State Plan section 3.5, page 12 (repeated in the FY2025 plan, page 12, and the + FY2027 plan, page 16) + url: https://liheapch.acf.gov/docs/2026/state-plans/OK_Plan_2026.pdf#page=12 + readings: + statute: No statute supplied; OAC 340:20-1-20(d) refers to Appendix C-7-A for the summer cooling benefit amounts. + Page 2 of the appendix pays the larger amount at net monthly income "$0 - $700" and the smaller amount at + "$701 - ineligible". + other: Plan section 3.5 says "The cooling program grants a larger benefit to households with net monthly incomes + under $700." + example: A one-person household with net monthly income of exactly $700 receives $500 under Appendix C-7-A and + $385 under the plan's wording. + pe_us: + follows: statute + code: + - policyengine_us/parameters/gov/states/ok/dhs/liheap/cooling/income_band.yaml + - policyengine_us/variables/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10748 + state: ruled + note: 'Ruled 2026-11-13 by the project lead; the ruling record is https://github.com/PolicyEngine/policyengine-us/pull/10748#issuecomment-6863978810. Follow Appendix C-7-A, which + the regulation names: net monthly income of $700 or less receives the larger amount and $701 or more the smaller + one (band threshold 701; test Case 2 pins both sides).' - id: us-ok:liheap-immigration-status-list program: liheap years: @@ -9308,7 +9343,7 @@ candidates: code: - policyengine_us/parameters/gov/states/ok/dhs/liheap/income/sources/unearned.yaml - policyengine_us/variables/gov/states/ok/dhs/liheap/income/ok_liheap_income_deductions.py - - policyengine_us/variables/gov/states/ok/dhs/liheap/eligibility/ok_liheap_eligible.py + - policyengine_us/variables/gov/states/ok/dhs/liheap/eligibility/ok_liheap_income_eligible.py - policyengine_us/variables/gov/states/ok/dhs/liheap/income/ok_liheap_gross_income.py - policyengine_us/variables/gov/states/ok/dhs/liheap/income/ok_liheap_deemed_income.py - policyengine_us/variables/gov/states/ok/dhs/liheap/income/ok_liheap_net_income.py @@ -9319,7 +9354,7 @@ candidates: premiums enter the medical deduction only for USDA elderly or disabled members. Eligible members'' deductions come after the gross test, in the net income that sets the payment, while ineligible members'' deductions are applied before their income is deemed. The list''s comment records the plan checkbox and says the plan narrative - also uses gross income (income/sources/unearned.yaml, ok_liheap_income_deductions.py, ok_liheap_eligible.py, + also uses gross income (income/sources/unearned.yaml, ok_liheap_income_deductions.py, ok_liheap_income_eligible.py, ok_liheap_gross_income.py, ok_liheap_deemed_income.py, ok_liheap_net_income.py). Reconcile the checkbox and verify page references.' - id: us-ok:liheap-resource-test @@ -9350,11 +9385,14 @@ candidates: follows: unknown code: - policyengine_us/variables/gov/states/ok/dhs/liheap/eligibility/ok_liheap_eligible.py + - policyengine_us/variables/gov/states/ok/dhs/liheap/cooling/ok_liheap_cooling_eligible.py prs: - https://github.com/PolicyEngine/policyengine-us/pull/9970 + - https://github.com/PolicyEngine/policyengine-us/pull/10748 state: unreviewed - note: PE-US applies no resource test, and the comment records that the September 15, 2026 amendment removed both - provisions (ok_liheap_eligible.py). Verify agency practice while the rules were in force. + note: PE-US applies no resource test to winter heating or summer cooling (ok_liheap_eligible.py, + ok_liheap_cooling_eligible.py), and the heating comment records that the September 15, 2026 amendment removed + both provisions. Verify agency practice while the rules were in force. - id: us-ok:ssp-ineligible-child-allocation program: ssi-state-supplement years: