diff --git a/changelog.d/fl-liheap.added.md b/changelog.d/fl-liheap.added.md new file mode 100644 index 00000000000..158a21f74f8 --- /dev/null +++ b/changelog.d/fl-liheap.added.md @@ -0,0 +1 @@ +Add Florida LIHEAP regular heating assistance. diff --git a/policyengine_us/parameters/gov/hhs/liheap/fpg_floor.yaml b/policyengine_us/parameters/gov/hhs/liheap/fpg_floor.yaml new file mode 100644 index 00000000000..ae7cb296211 --- /dev/null +++ b/policyengine_us/parameters/gov/hhs/liheap/fpg_floor.yaml @@ -0,0 +1,11 @@ +description: The US Department of Health and Human Services limits income-based exclusion to households with income of at least this percentage of the poverty guideline under the Low Income Home Energy Assistance Program. +# Pub. L. 98-558, section 605(a)(2), added the floor for fiscal year 1986 and later. +values: + 1985-10-01: 1.1 +metadata: + period: year + unit: /1 + label: LIHEAP poverty guideline income floor + reference: + - title: 42 U.S.C. 8624(b)(2)(B) + href: https://www.law.cornell.edu/uscode/text/42/8624 diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/categorical_programs.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/categorical_programs.yaml new file mode 100644 index 00000000000..c19e4b4620d --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/categorical_programs.yaml @@ -0,0 +1,21 @@ +description: Florida uses receipt of these programs as categorical income eligibility under the Low Income Home Energy Assistance Program. +values: + # The FY2025 plan also lists means-tested veterans programs, which no + # existing input identifies. + 2024-10-01: + # Each entry is take-up gated, so it reflects receipt rather than + # entitlement; tanf includes Florida Temporary Cash Assistance (fl_tca). + - snap + - tanf + - ssi +metadata: + unit: list + period: year + label: Florida LIHEAP categorical income programs + reference: + - title: Florida FY2026 LIHEAP State Plan, sections 1.4-1.6 (categorical income eligibility) + href: https://liheapch.acf.gov/docs/2026/state-plans/FL_Plan_2026.pdf#page=5 + - title: Florida LIHEAP Policies and Procedures Manual, May 27 2022, part 1200.01G(9) + href: https://liheapch.acf.gov/sites/default/files/webfiles/docs/2023/manuals/FL_PolicyManual_2023.pdf#page=50 + - title: Florida FY2025 LIHEAP State Plan, Sections 1.4-1.6 + href: https://liheapch.acf.gov/docs/2025/state-plans/FL_Plan_2025.pdf#page=5 diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/fpg_rate.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/fpg_rate.yaml new file mode 100644 index 00000000000..7ab0b446b54 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/fpg_rate.yaml @@ -0,0 +1,22 @@ +description: Florida sets the alternative heating income limit to this percentage of the federal poverty guidelines under the Low Income Home Energy Assistance Program. +# The heating maximum income value is the greater of the state median income +# limit and this share of the poverty guidelines. In FY2025 this gives 60% of +# state median income for sizes 1-8 and 150% of the guidelines for sizes 9 and +# above. FY2026 uses 60% of state median income for every size, so the +# poverty-guideline alternative is zero. +values: + 2024-10-01: 1.5 + 2025-10-01: 0 +metadata: + unit: /1 + period: year + label: Florida LIHEAP heating federal poverty guideline rate + reference: + - title: Florida FY2025 LIHEAP State Plan, Section 2.1 + href: https://liheapch.acf.gov/docs/2025/state-plans/FL_Plan_2025.pdf#page=8 + - title: Florida FY2025 LIHEAP Payment Matrix, maximum income value footnote + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/FL_BenefitMatrix_2025.pdf + - title: Florida FY2026 LIHEAP State Plan, Section 2.1 + href: https://liheapch.acf.gov/docs/2026/state-plans/FL_Plan_2026.pdf#page=8 + - title: Florida FY2026 LIHEAP Payment Matrix, maximum income value footnote + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/FL_BenefitMatrix_Heat-Cool_2026.pdf diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/fpg_year_lag.yaml new file mode 100644 index 00000000000..9b00c19ff04 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/fpg_year_lag.yaml @@ -0,0 +1,11 @@ +description: Florida uses the federal poverty guidelines from this number of years before the heating year under the Low Income Home Energy Assistance Program. +# The FY2025 matrix uses the 2024 guidelines published on January 17, 2024. +values: + 2024-10-01: 1 +metadata: + unit: year + period: year + label: Florida LIHEAP federal poverty guideline year lag + reference: + - title: Florida FY2025 LIHEAP Payment Matrix, guideline footnote + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/FL_BenefitMatrix_2025.pdf diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/smi_rate.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/smi_rate.yaml new file mode 100644 index 00000000000..c8ace75bc94 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/smi_rate.yaml @@ -0,0 +1,18 @@ +description: Florida limits annual heating-assistance income to this fraction of state median income under the Low Income Home Energy Assistance Program. +# The draft FFY2027 plan (section 2.1) keeps 60% of state median income for +# sizes 1-8 and 9 or more. +values: + 2024-10-01: 0.6 +metadata: + unit: /1 + period: year + label: Florida LIHEAP heating state median income rate + reference: + - title: Florida FY2026 LIHEAP State Plan, Section 2.1 + href: https://liheapch.acf.gov/docs/2026/state-plans/FL_Plan_2026.pdf#page=8 + - title: FY2026 LIHEAP income eligibility by component, Florida heating column + href: https://liheapch.acf.gov/delivery/income_eligibility.htm + - title: Florida FY2025 LIHEAP State Plan, Section 2.1 + href: https://liheapch.acf.gov/docs/2025/state-plans/FL_Plan_2025.pdf#page=8 + - title: Florida draft FFY2027 LIHEAP State Plan, section 2.1 + href: https://www.floridajobs.org/docs/lwdb-resources/lwdb-grants-management/economic-self-sufficiency-organizations/esso-grant-agreements/liheap/2026-liheap/draft-ffy2027_comm_liheap_model-plan-template_watermark.pdf#page=8 diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/truncates_smi_limit.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/truncates_smi_limit.yaml new file mode 100644 index 00000000000..0a97b3e8d80 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/eligibility/truncates_smi_limit.yaml @@ -0,0 +1,23 @@ +description: Florida uses state median income limits truncated to whole dollars, as in the federal table, rather than rounded half up when this is true under the Low Income Home Energy Assistance Program. +# Neither matrix states a rounding rule; the pattern is inferred from the +# printed amounts. FY2025 rounds 60% of state median income for each size to +# the nearest dollar (one person: $98,038 x 60% x 52% = $30,587.856, printed +# $30,588, where the federal FY2025 table prints $30,587). FY2026 reprints the +# federal FY2026 table, which truncates 60% of the four-person amount and then +# each size ($32,155 for one person). +values: + 2024-10-01: false + 2025-10-01: true +metadata: + unit: bool + period: year + label: Florida LIHEAP state median income limit truncation + reference: + - title: Florida FY2025 LIHEAP Payment Matrix, maximum income values + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/FL_BenefitMatrix_2025.pdf + - title: Florida State Median Income for FFY 2025 + href: https://liheapch.acf.gov/profiles/povertytables/FY2025/flsmi.htm + - title: Florida FY2026 LIHEAP Payment Matrix, maximum income values + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/FL_BenefitMatrix_Heat-Cool_2026.pdf + - title: Florida State Median Income for FFY 2026 + href: https://liheapch.acf.gov/profiles/povertytables/FY2026/flsmi.htm diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/income/adult_age.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/income/adult_age.yaml new file mode 100644 index 00000000000..738498137ae --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/income/adult_age.yaml @@ -0,0 +1,19 @@ +description: Florida uses this threshold as the age at which all members' income counts under the Low Income Home Energy Assistance Program. +# The statewide application and portal FAQ exclude all minors' income. +# The March 2025 application metadata does not establish a policy-change date; +# FY2025 uses this current rule as a backfilled assumption. +values: + 2024-10-01: 18 +metadata: + unit: year + period: year + label: Florida LIHEAP adult income age + reference: + - title: Florida FY2026 LIHEAP State Plan, section 1.9 + href: https://liheapch.acf.gov/docs/2026/state-plans/FL_Plan_2026.pdf#page=6 + - title: Florida statewide LIHEAP application, Monthly Household Income + href: https://storage.googleapis.com/florida-liheap-relief-static-assets/Florida_LIHEAP_Application_English.pdf#page=1 + - title: Florida statewide LIHEAP portal, What qualifies as income + href: https://floridaliheap.com/faq + - title: Florida FY2025 LIHEAP State Plan, Section 1.9 + href: https://liheapch.acf.gov/docs/2025/state-plans/FL_Plan_2025.pdf#page=6 diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/income/sources/earned.yaml new file mode 100644 index 00000000000..83487aabc26 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/income/sources/earned.yaml @@ -0,0 +1,20 @@ +description: Florida uses these sources as earned income of members aged 18 and older under the Low Income Home Energy Assistance Program. +# Existing net business inputs have no additional LIHEAP expense deduction. +values: + 2024-10-01: + - employment_income + - self_employment_income + - sstb_self_employment_income + - farm_operations_income + - partnership_s_corp_income +metadata: + unit: list + period: year + label: Florida LIHEAP earned income sources + reference: + - title: "Florida FY2026 LIHEAP State Plan, section 1.9 #page 5-6" + href: https://liheapch.acf.gov/docs/2026/state-plans/FL_Plan_2026.pdf#page=5 + - title: "Florida LIHEAP Policies and Procedures Manual, May 27 2022, part 1200.01E and G(12) #page 49-50" + href: https://liheapch.acf.gov/sites/default/files/webfiles/docs/2023/manuals/FL_PolicyManual_2023.pdf#page=49 + - title: "Florida FY2025 LIHEAP State Plan, Section 1.9 #page 5-6" + href: https://liheapch.acf.gov/docs/2025/state-plans/FL_Plan_2025.pdf#page=5 diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/income/sources/household.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/income/sources/household.yaml new file mode 100644 index 00000000000..f6b636a93bb --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/income/sources/household.yaml @@ -0,0 +1,15 @@ +description: Florida uses these household cash benefits as countable income under the Low Income Home Energy Assistance Program. +values: + 2024-10-01: + # The take-up-gated TANF total includes Florida Temporary Cash Assistance + # (fl_tca) and counts it only when the household receives it. + - tanf +metadata: + unit: list + period: year + label: Florida LIHEAP household cash income sources + reference: + - title: Florida FY2026 LIHEAP State Plan, section 1.9 (TANF counted) + href: https://liheapch.acf.gov/docs/2026/state-plans/FL_Plan_2026.pdf#page=6 + - title: Florida FY2025 LIHEAP State Plan, Section 1.9 + href: https://liheapch.acf.gov/docs/2025/state-plans/FL_Plan_2025.pdf#page=6 diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/income/sources/unearned.yaml new file mode 100644 index 00000000000..d8e77d795ce --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/income/sources/unearned.yaml @@ -0,0 +1,50 @@ +description: Florida uses these sources as unearned income of members aged 18 and older under the Low Income Home Energy Assistance Program. +values: + 2024-10-01: + - social_security + - ssi + # Military retirement pay is a separate input from the pension inputs that + # pension_income adds, so both are listed; a household reports the amount + # in one or the other. Plan Section 1.9 counts retirement and pension + # benefits. + - pension_income + - military_retirement_pay + - railroad_benefits + - survivor_benefits + - veterans_benefits + - workers_compensation + - disability_benefits + - strike_benefits + - general_assistance + - rental_income + - farm_rent_income + - interest_income + - ordinary_dividend_income + # Periodic estate/trust income, excluding separately recorded interest/dividends. + - estate_income + - child_support_received + - alimony_income +# Net gambling and lottery winnings are counted in the formula, with losses +# offsetting only winnings. +# The FY2025 and FY2026 plans (section 1.9) and the portal FAQ exclude +# unemployment compensation and cash gifts. +# Florida Optional State Supplementation (fl_oss) is not listed: it pays +# residents of assisted living facilities, adult family-care homes and mental +# health residential treatment facilities, whom manual 900.02B (page 39, +# residence paid through a state residential program) and 900.03B(1) (page +# 40, institutions) exclude from LIHEAP households. +# Pension/SSA subcomponents are not counted twice; TANF is counted once in +# household.yaml. +metadata: + unit: list + period: year + label: Florida LIHEAP person unearned income sources + reference: + - title: "Florida FY2026 LIHEAP State Plan, section 1.9 (included and excluded income sources) #page 5-7" + href: https://liheapch.acf.gov/docs/2026/state-plans/FL_Plan_2026.pdf#page=5 + - title: "Florida LIHEAP Policies and Procedures Manual, May 27 2022, parts 900 and 1200 #page 39-40,49-51" + href: https://liheapch.acf.gov/sites/default/files/webfiles/docs/2023/manuals/FL_PolicyManual_2023.pdf#page=39 + - title: "Florida FY2025 LIHEAP State Plan, Section 1.9 #page 5-7" + href: https://liheapch.acf.gov/docs/2025/state-plans/FL_Plan_2025.pdf#page=5 + - title: Florida statewide LIHEAP portal, What qualifies as income + href: https://floridaliheap.com/faq diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/base_amount.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/base_amount.yaml new file mode 100644 index 00000000000..86b0325477c --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/base_amount.yaml @@ -0,0 +1,30 @@ +description: Florida provides this base regular heating payment by income band under the Low Income Home Energy Assistance Program. +# The draft FFY2027 plan (section 2.6) estimates a $200 minimum and $700 +# maximum, matching these bases with all additions; no FY2027 matrix is +# published. +1: + 2024-10-01: 1_000 + 2025-10-01: 350 +2: + 2024-10-01: 750 + 2025-10-01: 300 +3: + 2024-10-01: 550 + 2025-10-01: 250 +4: + 2024-10-01: 400 + 2025-10-01: 200 +metadata: + unit: currency-USD + period: year + label: Florida LIHEAP base heating payment + breakdown: + - range(1, 5) + propagate_metadata_to_children: true + reference: + - title: Florida FY2025 LIHEAP Payment Matrix, home energy benefit + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/FL_BenefitMatrix_2025.pdf + - title: Florida FY2026 LIHEAP Payment Matrix, home energy benefit + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/FL_BenefitMatrix_Heat-Cool_2026.pdf + - title: Florida draft FFY2027 LIHEAP State Plan, section 2.6 + href: https://www.floridajobs.org/docs/lwdb-resources/lwdb-grants-management/economic-self-sufficiency-organizations/esso-grant-agreements/liheap/2026-liheap/draft-ffy2027_comm_liheap_model-plan-template_watermark.pdf#page=9 diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/child_max_age.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/child_max_age.yaml new file mode 100644 index 00000000000..7eaef85fe9f --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/child_max_age.yaml @@ -0,0 +1,12 @@ +description: Florida provides the young-child household heating supplement when a member is no older than this age in completed years under the Low Income Home Energy Assistance Program. +values: + 2024-10-01: 5 +metadata: + unit: year + period: year + label: Florida LIHEAP child supplement maximum age + reference: + - title: Florida FY2026 LIHEAP Payment Matrix, child additional assistance + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/FL_BenefitMatrix_Heat-Cool_2026.pdf + - title: Florida FY2025 LIHEAP Payment Matrix, child additional assistance + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/FL_BenefitMatrix_2025.pdf diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/elderly_min_age.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/elderly_min_age.yaml new file mode 100644 index 00000000000..52f38825392 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/elderly_min_age.yaml @@ -0,0 +1,12 @@ +description: Florida provides the elderly household heating supplement when a member is at least this age under the Low Income Home Energy Assistance Program. +values: + 2024-10-01: 60 +metadata: + unit: year + period: year + label: Florida LIHEAP elderly supplement minimum age + reference: + - title: Florida FY2026 LIHEAP Payment Matrix, elderly additional assistance + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/FL_BenefitMatrix_Heat-Cool_2026.pdf + - title: Florida FY2025 LIHEAP Payment Matrix, elderly additional assistance + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/FL_BenefitMatrix_2025.pdf diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/income_band_fpg_rate.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/income_band_fpg_rate.yaml new file mode 100644 index 00000000000..9afcea0c2c4 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/income_band_fpg_rate.yaml @@ -0,0 +1,18 @@ +description: Florida sets the poverty-guideline heating income-band upper bounds at this percentage of the federal poverty guidelines under the Low Income Home Energy Assistance Program. +# The FY2025 matrix prints the first band one dollar below 75% (for example, +# $43,574 at size 9), and the second band reads "At least 75%", so the first +# band excludes its upper bound. +first: + 2024-10-01: 0.75 +second: + 2024-10-01: 1 +third: + 2024-10-01: 1.25 +metadata: + unit: /1 + period: year + label: Florida LIHEAP heating income-band poverty guideline rates + propagate_metadata_to_children: true + reference: + - title: Florida FY2025 LIHEAP Payment Matrix, income bands for 9 to 20 people + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/FL_BenefitMatrix_2025.pdf diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/income_band_fraction.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/income_band_fraction.yaml new file mode 100644 index 00000000000..16661d542a8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/income_band_fraction.yaml @@ -0,0 +1,17 @@ +description: Florida sets these regular heating income-band upper bounds as fractions of the maximum household income under the Low Income Home Energy Assistance Program. +first: + 2024-10-01: 0.5 +second: + 2024-10-01: 0.7 +third: + 2024-10-01: 0.85 +metadata: + unit: /1 + period: year + label: Florida LIHEAP heating income-band fractions + propagate_metadata_to_children: true + reference: + - title: Florida FY2026 LIHEAP Payment Matrix, income bands + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/FL_BenefitMatrix_Heat-Cool_2026.pdf + - title: Florida FY2025 LIHEAP Payment Matrix, income bands for 1 to 8 people + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/FL_BenefitMatrix_2025.pdf diff --git a/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/supplement.yaml b/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/supplement.yaml new file mode 100644 index 00000000000..5b63a52e9e6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/fl/commerce/liheap/payment/supplement.yaml @@ -0,0 +1,19 @@ +description: Florida provides this additional heating payment once for each vulnerable household category present under the Low Income Home Energy Assistance Program. +elderly: + 2024-10-01: 100 +disabled: + 2024-10-01: 100 +child: + 2024-10-01: 150 +metadata: + unit: currency-USD + period: year + label: Florida LIHEAP vulnerable household heating supplements + propagate_metadata_to_children: true + reference: + - title: Florida FY2026 LIHEAP Payment Matrix, additional assistance + href: https://liheapch.acf.gov/docs/2026/benefits-matricies/FL_BenefitMatrix_Heat-Cool_2026.pdf + - title: Florida FY2025 LIHEAP Payment Matrix, additional assistance + href: https://liheapch.acf.gov/docs/2025/benefits-matricies/FL_BenefitMatrix_2025.pdf + - title: Florida FY2026 LIHEAP State Plan, section 2.4 + href: https://liheapch.acf.gov/docs/2026/state-plans/FL_Plan_2026.pdf#page=9 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 5250ab3aa89..51b131d634a 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -808,7 +808,7 @@ programs: category: Benefits agency: HHS status: partial - coverage: DC, Riverside County, MA, IL, IN, KS, KY, MD, MS, NC, NE, NJ, NY, OR, TX + coverage: DC, Riverside County, MA, FL, IL, IN, KS, KY, MD, MS, NC, NE, NJ, NY, OR, TX state_implementations: - state: DC status: complete @@ -822,6 +822,13 @@ programs: full_name: Massachusetts Low Income Home Energy Assistance Program variable: ma_liheap parameter_prefix: gov.states.ma.doer.liheap + - state: FL + status: partial + name: Florida LIHEAP + full_name: Florida Low Income Home Energy Assistance Program + variable: fl_liheap + parameter_prefix: gov.states.fl.commerce.liheap + notes: FY2025-FY2026 regular heating schedules are checked. FY2026 large-household eligibility conflicts with contract wording; above-range awards for categorical or 110%-poverty-floor households remain estimates. The current minor-income rule is backfilled to FY2025 without a confirmed change date. Crisis, cooling, weatherization and equipment assistance are out of scope. - state: IL status: complete name: Illinois LIHEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/eligibility/fl_liheap_categorically_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/eligibility/fl_liheap_categorically_eligible.yaml new file mode 100644 index 00000000000..5ce7c88d98d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/eligibility/fl_liheap_categorically_eligible.yaml @@ -0,0 +1,165 @@ +# Florida independent household income and categorical-income components; no final program eligibility or award is asserted. + +# FY2026 plan page 5 and manual page 50: any positive SNAP receipt waives the +# income test. High reported wages do not negate this component; no final +# award or band is asserted. +- name: Case 1, positive SNAP receipt establishes only the categorical income exemption. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + employment_income: 100_000 + spm_units: + spm_unit: + members: [person1] + fl_tca: 0 + snap: 1_200 + households: + household: + members: [person1] + state_code: FL + output: + fl_liheap_categorically_eligible: true + +# FY2026 plan page 5 and manual page 50: TANF receipt qualifies. The family's +# Florida TCA of 3_600 a year is used, not a national TANF aggregate. +- name: Case 2, positive Florida cash assistance establishes the categorical income exemption. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + person2: + age: 8 + immigration_status: CITIZEN + ssi: 0 + spm_units: + spm_unit: + members: [person1, person2] + fl_tca: 3_600 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_categorically_eligible: true + +# FY2026 plan page 5: SSI receipt by any household member qualifies. The +# child's 1_200 of SSI is excluded from income by the manual page 49 age rule; +# the adult's 12_000 of wages count. +- name: Case 3, a child SSI receipt qualifies categorically even when excluded from income. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + employment_income: 12_000 + person2: + age: 8 + immigration_status: CITIZEN + ssi: 1_200 + spm_units: + spm_unit: + members: [person1, person2] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_countable_income: 12_000 + fl_liheap_categorically_eligible: true + +# FY2026 plan page 5 requires receipt, not the is_ssi_eligible demographic and +# resource flag; SSI, SNAP and TCA are explicitly 0. +- name: Case 4, SSI demographic eligibility without any qualifying receipt does not establish categorical + status. + period: 2026 + input: + people: + person1: + age: 67 + immigration_status: CITIZEN + ssi: 0 + is_ssi_eligible: true + spm_units: + spm_unit: + members: [person1] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_liheap_categorically_eligible: false + +# The Florida categorical component returns false outside Florida; no final +# heating award is evaluated. +- name: Case 5, out of state categorical receipts do not establish Florida status. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + spm_units: + spm_unit: + members: [person1] + fl_tca: 0 + snap: 1_200 + households: + household: + members: [person1] + state_code: GA + output: + fl_liheap_categorically_eligible: false + +# FY2026 plan page 5: TANF receipt waives the income test. A grandparent with +# 48_000 of wages cares for a grandchild who gets a child-only Florida TCA +# grant of 180 a month (180 x 12 = 2_160). Countable income is 48_000 + +# 2_160 = 50_160 with take-up and 48_000 without, both above the 42_049 +# two-person limit, so only the categorical route can qualify. TCA is the only +# qualifying receipt: it counts when taken up (first household) and not when +# it is not (second). +- name: Case 6, Florida cash assistance establishes categorical status only when taken up. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: {age: 55, ssi: 0, employment_income: 48_000} + person2: {age: 8, ssi: 0} + person3: {age: 55, ssi: 0, employment_income: 48_000} + person4: {age: 8, ssi: 0} + spm_units: + spm_unit1: + members: [person1, person2] + fl_tca: 2_160 + takes_up_tanf_if_eligible: true + snap: 0 + spm_unit2: + members: [person3, person4] + fl_tca: 2_160 + takes_up_tanf_if_eligible: false + snap: 0 + households: + household1: + members: [person1, person2] + state_code: FL + household2: + members: [person3, person4] + state_code: FL + output: + tanf: [2_160, 0] + fl_liheap_countable_income: [50_160, 48_000] + fl_liheap_categorically_eligible: [true, false] diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/eligibility/fl_liheap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/eligibility/fl_liheap_eligible.yaml new file mode 100644 index 00000000000..1b671ea64bb --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/eligibility/fl_liheap_eligible.yaml @@ -0,0 +1,326 @@ +# Accepted FY2026 plan pages 5 and 8 and manual pages 23 and 41-43: ordinary +# and categorical income conditions, a qualified household and heating +# responsibility. Housing verification uses existing inputs as an +# approximation. + +- name: Case 1, the ordinary income ceiling is inclusive without an asset test. + period: 2026 + input: + state_code: + - FL + - FL + age: + - 40 + - 40 + immigration_status: + - CITIZEN + - CITIZEN + ssi: + - 0 + - 0 + fl_tca: + - 0 + - 0 + snap: + - 0 + - 0 + employment_income: + - 32_155 + - 32_155.01 + heating_type: + - NATURAL_GAS + - NATURAL_GAS + heating_expense: + - 1_200 + - 1_200 + spm_unit_assets: + - 1_000_000 + - 1_000_000 + output: + fl_liheap_eligible: + - true + - false +- name: Case 2, each reported receipt route waives the ordinary income ceiling. + period: 2026 + input: + state_code: + - FL + - FL + - FL + - FL + age: + - 40 + - 40 + - 40 + - 40 + immigration_status: + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + ssi: + - 0 + - 0 + - 1_200 + - 0 + fl_tca: + - 0 + - 1_200 + - 0 + - 0 + snap: + - 1_200 + - 0 + - 0 + - 0 + employment_income: + - 100_000 + - 100_000 + - 100_000 + - 100_000 + heating_type: + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + heating_expense: + - 1_200 + - 1_200 + - 1_200 + - 1_200 + output: + fl_liheap_eligible: + - true + - true + - true + - false +- name: Case 3, categorical receipts do not waive heating qualified membership or Florida residence. + period: 2026 + input: + state_code: + - FL + - FL + - FL + - GA + age: + - 40 + - 40 + - 40 + - 40 + immigration_status: + - CITIZEN + - UNDOCUMENTED + - CITIZEN + - CITIZEN + ssi: + - 0 + - 0 + - 0 + - 0 + fl_tca: + - 0 + - 0 + - 0 + - 0 + snap: + - 1_200 + - 1_200 + - 1_200 + - 1_200 + employment_income: + - 0 + - 0 + - 0 + - 0 + heating_type: + - NONE + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + heating_expense: + - 100 + - 100 + - 0 + - 100 + has_heating_expense: + - true + - true + - false + - true + output: + fl_liheap_eligible: + - false + - false + - false + - false +- name: Case 4, subsidized heat in rent needs a positive residual bill even with a general obligation + flag. + period: 2026 + input: + state_code: + - FL + - FL + - FL + - FL + - FL + age: + - 40 + - 40 + - 40 + - 40 + - 40 + immigration_status: + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + ssi: + - 0 + - 0 + - 0 + - 0 + - 0 + fl_tca: + - 0 + - 0 + - 0 + - 0 + - 0 + snap: + - 0 + - 0 + - 0 + - 0 + - 0 + employment_income: + - 0 + - 0 + - 0 + - 0 + - 0 + heating_type: + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + heating_expense: + - 0 + - 0 + - 120 + - 0 + - 120 + has_heating_expense: + - false + - true + - true + - true + - true + heat_expense_included_in_rent: + - true + - true + - true + - true + - true + receives_housing_assistance: + - false + - true + - true + - false + - false + is_in_public_housing: + - false + - false + - false + - true + - true + output: + fl_liheap_eligible: + - true + - false + - true + - false + - true +- name: Case 5, a directly reported heating obligation qualifies without a current positive bill. + period: 2026 + input: + state_code: + - FL + - FL + age: + - 40 + - 40 + immigration_status: + - CITIZEN + - CITIZEN + ssi: + - 0 + - 0 + fl_tca: + - 0 + - 0 + snap: + - 0 + - 0 + employment_income: + - 0 + - 0 + heating_type: + - NATURAL_GAS + - NATURAL_GAS + heating_expense: + - 0 + - 0 + has_heating_expense: + - true + - false + heat_expense_included_in_rent: + - false + - false + output: + fl_liheap_eligible: + - true + - false + +# Boundary amounts. FY2025 matrix: the size-1 maximum income value, +# 98_038 x 52% x 60% = 30_587.856, is printed rounded to 30_588. The size-9 +# value is 150% of the 2024 guideline, 58_100 x 1.5 = 87_150. Income at each +# printed value qualifies; one more cent does not. +- name: Case 6, fiscal year 2025 income at the printed maximum income value qualifies. + period: 2025 + input: + state_code: [FL, FL, FL, FL] + age: [40, 40, 40, 40] + immigration_status: [CITIZEN, CITIZEN, CITIZEN, CITIZEN] + ssi: [0, 0, 0, 0] + fl_tca: [0, 0, 0, 0] + snap: [0, 0, 0, 0] + employment_income: [30_588, 30_588.01, 87_150, 87_150.01] + fl_liheap_household_size: [1, 1, 9, 9] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS] + heating_expense: [1_200, 1_200, 1_200, 1_200] + output: + fl_liheap_eligible: [true, false, true, false] + +# Outside rent, has_heating_expense is the heating obligation (manual 900.01A, +# page 39; 1100.04A, page 47). It defaults to true when the primary fuel's bill +# is positive; an explicit false is respected even with a 1_200 gas bill. +# Part-time Florida minimum-wage earnings: 20 x (39 x 14 + 13 x 15) = 14_820, +# under the 32_155 one-person limit. +- name: Case 7, an explicit absence of a heating obligation outside rent is respected despite a fuel bill. + period: 2026 + input: + state_code: [FL, FL] + age: [40, 40] + immigration_status: [CITIZEN, CITIZEN] + ssi: [0, 0] + fl_tca: [0, 0] + snap: [0, 0] + employment_income: [14_820, 14_820] + heating_type: [NATURAL_GAS, NATURAL_GAS] + gas_expense: [1_200, 1_200] + heat_expense_included_in_rent: [false, false] + has_heating_expense: [true, false] + output: + fl_liheap_eligible: [true, false] diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/eligibility/fl_liheap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/eligibility/fl_liheap_income_limit.yaml new file mode 100644 index 00000000000..2728086240c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/eligibility/fl_liheap_income_limit.yaml @@ -0,0 +1,172 @@ +# FY2026 matrix, sizes 1-12 as printed. Its stated 60% of state median income +# rule gives floor(61_837 x 1.53) = 94_610 at size 13, which the model uses for +# both the limit and the payment bands; the printed 157_686 is 100% of state +# median income and exceeds the federal ceiling of 42 U.S.C. 8624(b)(2)(B). + +- name: Case 1, all twelve consistent published heating limits match the current matrix. + period: 2026 + input: + state_code: + - FL + - FL + - FL + - FL + - FL + - FL + - FL + - FL + - FL + - FL + - FL + - FL + age: + - 40 + - 40 + - 40 + - 40 + - 40 + - 40 + - 40 + - 40 + - 40 + - 40 + - 40 + - 40 + immigration_status: + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + ssi: + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + fl_tca: + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + snap: + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + employment_income: + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + fl_liheap_household_size: + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + - 10 + - 11 + - 12 + output: + fl_liheap_income_limit: + - 32_155 + - 42_049 + - 51_943 + - 61_837 + - 71_730 + - 81_624 + - 83_479 + - 85_335 + - 87_190 + - 89_045 + - 90_900 + - 92_755 +- name: Case 2, size thirteen follows the stated sixty percent SMI rule despite the anomalous printed + row. + period: 2026 + input: + state_code: + - FL + age: + - 40 + immigration_status: + - CITIZEN + ssi: + - 0 + fl_tca: + - 0 + snap: + - 0 + employment_income: + - 0 + fl_liheap_household_size: + - 13 + output: + fl_liheap_income_limit: + - 94_610 + +# FY2025 matrix footnote and accepted FY2025 plan section 2.1, page 8: the +# limit is the greater of 60% of state median income and 150% of the 2024 +# poverty guidelines. State median income: 98_038 x size share x 60%, with +# shares 52%, 68%, 100%, 132% and 138% for sizes 1, 2, 4, 6 and 8, giving +# 30_587.856, 39_999.504, 58_822.8, 77_646.096 and 81_175.464 (printed +# 30_588, 40_000, 58_823, 77_646 and 81_175). Guidelines: 15_060 + 5_380 per +# additional person, times 1.5, give 87_150, 111_360 and 175_920 for sizes 9, +# 12 and 20, above the state median income amounts (82_940.148 at size 9). +- name: Case 3, fiscal year 2025 limits use the greater of state median income and poverty guideline amounts. + period: 2025 + absolute_error_margin: 0.01 + input: + state_code: [FL, FL, FL, FL, FL, FL, FL, FL] + age: [40, 40, 40, 40, 40, 40, 40, 40] + immigration_status: [CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN] + ssi: [0, 0, 0, 0, 0, 0, 0, 0] + fl_tca: [0, 0, 0, 0, 0, 0, 0, 0] + snap: [0, 0, 0, 0, 0, 0, 0, 0] + employment_income: [0, 0, 0, 0, 0, 0, 0, 0] + fl_liheap_household_size: [1, 2, 4, 6, 8, 9, 12, 20] + output: + fl_liheap_income_limit: [30_587.856, 39_999.504, 58_822.8, 77_646.096, 81_175.464, 87_150, 111_360, 175_920] diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/fl_liheap.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/fl_liheap.yaml new file mode 100644 index 00000000000..6332e00fd67 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/fl_liheap.yaml @@ -0,0 +1,859 @@ +# FY2026 matrix and accepted FY2026 plan page 9: bases of 350/300/250/200. +# FY2025 matrix: bases of 1_000/750/550/400. Both years add 100 for a member +# age 60 or older, 100 for a disabled member and 150 for a child age 5 or +# younger, each once per household. Manual page 23 bases the payment on the +# matrix, not the actual bill. Categorical households, and households of 15 or +# more protected by the federal 110% poverty floor, with income above the table +# receive the smallest base as a documented estimate; the sources give no +# express instruction for that case. + +- name: Case 1, published income band tops include exact amounts and the next cent starts the next band. + period: 2026 + input: + state_code: + - FL + - FL + - FL + - FL + - FL + - FL + - FL + - FL + age: + - 40 + - 40 + - 40 + - 40 + - 40 + - 40 + - 40 + - 40 + immigration_status: + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + ssi: + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + fl_tca: + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + snap: + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + employment_income: + - 0 + - 16_078 + - 16_078.01 + - 22_509 + - 22_509.01 + - 27_332 + - 27_332.01 + - 32_155 + heating_type: + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + heating_expense: + - 1_200 + - 1_200 + - 1_200 + - 1_200 + - 1_200 + - 1_200 + - 1_200 + - 1_200 + output: + fl_liheap: + - 350 + - 350 + - 300 + - 300 + - 250 + - 250 + - 200 + - 200 +- name: Case 2, age sixty and disability each add one hundred and both categories can stack. + period: 2026 + input: + state_code: + - FL + - FL + - FL + - FL + age: + - 59 + - 60 + - 59 + - 60 + immigration_status: + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + ssi: + - 0 + - 0 + - 0 + - 0 + fl_tca: + - 0 + - 0 + - 0 + - 0 + snap: + - 0 + - 0 + - 0 + - 0 + employment_income: + - 0 + - 0 + - 0 + - 0 + heating_type: + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + heating_expense: + - 1_200 + - 1_200 + - 1_200 + - 1_200 + is_disabled: + - false + - false + - true + - true + output: + fl_liheap: + - 350 + - 450 + - 450 + - 550 +- name: Case 3, a child age five qualifies for the young child addition. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + person2: + age: 5 + immigration_status: CITIZEN + ssi: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + heating_expense: 1_200 + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap: 500 +- name: Case 4, a child age six no longer qualifies for the young child addition. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + person2: + age: 6 + immigration_status: CITIZEN + ssi: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + heating_expense: 1_200 + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap: 350 +- name: Case 5, multiple elderly disabled and young members add each category only once. + period: 2026 + input: + people: + person1: + age: 65 + immigration_status: CITIZEN + ssi: 0 + is_disabled: true + person2: + age: 64 + immigration_status: CITIZEN + ssi: 0 + is_disabled: true + person3: + age: 40 + immigration_status: CITIZEN + ssi: 0 + person4: + age: 5 + immigration_status: CITIZEN + ssi: 0 + person5: + age: 3 + immigration_status: CITIZEN + ssi: 0 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + heating_type: NATURAL_GAS + heating_expense: 1_200 + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: FL + output: + fl_liheap: 700 +# The qualified child is assumed to be the applicant; manual 900.04D.1 (page 41) would deny +# an application made by the undocumented parent. +- name: Case 6, a nonqualified parent's full income determines the band for the qualified child. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: UNDOCUMENTED + ssi: 0 + employment_income: 30_000 + person2: + age: 5 + immigration_status: CITIZEN + ssi: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + heating_expense: 1_200 + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_household_size: 1 + fl_liheap_countable_income: 30_000 + fl_liheap: 350 +- name: Case 7, categorical income above the table uses the documented minimum base estimate. + period: 2026 + input: + state_code: + - FL + age: + - 40 + immigration_status: + - CITIZEN + ssi: + - 0 + fl_tca: + - 0 + snap: + - 1_200 + employment_income: + - 100_000 + heating_type: + - NATURAL_GAS + heating_expense: + - 1_200 + output: + fl_liheap_eligible: + - true + fl_liheap: + - 200 +- name: Case 8, a subsidized household receives the full regular award without a HUD deduction or bill + cap. + period: 2026 + input: + state_code: + - FL + age: + - 40 + immigration_status: + - CITIZEN + ssi: + - 0 + fl_tca: + - 0 + snap: + - 0 + employment_income: + - 0 + heating_type: + - NATURAL_GAS + heating_expense: + - 10 + hud_utility_allowance: + - 2_400 + is_in_public_housing: + - true + receives_housing_assistance: + - true + output: + fl_liheap: + - 350 +- name: Case 9, the final award follows the heat in rent and subsidized residual cost routes. + period: 2026 + input: + state_code: + - FL + - FL + - FL + age: + - 40 + - 40 + - 40 + immigration_status: + - CITIZEN + - CITIZEN + - CITIZEN + ssi: + - 0 + - 0 + - 0 + fl_tca: + - 0 + - 0 + - 0 + snap: + - 0 + - 0 + - 0 + employment_income: + - 0 + - 0 + - 0 + heating_type: + - NATURAL_GAS + - NATURAL_GAS + - NATURAL_GAS + heating_expense: + - 0 + - 0 + - 10 + heat_expense_included_in_rent: + - true + - true + - true + receives_housing_assistance: + - false + - true + - true + output: + fl_liheap: + - 350 + - 0 + - 350 +- name: Case 10, the regular matrix is fuel neutral and applies only within Florida. + period: 2026 + input: + state_code: + - FL + - FL + - FL + - GA + age: + - 40 + - 40 + - 40 + - 40 + immigration_status: + - CITIZEN + - CITIZEN + - CITIZEN + - CITIZEN + ssi: + - 0 + - 0 + - 0 + - 0 + fl_tca: + - 0 + - 0 + - 0 + - 0 + snap: + - 0 + - 0 + - 0 + - 0 + employment_income: + - 0 + - 0 + - 0 + - 0 + heating_type: + - ELECTRICITY + - NATURAL_GAS + - WOOD + - NATURAL_GAS + heating_expense: + - 10 + - 10 + - 10 + - 10 + output: + fl_liheap: + - 350 + - 350 + - 350 + - 0 + +# Accepted FY2026 plan section 1.9, page 7, and the FY2026 matrix: net +# gambling of 40_000 - 30_000 = 10_000 falls in the 350 band; 40_000 of +# periodic estate receipts exceeds the 32_155 limit. No categorical receipts. +- name: Case 11, net gambling and periodic estate income determine ordinary awards. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [FL, FL] + age: [40, 40] + immigration_status: [CITIZEN, CITIZEN] + ssi: [0, 0] + fl_tca: [0, 0] + snap: [0, 0] + gambling_winnings: [40_000, 0] + gambling_losses: [30_000, 0] + estate_income: [0, 40_000] + heating_type: [NATURAL_GAS, NATURAL_GAS] + heating_expense: [1_200, 1_200] + output: + fl_liheap_countable_income: [10_000, 40_000] + fl_liheap: [350, 0] + +# FY2026 matrix p1: five completed years includes age 5.5, before the sixth +# birthday. Zero income gives the 350 base plus the 150 child supplement. +- name: Case 12, a child between the fifth and sixth birthdays retains the addition. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + person2: + age: 5.5 + immigration_status: CITIZEN + ssi: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + heating_expense: 1_200 + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap: 500 + +# FY2025 matrix ("Updated FY 2024/2025"), size 1: the maximum income value is +# 98_038 x 52% x 60% = 30_587.856 (printed 30_588). The first band ends at +# 30_587.856 x 50% = 15_293.928, printed 15_294. Wages of 10_000 fall in the +# first band, which pays 1_000; nobody qualifies for an addition. +- name: Case 13, a one-person household in fiscal year 2025 receives the first band award. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit: + members: [person1] + heating_type: NATURAL_GAS + heating_expense: 1_200 + fl_tca: 0 + snap: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_liheap_household_size: 1 + fl_liheap_countable_income: 10_000 + fl_liheap_income_limit: 30_587.856 + fl_liheap_eligible: true + fl_liheap: 1_000 + +# Boundary amounts. FY2025 matrix, size 1, prints the bands 15_294 or less, +# 15_295-21_411, 21_412-26_000 and 26_001-30_588. These round +# 30_587.856 x 50%, 70% and 85% (15_293.928, 21_411.499 and 25_999.678) and +# the maximum income value to the nearest dollar. Each printed top pays its +# band's base; one dollar more moves to the next band, and 30_589 exceeds the +# maximum income value. +- name: Case 14, fiscal year 2025 one-person band tops follow the printed matrix. + period: 2025 + input: + state_code: [FL, FL, FL, FL, FL, FL, FL, FL] + age: [40, 40, 40, 40, 40, 40, 40, 40] + immigration_status: [CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN] + ssi: [0, 0, 0, 0, 0, 0, 0, 0] + fl_tca: [0, 0, 0, 0, 0, 0, 0, 0] + snap: [0, 0, 0, 0, 0, 0, 0, 0] + employment_income: [15_294, 15_295, 21_411, 21_412, 26_000, 26_001, 30_588, 30_589] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS] + heating_expense: [1_200, 1_200, 1_200, 1_200, 1_200, 1_200, 1_200, 1_200] + output: + fl_liheap: [1_000, 750, 750, 550, 550, 400, 400, 0] + +# FY2025 matrix footnote and accepted FY2025 plan section 2.1, page 8: sizes 9 +# and above use 150% of the 2024 poverty guidelines when that exceeds 60% of +# state median income. Guideline 15_060 + 8 x 5_380 = 58_100, so the limit is +# 58_100 x 1.5 = 87_150; 60% of state median income is only +# 98_038 x 141% x 60% = 82_940.148. Wages of 50_000 + 35_000 = 85_000 fall in +# the over-125% band (72_626-87_150), which pays 400. No member is 60 or +# older, disabled, or 5 or younger. +- name: Case 15, a nine-person household in fiscal year 2025 qualifies under the poverty guideline limit. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: {age: 44, ssi: 0, employment_income: 50_000} + person2: {age: 42, ssi: 0, employment_income: 35_000} + person3: {age: 17, ssi: 0} + person4: {age: 15, ssi: 0} + person5: {age: 13, ssi: 0} + person6: {age: 11, ssi: 0} + person7: {age: 9, ssi: 0} + person8: {age: 8, ssi: 0} + person9: {age: 6, ssi: 0} + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] + heating_type: NATURAL_GAS + heating_expense: 1_200 + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9] + state_code: FL + output: + fl_liheap_household_size: 9 + fl_liheap_countable_income: 85_000 + fl_liheap_income_limit: 87_150 + fl_liheap_eligible: true + fl_liheap: 400 + +# Boundary amounts. FY2025 matrix, size 9: the bands are percentages of the +# 58_100 guideline. "75% of FPG or Less" prints 43_574, and "At least 75%" +# starts at 58_100 x 75% = 43_575. The second band ends at 58_100 (100%), the +# third at 72_625 (125%), and the maximum income value is 87_150 (150%). +- name: Case 16, fiscal year 2025 nine-person bands follow poverty guideline percentages. + period: 2025 + input: + state_code: [FL, FL, FL, FL, FL, FL, FL, FL] + age: [40, 40, 40, 40, 40, 40, 40, 40] + immigration_status: [CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN] + ssi: [0, 0, 0, 0, 0, 0, 0, 0] + fl_tca: [0, 0, 0, 0, 0, 0, 0, 0] + snap: [0, 0, 0, 0, 0, 0, 0, 0] + employment_income: [43_574, 43_575, 58_100, 58_101, 72_625, 72_626, 87_150, 87_151] + fl_liheap_household_size: [9, 9, 9, 9, 9, 9, 9, 9] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS] + heating_expense: [1_200, 1_200, 1_200, 1_200, 1_200, 1_200, 1_200, 1_200] + output: + fl_liheap: [1_000, 750, 750, 550, 550, 400, 400, 0] + +# Boundary amounts. FY2026 matrix: 70% of the maximum income value is exactly +# half a dollar at sizes 8, 10 and 12 (85_335 x 70% = 59_734.5, +# 89_045 x 70% = 62_331.5 and 92_755 x 70% = 64_928.5). The matrix rounds each +# up, so the second band ends at 59_735, 62_332 and 64_929. The printed top +# pays 300, and the next cent starts the third band, which pays 250. +- name: Case 17, fiscal year 2026 second band tops for sizes eight, ten and twelve round half up. + period: 2026 + input: + state_code: [FL, FL, FL, FL, FL, FL] + age: [40, 40, 40, 40, 40, 40] + immigration_status: [CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN] + ssi: [0, 0, 0, 0, 0, 0] + fl_tca: [0, 0, 0, 0, 0, 0] + snap: [0, 0, 0, 0, 0, 0] + employment_income: [59_735, 59_735.01, 62_332, 62_332.01, 64_929, 64_929.01] + fl_liheap_household_size: [8, 8, 10, 10, 12, 12] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS] + heating_expense: [1_200, 1_200, 1_200, 1_200, 1_200, 1_200] + output: + fl_liheap: [300, 250, 300, 250, 300, 250] + +# Accepted FY2026 plan section 1.9, page 6, counts retirement and pension +# benefits; military retirement pay and railroad retirement benefits are +# separate inputs from pension_income. 35_000 of military retirement pay +# exceeds the 32_155 one-person limit. 20_000 of railroad retirement benefits +# falls in the second band (16_079-22_509): 300 base + 100 for age 60 or older. +- name: Case 18, military retirement pay and railroad retirement benefits count toward income. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [FL, FL] + age: [50, 62] + immigration_status: [CITIZEN, CITIZEN] + ssi: [0, 0] + fl_tca: [0, 0] + snap: [0, 0] + military_retirement_pay: [35_000, 0] + railroad_benefits: [0, 20_000] + heating_type: [NATURAL_GAS, NATURAL_GAS] + heating_expense: [1_200, 1_200] + output: + fl_liheap_countable_income: [35_000, 20_000] + fl_liheap_eligible: [false, true] + fl_liheap: [0, 400] + +# Accepted FY2026 plan section 1.8, page 5, counts gross income, and section +# 1.9, page 7, counts "net gambling or lottery winnings". A 20_000 +# self-employment loss does not offset 40_000 of wages. Gambling losses of +# 3_000 offset only the 1_000 of winnings, leaving 34_000 of wages. Both +# amounts exceed the 32_155 one-person limit. +- name: Case 19, a business loss or excess gambling losses do not bring income under the limit. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [FL, FL] + age: [40, 40] + immigration_status: [CITIZEN, CITIZEN] + ssi: [0, 0] + fl_tca: [0, 0] + snap: [0, 0] + employment_income: [40_000, 34_000] + self_employment_income: [-20_000, 0] + gambling_winnings: [0, 1_000] + gambling_losses: [0, 3_000] + heating_type: [NATURAL_GAS, NATURAL_GAS] + heating_expense: [1_200, 1_200] + output: + fl_liheap_countable_income: [40_000, 34_000] + fl_liheap_eligible: [false, false] + fl_liheap: [0, 0] + +# Accepted FY2025 plan section 2.6, page 10: "Maximum Benefit $1,350". FY2025 +# matrix, size 2: 98_038 x 68% x 60% = 39_999.504 (printed 40_000); the first +# band ends at 39_999.504 x 50% = 19_999.752, printed 20_000. Gross Social +# Security of 14_400 falls in the first band: 1_000 base + 100 elderly + 100 +# disabled + 150 for a child age 5 or younger = 1_350. +- name: Case 20, a fiscal year 2025 household with every addition receives the published maximum. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 66 + immigration_status: CITIZEN + is_disabled: true + ssi: 0 + social_security: 14_400 + person2: + age: 4 + immigration_status: CITIZEN + ssi: 0 + spm_units: + spm_unit: + members: [person1, person2] + heating_type: NATURAL_GAS + heating_expense: 1_200 + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_countable_income: 14_400 + fl_liheap_income_limit: 39_999.504 + fl_liheap: 1_350 + +# Part-time wages at the Florida minimum wage (Fla. Const. art. X, sec. 24): +# 20 hours a week for 39 weeks at 14.00, then 13 weeks at 15.00 after the +# September 30, 2026 increase, so 20 x (39 x 14 + 13 x 15) = 14_820. That is +# under the FY2026 one-person maximum of 32_155. Heat is not included in rent +# and no heating fuel is reported, so the reported heating cost does not +# qualify: an unspecified fuel counts only when heat is included in rent. +- name: Case 21, an unspecified heating fuel outside rent does not qualify despite a reported heating cost. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + employment_income: 14_820 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + has_heating_expense: true + heat_expense_included_in_rent: false + fl_tca: 0 + snap: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_liheap_countable_income: 14_820 + fl_liheap_eligible: false + fl_liheap: 0 + +# Same 14_820 of part-time wages as Case 21. Heat is included in unsubsidized +# rent and the tenant does not know the building's fuel, so heating_type stays +# UNSPECIFIED. FY2026 matrix, size 1: 60% of the four-person state median +# income of 103_063 is 61_837 (truncated), and 61_837 x 52% = 32_155 +# (truncated). The first band ends at 32_155 x 50% = 16_077.5, printed 16_078. +# Wages of 14_820 fall in the first band, which pays 350. Nobody is 60 or +# older, disabled, or 5 or younger, so no addition applies. +- name: Case 22, an unspecified heating fuel included in unsubsidized rent receives the first band award. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + employment_income: 14_820 + spm_units: + spm_unit: + members: [person1] + heating_type: UNSPECIFIED + heat_expense_included_in_rent: true + receives_housing_assistance: false + fl_tca: 0 + snap: 0 + households: + household: + members: [person1] + state_code: FL + is_in_public_housing: false + output: + fl_liheap_countable_income: 14_820 + fl_liheap_income_limit: 32_155 + fl_liheap_eligible: true + fl_liheap: 350 + +# Statewide application p1 and portal FAQ exclude all minor income regardless +# of school attendance. The adult with the same 34_000 income is over the +# FY2026 one-person limit 32_155; minors qualify for the 350 first-band base. +- name: Case 23, minor nonstudent income is excluded through the final benefit. + period: 2026 + input: + state_code: [FL, FL, FL] + age: [16, 17, 18] + immigration_status: [CITIZEN, CITIZEN, CITIZEN] + is_full_time_student: [false, false, false] + employment_income: [30_000, 30_000, 30_000] + social_security: [4_000, 4_000, 4_000] + ssi: [0, 0, 0] + tanf: [0, 0, 0] + snap: [0, 0, 0] + heating_type: [ELECTRICITY, ELECTRICITY, ELECTRICITY] + heating_expense: [1_200, 1_200, 1_200] + output: + fl_liheap_countable_income: [0, 0, 34_000] + fl_liheap_income_limit: [32_155, 32_155, 32_155] + fl_liheap_eligible: [true, true, false] + fl_liheap: [350, 350, 0] + +# FY2026, size 13: the matrix footnote's 60% of state median income gives +# floor(61_837 x 1.53) = 94_610; the printed 157_686 row (100% of state median +# income) is not followed. Band tops round half up: 94_610 x 50% = 47_305, +# x 70% = 66_227 and x 85% = 80_418.5, so 80_419. 60_000 is in band 2 (300), as +# at sizes 12 (46_379-64_929) and 14 (48_234-67_526). Income above 94_610 is +# ineligible without receipt (the 110% floor for 13 is 89_815); SNAP receipt +# waives the test and income above the table pays the 200 base. +- name: Case 24, thirteen-person bands follow the sixty percent state median income limit. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [FL, FL, FL, FL, FL, FL, FL, FL, FL, FL] + age: [40, 40, 40, 40, 40, 40, 40, 40, 40, 40] + immigration_status: [CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN, CITIZEN] + fl_liheap_household_size: [13, 13, 13, 13, 13, 13, 13, 13, 13, 13] + fl_liheap_countable_income: [47_305, 47_305.01, 60_000, 66_227, 66_227.01, 80_419, 80_419.01, 94_610, 94_610.01, 100_000] + snap: [0, 0, 0, 0, 0, 0, 0, 0, 0, 1] + tanf: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ssi: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + heating_type: [ELECTRICITY, ELECTRICITY, ELECTRICITY, ELECTRICITY, ELECTRICITY, ELECTRICITY, ELECTRICITY, ELECTRICITY, ELECTRICITY, ELECTRICITY] + heating_expense: [1_200, 1_200, 1_200, 1_200, 1_200, 1_200, 1_200, 1_200, 1_200, 1_200] + output: + fl_liheap_income_limit: [94_610, 94_610, 94_610, 94_610, 94_610, 94_610, 94_610, 94_610, 94_610, 94_610] + fl_liheap_eligible: [true, true, true, true, true, true, true, true, false, true] + fl_liheap: [350, 300, 300, 300, 250, 250, 200, 200, 0, 200] + +# Federal 110% poverty floor: 42 U.S.C. 8624(b)(2)(B), repeated in the accepted +# FY2026 plan assurances (page 45) and contract G(8)e, bars excluding a +# household on income below 110 percent of the poverty level. Period 2026 uses +# the 2025 guideline: size 15 is 15_650 + 14 x 5_500 = 92_650 (floor 101_915), +# size 16 is 98_150 (floor 107_965). The FY2026 limits are +# floor(61_837 x 1.59) = 98_320 and floor(61_837 x 1.62) = 100_175. Incomes +# between each limit and floor stay eligible in band 4 (200); 101_915.01 is +# excluded. +- name: Case 25, households of fifteen or more below 110 percent of the poverty guideline remain income eligible. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [FL, FL, FL, FL] + age: [40, 40, 40, 40] + immigration_status: [CITIZEN, CITIZEN, CITIZEN, CITIZEN] + ssi: [0, 0, 0, 0] + fl_tca: [0, 0, 0, 0] + snap: [0, 0, 0, 0] + employment_income: [100_000, 105_000, 101_914.99, 101_915.01] + fl_liheap_household_size: [15, 16, 15, 15] + heating_type: [NATURAL_GAS, NATURAL_GAS, NATURAL_GAS, NATURAL_GAS] + heating_expense: [1_200, 1_200, 1_200, 1_200] + output: + fl_liheap_income_limit: [98_320, 100_175, 98_320, 98_320] + fl_liheap_eligible: [true, true, true, false] + fl_liheap: [200, 200, 200, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/fl_liheap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/fl_liheap_household_size.yaml new file mode 100644 index 00000000000..280170da862 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/fl_liheap_household_size.yaml @@ -0,0 +1,63 @@ +# Florida LIHEAP household size counts citizens and qualified noncitizens; no final program eligibility or award is asserted. + +# Manual pages 41-42 count citizens and qualified noncitizens and exclude +# nonqualified people from the size; SNAP-specific waiting periods do not apply. +- name: Case 1, qualified adults and children count without a SNAP waiting bar. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: LEGAL_PERMANENT_RESIDENT + ssi: 0 + person2: + age: 8 + immigration_status: CITIZEN + ssi: 0 + person3: + age: 35 + immigration_status: ASYLEE + ssi: 0 + person4: + age: 22 + immigration_status: DACA + ssi: 0 + person5: + age: 39 + immigration_status: UNDOCUMENTED + ssi: 0 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: FL + output: + fl_liheap_household_size: 3 + +# Manual pages 41-42 require at least one qualified member for final program +# eligibility; this size component returns 0, and the income limit is masked to +# 0 (the SMI size factor would otherwise treat size 0 as one person, 32_155). +- name: Case 2, only nonqualified members produce a zero household size. + period: 2026 + input: + people: + person1: + age: 40 + immigration_status: UNDOCUMENTED + ssi: 0 + spm_units: + spm_unit: + members: [person1] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_liheap_household_size: 0 + fl_liheap_income_limit: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/income/fl_liheap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/income/fl_liheap_countable_income.yaml new file mode 100644 index 00000000000..53a1e49f87e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/fl/commerce/liheap/income/fl_liheap_countable_income.yaml @@ -0,0 +1,626 @@ +# Florida independent household income and categorical-income components; no final program eligibility or award is asserted. + +# Manual pages 49-50 and FY2026 plan pages 5-6: 12_000 + 2_400 + 600 + 1_200 + +# 1_200 = 17_400 from the existing net business inputs. +- name: Case 1, adult wages and existing net business income count without a second expense deduction. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + employment_income: 12_000 + self_employment_income: 2_400 + sstb_self_employment_income: 600 + farm_operations_income: 1_200 + partnership_s_corp_income: 1_200 + spm_units: + spm_unit: + members: [person1] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_liheap_countable_income: 17_400 + +# FY2026 plan section 1.8, page 5, counts gross income, and manual 1200.01B, +# page 49, counts "the gross amount of income", so each source is floored at +# zero: 12_000 wages + max(-6_000, 0) + 600 partnership income = 12_600. +- name: Case 2, a self-employment loss does not offset wages or partnership income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + employment_income: 12_000 + self_employment_income: -6_000 + partnership_s_corp_income: 600 + spm_units: + spm_unit: + members: [person1] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_liheap_countable_income: 12_600 + +# Each source is floored at zero: 1_200 wages + max(-6_000, 0) = 1_200. +- name: Case 3, a self-employment loss larger than wages leaves the wages counted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + employment_income: 1_200 + self_employment_income: -6_000 + spm_units: + spm_unit: + members: [person1] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_liheap_countable_income: 1_200 + +# FY2026 plan page 6 leaves unemployment compensation and cash gifts +# unselected. Wages of 30_000 count; 6_000 of unemployment compensation, 2_400 +# of gifts and 6_000 of SNAP do not. +- name: Case 4, current plan excludes unemployment and cash gifts. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + employment_income: 30_000 + unemployment_compensation: 6_000 + financial_assistance: 2_400 + spm_units: + spm_unit: + members: [person1] + fl_tca: 0 + snap: 6_000 + households: + household: + members: [person1] + state_code: FL + output: + fl_liheap_countable_income: 30_000 + +# The statewide application, Monthly Household Income (page 1), excludes +# all minors' income. The FY2026 plan endorses this portal in section 1.10. +# The young member's 9_800 total income is excluded, leaving parent income. +- name: Case 5, a 15-year-old nonstudent's income is excluded under the statewide application. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + immigration_status: CITIZEN + ssi: 0 + employment_income: 12_000 + person2: + age: 15 + immigration_status: CITIZEN + is_full_time_student: false + ssi: 0 + employment_income: 6_000 + self_employment_income: 1_200 + social_security: 1_200 + estate_income: 900 + gambling_winnings: 600 + gambling_losses: 100 + spm_units: + spm_unit: + members: [person1, person2] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_countable_income: 12_000 + +# The statewide application page 1 and portal FAQ exclude all minors' income, +# without a student exception. Only the parent's 12_000 counts. +- name: Case 6, a 16-year-old nonstudent's earned and unearned income are both excluded. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + immigration_status: CITIZEN + ssi: 0 + employment_income: 12_000 + person2: + age: 16 + immigration_status: CITIZEN + is_full_time_student: false + ssi: 0 + employment_income: 6_000 + self_employment_income: 1_200 + social_security: 1_200 + estate_income: 900 + gambling_winnings: 600 + gambling_losses: 100 + spm_units: + spm_unit: + members: [person1, person2] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_countable_income: 12_000 + +# The statewide application page 1 and portal FAQ exclude all minors' income, +# without a student exception. Only the parent's 12_000 counts. +- name: Case 7, a 16-year-old full-time student's earned and unearned income are both excluded. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + immigration_status: CITIZEN + ssi: 0 + employment_income: 12_000 + person2: + age: 16 + immigration_status: CITIZEN + is_full_time_student: true + ssi: 0 + employment_income: 6_000 + self_employment_income: 1_200 + social_security: 1_200 + estate_income: 900 + gambling_winnings: 600 + gambling_losses: 100 + spm_units: + spm_unit: + members: [person1, person2] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_countable_income: 12_000 + +# The statewide application page 1 and portal FAQ exclude all minors' income, +# without a student exception. Only the parent's 12_000 counts. +- name: Case 8, a 17-year-old nonstudent's earned and unearned income are both excluded. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + immigration_status: CITIZEN + ssi: 0 + employment_income: 12_000 + person2: + age: 17 + immigration_status: CITIZEN + is_full_time_student: false + ssi: 0 + employment_income: 6_000 + self_employment_income: 1_200 + social_security: 1_200 + estate_income: 900 + gambling_winnings: 600 + gambling_losses: 100 + spm_units: + spm_unit: + members: [person1, person2] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_countable_income: 12_000 + +# The statewide application page 1 and portal FAQ exclude all minors' income, +# without a student exception. Only the parent's 12_000 counts. +- name: Case 9, a 17-year-old full-time student's earned and unearned income are both excluded. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + immigration_status: CITIZEN + ssi: 0 + employment_income: 12_000 + person2: + age: 17 + immigration_status: CITIZEN + is_full_time_student: true + ssi: 0 + employment_income: 6_000 + self_employment_income: 1_200 + social_security: 1_200 + estate_income: 900 + gambling_winnings: 600 + gambling_losses: 100 + spm_units: + spm_unit: + members: [person1, person2] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_countable_income: 12_000 + +# Manual 1200.01D, page 49, counts any income of a member 18 and older, +# whether or not a full-time student: parent 12_000 + young member 6_000 +# wages + 1_200 self-employment + 1_200 Social Security + 900 estate + +# (600 - 100) gambling = 21_800. +- name: Case 10, an 18-year-old full-time student's earned and unearned income both count. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + immigration_status: CITIZEN + ssi: 0 + employment_income: 12_000 + person2: + age: 18 + immigration_status: CITIZEN + is_full_time_student: true + ssi: 0 + employment_income: 6_000 + self_employment_income: 1_200 + social_security: 1_200 + estate_income: 900 + gambling_winnings: 600 + gambling_losses: 100 + spm_units: + spm_unit: + members: [person1, person2] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_countable_income: 21_800 + +# FY2026 plan page 6 rent and retirement categories: 30_000 wages + 1_200 +# rent + 5_000 farm rent + 1_200 survivor benefits = 37_400, with no added +# allowance. +- name: Case 11, rental and survivor inputs count independently in full. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + employment_income: 30_000 + rental_income: 1_200 + farm_rent_income: 5_000 + survivor_benefits: 1_200 + spm_units: + spm_unit: + members: [person1] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_liheap_countable_income: 37_400 + +# FY2026 plan pages 6-7: 1_200 SSI + 18_000 Social Security + 2_400 pension + +# 1_200 survivor + 600 workers' compensation + 600 disability + 600 veterans + +# 300 general assistance + 300 strike + 1_200 child support + 600 alimony + +# 120 interest + 240 dividends = 27_360, plus 2_400 of periodic estate income +# = 29_760. Estate receipts exclude inherited principal and separately reported +# interest and dividends; each source counts once. +- name: Case 12, disjoint covered unearned receipts and canonical dividends count once. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 67 + immigration_status: CITIZEN + ssi: 1_200 + social_security: 18_000 + pension_income: 2_400 + survivor_benefits: 1_200 + workers_compensation: 600 + disability_benefits: 600 + veterans_benefits: 600 + general_assistance: 300 + strike_benefits: 300 + child_support_received: 1_200 + alimony_income: 600 + interest_income: 120 + ordinary_dividend_income: 240 + estate_income: 2_400 + spm_units: + spm_unit: + members: [person1] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_liheap_countable_income: 29_760 + +# FY2026 plan page 6 counts Social Security "Including MediCare deduction"; +# manual page 50 adds premiums back to net checks. Gross 24_000 counts, not +# 21_600. +- name: Case 13, gross Social Security remains counted before Medicare premiums. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 67 + immigration_status: CITIZEN + ssi: 0 + social_security: 24_000 + medicare_part_b_premium: 2_400 + spm_units: + spm_unit: + members: [person1] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_liheap_countable_income: 24_000 + +# FY2026 plan page 6 counts TANF: 6_000 adult wages + 3_600 annual Florida +# TCA = 9_600. The child's 1_200 of Social Security is excluded by the manual's +# age rule; the monthly state grant is added once per family. +- name: Case 14, state cash assistance is annualized once for the family. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + employment_income: 6_000 + person2: + age: 8 + immigration_status: CITIZEN + ssi: 0 + social_security: 1_200 + spm_units: + spm_unit: + members: [person1, person2] + fl_tca: 3_600 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_countable_income: 9_600 + +# Manual page 42 retains all of a nonqualified adult's income although the +# household size is 1; the minor's Social Security is excluded under the +# manual page 49 age rule. No proration. +- name: Case 15, nonqualified adult income is retained in full for a qualified child household. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: UNDOCUMENTED + ssi: 0 + employment_income: 20_000 + person2: + age: 8 + immigration_status: CITIZEN + ssi: 0 + social_security: 1_200 + spm_units: + spm_unit: + members: [person1, person2] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_household_size: 1 + fl_liheap_countable_income: 20_000 + +# Accepted FY2026 plan section 1.9, page 7: net gambling or lottery winnings. +# 40_000 winnings - 30_000 losses = 10_000. +- name: Case 16, gambling winnings count net of associated losses. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + ssi: 0 + gambling_winnings: 40_000 + gambling_losses: 30_000 + spm_units: + spm_unit: + members: [person1] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1] + state_code: FL + output: + fl_liheap_countable_income: 10_000 + +# Plan section 1.9, page 7, counts net gambling winnings, so losses offset only +# winnings: 1_200 wages + max(4_000 - losses, 0) = 1_200 for losses of 4_000, +# 5_000 and 10_000. +- name: Case 17, gambling losses offset only gambling winnings. + period: 2026 + absolute_error_margin: 0.01 + input: + state_code: [FL, FL, FL] + age: [40, 40, 40] + immigration_status: [CITIZEN, CITIZEN, CITIZEN] + ssi: [0, 0, 0] + fl_tca: [0, 0, 0] + snap: [0, 0, 0] + employment_income: [1_200, 1_200, 1_200] + gambling_winnings: [4_000, 4_000, 4_000] + gambling_losses: [4_000, 5_000, 10_000] + output: + fl_liheap_countable_income: [1_200, 1_200, 1_200] + +# FY2026 plan section 1.9, page 6, counts retirement and pension benefits. +# Military retirement pay and railroad retirement benefits are separate inputs +# from pension_income: 24_000 military retirement pay + 6_000 private pension +# + 18_000 railroad retirement benefits = 48_000. +- name: Case 18, military retirement pay and railroad retirement benefits count beside pensions. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 58 + immigration_status: CITIZEN + ssi: 0 + military_retirement_pay: 24_000 + taxable_private_pension_income: 6_000 + person2: + age: 63 + immigration_status: CITIZEN + ssi: 0 + railroad_benefits: 18_000 + spm_units: + spm_unit: + members: [person1, person2] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_countable_income: 48_000 + +# FY2026 plan section 1.8, page 5, counts gross income, so each earned and +# unearned source is floored at zero and a loss in one source or member cannot +# offset another. Counted: 30_000 wages + 500 interest = 30_500. Floored to +# zero: farm operations -2_500 and farm rent -4_000 (person1); self-employment +# -8_000, partnership -1_000, rental -3_000 and estate -1_500 (person2). +- name: Case 19, losses in business, rental, farm rent and estate sources are each floored at zero. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + immigration_status: CITIZEN + ssi: 0 + employment_income: 30_000 + farm_operations_income: -2_500 + farm_rent_income: -4_000 + person2: + age: 44 + immigration_status: CITIZEN + ssi: 0 + self_employment_income: -8_000 + partnership_s_corp_income: -1_000 + rental_income: -3_000 + estate_income: -1_500 + interest_income: 500 + spm_units: + spm_unit: + members: [person1, person2] + fl_tca: 0 + snap: 0 + households: + household: + members: [person1, person2] + state_code: FL + output: + fl_liheap_countable_income: 30_500 + +# FY2026 plan section 1.9, page 6, counts TANF received. Florida TCA for a +# family of three with a shelter obligation over $50 is 303 a month, or +# 303 x 12 = 3_636 a year. The take-up-gated tanf total counts it when the +# family takes up TCA (first household) and adds 0 when it does not (second). +- name: Case 20, Florida cash assistance counts only when the family takes it up. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: {age: 30, ssi: 0} + person2: {age: 7, ssi: 0} + person3: {age: 4, ssi: 0} + person4: {age: 30, ssi: 0} + person5: {age: 7, ssi: 0} + person6: {age: 4, ssi: 0} + spm_units: + spm_unit1: + members: [person1, person2, person3] + fl_tca: 3_636 + takes_up_tanf_if_eligible: true + snap: 0 + spm_unit2: + members: [person4, person5, person6] + fl_tca: 3_636 + takes_up_tanf_if_eligible: false + snap: 0 + households: + household1: + members: [person1, person2, person3] + state_code: FL + household2: + members: [person4, person5, person6] + state_code: FL + output: + tanf: [3_636, 0] + fl_liheap_countable_income: [3_636, 0] diff --git a/policyengine_us/variables/gov/states/fl/commerce/liheap/eligibility/fl_liheap_categorically_eligible.py b/policyengine_us/variables/gov/states/fl/commerce/liheap/eligibility/fl_liheap_categorically_eligible.py new file mode 100644 index 00000000000..ff4810b8eec --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/commerce/liheap/eligibility/fl_liheap_categorically_eligible.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class fl_liheap_categorically_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Florida LIHEAP categorical income eligibility" + defined_for = StateCode.FL + reference = ( + "https://liheapch.acf.gov/docs/2026/state-plans/FL_Plan_2026.pdf#page=5", + "https://liheapch.acf.gov/sites/default/files/webfiles/docs/2023/manuals/FL_PolicyManual_2023.pdf#page=50", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.fl.commerce.liheap.eligibility + receipts = add(spm_unit, period, p.categorical_programs, options=[ADD]) + # Positive take-up-gated SNAP, TANF, or SSI is the receipt proxy. + # A minor's SSI may establish this status even when excluded from income. + # This waives only the income test, not heating responsibility, residency, + # or qualified-member requirements, and does not select a benefit band. + return receipts > 0 diff --git a/policyengine_us/variables/gov/states/fl/commerce/liheap/eligibility/fl_liheap_eligible.py b/policyengine_us/variables/gov/states/fl/commerce/liheap/eligibility/fl_liheap_eligible.py new file mode 100644 index 00000000000..ffd8e2095ad --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/commerce/liheap/eligibility/fl_liheap_eligible.py @@ -0,0 +1,73 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class fl_liheap_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Florida LIHEAP regular heating eligibility" + defined_for = StateCode.FL + reference = ( + "https://www.law.cornell.edu/uscode/text/42/8624", + # PDF pages 5, 8, 45 + "https://liheapch.acf.gov/docs/2026/state-plans/FL_Plan_2026.pdf#page=5", + # PDF pages 4, 23, 39, 41, 43, 47-48, 50-51 + "https://liheapch.acf.gov/sites/default/files/webfiles/docs/2023/manuals/FL_PolicyManual_2023.pdf#page=4", + # PDF pages 12-13 + "https://www.pbcgov.com/pubInf/Agenda/20260106/3E2.pdf#page=12", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.fl.commerce.liheap.eligibility + p_hhs = parameters(period).gov.hhs.liheap + size = spm_unit("fl_liheap_household_size", period) + income = spm_unit("fl_liheap_countable_income", period) + # The matrices print the maximum income value in whole dollars. Manual + # 1200.03A (page 51) and contract G(8)a annualize 30 days of income + # against it; the portal instead compares one month with monthly + # maximums rounded to whole dollars, which differ from this annual + # value by at most $6 a year either way ($2,680 for one person is $5 + # more lenient than 32,155 / 12 = 2,679.58; $3,504 for two is $1 + # stricter). + limit = np.floor(spm_unit("fl_liheap_income_limit", period) + 0.5) + state_group = spm_unit.household("state_group_str", period) + guideline = fpg(size, state_group, period, parameters, year_lag=p.fpg_year_lag) + # 42 U.S.C. 8624(b)(2)(B), the FY2026 plan assurances (page 45) and + # contract G(8)e bar excluding a household on income below 110% of the + # poverty level; from 15 people this floor exceeds the FY2026 limit. + income_eligible = (income <= limit) | (income < guideline * p_hhs.fpg_floor) + categorical = spm_unit("fl_liheap_categorically_eligible", period) + heating_expense = spm_unit("heating_expense", period) + heat_in_rent = spm_unit("heat_expense_included_in_rent", period) + subsidized = spm_unit("receives_housing_assistance", period) | ( + spm_unit.household("is_in_public_housing", period) + ) + # The nonsubsidized rent flag represents a verified landlord heating + # arrangement. Actual verification and account ownership are absent + # from existing inputs. In subsidized heat-in-rent housing, a positive + # heating expense represents the household's verified excess charge. + # Outside rent, has_heating_expense (true by default when the primary + # fuel's bill is positive) is the obligation, and an explicit false is + # respected. + # Source conflict: manual 900.01A (page 39) allows "non-subsidized rent + # that includes utilities", but 1100.04B(1) (page 47) asks for a + # landlord statement that "Home energy costs are not included in their + # rent". This follows 900.01A, 100.01 (page 4) and FY2025 plan item + # 2.3's utilities-in-rent answer (page 9); the same FY2025 item repeats + # the landlord statement under Renters (page 8), and the FY2026 plan + # answers No to all three renter rows (page 8). + responsible = where( + heat_in_rent, + ~subsidized | (heating_expense > 0), + spm_unit("has_heating_expense", period), + ) + heating_type = spm_unit("heating_type", period) + types = heating_type.possible_values + # An unspecified fuel qualifies only when heat is included in rent. + fuel_qualifies = (heating_type != types.NONE) & ( + heat_in_rent | (heating_type != types.UNSPECIFIED) + ) + return ( + (size > 0) & (income_eligible | categorical) & responsible & fuel_qualifies + ) diff --git a/policyengine_us/variables/gov/states/fl/commerce/liheap/eligibility/fl_liheap_income_limit.py b/policyengine_us/variables/gov/states/fl/commerce/liheap/eligibility/fl_liheap_income_limit.py new file mode 100644 index 00000000000..1c88a8949e7 --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/commerce/liheap/eligibility/fl_liheap_income_limit.py @@ -0,0 +1,55 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.hhs_smi import liheap_smi_limit, smi +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class fl_liheap_income_limit(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Florida LIHEAP annual heating maximum income value before rounding" + defined_for = StateCode.FL + reference = ( + "https://liheapch.acf.gov/docs/2026/state-plans/FL_Plan_2026.pdf#page=8", + "https://liheapch.acf.gov/docs/2026/benefits-matricies/FL_BenefitMatrix_Heat-Cool_2026.pdf", + "https://liheapch.acf.gov/delivery/income_eligibility.htm", + "https://liheapch.acf.gov/docs/2025/state-plans/FL_Plan_2025.pdf#page=8", + "https://liheapch.acf.gov/docs/2025/benefits-matricies/FL_BenefitMatrix_2025.pdf", + "https://www.law.cornell.edu/uscode/text/42/8624", + "https://floridaliheap.com/faq", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.fl.commerce.liheap.eligibility + size = spm_unit("fl_liheap_household_size", period) + state = spm_unit.household("state_code_str", period) + if p.truncates_smi_limit: + # The HHS floor order reconciles all FY2026 matrix rows, sizes 1-12. + smi_limit = liheap_smi_limit(size, state, p.smi_rate, period, parameters) + else: + # The FY2025 matrix rounds this unrounded amount, and each band + # cutoff derived from it, to the nearest dollar. + smi_limit = smi(size, state, period, parameters) * p.smi_rate + # Source conflict: manual 900.01D (page 39) sets 60% of SMI for sizes + # 1-8 and 150% of the poverty guideline for 9 or more, while 1100.03D + # (page 47) and 1200.01A (page 49) set 150% of the guideline for every + # size. The FY2025 plan and matrix match 900.01D. The FY2026 plan + # (page 8) and matrix use 60% of SMI for every size, and the manual + # says to follow DEO's current benefit matrix (page 9), so FY2026 + # follows the matrix. + # The printed FY2026 size-13 row tops out at $157,686, which is 100% of + # SMI (103,063 x 1.53), and the portal FAQ prints $13,141 a month + # (157,686 / 12). The matrix footnote says 60% of SMI, plan item 2.1 + # (page 8) lists 60% for sizes 1-9, and 42 U.S.C. 8624(b)(2)(B) caps + # eligibility at the greater of 150% of poverty and 60% of SMI, which + # the printed row exceeds. Size 13 therefore uses 60% of SMI ($94,610) + # for both this limit and the payment bands. The federal table + # restricts its 150%-FPG large-household exception to cooling/crisis. + # Larger sizes follow the federal factors without table verification; + # from 15 people the 110%-of-poverty floor in fl_liheap_eligible + # exceeds this limit. + state_group = spm_unit.household("state_group_str", period) + guideline = fpg(size, state_group, period, parameters, year_lag=p.fpg_year_lag) + limit = max_(smi_limit, guideline * p.fpg_rate) + return where(size > 0, limit, 0) diff --git a/policyengine_us/variables/gov/states/fl/commerce/liheap/fl_liheap.py b/policyengine_us/variables/gov/states/fl/commerce/liheap/fl_liheap.py new file mode 100644 index 00000000000..3e1a5e7312e --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/commerce/liheap/fl_liheap.py @@ -0,0 +1,85 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class fl_liheap(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Florida LIHEAP regular heating assistance" + defined_for = StateCode.FL + reference = ( + "https://liheapch.acf.gov/docs/2026/benefits-matricies/FL_BenefitMatrix_Heat-Cool_2026.pdf", + # PDF pages 8-9, 23-24, 43 + "https://liheapch.acf.gov/sites/default/files/webfiles/docs/2023/manuals/FL_PolicyManual_2023.pdf#page=8", + "https://liheapch.acf.gov/docs/2026/state-plans/FL_Plan_2026.pdf#page=9", + "https://liheapch.acf.gov/docs/2025/benefits-matricies/FL_BenefitMatrix_2025.pdf", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.fl.commerce.liheap + income = spm_unit("fl_liheap_countable_income", period) + limit = spm_unit("fl_liheap_income_limit", period) + size = spm_unit("fl_liheap_household_size", period) + state_group = spm_unit.household("state_group_str", period) + guideline = fpg( + size, + state_group, + period, + parameters, + year_lag=p.eligibility.fpg_year_lag, + ) + # Where the poverty-guideline limit sets the maximum income value + # (FY2025 sizes 9 and above), the bands are guideline percentages. + fpg_based = guideline * p.eligibility.fpg_rate >= limit + fraction = p.payment.income_band_fraction + band_fpg_rate = p.payment.income_band_fpg_rate + # Half-up dollar cutoffs reproduce the printed bands without leaving + # gaps for income with cents between successive printed dollar bounds. + first = where( + fpg_based, + guideline * band_fpg_rate.first, + np.floor(limit * fraction.first + 0.5), + ) + second = where( + fpg_based, + guideline * band_fpg_rate.second, + np.floor(limit * fraction.second + 0.5), + ) + third = where( + fpg_based, + guideline * band_fpg_rate.third, + np.floor(limit * fraction.third + 0.5), + ) + # The FY2025 second guideline band starts "At least 75%" of the + # guideline, so the first guideline band excludes its upper bound. + in_first = where(fpg_based, income < first, income <= first) + band = select( + [in_first, income <= second, income <= third], + [1, 2, 3], + default=4, + ) + # Categorical households and households protected by the federal + # 110%-of-poverty floor (fl_liheap_eligible) can have income above the + # maximum income value. They receive the band 4 (smallest) base as an + # estimate; the sources do not supply an above-range benefit band. + # Receipt alone never selects a higher-paying band. + base = p.payment.base_amount[band] + age = spm_unit.members("age", period) + elderly = spm_unit.any(age >= p.payment.elderly_min_age) + disabled = add(spm_unit, period, ["is_disabled"]) > 0 + child = spm_unit.any(age < p.payment.child_max_age + 1) + supplement = p.payment.supplement + supplements = ( + elderly * supplement.elderly + + disabled * supplement.disabled + + child * supplement.child + ) + # FY2026 follows the operative October 2025 matrix ($200-$700), as + # required by the manual; the FY2026 plan's estimated $400-$1,350 + # extrema conflict with it. The FY2025 plan and matrix agree. + # One award per year is modeled. No actual-bill cap or HUD deduction + # applies to regular benefits; previous awards require unavailable data. + eligible = spm_unit("fl_liheap_eligible", period) + return eligible * (base + supplements) diff --git a/policyengine_us/variables/gov/states/fl/commerce/liheap/fl_liheap_household_size.py b/policyengine_us/variables/gov/states/fl/commerce/liheap/fl_liheap_household_size.py new file mode 100644 index 00000000000..06db9d841f5 --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/commerce/liheap/fl_liheap_household_size.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class fl_liheap_household_size(Variable): + value_type = int + entity = SPMUnit + definition_period = YEAR + label = "Florida LIHEAP household size" + defined_for = StateCode.FL + # PDF pages 41-42 + reference = "https://liheapch.acf.gov/sites/default/files/webfiles/docs/2023/manuals/FL_PolicyManual_2023.pdf#page=41" + + # Manual 900.04A (page 41) makes a household eligible when "at least one + # member, preferably an adult," qualifies, but 900.04D.1 denies the + # application when "The applicant is an illegal alien". No input names + # the applicant, so a qualified member is assumed to apply. + # Ineligible members are excluded from size, but their otherwise countable + # income remains included in full. SPM membership approximates the energy + # economic unit; roomers, separate energy units, special status documents, + # and tribal-provider assignments are not completely identified by inputs. + adds = ["is_citizen_or_legal_immigrant"] diff --git a/policyengine_us/variables/gov/states/fl/commerce/liheap/income/fl_liheap_countable_income.py b/policyengine_us/variables/gov/states/fl/commerce/liheap/income/fl_liheap_countable_income.py new file mode 100644 index 00000000000..6a15de059a1 --- /dev/null +++ b/policyengine_us/variables/gov/states/fl/commerce/liheap/income/fl_liheap_countable_income.py @@ -0,0 +1,60 @@ +from policyengine_us.model_api import * + + +class fl_liheap_countable_income(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "Florida LIHEAP annual countable household income" + defined_for = StateCode.FL + # Plan section 1.9 + reference = ( + # PDF pages 5-7 + "https://liheapch.acf.gov/docs/2026/state-plans/FL_Plan_2026.pdf#page=5", + # PDF pages 49-51 + "https://liheapch.acf.gov/sites/default/files/webfiles/docs/2023/manuals/FL_PolicyManual_2023.pdf#page=49", + # PDF pages 5-7 + "https://liheapch.acf.gov/docs/2025/state-plans/FL_Plan_2025.pdf#page=5", + "https://storage.googleapis.com/florida-liheap-relief-static-assets/Florida_LIHEAP_Application_English.pdf#page=1", + "https://floridaliheap.com/faq", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.fl.commerce.liheap.income + person = spm_unit.members + age = person("age", period) + # The current statewide application excludes all minors' income, + # matching the portal FAQ. The FY2026 plan endorses this portal in + # section 1.10. This supersedes the older manual's nonstudent exception. + # The application was created in March 2025 but supplies no rule-change + # effective date; applying it throughout FY2025 is a backfilled assumption. + income_counted = age >= p.adult_age + # Use existing net business inputs without another expense deduction. + # Plan section 1.8 counts gross income and manual 1200.01B counts "the + # gross amount of income", so each source is floored at zero and a + # loss in one source cannot offset another. + earned = 0 + for source in p.sources.earned: + earned = earned + max_(person(source, period), 0) + unearned = 0 + for source in p.sources.unearned: + unearned = unearned + max_(person(source, period, options=[ADD]), 0) + # Plan section 1.9 counts "net gambling or lottery winnings", so + # losses offset only winnings. + gambling = max_( + person("gambling_winnings", period) - person("gambling_losses", period), + 0, + ) + # Count TANF once at SPM level. The take-up-gated tanf total includes + # fl_tca; fl_tca alone is the entitlement a nonrecipient could get. + cash_grant = add(spm_unit, period, p.sources.household, options=[ADD]) + # Annual inputs approximate the prior 30 days/current economic situation. + # Nonqualified members' countable income is retained in full. UI and + # cash gifts are excluded by the plans. Gross SSA is included; the + # manual expressly adds Medicare premiums back to net checks. + # Existing inputs do not isolate work-study, royalties, mortgage/sale + # installments, and all countable insurance/lump-sum receipts. + return ( + spm_unit.sum((earned + unearned + gambling) * income_counted) + cash_grant + )