diff --git a/changelog.d/nh-liheap-wave2b.added.md b/changelog.d/nh-liheap-wave2b.added.md new file mode 100644 index 00000000000..2bb2cb3cede --- /dev/null +++ b/changelog.d/nh-liheap-wave2b.added.md @@ -0,0 +1 @@ +Add New Hampshire Fuel Assistance Program (nh_fap): PY2027 regular heating benefit from the Attachment D matrix with the 60% state median income test and a bedroom-based heating-cost estimate. diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/fpg_year_lag.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/fpg_year_lag.yaml new file mode 100644 index 00000000000..82dbc588604 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/fpg_year_lag.yaml @@ -0,0 +1,13 @@ +description: New Hampshire uses federal poverty guidelines from this many years before the modeled heating season under the Fuel Assistance Program. +# The annual model uses the PY2027 starting schedule with 2026 guidelines. +# The manual's within-season February updates are not separately modeled. +values: + 2026-10-01: 1 + +metadata: + unit: year + period: year + label: New Hampshire FAP federal poverty guideline year lag + reference: + - title: "PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Income Guidelines and Federal Poverty Guideline Updates #page 10,17,74" + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=10 diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/heating_cost/dwelling_factor.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/heating_cost/dwelling_factor.yaml new file mode 100644 index 00000000000..0a063515fde --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/heating_cost/dwelling_factor.yaml @@ -0,0 +1,17 @@ +description: New Hampshire uses these dwelling energy factors to estimate heating cost under the Fuel Assistance Program. +SINGLE_FAMILY_OR_MODULAR: + 2026-10-01: 2_000 +MOBILE_HOME: + 2026-10-01: 1_800 +APARTMENT_CONDO_OR_DUPLEX: + 2026-10-01: 1_400 + +metadata: + unit: /1 + period: year + label: New Hampshire FAP dwelling energy factor + breakdown: + - nh_fap_dwelling_type + reference: + - title: "PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Benefit Determination #page 76-77" + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=76 diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/heating_cost/fuel_cost_per_mbtu.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/heating_cost/fuel_cost_per_mbtu.yaml new file mode 100644 index 00000000000..3e390f72fe8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/heating_cost/fuel_cost_per_mbtu.yaml @@ -0,0 +1,30 @@ +description: New Hampshire uses these fuel costs per million British thermal units to estimate heating cost under the Fuel Assistance Program. +KEROSENE: + 2026-10-01: 35.185 +FUEL_OIL: + 2026-10-01: 28.881 +NATURAL_GAS: + 2026-10-01: 15 +COAL: + 2026-10-01: 14.286 +WOOD: + 2026-10-01: 21.65 +ELECTRICITY: + 2026-10-01: 64.706 +PROPANE: + 2026-10-01: 42.497 +# SOLAR takes the electricity row because heating_expense reads a solar +# home's bill as its grid electricity bill. +SOLAR: + 2026-10-01: 64.706 +# Unsupported fuel contributes no estimate, not a legal zero cost. +UNAVAILABLE: + 2026-10-01: 0 + +metadata: + unit: currency-USD + period: year + label: New Hampshire FAP fuel cost per million British thermal units + reference: + - title: PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Benefit Determination + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=77 diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/heating_cost/fuel_efficiency.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/heating_cost/fuel_efficiency.yaml new file mode 100644 index 00000000000..69bf0e0deae --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/heating_cost/fuel_efficiency.yaml @@ -0,0 +1,31 @@ +description: New Hampshire uses these fuel efficiency rates to estimate heating cost under the Fuel Assistance Program. +KEROSENE: + 2026-10-01: 0.78 +FUEL_OIL: + 2026-10-01: 0.78 +NATURAL_GAS: + 2026-10-01: 0.82 +COAL: + 2026-10-01: 0.75 +# Existing WOOD represents cordwood; pellets and bio-bricks are unobserved. +WOOD: + 2026-10-01: 0.63 +ELECTRICITY: + 2026-10-01: 1 +PROPANE: + 2026-10-01: 0.78 +# SOLAR takes the electricity row because heating_expense reads a solar +# home's bill as its grid electricity bill. +SOLAR: + 2026-10-01: 1 +# A safe denominator for the zero-cost computational fallback. +UNAVAILABLE: + 2026-10-01: 1 + +metadata: + unit: /1 + period: year + label: New Hampshire FAP fuel efficiency rate + reference: + - title: PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Benefit Determination + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=77 diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/heating_cost/heating_degree_days.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/heating_cost/heating_degree_days.yaml new file mode 100644 index 00000000000..70dc97688ca --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/heating_cost/heating_degree_days.yaml @@ -0,0 +1,36 @@ +description: New Hampshire uses these agency heating degree days by county to estimate heating cost under the Fuel Assistance Program. +BELKNAP_COUNTY_NH: + 2026-10-01: 6_610 +MERRIMACK_COUNTY_NH: + 2026-10-01: 6_610 +HILLSBOROUGH_COUNTY_NH: + 2026-10-01: 5_993 +ROCKINGHAM_COUNTY_NH: + 2026-10-01: 5_993 +STRAFFORD_COUNTY_NH: + 2026-10-01: 6_061 +CHESHIRE_COUNTY_NH: + 2026-10-01: 6_588 +SULLIVAN_COUNTY_NH: + 2026-10-01: 6_588 +CARROLL_COUNTY_NH: + 2026-10-01: 7_672 +COOS_COUNTY_NH: + 2026-10-01: 7_672 +GRAFTON_COUNTY_NH: + 2026-10-01: 7_672 +# Unsupported geography contributes no estimate, not a legal zero cost. +UNAVAILABLE: + 2026-10-01: 0 + +metadata: + unit: /1 + period: year + label: New Hampshire FAP agency heating degree days by county + reference: + - title: PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Benefit Determination + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=77 + - title: Community Action Partnership of New Hampshire, Agency County Service Areas + href: https://www.capnh.org/home-old + - title: Community Action Partnership of New Hampshire, Agency County Service Areas (Wayback Machine capture, June 13, 2026) + href: https://web.archive.org/web/20260613220254/https://www.capnh.org/home-old diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/income/business_sources.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/income/business_sources.yaml new file mode 100644 index 00000000000..e491b5037f6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/income/business_sources.yaml @@ -0,0 +1,18 @@ +description: New Hampshire counts these business income sources under the Fuel Assistance Program. +# Each source's losses count as zero (page 26), so a loss cannot offset +# another source. +values: + 2026-10-01: + - self_employment_income + - sstb_self_employment_income + - farm_operations_income + - partnership_income + - s_corp_income + +metadata: + unit: list + period: year + label: New Hampshire FAP business income sources + reference: + - title: "PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Self Employment #page 25-28" + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=25 diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/income/investment_disregard.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/income/investment_disregard.yaml new file mode 100644 index 00000000000..867c230a094 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/income/investment_disregard.yaml @@ -0,0 +1,17 @@ +description: New Hampshire excludes this amount of annual interest and dividend income under the Fuel Assistance Program. +# One $50 exclusion applies to combined interest and dividends per SPM unit, +# following page 17's allowable expense "$50 of earned interest and/or +# dividends annually". Page 15 counts "Interest over $50 a year" and +# "Dividends over $50 a year", and page 16 excludes "the first $50" of each, +# which would allow up to $100. None of these pages says whether the amount +# applies per person or per household. +values: + 2026-10-01: 50 + +metadata: + unit: currency-USD + period: year + label: New Hampshire FAP annual investment income exclusion per SPM unit + reference: + - title: "PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Countable and Non-countable Income and Allowable Expenses #page 15-17" + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=15 diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/income/ssi_min_age.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/income/ssi_min_age.yaml new file mode 100644 index 00000000000..55441f99478 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/income/ssi_min_age.yaml @@ -0,0 +1,11 @@ +description: New Hampshire excludes Supplemental Security Income for people below this age under the Fuel Assistance Program. +values: + 2026-10-01: 18 + +metadata: + unit: year + period: year + label: New Hampshire FAP minimum age for countable SSI + reference: + - title: "PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Non-countable Income #page 15-16" + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=15 diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/income/unearned_sources.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/income/unearned_sources.yaml new file mode 100644 index 00000000000..937869e9ca5 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/income/unearned_sources.yaml @@ -0,0 +1,47 @@ +description: New Hampshire counts these unearned income sources under the Fuel Assistance Program. +# nh_fap_countable_income adds adult SSI, FANF and interest and dividends +# above the $50 exclusion to these sources. +values: + 2026-10-01: + - social_security + - pension_income + - military_retirement_income + - retirement_distributions + - railroad_benefits + - survivor_benefits + - veterans_benefits + - total_unemployment_compensation + - workers_compensation + - disability_benefits + - nh_ssp + - strike_benefits + - financial_assistance + - alimony_income + - rental_income + - farm_rent_income + - estate_income + - gambling_winnings + +# Broad receipts approximate the source's regular payments. Inputs do not +# identify VA Aid and Attendance, educational VA benefits, special-needs +# trusts, or irregular injury/insurance payments. Financial assistance lacks +# the required six-month regularity flag. nh_ssp holds the APTD, ANB and OAA +# state welfare payments, FANF is included separately once per SPM unit, and +# RCA has no input. Page 15's state welfare payments are APTD, ANB, FANF, OAA +# and RCA, and plan item 1.9 leaves General Assistance benefits unchecked, so +# municipal general assistance (RSA 165) is not counted. +# Rental inputs are treated as net and nonnegative without reconstructing +# business expenses. Pension income includes annuities and insurance income. +# Gambling winnings approximate the taxable gambling and lottery category. +# Missing taxable grants, adoption subsidies, royalties and tribal receipts +# are not imputed; balances, capital gains and regular child support received +# are not counted as income. +metadata: + unit: list + period: year + label: New Hampshire FAP unearned income sources + reference: + - title: "PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Countable Income, Non-countable Income, and Rental Property Income #page 15-17,23,29" + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=15 + - title: New Hampshire FY2026 LIHEAP State Plan, Section 1.9 + href: https://liheapch.acf.gov/docs/2026/state-plans/NH_Plan_2026.pdf#page=6 diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/payment/benefit_multiplier.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/payment/benefit_multiplier.yaml new file mode 100644 index 00000000000..9c183ec9e99 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/payment/benefit_multiplier.yaml @@ -0,0 +1,41 @@ +description: New Hampshire provides this share of the delivered-fuel scheduled benefit under the Fuel Assistance Program. +# Whole-dollar half-up rounding reproduces all 24 published utility cells. +# SOLAR takes the electricity row because heating_expense reads a solar +# home's bill as its grid electricity bill. OTHER has no row on page 77 and +# no fuel on the application, and UNSPECIFIED names no fuel; zero marks an +# unsupported amount, not a legal zero benefit. +UNSPECIFIED: + 2026-10-01: 0 +ELECTRICITY: + 2026-10-01: 0.75 +NATURAL_GAS: + 2026-10-01: 0.75 +FUEL_OIL: + 2026-10-01: 1 +KEROSENE: + 2026-10-01: 1 +PROPANE: + 2026-10-01: 1 +# WOOD also represents pellets and bio-bricks, which share the 1.000 +# multiplier. Winter blend is a heating-oil blend entered as FUEL_OIL or +# KEROSENE, which share the same multiplier. +WOOD: + 2026-10-01: 1 +COAL: + 2026-10-01: 1 +SOLAR: + 2026-10-01: 0.75 +OTHER: + 2026-10-01: 0 +NONE: + 2026-10-01: 0 + +metadata: + unit: /1 + period: year + label: New Hampshire FAP benefit multiplier + breakdown: + - heating_type + reference: + - title: PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Benefit Determination, Fuel Cost, Efficiency, and Benefit Multiplier + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=77 diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/payment/delivered_benefit.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/payment/delivered_benefit.yaml new file mode 100644 index 00000000000..cbee26ef772 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/payment/delivered_benefit.yaml @@ -0,0 +1,63 @@ +description: New Hampshire provides this annual delivered-fuel scheduled benefit by heating cost band and income band under the Fuel Assistance Program. +DD: + A: + 2026-10-01: 750 + B: + 2026-10-01: 650 + C: + 2026-10-01: 550 + D: + 2026-10-01: 500 + E: + 2026-10-01: 440 + F: + 2026-10-01: 400 +CC: + A: + 2026-10-01: 1_460 + B: + 2026-10-01: 1_270 + C: + 2026-10-01: 1_150 + D: + 2026-10-01: 950 + E: + 2026-10-01: 730 + F: + 2026-10-01: 525 +BB: + A: + 2026-10-01: 2_350 + B: + 2026-10-01: 2_040 + C: + 2026-10-01: 1_720 + D: + 2026-10-01: 1_410 + E: + 2026-10-01: 1_100 + F: + 2026-10-01: 800 +AA: + A: + 2026-10-01: 2_500 + B: + 2026-10-01: 2_150 + C: + 2026-10-01: 1_825 + D: + 2026-10-01: 1_500 + E: + 2026-10-01: 1_200 + F: + 2026-10-01: 825 + +# The operative PY2027 matrix supersedes inconsistent illustrative amounts +# in the manual's older examples. No actual-heating-cost cap is applied. +metadata: + unit: currency-USD + period: year + label: New Hampshire FAP delivered-fuel scheduled benefit + reference: + - title: PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Fuel Assistance Program Benefits + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=78 diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/payment/heating_cost_threshold.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/payment/heating_cost_threshold.yaml new file mode 100644 index 00000000000..67d06f05cd8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/payment/heating_cost_threshold.yaml @@ -0,0 +1,17 @@ +description: New Hampshire uses these inclusive lower annual heating cost thresholds for benefit bands above the lowest band under the Fuel Assistance Program. +CC: + 2026-10-01: 1_000 +BB: + 2026-10-01: 1_750 +AA: + 2026-10-01: 3_500 + +# Page 78 utility labels overlap at the endpoints; the non-overlapping +# page 77 Heating Cost Tiers table and delivered schedule establish the tiers. +metadata: + unit: currency-USD + period: year + label: New Hampshire FAP heating cost band thresholds + reference: + - title: "PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Benefit Determination, Heating Cost Tiers and Benefits #page 76-78" + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=76 diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/payment/income_band_upper_bound.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/payment/income_band_upper_bound.yaml new file mode 100644 index 00000000000..63939fc27ae --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/payment/income_band_upper_bound.yaml @@ -0,0 +1,20 @@ +description: New Hampshire assigns these inclusive upper federal poverty guideline shares to the first five income bands under the Fuel Assistance Program. +A: + 2026-10-01: 0.75 +B: + 2026-10-01: 1 +C: + 2026-10-01: 1.25 +D: + 2026-10-01: 1.5 +E: + 2026-10-01: 1.75 + +# Band F covers income above band E through the separate 60% SMI limit. +metadata: + unit: /1 + period: year + label: New Hampshire FAP income band upper bounds + reference: + - title: "PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Income Guidelines #page 17,74" + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=17 diff --git a/policyengine_us/parameters/gov/states/nh/doe/fap/smi_rate.yaml b/policyengine_us/parameters/gov/states/nh/doe/fap/smi_rate.yaml new file mode 100644 index 00000000000..219b33151ba --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/doe/fap/smi_rate.yaml @@ -0,0 +1,13 @@ +description: New Hampshire limits annual income to this share of state median income under the Fuel Assistance Program. +values: + 2026-10-01: 0.6 + +metadata: + unit: /1 + period: year + label: New Hampshire FAP state median income limit rate + reference: + - title: "PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Income Guidelines #page 17,74" + href: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=17 + - title: New Hampshire FY2026 LIHEAP State Plan, Section 2.1 + href: https://liheapch.acf.gov/docs/2026/state-plans/NH_Plan_2026.pdf#page=8 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 681d557eb61..82cc7e52950 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1132,6 +1132,14 @@ programs: parameter_prefix: gov.states.ne.dhhs.liheap verified_years: "2026" notes: FY2026 regular heating only, with the single-family and multifamily schedules and the earned-income disregard. Crisis, cooling and weatherization assistance are out of scope. + - state: NH + status: partial + name: New Hampshire FAP + full_name: New Hampshire Fuel Assistance Program + variable: nh_fap + parameter_prefix: gov.states.nh.doe.fap + verified_years: "2027" + notes: PY2027 regular heating, estimating heating cost with bedrooms (at least one room) as the room count; unsubsidized heat in rent receives the ordinary schedule, which prints no heat-in-rent reduction. Crisis, cooling, weatherization and equipment assistance are out of scope. - state: NJ status: partial name: New Jersey LIHEAP diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap.yaml new file mode 100644 index 00000000000..abde032c84d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap.yaml @@ -0,0 +1,2901 @@ +# Source: PY27 NH Fuel Assistance Program Procedures Manual. +# https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf +# Physical PDF pages: 10, 17, 18, 35, 36, 74, 76, 77, 78. +# Period 2027 represents the researched 2026-2027 schedule with 2026 FPG. +# Inputs are annual; SSI and FANF totals are explicitly supplied to isolate receipts. +# Final modeled awards use the larger of the actual and estimated costs and the +# ordinary fuel schedule. Unsubsidized heat in rent gets no further reduction because +# the PY2027 schedule (page 78) prints none; unsupported fuel amounts remain zero. + +# Manual p78, delivered DD/A cell. Actual annual primary-fuel bill selects the row. +- name: "Case 1, delivered matrix cost tier DD and income band A." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 10_000 + nh_fap: 750 + +# Manual p78, utility DD/A cell, including published whole-dollar rounding. +- name: "Case 2, utility matrix cost tier DD and income band A." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 10_000 + nh_fap: 563 + +# Manual p78, delivered DD/B cell. Actual annual primary-fuel bill selects the row. +- name: "Case 3, delivered matrix cost tier DD and income band B." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 14_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 14_000 + nh_fap: 650 + +# Manual p78, utility DD/B cell, including published whole-dollar rounding. +- name: "Case 4, utility matrix cost tier DD and income band B." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 14_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "ELECTRICITY" + heat_expense_included_in_rent: false + receives_housing_assistance: false + pre_subsidy_electricity_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 14_000 + nh_fap: 488 + +# Manual p78, delivered DD/C cell. Actual annual primary-fuel bill selects the row. +- name: "Case 5, delivered matrix cost tier DD and income band C." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 18_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 18_000 + nh_fap: 550 + +# Manual p78, utility DD/C cell, including published whole-dollar rounding. +- name: "Case 6, utility matrix cost tier DD and income band C." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 18_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 18_000 + nh_fap: 413 + +# Manual p78, delivered DD/D cell. Actual annual primary-fuel bill selects the row. +- name: "Case 7, delivered matrix cost tier DD and income band D." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 22_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 22_000 + nh_fap: 500 + +# Manual p78, utility DD/D cell, including published whole-dollar rounding. +- name: "Case 8, utility matrix cost tier DD and income band D." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 22_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "ELECTRICITY" + heat_expense_included_in_rent: false + receives_housing_assistance: false + pre_subsidy_electricity_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 22_000 + nh_fap: 375 + +# Manual p78, delivered DD/E cell. Actual annual primary-fuel bill selects the row. +- name: "Case 9, delivered matrix cost tier DD and income band E." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 26_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 26_000 + nh_fap: 440 + +# Manual p78, utility DD/E cell, including published whole-dollar rounding. +- name: "Case 10, utility matrix cost tier DD and income band E." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 26_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 26_000 + nh_fap: 330 + +# Manual p78, delivered DD/F cell. Actual annual primary-fuel bill selects the row. +- name: "Case 11, delivered matrix cost tier DD and income band F." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 40_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 40_000 + nh_fap: 400 + +# Manual p78, utility DD/F cell, including published whole-dollar rounding. +- name: "Case 12, utility matrix cost tier DD and income band F." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 40_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "ELECTRICITY" + heat_expense_included_in_rent: false + receives_housing_assistance: false + pre_subsidy_electricity_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 40_000 + nh_fap: 300 + +# Manual p78, delivered CC/A cell. Actual annual primary-fuel bill selects the row. +- name: "Case 13, delivered matrix cost tier CC and income band A." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 1_200 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 10_000 + nh_fap: 1_460 + +# Manual p78, utility CC/A cell, including published whole-dollar rounding. +- name: "Case 14, utility matrix cost tier CC and income band A." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "ELECTRICITY" + heat_expense_included_in_rent: false + receives_housing_assistance: false + pre_subsidy_electricity_expense: 1_200 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 10_000 + nh_fap: 1_095 + +# Manual p78, delivered CC/B cell. Actual annual primary-fuel bill selects the row. +- name: "Case 15, delivered matrix cost tier CC and income band B." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 14_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 1_200 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 14_000 + nh_fap: 1_270 + +# Manual p78, utility CC/B cell, including published whole-dollar rounding. +- name: "Case 16, utility matrix cost tier CC and income band B." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 14_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 1_200 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 14_000 + nh_fap: 953 + +# Manual p78, delivered CC/C cell. Actual annual primary-fuel bill selects the row. +- name: "Case 17, delivered matrix cost tier CC and income band C." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 18_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 1_200 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 18_000 + nh_fap: 1_150 + +# Manual p78, utility CC/C cell, including published whole-dollar rounding. +- name: "Case 18, utility matrix cost tier CC and income band C." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 18_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "ELECTRICITY" + heat_expense_included_in_rent: false + receives_housing_assistance: false + pre_subsidy_electricity_expense: 1_200 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 18_000 + nh_fap: 863 + +# Manual p78, delivered CC/D cell. Actual annual primary-fuel bill selects the row. +- name: "Case 19, delivered matrix cost tier CC and income band D." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 22_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 1_200 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 22_000 + nh_fap: 950 + +# Manual p78, utility CC/D cell, including published whole-dollar rounding. +- name: "Case 20, utility matrix cost tier CC and income band D." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 22_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 1_200 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 22_000 + nh_fap: 713 + +# Manual p78, delivered CC/E cell. Actual annual primary-fuel bill selects the row. +- name: "Case 21, delivered matrix cost tier CC and income band E." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 26_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 1_200 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 26_000 + nh_fap: 730 + +# Manual p78, utility CC/E cell, including published whole-dollar rounding. +- name: "Case 22, utility matrix cost tier CC and income band E." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 26_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "ELECTRICITY" + heat_expense_included_in_rent: false + receives_housing_assistance: false + pre_subsidy_electricity_expense: 1_200 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 26_000 + nh_fap: 548 + +# Manual p78, delivered CC/F cell. Actual annual primary-fuel bill selects the row. +- name: "Case 23, delivered matrix cost tier CC and income band F." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 40_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 1_200 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 40_000 + nh_fap: 525 + +# Manual p78, utility CC/F cell, including published whole-dollar rounding. +- name: "Case 24, utility matrix cost tier CC and income band F." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 40_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 1_200 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 40_000 + nh_fap: 394 + +# Manual p78, delivered BB/A cell. Actual annual primary-fuel bill selects the row. +- name: "Case 25, delivered matrix cost tier BB and income band A." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 10_000 + nh_fap: 2_350 + +# Manual p78, utility BB/A cell, including published whole-dollar rounding. +- name: "Case 26, utility matrix cost tier BB and income band A." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 10_000 + nh_fap: 1_763 + +# Manual p78, delivered BB/B cell. Actual annual primary-fuel bill selects the row. +- name: "Case 27, delivered matrix cost tier BB and income band B." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 14_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 14_000 + nh_fap: 2_040 + +# Manual p78, utility BB/B cell, including published whole-dollar rounding. +- name: "Case 28, utility matrix cost tier BB and income band B." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 14_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "ELECTRICITY" + heat_expense_included_in_rent: false + receives_housing_assistance: false + pre_subsidy_electricity_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 14_000 + nh_fap: 1_530 + +# Manual p78, delivered BB/C cell. Actual annual primary-fuel bill selects the row. +- name: "Case 29, delivered matrix cost tier BB and income band C." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 18_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 18_000 + nh_fap: 1_720 + +# Manual p78, utility BB/C cell, including published whole-dollar rounding. +- name: "Case 30, utility matrix cost tier BB and income band C." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 18_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 18_000 + nh_fap: 1_290 + +# Manual p78, delivered BB/D cell. Actual annual primary-fuel bill selects the row. +- name: "Case 31, delivered matrix cost tier BB and income band D." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 22_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 22_000 + nh_fap: 1_410 + +# Manual p78, utility BB/D cell, including published whole-dollar rounding. +- name: "Case 32, utility matrix cost tier BB and income band D." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 22_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "ELECTRICITY" + heat_expense_included_in_rent: false + receives_housing_assistance: false + pre_subsidy_electricity_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 22_000 + nh_fap: 1_058 + +# Manual p78, delivered BB/E cell. Actual annual primary-fuel bill selects the row. +- name: "Case 33, delivered matrix cost tier BB and income band E." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 26_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 26_000 + nh_fap: 1_100 + +# Manual p78, utility BB/E cell, including published whole-dollar rounding. +- name: "Case 34, utility matrix cost tier BB and income band E." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 26_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 26_000 + nh_fap: 825 + +# Manual p78, delivered BB/F cell. Actual annual primary-fuel bill selects the row. +- name: "Case 35, delivered matrix cost tier BB and income band F." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 40_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 40_000 + nh_fap: 800 + +# Manual p78, utility BB/F cell, including published whole-dollar rounding. +- name: "Case 36, utility matrix cost tier BB and income band F." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 40_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "ELECTRICITY" + heat_expense_included_in_rent: false + receives_housing_assistance: false + pre_subsidy_electricity_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 40_000 + nh_fap: 600 + +# Manual p78, delivered AA/A cell. Actual annual primary-fuel bill selects the row. +- name: "Case 37, delivered matrix cost tier AA and income band A." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 10_000 + nh_fap: 2_500 + +# Manual p78, utility AA/A cell, including published whole-dollar rounding. +- name: "Case 38, utility matrix cost tier AA and income band A." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "ELECTRICITY" + heat_expense_included_in_rent: false + receives_housing_assistance: false + pre_subsidy_electricity_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 10_000 + nh_fap: 1_875 + +# Manual p78, delivered AA/B cell. Actual annual primary-fuel bill selects the row. +- name: "Case 39, delivered matrix cost tier AA and income band B." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 14_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 14_000 + nh_fap: 2_150 + +# Manual p78, utility AA/B cell, including published whole-dollar rounding. +- name: "Case 40, utility matrix cost tier AA and income band B." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 14_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 14_000 + nh_fap: 1_613 + +# Manual p78, delivered AA/C cell. Actual annual primary-fuel bill selects the row. +- name: "Case 41, delivered matrix cost tier AA and income band C." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 18_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 18_000 + nh_fap: 1_825 + +# Manual p78, utility AA/C cell, including published whole-dollar rounding. +- name: "Case 42, utility matrix cost tier AA and income band C." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 18_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "ELECTRICITY" + heat_expense_included_in_rent: false + receives_housing_assistance: false + pre_subsidy_electricity_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 18_000 + nh_fap: 1_369 + +# Manual p78, delivered AA/D cell. Actual annual primary-fuel bill selects the row. +- name: "Case 43, delivered matrix cost tier AA and income band D." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 22_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 22_000 + nh_fap: 1_500 + +# Manual p78, utility AA/D cell, including published whole-dollar rounding. +- name: "Case 44, utility matrix cost tier AA and income band D." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 22_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 22_000 + nh_fap: 1_125 + +# Manual p78, delivered AA/E cell. Actual annual primary-fuel bill selects the row. +- name: "Case 45, delivered matrix cost tier AA and income band E." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 26_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 26_000 + nh_fap: 1_200 + +# Manual p78, utility AA/E cell, including published whole-dollar rounding. +- name: "Case 46, utility matrix cost tier AA and income band E." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 26_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "ELECTRICITY" + heat_expense_included_in_rent: false + receives_housing_assistance: false + pre_subsidy_electricity_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 26_000 + nh_fap: 900 + +# Manual p78, delivered AA/F cell. Actual annual primary-fuel bill selects the row. +- name: "Case 47, delivered matrix cost tier AA and income band F." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 40_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 40_000 + nh_fap: 825 + +# Manual p78, utility AA/F cell, including published whole-dollar rounding. +- name: "Case 48, utility matrix cost tier AA and income band F." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 40_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 40_000 + nh_fap: 619 + +# Manual pp17 and74; one-person 2026 FPG of 15,960 for the initial PY2027 snapshot. +- name: "Case 49, income exactly 11970 remains in its inclusive FPG band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 11_970 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 2_500 + +# Manual pp17,74 and78; strict upper-band transition. +- name: "Case 50, income one cent above 11970 enters the next FPG band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 11_970.01 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 2_150 + +# Manual pp17 and74; one-person 2026 FPG of 15,960 for the initial PY2027 snapshot. +- name: "Case 51, income exactly 15960 remains in its inclusive FPG band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 15_960 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 2_150 + +# Manual pp17,74 and78; strict upper-band transition. +- name: "Case 52, income one cent above 15960 enters the next FPG band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 15_960.01 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 1_825 + +# Manual pp17 and74; one-person 2026 FPG of 15,960 for the initial PY2027 snapshot. +- name: "Case 53, income exactly 19950 remains in its inclusive FPG band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 19_950 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 1_825 + +# Manual pp17,74 and78; strict upper-band transition. +- name: "Case 54, income one cent above 19950 enters the next FPG band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 19_950.01 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 1_500 + +# Manual pp17 and74; one-person 2026 FPG of 15,960 for the initial PY2027 snapshot. +- name: "Case 55, income exactly 23940 remains in its inclusive FPG band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 23_940 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 1_500 + +# Manual pp17,74 and78; strict upper-band transition. +- name: "Case 56, income one cent above 23940 enters the next FPG band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 23_940.01 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 1_200 + +# Manual pp17 and74; one-person 2026 FPG of 15,960 for the initial PY2027 snapshot. +- name: "Case 57, income exactly 27930 remains in its inclusive FPG band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 27_930 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 1_200 + +# Manual pp17,74 and78; strict upper-band transition. +- name: "Case 58, income one cent above 27930 enters the next FPG band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 27_930.01 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 825 + +# Manual pp77-78 exact cost ranges and utility schedule. +- name: "Case 59, utility annual cost 999.99 selects the current cost tier." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 999.99 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 563 + +# Manual pp77-78 exact cost ranges and utility schedule. +- name: "Case 60, utility annual cost 1000 selects the current cost tier." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 1_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 1_095 + +# Manual pp77-78 exact cost ranges and utility schedule. +- name: "Case 61, utility annual cost 1749.99 selects the current cost tier." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 1_749.99 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 1_095 + +# Manual pp77-78 exact cost ranges and utility schedule. +- name: "Case 62, utility annual cost 1750 selects the current cost tier." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 1_750 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 1_763 + +# Manual pp77-78 exact cost ranges and utility schedule. +- name: "Case 63, utility annual cost 3499.99 selects the current cost tier." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 3_499.99 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 1_763 + +# Manual pp77-78 exact cost ranges and utility schedule. +- name: "Case 64, utility annual cost 3500 selects the current cost tier." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 3_500 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 1_875 + +# Manual p77 multiplier 1.000 and p78 BB/F delivered benefit. +- name: "Case 65, kerosene uses the full delivered-fuel schedule." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 40_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "KEROSENE" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 800 + +# Manual p77 multiplier 1.000 and p78 BB/F delivered benefit. +- name: "Case 66, propane uses the full delivered-fuel schedule." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 40_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "PROPANE" + heat_expense_included_in_rent: false + receives_housing_assistance: false + bottled_gas_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 800 + +# Manual p77 multiplier 1.000 and p78 BB/F delivered benefit. +- name: "Case 67, wood uses the full delivered-fuel schedule." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 40_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "WOOD" + heat_expense_included_in_rent: false + receives_housing_assistance: false + wood_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 800 + +# Manual p77 multiplier 1.000 and p78 BB/F delivered benefit. +- name: "Case 68, coal uses the full delivered-fuel schedule." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 40_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "COAL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + coal_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 800 + +# Manual p78 DD/A amount is 750; no actual-cost cap is stated. The one-room Belknap +# estimate, 2,000 * 1 * 6,610 / 1,000,000 * 28.881 / 0.78 = 489.50, exceeds the +# 100 bill and also falls in tier DD. +- name: "Case 69, the scheduled award is not capped at a small positive bill." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 100 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 750 + +# Manual p10 provides application priority; pp77-78 contain no age supplement. +- name: "Case 70, an older adult receives the same regular schedule." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 60 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 14_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 2_150 + +# Manual p10 provides application priority; pp77-78 contain no disability supplement. +- name: "Case 71, disability does not add an unsourced regular supplement." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + is_disabled: true + employment_income: 14_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 2_150 + +# Manual p74: size 2 D band ends at 32,460; p78 AA/D is 1500. +- name: "Case 72, two qualified members use the published two-person FPG." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 15_000 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 15_000 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_household_size: 2 + nh_fap_countable_income: 30_000 + nh_fap: 1_500 + +# Manual p36 includes ineligible-member income but excludes their size; size 1 band F applies without income proration. +- name: "Case 73, mixed status counts both incomes but only the qualified person." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 15_000 + person2: + age: 40 + immigration_status: "UNDOCUMENTED" + ssi: 0 + employment_income: 15_000 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_household_size: 1 + nh_fap_countable_income: 30_000 + nh_fap: 825 + +# Manual p74 size 1 ceiling 48,713; p78 AA/F is 825. +- name: "Case 74, the inclusive income ceiling retains the base schedule." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 48_713 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 825 + +# Manual p74 size 1 maximum 48,713. +- name: "Case 75, income above the ceiling removes the scheduled benefit." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 48_714 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap: 0 + +# Manual pp76-78 formula and matrix with four bedrooms alone: cost 2272.564 selects BB, income 45120 selects F, yielding a modeled award of 800. +- name: "Case 76, bedrooms alone determine the two-person oil benefit cost band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 45_120 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + fuel_oil_expense: 0 + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + heat_expense_included_in_rent: false + receives_housing_assistance: false + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + output: + nh_fap_heating_cost: 2_272.564431 + nh_fap_countable_income: 45_120 + nh_fap: 800 + +# Manual pp18,77-78: two bedrooms alone give estimated cost 1136.282, selecting CC/A 1460; actual 4000 selects AA/A 2500. The 500 bill does not cap the benefit. +- name: "Case 77, the larger cost basis determines the delivered benefit." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + nh_fanf: 0 + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 500 + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit2: + members: ["person2"] + heating_type: "FUEL_OIL" + nh_fanf: 0 + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 2 + household2: + members: ["person2"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 2 + output: + nh_fap_heating_cost: [1_136.282215, 4_000] + nh_fap: [1_460, 2_500] + +# Manual pp77-78: two-bedroom Coos gas cost 561.366 selects DD/A 750 * .75 =562.50, rounded to 563; actual 4000 selects AA/A 2500 * .75 =1875. +- name: "Case 78, utility reduction follows the selected proxy or actual cost band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "NATURAL_GAS" + nh_fanf: 0 + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 0 + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit2: + members: ["person2"] + heating_type: "NATURAL_GAS" + nh_fanf: 0 + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_expense: 4_000 + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 2 + household2: + members: ["person2"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 2 + output: + nh_fap_heating_cost: [561.365854, 4_000] + nh_fap: [563, 1_875] + +# The PY2027 schedule prints no heat-in-rent reduction, so the ordinary schedule applies. +# Manual pp76-78: default single-family factor 2000, Belknap HDD 6610, +# 3 bedrooms used as rooms, electricity 64.706/MBTU at efficiency 1. +# Estimated cost = 2000 * 3 * 6610 / 1_000_000 * 64.706 = 2566.23996. +# Income band A and cost band BB: 2350 * 0.75, rounded half up = 1763. +- name: Case 79, unsubsidized heat-in-rent with three bedrooms and electricity receives the modeled final award. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + parent1: + age: 40 + immigration_status: CITIZEN + employment_income: 10_000 + ssi: 0 + parent2: + age: 38 + immigration_status: CITIZEN + ssi: 0 + child: + age: 8 + immigration_status: CITIZEN + ssi: 0 + spm_units: + family: + members: [parent1, parent2, child] + nh_fanf: 0 + heating_expense: 0 + heating_type: ELECTRICITY + heat_expense_included_in_rent: true + receives_housing_assistance: false + households: + home: + members: [parent1, parent2, child] + state_code: NH + bedrooms: 3 + output: + nh_fap_countable_income: 10_000 + nh_fap_heating_cost: 2_566.23996 + nh_fap_eligible: true + nh_fap: 1_763 + +# Manual p78 AA/A: delivered 2500; electricity and gas 2500 * 0.75 = 1875. +# That fuel schedule applies once to direct-pay and heat-in-rent households. +# Manual p21 excludes subsidized heat-in-rent, not subsidized direct-pay households. +- name: Case 80, heat-in-rent retains each fuel schedule while subsidized heat-in-rent is excluded. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + electric_direct: + age: 40 + immigration_status: CITIZEN + employment_income: 10_000 + ssi: 0 + electric_rent: + age: 40 + immigration_status: CITIZEN + employment_income: 10_000 + ssi: 0 + gas_direct: + age: 40 + immigration_status: CITIZEN + employment_income: 10_000 + ssi: 0 + gas_rent: + age: 40 + immigration_status: CITIZEN + employment_income: 10_000 + ssi: 0 + oil_direct: + age: 40 + immigration_status: CITIZEN + employment_income: 10_000 + ssi: 0 + oil_rent: + age: 40 + immigration_status: CITIZEN + employment_income: 10_000 + ssi: 0 + subsidized_rent: + age: 40 + immigration_status: CITIZEN + employment_income: 10_000 + ssi: 0 + subsidized_direct: + age: 40 + immigration_status: CITIZEN + employment_income: 10_000 + ssi: 0 + spm_units: + electric_direct: + members: [electric_direct] + nh_fanf: 0 + heating_expense: 4_000 + heating_type: ELECTRICITY + heat_expense_included_in_rent: false + receives_housing_assistance: false + electric_rent: + members: [electric_rent] + nh_fanf: 0 + heating_expense: 4_000 + heating_type: ELECTRICITY + heat_expense_included_in_rent: true + receives_housing_assistance: false + gas_direct: + members: [gas_direct] + nh_fanf: 0 + heating_expense: 4_000 + heating_type: NATURAL_GAS + heat_expense_included_in_rent: false + receives_housing_assistance: false + gas_rent: + members: [gas_rent] + nh_fanf: 0 + heating_expense: 4_000 + heating_type: NATURAL_GAS + heat_expense_included_in_rent: true + receives_housing_assistance: false + oil_direct: + members: [oil_direct] + nh_fanf: 0 + heating_expense: 4_000 + heating_type: FUEL_OIL + heat_expense_included_in_rent: false + receives_housing_assistance: false + oil_rent: + members: [oil_rent] + nh_fanf: 0 + heating_expense: 4_000 + heating_type: FUEL_OIL + heat_expense_included_in_rent: true + receives_housing_assistance: false + subsidized_rent: + members: [subsidized_rent] + nh_fanf: 0 + heating_expense: 4_000 + heating_type: ELECTRICITY + heat_expense_included_in_rent: true + receives_housing_assistance: true + subsidized_direct: + members: [subsidized_direct] + nh_fanf: 0 + heating_expense: 4_000 + heating_type: ELECTRICITY + heat_expense_included_in_rent: false + receives_housing_assistance: true + households: + electric_direct: + members: [electric_direct] + state_code: NH + bedrooms: 3 + electric_rent: + members: [electric_rent] + state_code: NH + bedrooms: 3 + gas_direct: + members: [gas_direct] + state_code: NH + bedrooms: 3 + gas_rent: + members: [gas_rent] + state_code: NH + bedrooms: 3 + oil_direct: + members: [oil_direct] + state_code: NH + bedrooms: 3 + oil_rent: + members: [oil_rent] + state_code: NH + bedrooms: 3 + subsidized_rent: + members: [subsidized_rent] + state_code: NH + bedrooms: 3 + subsidized_direct: + members: [subsidized_direct] + state_code: NH + bedrooms: 3 + output: + nh_fap_eligible: [true, true, true, true, true, true, false, true] + nh_fap: [1_875, 1_875, 1_875, 1_875, 2_500, 2_500, 0, 1_875] + +# Manual page 15 counts ordinary DoD retirement separately from pension/VA income. +# Primary pay of 50,000 exceeds the one-person 48,713 ceiling. The 10,000 control +# remains in income band A; a 500 electric bill uses DD/A: 750 * 0.75 -> 563. +- name: "Case 81, ordinary military retirement pay affects eligibility and retains eligible retirees." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_veteran: true + years_in_military: 20 + military_retirement_pay: 50_000 + pension_income: 0 + veterans_benefits: 0 + person2: + age: 40 + immigration_status: CITIZEN + is_veteran: true + years_in_military: 20 + military_retirement_pay: 10_000 + pension_income: 0 + veterans_benefits: 0 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + spm_units: + spm_unit1: + members: [person1] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 500 + spm_unit2: + members: [person2] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 500 + households: + household1: + members: [person1] + state_code: NH + bedrooms: 0 + household2: + members: [person2] + state_code: NH + bedrooms: 0 + output: + nh_fap_countable_income: [50_000, 10_000] + nh_fap_income_limit: [48_713, 48_713] + nh_fap_eligible: [false, true] + nh_fap: [0, 563] + +# Manual pages 13,15-16 count received welfare and adult SSI. The first family +# does not take up TANF, so only SSI of 9,600 counts. The second family reports +# actual TANF receipts of 3,600, counted once: 9,600 + 3,600 = 13,200. +# Both are below the two-person A ceiling of 16,230, receiving AA/A = 2,500. +# No counterfactual FANF entitlement is supplied or asserted as a legal award. +- name: "Case 82, actual TANF receipt counts once and nonreceipt does not reduce the heating award." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: CITIZEN + is_disabled: true + ssi: 9_600 + nh_ssp: 0 + person2: + age: 10 + immigration_status: CITIZEN + person3: + age: 40 + immigration_status: CITIZEN + is_disabled: true + ssi: 9_600 + nh_ssp: 0 + person4: + age: 10 + immigration_status: CITIZEN + tax_units: + tax_unit1: + members: [person1, person2] + tax_unit2: + members: [person3, person4] + spm_units: + spm_unit1: + members: [person1, person2] + takes_up_tanf_if_eligible: false + heating_type: FUEL_OIL + fuel_oil_expense: 4_000 + spm_unit2: + members: [person3, person4] + tanf: 3_600 + heating_type: FUEL_OIL + fuel_oil_expense: 4_000 + households: + household1: + members: [person1, person2] + state_code: NH + bedrooms: 0 + household2: + members: [person3, person4] + state_code: NH + bedrooms: 0 + output: + tanf: [0, 3_600] + nh_fap_countable_income: [9_600, 13_200] + nh_fap_eligible: [true, true] + nh_fap: [2_500, 2_500] + +# 42 USC 8624(b)(2)(B) protects income strictly below 110% FPG. PY2027 uses +# 2026 guidelines: 15,960 + 27 * 5,680 = 169,320; the floor is 186,252. +# Each economic household has 28 adult relatives with separate tax units. +# Income 186,000 and a cent below the floor qualify despite SMI of 185,486; +# equality and a cent above do not. Protected income uses band C and a 1,000 +# electric bill uses cost band CC: 1,150 * 0.75 = 862.50 -> 863. +- name: "Case 83, the federal floor protects large households strictly below the season-start threshold." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: {age: 40, immigration_status: CITIZEN, employment_income: 186_000} + person2: {age: 40, immigration_status: CITIZEN} + person3: {age: 40, immigration_status: CITIZEN} + person4: {age: 40, immigration_status: CITIZEN} + person5: {age: 40, immigration_status: CITIZEN} + person6: {age: 40, immigration_status: CITIZEN} + person7: {age: 40, immigration_status: CITIZEN} + person8: {age: 40, immigration_status: CITIZEN} + person9: {age: 40, immigration_status: CITIZEN} + person10: {age: 40, immigration_status: CITIZEN} + person11: {age: 40, immigration_status: CITIZEN} + person12: {age: 40, immigration_status: CITIZEN} + person13: {age: 40, immigration_status: CITIZEN} + person14: {age: 40, immigration_status: CITIZEN} + person15: {age: 40, immigration_status: CITIZEN} + person16: {age: 40, immigration_status: CITIZEN} + person17: {age: 40, immigration_status: CITIZEN} + person18: {age: 40, immigration_status: CITIZEN} + person19: {age: 40, immigration_status: CITIZEN} + person20: {age: 40, immigration_status: CITIZEN} + person21: {age: 40, immigration_status: CITIZEN} + person22: {age: 40, immigration_status: CITIZEN} + person23: {age: 40, immigration_status: CITIZEN} + person24: {age: 40, immigration_status: CITIZEN} + person25: {age: 40, immigration_status: CITIZEN} + person26: {age: 40, immigration_status: CITIZEN} + person27: {age: 40, immigration_status: CITIZEN} + person28: {age: 40, immigration_status: CITIZEN} + person29: {age: 40, immigration_status: CITIZEN, employment_income: 186_251.99} + person30: {age: 40, immigration_status: CITIZEN} + person31: {age: 40, immigration_status: CITIZEN} + person32: {age: 40, immigration_status: CITIZEN} + person33: {age: 40, immigration_status: CITIZEN} + person34: {age: 40, immigration_status: CITIZEN} + person35: {age: 40, immigration_status: CITIZEN} + person36: {age: 40, immigration_status: CITIZEN} + person37: {age: 40, immigration_status: CITIZEN} + person38: {age: 40, immigration_status: CITIZEN} + person39: {age: 40, immigration_status: CITIZEN} + person40: {age: 40, immigration_status: CITIZEN} + person41: {age: 40, immigration_status: CITIZEN} + person42: {age: 40, immigration_status: CITIZEN} + person43: {age: 40, immigration_status: CITIZEN} + person44: {age: 40, immigration_status: CITIZEN} + person45: {age: 40, immigration_status: CITIZEN} + person46: {age: 40, immigration_status: CITIZEN} + person47: {age: 40, immigration_status: CITIZEN} + person48: {age: 40, immigration_status: CITIZEN} + person49: {age: 40, immigration_status: CITIZEN} + person50: {age: 40, immigration_status: CITIZEN} + person51: {age: 40, immigration_status: CITIZEN} + person52: {age: 40, immigration_status: CITIZEN} + person53: {age: 40, immigration_status: CITIZEN} + person54: {age: 40, immigration_status: CITIZEN} + person55: {age: 40, immigration_status: CITIZEN} + person56: {age: 40, immigration_status: CITIZEN} + person57: {age: 40, immigration_status: CITIZEN, employment_income: 186_252} + person58: {age: 40, immigration_status: CITIZEN} + person59: {age: 40, immigration_status: CITIZEN} + person60: {age: 40, immigration_status: CITIZEN} + person61: {age: 40, immigration_status: CITIZEN} + person62: {age: 40, immigration_status: CITIZEN} + person63: {age: 40, immigration_status: CITIZEN} + person64: {age: 40, immigration_status: CITIZEN} + person65: {age: 40, immigration_status: CITIZEN} + person66: {age: 40, immigration_status: CITIZEN} + person67: {age: 40, immigration_status: CITIZEN} + person68: {age: 40, immigration_status: CITIZEN} + person69: {age: 40, immigration_status: CITIZEN} + person70: {age: 40, immigration_status: CITIZEN} + person71: {age: 40, immigration_status: CITIZEN} + person72: {age: 40, immigration_status: CITIZEN} + person73: {age: 40, immigration_status: CITIZEN} + person74: {age: 40, immigration_status: CITIZEN} + person75: {age: 40, immigration_status: CITIZEN} + person76: {age: 40, immigration_status: CITIZEN} + person77: {age: 40, immigration_status: CITIZEN} + person78: {age: 40, immigration_status: CITIZEN} + person79: {age: 40, immigration_status: CITIZEN} + person80: {age: 40, immigration_status: CITIZEN} + person81: {age: 40, immigration_status: CITIZEN} + person82: {age: 40, immigration_status: CITIZEN} + person83: {age: 40, immigration_status: CITIZEN} + person84: {age: 40, immigration_status: CITIZEN} + person85: {age: 40, immigration_status: CITIZEN, employment_income: 186_252.01} + person86: {age: 40, immigration_status: CITIZEN} + person87: {age: 40, immigration_status: CITIZEN} + person88: {age: 40, immigration_status: CITIZEN} + person89: {age: 40, immigration_status: CITIZEN} + person90: {age: 40, immigration_status: CITIZEN} + person91: {age: 40, immigration_status: CITIZEN} + person92: {age: 40, immigration_status: CITIZEN} + person93: {age: 40, immigration_status: CITIZEN} + person94: {age: 40, immigration_status: CITIZEN} + person95: {age: 40, immigration_status: CITIZEN} + person96: {age: 40, immigration_status: CITIZEN} + person97: {age: 40, immigration_status: CITIZEN} + person98: {age: 40, immigration_status: CITIZEN} + person99: {age: 40, immigration_status: CITIZEN} + person100: {age: 40, immigration_status: CITIZEN} + person101: {age: 40, immigration_status: CITIZEN} + person102: {age: 40, immigration_status: CITIZEN} + person103: {age: 40, immigration_status: CITIZEN} + person104: {age: 40, immigration_status: CITIZEN} + person105: {age: 40, immigration_status: CITIZEN} + person106: {age: 40, immigration_status: CITIZEN} + person107: {age: 40, immigration_status: CITIZEN} + person108: {age: 40, immigration_status: CITIZEN} + person109: {age: 40, immigration_status: CITIZEN} + person110: {age: 40, immigration_status: CITIZEN} + person111: {age: 40, immigration_status: CITIZEN} + person112: {age: 40, immigration_status: CITIZEN} + tax_units: + tax_unit1: {members: [person1]} + tax_unit2: {members: [person2]} + tax_unit3: {members: [person3]} + tax_unit4: {members: [person4]} + tax_unit5: {members: [person5]} + tax_unit6: {members: [person6]} + tax_unit7: {members: [person7]} + tax_unit8: {members: [person8]} + tax_unit9: {members: [person9]} + tax_unit10: {members: [person10]} + tax_unit11: {members: [person11]} + tax_unit12: {members: [person12]} + tax_unit13: {members: [person13]} + tax_unit14: {members: [person14]} + tax_unit15: {members: [person15]} + tax_unit16: {members: [person16]} + tax_unit17: {members: [person17]} + tax_unit18: {members: [person18]} + tax_unit19: {members: [person19]} + tax_unit20: {members: [person20]} + tax_unit21: {members: [person21]} + tax_unit22: {members: [person22]} + tax_unit23: {members: [person23]} + tax_unit24: {members: [person24]} + tax_unit25: {members: [person25]} + tax_unit26: {members: [person26]} + tax_unit27: {members: [person27]} + tax_unit28: {members: [person28]} + tax_unit29: {members: [person29]} + tax_unit30: {members: [person30]} + tax_unit31: {members: [person31]} + tax_unit32: {members: [person32]} + tax_unit33: {members: [person33]} + tax_unit34: {members: [person34]} + tax_unit35: {members: [person35]} + tax_unit36: {members: [person36]} + tax_unit37: {members: [person37]} + tax_unit38: {members: [person38]} + tax_unit39: {members: [person39]} + tax_unit40: {members: [person40]} + tax_unit41: {members: [person41]} + tax_unit42: {members: [person42]} + tax_unit43: {members: [person43]} + tax_unit44: {members: [person44]} + tax_unit45: {members: [person45]} + tax_unit46: {members: [person46]} + tax_unit47: {members: [person47]} + tax_unit48: {members: [person48]} + tax_unit49: {members: [person49]} + tax_unit50: {members: [person50]} + tax_unit51: {members: [person51]} + tax_unit52: {members: [person52]} + tax_unit53: {members: [person53]} + tax_unit54: {members: [person54]} + tax_unit55: {members: [person55]} + tax_unit56: {members: [person56]} + tax_unit57: {members: [person57]} + tax_unit58: {members: [person58]} + tax_unit59: {members: [person59]} + tax_unit60: {members: [person60]} + tax_unit61: {members: [person61]} + tax_unit62: {members: [person62]} + tax_unit63: {members: [person63]} + tax_unit64: {members: [person64]} + tax_unit65: {members: [person65]} + tax_unit66: {members: [person66]} + tax_unit67: {members: [person67]} + tax_unit68: {members: [person68]} + tax_unit69: {members: [person69]} + tax_unit70: {members: [person70]} + tax_unit71: {members: [person71]} + tax_unit72: {members: [person72]} + tax_unit73: {members: [person73]} + tax_unit74: {members: [person74]} + tax_unit75: {members: [person75]} + tax_unit76: {members: [person76]} + tax_unit77: {members: [person77]} + tax_unit78: {members: [person78]} + tax_unit79: {members: [person79]} + tax_unit80: {members: [person80]} + tax_unit81: {members: [person81]} + tax_unit82: {members: [person82]} + tax_unit83: {members: [person83]} + tax_unit84: {members: [person84]} + tax_unit85: {members: [person85]} + tax_unit86: {members: [person86]} + tax_unit87: {members: [person87]} + tax_unit88: {members: [person88]} + tax_unit89: {members: [person89]} + tax_unit90: {members: [person90]} + tax_unit91: {members: [person91]} + tax_unit92: {members: [person92]} + tax_unit93: {members: [person93]} + tax_unit94: {members: [person94]} + tax_unit95: {members: [person95]} + tax_unit96: {members: [person96]} + tax_unit97: {members: [person97]} + tax_unit98: {members: [person98]} + tax_unit99: {members: [person99]} + tax_unit100: {members: [person100]} + tax_unit101: {members: [person101]} + tax_unit102: {members: [person102]} + tax_unit103: {members: [person103]} + tax_unit104: {members: [person104]} + tax_unit105: {members: [person105]} + tax_unit106: {members: [person106]} + tax_unit107: {members: [person107]} + tax_unit108: {members: [person108]} + tax_unit109: {members: [person109]} + tax_unit110: {members: [person110]} + tax_unit111: {members: [person111]} + tax_unit112: {members: [person112]} + spm_units: + spm_unit1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15, person16, person17, person18, person19, person20, person21, person22, person23, person24, person25, person26, person27, person28] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_000 + spm_unit2: + members: [person29, person30, person31, person32, person33, person34, person35, person36, person37, person38, person39, person40, person41, person42, person43, person44, person45, person46, person47, person48, person49, person50, person51, person52, person53, person54, person55, person56] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_000 + spm_unit3: + members: [person57, person58, person59, person60, person61, person62, person63, person64, person65, person66, person67, person68, person69, person70, person71, person72, person73, person74, person75, person76, person77, person78, person79, person80, person81, person82, person83, person84] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_000 + spm_unit4: + members: [person85, person86, person87, person88, person89, person90, person91, person92, person93, person94, person95, person96, person97, person98, person99, person100, person101, person102, person103, person104, person105, person106, person107, person108, person109, person110, person111, person112] + heating_type: ELECTRICITY + pre_subsidy_electricity_expense: 1_000 + households: + household1: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10, person11, person12, person13, person14, person15, person16, person17, person18, person19, person20, person21, person22, person23, person24, person25, person26, person27, person28] + state_code: NH + bedrooms: 0 + household2: + members: [person29, person30, person31, person32, person33, person34, person35, person36, person37, person38, person39, person40, person41, person42, person43, person44, person45, person46, person47, person48, person49, person50, person51, person52, person53, person54, person55, person56] + state_code: NH + bedrooms: 0 + household3: + members: [person57, person58, person59, person60, person61, person62, person63, person64, person65, person66, person67, person68, person69, person70, person71, person72, person73, person74, person75, person76, person77, person78, person79, person80, person81, person82, person83, person84] + state_code: NH + bedrooms: 0 + household4: + members: [person85, person86, person87, person88, person89, person90, person91, person92, person93, person94, person95, person96, person97, person98, person99, person100, person101, person102, person103, person104, person105, person106, person107, person108, person109, person110, person111, person112] + state_code: NH + bedrooms: 0 + output: + nh_fap_household_size: [28, 28, 28, 28] + nh_fap_countable_income: [186_000, 186_251.99, 186_252, 186_252.01] + nh_fap_income_limit: [185_486, 185_486, 185_486, 185_486] + nh_fap_eligible: [true, true, false, false] + nh_fap: [863, 863, 0, 0] + +# Manual page 15 counts annuity payments and military retirement pay. A uniformed +# services Survivor Benefit Plan annuity is reported in military_retirement_pay_survivors. +# Income 20,000 is above 125% of the 2026 one-person FPG (15,960 * 1.25 = 19,950) +# and within 150% (23,940), so band D. No bill: Coos single-family proxy with four +# bedrooms, 2,000 * 4 * 7,672 / 1,000,000 * 28.881 / 0.78 = 2,272.56, cost band BB. +# Fuel oil multiplier 1: BB/D = 1,410. +- name: Case 84, a military Survivor Benefit Plan annuity counts as unearned income. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + nh_ssp: 0 + immigration_status: CITIZEN + military_retirement_pay_survivors: 20_000 + spm_units: + spm_unit1: + members: [person1] + heating_type: FUEL_OIL + households: + household1: + members: [person1] + state_code: NH + county_str: COOS_COUNTY_NH + bedrooms: 4 + output: + nh_fap_countable_income: 20_000 + nh_fap_heating_cost: 2_272.564431 + nh_fap_eligible: true + nh_fap: 1_410 + +# Manual pp12,18,21,77-78: unsubsidized heat in rent with no bill and no bedrooms. +# Unit 1: one room in Belknap County, +# 2,000 * 1 * 6,610 / 1,000,000 * 28.881 / 0.78 = 489.50, tier DD; 10,000 is within +# 75% of 15,960 (11,970), band A; DD/A = 750. +# Unit 2: an unknown county gives no estimate, so the cost is 0 and no award is paid +# although the household is eligible. +- name: "Case 85, heat in rent with no bill uses the one-room estimate, and no estimate pays nothing." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: true + receives_housing_assistance: false + spm_unit2: + members: ["person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: true + receives_housing_assistance: false + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "BELKNAP_COUNTY_NH" + household2: + members: ["person2"] + state_code: "NH" + county_str: "UNKNOWN" + output: + nh_fap_heating_cost: [489.495923, 0] + nh_fap_eligible: [true, true] + nh_fap: [750, 0] + +# Manual pp15,17: Social Security of 28,000 is 2,333.33 a month, or 2,313.33 after +# the $20 exclusion, above the MSP limit (135% of the 2027 one-person guideline, +# about 1,838), so the enrollee pays 202.90 * 12 = 2,434.80. +# 28,000 - 2,434.80 = 25,565.20, 160.2% of 15,960: above 150% (23,940) and within +# 175% (27,930), band E. The 2,000 oil bill is in tier BB; BB/E = 1,100. +- name: "Case 86, the Part B deduction moves a Social Security recipient into a higher-paying band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + social_security: 28_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + medicare_part_b_premium: 2_434.8 + nh_fap_countable_income: 25_565.2 + nh_fap: 1_100 + +# Manual p15 and plan item 1.9: municipal general assistance is not counted. +# 19,500 is 122.2% of 15,960: above 100% and within 125% (19,950), band C. +# The 2,000 oil bill is in tier BB; BB/C = 1,720. +- name: "Case 87, general assistance does not raise the income band." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 19_500 + general_assistance: 1_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 2_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 19_500 + nh_fap: 1_720 + +# A solar home's bill is its grid electricity bill, so SOLAR uses the electricity +# row and utility multiplier. The 1,200 bill exceeds the one-room Belknap estimate +# 2,000 * 1 * 6,610 / 1,000,000 * 64.706 = 855.41 and is in tier CC; 10,000 is +# band A; CC/A = 1,460 * 0.75 = 1,095. +- name: "Case 88, solar heat with an electricity bill receives the utility schedule." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "SOLAR" + heat_expense_included_in_rent: false + receives_housing_assistance: false + pre_subsidy_electricity_expense: 1_200 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_heating_cost: 1_200 + nh_fap: 1_095 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_countable_income.yaml new file mode 100644 index 00000000000..aab8c32eef7 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_countable_income.yaml @@ -0,0 +1,1143 @@ +# Source: PY27 NH Fuel Assistance Program Procedures Manual. +# https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf +# Physical PDF pages: 13, 14, 15, 16, 17, 23, 25, 26, 29, 34, 36. +# Period 2027 represents the researched 2026-2027 schedule with 2026 FPG. +# Inputs are annual; SSI and FANF totals are explicitly supplied to isolate receipts. +# Investment income receives one combined $50 exclusion per SPM unit (p17's +# interest "and/or" dividends wording), a modeling convention; pp15-16 list +# the two exclusions separately. + +# Manual p15 counts salaries and wages before deductions; p17 does not list a general earned-income disregard. +- name: "Case 1, gross annual wages receive no general earnings disregard." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 12_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 12_000 + +# Manual pp16 and23 specifically exclude regular child support. +- name: "Case 2, regular child support received is excluded." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 11_900 + child_support_received: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 11_900 + +# Manual pp17 and23 allow regular support paid during the income period. +- name: "Case 3, documented child support paid is deducted." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 12_100 + child_support_expense: 200 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 11_900 + +# Contract household income floor; sourced support deduction exceeds otherwise countable receipts. +- name: "Case 4, support expenses cannot produce negative household income." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 100 + child_support_expense: 200 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 0 + +# Manual p16 excludes SSI for children under 18; annual SSI input represents total receipts. +- name: "Case 5, SSI for a child just below age eighteen is excluded." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person2: + age: 17 + immigration_status: "CITIZEN" + ssi: 6_000 + is_disabled: true + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_countable_income: 10_000 + +# Manual pp15-16 adult SSI is countable; exclusion ends at 18. +- name: "Case 6, SSI at age eighteen is countable." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person2: + age: 18 + immigration_status: "CITIZEN" + ssi: 6_000 + nh_ssp: 0 + is_disabled: true + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_countable_income: 16_000 + +# Manual p16 excludes earned income from full-time high-school students, without a stated age 18 cutoff. +- name: "Case 7, full-time high-school wages and net business income are excluded." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person2: + age: 18 + immigration_status: "CITIZEN" + ssi: 0 + is_full_time_student: true + is_in_secondary_school: true + employment_income: 3_000 + self_employment_income: 2_000 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_countable_income: 10_000 + +# Manual p16 requires full-time high-school attendance for the earnings exclusion. +- name: "Case 8, part-time high-school earnings remain countable." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person2: + age: 18 + immigration_status: "CITIZEN" + ssi: 0 + is_full_time_student: false + is_in_secondary_school: true + employment_income: 3_000 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_countable_income: 13_000 + +# Manual pp16 and34 distinguish high-school earnings from a resident college student's countable income. +- name: "Case 9, full-time college earnings remain countable." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person2: + age: 19 + immigration_status: "CITIZEN" + ssi: 0 + is_full_time_student: true + is_in_secondary_school: false + employment_income: 3_000 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_countable_income: 13_000 + +# Manual p16 exempts specified full-time high-school earnings, not every minor's earnings. +- name: "Case 10, a minor without reported high-school attendance has countable earnings." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person2: + age: 17 + immigration_status: "CITIZEN" + ssi: 0 + is_full_time_student: false + is_in_secondary_school: false + employment_income: 3_000 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_countable_income: 13_000 + +# Manual p15 counts Social Security; p16 high-school exclusion is for earned income. +- name: "Case 11, high-school exclusion does not exempt unearned Social Security." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person2: + age: 18 + immigration_status: "CITIZEN" + ssi: 0 + is_full_time_student: true + is_in_secondary_school: true + employment_income: 3_000 + social_security: 1_200 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_countable_income: 11_200 + +# Manual p36 requires income of ineligible noncitizens in household income. +- name: "Case 12, mixed status includes all income without proration." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 15_000 + person2: + age: 40 + immigration_status: "UNDOCUMENTED" + ssi: 0 + employment_income: 15_000 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_countable_income: 30_000 + +# Manual p26 example counts profitable business 800 and loss business 0; reported net inputs used without reconstructing deductions. +- name: "Case 13, each reported business source loss is floored separately." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + self_employment_income: 800 + sstb_self_employment_income: -600 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 10_800 + +# Manual p26 prohibits subtracting negative self-employment income from other household income. +- name: "Case 14, one member's business loss does not offset another member's income." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + self_employment_income: 800 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + self_employment_income: -600 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_countable_income: 800 + +# Manual p15 net rent and pp25-29 business treatment; each rental stream is floored +# at zero, so a loss on one stream cannot offset another. +- name: "Case 15, negative rental income does not offset a separate positive rental stream." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + rental_income: -300 + farm_rent_income: 600 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 10_600 + +# Manual p25 requires Schedule F farms and partnership/corporation returns; reported net sources are separate. +- name: "Case 16, reported farm and partnership business profits count once." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + farm_operations_income: 800 + partnership_income: 600 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 1_400 + +# Page 17's "$50 of earned interest and/or dividends" gives one $50 annual exclusion +# per SPM unit; 50 + 50 - 50 = 50. +- name: "Case 17, interest and dividends share one fifty-dollar exclusion." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + interest_income: 50 + ordinary_dividend_income: 50 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 50 + +# Apply the $50 exclusion once to combined interest and dividends: 51 + 51 - 50 = 52. +- name: "Case 18, combined investment receipts above the shared exclusion are countable." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + interest_income: 51 + ordinary_dividend_income: 51 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 52 + +# Both members share one SPM-unit exclusion: 40 + 20 + 40 + 40 - 50 = 90. +- name: "Case 19, members of one SPM unit share one investment exclusion." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + interest_income: 40 + ordinary_dividend_income: 20 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + interest_income: 40 + ordinary_dividend_income: 40 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_countable_income: 90 + +# The canonical ordinary_dividend_income includes both dividend components; 100 + 100 - 50 = 150. +- name: "Case 20, qualified and nonqualified dividends feed the canonical ordinary aggregate." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + qualified_dividend_income: 100 + non_qualified_dividend_income: 100 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 150 + +# Manual p15; annual SSI receipts count once. At age 40 there is no Medicare Part B premium. +- name: "Case 21, gross Social Security and adult SSI are both countable." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 6_000 + social_security: 12_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 18_000 + +# Manual p15 lists pensions, retirement withdrawals, unemployment, workers compensation, alimony and regular estates/trust receipts. +- name: "Case 22, retirement receipts and other regular listed cash income count." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + pension_income: 2_400 + retirement_distributions: 1_200 + unemployment_compensation: 1_200 + workers_compensation: 600 + alimony_income: 600 + estate_income: 600 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 6_600 + +# Manual p15 counts state welfare payments (APTD, ANB, FANF, OAA, RCA), regular +# outside support, nonexempt veterans benefits and strike pay. Plan item 1.9 leaves +# General Assistance benefits unchecked, so the 600 of municipal general assistance +# (RSA 165) is excluded: 1,200 + 1,200 + 600 = 3,000. +- name: "Case 23, municipal general assistance is excluded while regular support, veterans and strike income count." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + general_assistance: 600 + financial_assistance: 1_200 + veterans_benefits: 1_200 + strike_benefits: 600 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 3_000 + +# Manual p15 counts FANF, SSI and Social Security: 1000+2400+4800+3600; FANF is a household annual total. +- name: "Case 24, state FANF receipts count once for the household." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 1_000 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 2_400 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + social_security: 4_800 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3"] + nh_fanf: 3_600 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3"] + state_code: "NH" + output: + nh_fap_countable_income: 11_800 + +# Manual p16 excludes capital gains. +- name: "Case 25, capital gains are excluded." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + short_term_capital_gains: 4_000 + long_term_capital_gains: 6_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 10_000 + +# Manual p17 does not allow generic medical or child-care expenses. At age 40 there is +# no Medicare Part B premium to deduct. +- name: "Case 26, no automatic medical or child-care deduction is applied." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 12_000 + other_medical_expenses: 1_200 + health_insurance_premiums: 2_400 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + childcare_expenses: 3_600 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 12_000 + +# Manual p17 deducts Medicare premiums withheld from Social Security. Social +# Security of 12,000 is 1,000 a month, or 980 after the $20 exclusion, within the +# Medicare Savings Program limit (135% of the 2027 one-person guideline, about +# 1,838 a month), so MSP pays the premium and nothing is withheld or deducted. +- name: "Case 27, no Part B deduction applies when the Medicare Savings Program pays the premium." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + social_security: 12_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + households: + household1: + members: ["person1"] + state_code: "NH" + output: + medicare_part_b_premium: 0 + nh_fap_countable_income: 12_000 + +# Manual pp15,17 deduct the Medicare premium withheld from railroad retirement. +# railroad_benefits is not an SSI unearned source in the model, so MSP status +# turns on assets: 20,000 exceeds the 9,950 MSP resource limit and the enrollee +# pays the 2027 premium of 202.90 * 12 = 2,434.80. 18,000 - 2,434.80 = 15,565.20. +- name: "Case 28, the Part B premium withheld from railroad retirement is deducted." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + railroad_benefits: 18_000 + bank_account_assets: 20_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + households: + household1: + members: ["person1"] + state_code: "NH" + output: + medicare_part_b_premium: 2_434.8 + nh_fap_countable_income: 15_565.2 + +# Manual pp14-17 allow support paid and the withheld Medicare premium separately. +# Social Security of 2,000 a month is above the MSP limit (about 1,838 a month), +# so the premium is 2,434.80: 24,000 - 2,000 - 2,434.80 = 19,565.20. +- name: "Case 29, support paid and the Part B premium are both deducted." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + social_security: 24_000 + child_support_expense: 2_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + households: + household1: + members: ["person1"] + state_code: "NH" + output: + medicare_part_b_premium: 2_434.8 + nh_fap_countable_income: 19_565.2 + +# Manual pp14-17 deductions; 24,000 - 23,000 - 2,434.80 is negative and floors at 0. +- name: "Case 30, combined allowed deductions cannot produce negative income." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + social_security: 24_000 + child_support_expense: 23_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + households: + household1: + members: ["person1"] + state_code: "NH" + output: + medicare_part_b_premium: 2_434.8 + nh_fap_countable_income: 0 + +# Manual p17 and plan item 1.9 count Social Security net of the Medicare deduction. +# An enrollee aged 70 needs no reported amount: 1,980 a month after the $20 +# exclusion is above the MSP limit (about 1,838), so the premium is +# 202.90 * 12 = 2,434.80 and 24,000 - 2,434.80 = 21,565.20. +- name: "Case 31, a Medicare enrollee's Part B premium is deducted from Social Security." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + social_security: 24_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + households: + household1: + members: ["person1"] + state_code: "NH" + output: + medicare_part_b_premium: 2_434.8 + nh_fap_countable_income: 21_565.2 + +# Manual pp14-17; each member's withheld premium is deducted within its own SPM +# unit. Separate tax and marital units keep each person's MSP test individual. +# Person1 (Social Security above the MSP limit) and person2 (assets of 20,000 above +# the 9,950 limit) each pay 2,434.80: 24,000 + 18,000 - 2 * 2,434.80 = 37,130.40. +# Person3's 980 a month after the $20 exclusion is within the MSP limit, so MSP +# pays the premium and unit 2 keeps 12,000. +- name: "Case 32, each SPM unit deducts its members' Part B premiums, and none that MSP pays." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + social_security: 24_000 + person2: + age: 68 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + railroad_benefits: 18_000 + bank_account_assets: 20_000 + person3: + age: 70 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + social_security: 12_000 + tax_units: + tax_unit1: + members: ["person1"] + tax_unit2: + members: ["person2"] + tax_unit3: + members: ["person3"] + marital_units: + marital_unit1: + members: ["person1"] + marital_unit2: + members: ["person2"] + marital_unit3: + members: ["person3"] + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + spm_unit2: + members: ["person3"] + nh_fanf: 0 + heating_type: "NATURAL_GAS" + households: + household1: + members: ["person1", "person2", "person3"] + state_code: "NH" + output: + medicare_part_b_premium: [2_434.8, 2_434.8, 0] + nh_fap_countable_income: [37_130.4, 12_000] + +# Each SPM unit in the same household gets its own $50 exclusion. +# Unit 1: 40 + 40 - 50 = 30. Unit 2: 25 + 25 - 50 = 0. +# Unit 3: investment income of 10 + 20 is fully excluded; the unused $20 +# of the allowance does not offset $10,000 of earnings. +- name: "Case 33, each SPM unit receives its own exclusion limited to investment income." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + interest_income: 40 + ordinary_dividend_income: 40 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + interest_income: 25 + ordinary_dividend_income: 25 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + interest_income: 10 + ordinary_dividend_income: 20 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + spm_unit2: + members: ["person2"] + nh_fanf: 0 + spm_unit3: + members: ["person3"] + nh_fanf: 0 + households: + household1: + members: ["person1", "person2", "person3"] + state_code: "NH" + output: + nh_fap_countable_income: [30, 0, 10_000] + +# Manual p15 counts state welfare payments (APTD, ANB, FANF, OAA, RCA); the +# state supplement pays APTD, ANB and OAA. $100 a month x 12 = $1,200. +- name: "Case 34, state supplement payments count as unearned income." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 1_200 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 1_200 + +# Manual pp15,25-29 count business income, survivor and disability benefits, +# gambling and lottery winnings and net rent. Distinct positive amounts for an +# adult who is not a high-school student make each source visible: +# 3,200 + 1,600 + 800 + 400 + 200 + 100 = 6,300. +- name: "Case 35, S corporation, SSTB, rental, survivor, disability and gambling income each count." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + s_corp_income: 3_200 + sstb_self_employment_income: 1_600 + rental_income: 800 + survivor_benefits: 400 + disability_benefits: 200 + gambling_winnings: 100 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 6_300 + +# Manual p17 deducts Medicare premiums withheld from Social Security or railroad +# retirement, so the deduction cannot exceed those benefits. Pension income of +# 30,000 keeps both enrollees above the MSP limit, so each pays 2,434.80. +# Unit 1: 30,000 + 1,200 - min(2,434.80, 1,200) = 30,000. +# Unit 2: no Social Security or railroad retirement, so 30,000 - 0 = 30,000. +- name: "Case 36, the Part B deduction is capped at the Social Security and railroad benefits." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + social_security: 1_200 + pension_income: 30_000 + person2: + age: 70 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + pension_income: 30_000 + tax_units: + tax_unit1: + members: ["person1"] + tax_unit2: + members: ["person2"] + marital_units: + marital_unit1: + members: ["person1"] + marital_unit2: + members: ["person2"] + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + spm_unit2: + members: ["person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + households: + household1: + members: ["person1"] + state_code: "NH" + household2: + members: ["person2"] + state_code: "NH" + output: + medicare_part_b_premium: [2_434.8, 2_434.8] + nh_fap_countable_income: [30_000, 30_000] diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_eligible.yaml new file mode 100644 index 00000000000..0a6b296b81d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_eligible.yaml @@ -0,0 +1,1204 @@ +# Source: PY27 NH Fuel Assistance Program Procedures Manual. +# https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf +# Physical PDF pages: 12, 17, 18, 21, 35, 36, 74. +# Period 2027 represents the researched 2026-2027 schedule with 2026 FPG. +# Inputs are annual; SSI and FANF totals are explicitly supplied to isolate receipts. +# Heat-in-rent awards are asserted in nh_fap.yaml. + +# Manual pp12,17 and74; maximum is inclusive. +- name: "Case 1, income at the 1-person annual ceiling is eligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 48_713 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_eligible: true + +# Manual pp12,17 and74; above published maximum. +- name: "Case 2, income one cent above the 1-person annual ceiling is ineligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 48_713.01 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_eligible: false + +# Manual pp12,17 and74; maximum is inclusive. +- name: "Case 3, income at the 2-person annual ceiling is eligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 63_702 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_eligible: true + +# Manual pp12,17 and74; above published maximum. +- name: "Case 4, income one cent above the 2-person annual ceiling is ineligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 63_702.01 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_eligible: false + +# Manual pp12,17 and74; maximum is inclusive. +- name: "Case 5, income at the 3-person annual ceiling is eligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 78_691 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3"] + state_code: "NH" + output: + nh_fap_eligible: true + +# Manual pp12,17 and74; above published maximum. +- name: "Case 6, income one cent above the 3-person annual ceiling is ineligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 78_691.01 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3"] + state_code: "NH" + output: + nh_fap_eligible: false + +# Manual pp12,17 and74; maximum is inclusive. +- name: "Case 7, income at the 4-person annual ceiling is eligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 93_680 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4"] + state_code: "NH" + output: + nh_fap_eligible: true + +# Manual pp12,17 and74; above published maximum. +- name: "Case 8, income one cent above the 4-person annual ceiling is ineligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 93_680.01 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4"] + state_code: "NH" + output: + nh_fap_eligible: false + +# Manual pp12,17 and74; maximum is inclusive. +- name: "Case 9, income at the 5-person annual ceiling is eligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 108_668 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4", "person5"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4", "person5"] + state_code: "NH" + output: + nh_fap_eligible: true + +# Manual pp12,17 and74; above published maximum. +- name: "Case 10, income one cent above the 5-person annual ceiling is ineligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 108_668.01 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4", "person5"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4", "person5"] + state_code: "NH" + output: + nh_fap_eligible: false + +# Manual pp12,17 and74; maximum is inclusive. +- name: "Case 11, income at the 6-person annual ceiling is eligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 123_657 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person6: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4", "person5", "person6"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4", "person5", "person6"] + state_code: "NH" + output: + nh_fap_eligible: true + +# Manual pp12,17 and74; above published maximum. +- name: "Case 12, income one cent above the 6-person annual ceiling is ineligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 123_657.01 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person6: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4", "person5", "person6"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4", "person5", "person6"] + state_code: "NH" + output: + nh_fap_eligible: false + +# Manual pp12,17 and74; maximum is inclusive. +- name: "Case 13, income at the 7-person annual ceiling is eligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 126_468 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person6: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person7: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4", "person5", "person6", "person7"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4", "person5", "person6", "person7"] + state_code: "NH" + output: + nh_fap_eligible: true + +# Manual pp12,17 and74; above published maximum. +- name: "Case 14, income one cent above the 7-person annual ceiling is ineligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 126_468.01 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person6: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person7: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4", "person5", "person6", "person7"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4", "person5", "person6", "person7"] + state_code: "NH" + output: + nh_fap_eligible: false + +# Manual pp12,17 and74; maximum is inclusive. +- name: "Case 15, income at the 8-person annual ceiling is eligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 129_278 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person6: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person7: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person8: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4", "person5", "person6", "person7", "person8"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4", "person5", "person6", "person7", "person8"] + state_code: "NH" + output: + nh_fap_eligible: true + +# Manual pp12,17 and74; above published maximum. +- name: "Case 16, income one cent above the 8-person annual ceiling is ineligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 129_278.01 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person6: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person7: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person8: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4", "person5", "person6", "person7", "person8"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4", "person5", "person6", "person7", "person8"] + state_code: "NH" + output: + nh_fap_eligible: false + +# Manual p12 primary New Hampshire residence required. +- name: "Case 17, a residence outside New Hampshire is ineligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "MA" + output: + nh_fap_eligible: false + +# Manual pp35-36 require a qualified recipient. +- name: "Case 18, no qualified household members are ineligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "UNDOCUMENTED" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_eligible: false + +# Contract represents no heating exposure through heating_type NONE; manual p12 requires energy responsibility. +- name: "Case 19, no heating type is ineligible despite an unrelated fuel bill." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NONE" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_eligible: false + +# Manual pp12,18: with no bill, the estimate gives the heating cost. With no +# bedrooms the dwelling counts as one room, and with no county input the Belknap +# fallback applies: 2,000 * 1 * 6,610 / 1,000,000 * 28.881 / 0.78 = 489.50 > 0. +- name: "Case 20, a household with no bill and no bedrooms has a one-room heating cost." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 0 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_eligible: true + +# Manual p12 has no positive-dollar expense minimum. An unknown county gives no +# estimate, so the one-cent bill alone establishes the heating cost. +- name: "Case 21, a positive direct heating cost satisfies energy responsibility." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 0.01 + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "UNKNOWN" + output: + nh_fap_eligible: true + +# Manual pp12 and21. Unsubsidized heat in rent establishes energy responsibility. +- name: "Case 22, nonsubsidized heat in rent can qualify without a separate bill." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: true + receives_housing_assistance: false + fuel_oil_expense: 0 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_eligible: true + +# Manual p21 excludes subsidized housing with heat included in rent. +- name: "Case 23, subsidized housing with heat included in rent is ineligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: true + receives_housing_assistance: true + fuel_oil_expense: 0 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_eligible: false + +# Manual p21 permits subsidized tenants otherwise eligible when they pay their own heat. +- name: "Case 24, subsidized housing with separately paid heat can qualify." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: true + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_eligible: true + +# Manual p35 all qualified noncitizens regardless of entry date. +- name: "Case 25, a new lawful permanent resident has no five-year bar." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "LEGAL_PERMANENT_RESIDENT" + ssi: 0 + years_since_us_entry: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_eligible: true + +# Manual pp17,74: the 2027 Part B premium of 202.90 * 12 = 2,434.80 withheld from +# Social Security is deducted for the enrollee: 50,000 - 2,434.80 = 47,565.20, within +# the 48,713 ceiling. Social Security of 50,000 is far above the MSP limit. The +# person who is not enrolled in Medicare pays no premium and stays above it. +- name: "Case 26, the withheld Part B premium brings an enrollee within the income ceiling." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + social_security: 50_000 + medicare_enrolled: false + person2: + age: 70 + immigration_status: "CITIZEN" + ssi: 0 + nh_ssp: 0 + social_security: 50_000 + medicare_enrolled: true + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + fuel_oil_expense: 4_000 + heat_expense_included_in_rent: false + receives_housing_assistance: false + spm_unit2: + members: ["person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + fuel_oil_expense: 4_000 + heat_expense_included_in_rent: false + receives_housing_assistance: false + households: + household1: + members: ["person1"] + state_code: "NH" + household2: + members: ["person2"] + state_code: "NH" + output: + medicare_part_b_premium: [0, 2_434.8] + nh_fap_countable_income: [50_000, 47_565.2] + nh_fap_eligible: [false, true] + +# Manual pp12,18,21,35: estimate may replace an absent actual bill; retain income, qualified-member, subsidized heat-in-rent, fuel and state requirements. +# Unit 2 has 0 bedrooms and counts as one room: 2,000 * 1 * 7,672 / 1,000,000 * 28.881 / 0.78 = 568.14. +# Unit 7's unknown county gives no estimate. +- name: "Case 27, a room proxy establishes heating costs while other gates remain." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 60_000 + person4: + age: 40 + immigration_status: "UNDOCUMENTED" + ssi: 0 + employment_income: 10_000 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person6: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person7: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person8: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + person9: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + nh_fanf: 0 + heat_expense_included_in_rent: false + receives_housing_assistance: false + spm_unit2: + members: ["person2"] + heating_type: "FUEL_OIL" + nh_fanf: 0 + heat_expense_included_in_rent: false + receives_housing_assistance: false + spm_unit3: + members: ["person3"] + heating_type: "FUEL_OIL" + nh_fanf: 0 + heat_expense_included_in_rent: false + receives_housing_assistance: false + spm_unit4: + members: ["person4"] + heating_type: "FUEL_OIL" + nh_fanf: 0 + heat_expense_included_in_rent: false + receives_housing_assistance: false + spm_unit5: + members: ["person5"] + heating_type: "FUEL_OIL" + nh_fanf: 0 + heat_expense_included_in_rent: true + receives_housing_assistance: true + spm_unit6: + members: ["person6"] + heating_type: "NONE" + nh_fanf: 0 + heat_expense_included_in_rent: false + receives_housing_assistance: false + spm_unit7: + members: ["person7"] + heating_type: "FUEL_OIL" + nh_fanf: 0 + heat_expense_included_in_rent: false + receives_housing_assistance: false + spm_unit8: + members: ["person8"] + heating_type: "FUEL_OIL" + nh_fanf: 0 + heat_expense_included_in_rent: false + receives_housing_assistance: false + spm_unit9: + members: ["person9"] + heating_type: "FUEL_OIL" + nh_fanf: 0 + heat_expense_included_in_rent: false + receives_housing_assistance: true + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + household2: + members: ["person2"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 0 + household3: + members: ["person3"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + household4: + members: ["person4"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + household5: + members: ["person5"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + household6: + members: ["person6"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + household7: + members: ["person7"] + state_code: "NH" + county_str: "UNKNOWN" + bedrooms: 4 + household8: + members: ["person8"] + state_code: "MA" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + household9: + members: ["person9"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + output: + nh_fap_eligible: [true, true, false, false, false, false, false, false, true] + +# The shared $50 investment exclusion leaves $25 of $75 interest countable; +# 48,713 + 25 = 48,738 exceeds the one-person income limit. +- name: "Case 28, interest remaining after the SPM-unit exclusion can put income above the limit." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 48_713 + interest_income: 75 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_countable_income: 48_738 + nh_fap_eligible: false + nh_fap: 0 + +# Manual p21 excludes subsidized tenants whose heat is included in rent; +# public housing is subsidized housing. +- name: "Case 29, public housing with heat included in rent is ineligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: true + receives_housing_assistance: false + fuel_oil_expense: 0 + households: + household1: + members: ["person1"] + state_code: "NH" + is_in_public_housing: true + output: + nh_fap_eligible: false + +# Manual p12 requires responsibility for heating costs. Unsubsidized heat in rent +# passes the cost and housing tests, but heating type NONE means the home has no +# heating, so the household is ineligible. +- name: "Case 30, heat in rent with no heating type is ineligible." + period: 2027 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 10_000 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "NONE" + heat_expense_included_in_rent: true + receives_housing_assistance: false + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_heating_cost.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_heating_cost.yaml new file mode 100644 index 00000000000..63e372ec840 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_heating_cost.yaml @@ -0,0 +1,676 @@ +# Source: PY27 NH Fuel Assistance Program Procedures Manual, physical pages 17, 18, 76, 77. +# https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf +# Agency service counties: https://www.capnh.org/home-old +# No room-count input exists, so bedrooms stand in for the manual's room count, with at +# least one room for a dwelling. Page 17 also counts kitchens and living rooms, so this +# understates rooms. +# Inputs and estimates are annual; actual bills and the estimated cost are not added together. + +# Manual pp76-77 formula with bedrooms as the room count: 2000 * 4 * 7672 / 1,000,000 * 28.881 / .78 = 2272.564431. +- name: "Case 1, four bedrooms produce a four-room oil estimate without added rooms." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + fuel_oil_expense: 0 + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + output: + nh_fap_heating_cost: 2_272.564431 + +# Manual p77: single-family factor 2000 * two bedrooms * 7672 HDD; apply each fuel price / efficiency. WOOD is cordwood; electricity has no extra 70% reduction. +- name: "Case 2, each observed fuel uses its published heating-cost conversion." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person6: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person7: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "KEROSENE" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit2: + members: ["person2"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit3: + members: ["person3"] + heating_type: "NATURAL_GAS" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit4: + members: ["person4"] + heating_type: "COAL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit5: + members: ["person5"] + heating_type: "WOOD" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit6: + members: ["person6"] + heating_type: "ELECTRICITY" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit7: + members: ["person7"] + heating_type: "PROPANE" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 2 + household2: + members: ["person2"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 2 + household3: + members: ["person3"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 2 + household4: + members: ["person4"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 2 + household5: + members: ["person5"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 2 + household6: + members: ["person6"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 2 + household7: + members: ["person7"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 2 + output: + nh_fap_heating_cost: [1_384.304205, 1_136.282215, 561.365854, 584.545024, 1_054.595556, 1_985.697728, 1_671.984533] + +# Manual p77 agency HDD and CAPNH county directory; factor 2000 * two bedrooms * HDD / 1,000,000 * 28.881 / .78. +- name: "Case 3, all ten counties use the agency heating degree days." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person6: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person7: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person8: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person9: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person10: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit2: + members: ["person2"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit3: + members: ["person3"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit4: + members: ["person4"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit5: + members: ["person5"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit6: + members: ["person6"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit7: + members: ["person7"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit8: + members: ["person8"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit9: + members: ["person9"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit10: + members: ["person10"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "BELKNAP_COUNTY_NH" + bedrooms: 2 + household2: + members: ["person2"] + state_code: "NH" + county_str: "MERRIMACK_COUNTY_NH" + bedrooms: 2 + household3: + members: ["person3"] + state_code: "NH" + county_str: "HILLSBOROUGH_COUNTY_NH" + bedrooms: 2 + household4: + members: ["person4"] + state_code: "NH" + county_str: "ROCKINGHAM_COUNTY_NH" + bedrooms: 2 + household5: + members: ["person5"] + state_code: "NH" + county_str: "STRAFFORD_COUNTY_NH" + bedrooms: 2 + household6: + members: ["person6"] + state_code: "NH" + county_str: "CHESHIRE_COUNTY_NH" + bedrooms: 2 + household7: + members: ["person7"] + state_code: "NH" + county_str: "SULLIVAN_COUNTY_NH" + bedrooms: 2 + household8: + members: ["person8"] + state_code: "NH" + county_str: "CARROLL_COUNTY_NH" + bedrooms: 2 + household9: + members: ["person9"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 2 + household10: + members: ["person10"] + state_code: "NH" + county_str: "GRAFTON_COUNTY_NH" + bedrooms: 2 + output: + nh_fap_heating_cost: [978.991846, 978.991846, 887.6094, 887.6094, 897.680723, 975.733477, 975.733477, 1_136.282215, 1_136.282215, 1_136.282215] + +# Manual p77: dwelling factors 2000, 1800 and 1400 with Strafford HDD 6061. +- name: "Case 4, dwelling factors change a two-bedroom oil estimate." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "SINGLE_FAMILY_OR_MODULAR" + spm_unit2: + members: ["person2"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "MOBILE_HOME" + spm_unit3: + members: ["person3"] + heating_type: "FUEL_OIL" + nh_fap_dwelling_type: "APARTMENT_CONDO_OR_DUPLEX" + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "STRAFFORD_COUNTY_NH" + bedrooms: 2 + household2: + members: ["person2"] + state_code: "NH" + county_str: "STRAFFORD_COUNTY_NH" + bedrooms: 2 + household3: + members: ["person3"] + state_code: "NH" + county_str: "STRAFFORD_COUNTY_NH" + bedrooms: 2 + output: + nh_fap_heating_cost: [897.680723, 807.912651, 628.376506] + +# A dwelling has at least one room, so zero or negative bedrooms give the one-room +# estimate 2000 * 1 * 7672 / 1,000,000 * 28.881 / .78 = 568.141108; larger bills replace it. +- name: "Case 5, zero or negative bedrooms count as one room below larger actual bills." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + fuel_oil_expense: 0 + spm_unit2: + members: ["person2"] + heating_type: "FUEL_OIL" + fuel_oil_expense: 650 + spm_unit3: + members: ["person3"] + heating_type: "FUEL_OIL" + fuel_oil_expense: 750 + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 0 + household2: + members: ["person2"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 0 + household3: + members: ["person3"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: -1 + output: + nh_fap_heating_cost: [568.141108, 650, 750] + +# Manual p18: compare actual annual cost and design heat load for best benefit; 500 is below the four-bedroom estimate. +- name: "Case 6, the estimate is retained when the actual bill is lower." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + fuel_oil_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + output: + nh_fap_heating_cost: 2_272.564431 + +# Manual p18 allows documented actual cost for high usage; 5000 exceeds 2272.564431. +- name: "Case 7, a larger annual bill replaces the estimate." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + fuel_oil_expense: 5_000 + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + output: + nh_fap_heating_cost: 5_000 + +# Page 77 has no OTHER row, and UNSPECIFIED and NONE name no fuel, so they give no +# estimate; the canonical OTHER bill is retained. SOLAR uses the electricity row, +# as heating_expense reads a solar home's grid electricity bill: +# 2000 * 4 * 7672 / 1,000,000 * 64.706 / 1 = 3971.395456, above the 650 bill. +- name: "Case 8, OTHER, UNSPECIFIED and NONE give no estimate while SOLAR uses the electricity estimate." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "OTHER" + other_heating_fuel_expense: 250 + spm_unit2: + members: ["person2"] + heating_type: "SOLAR" + pre_subsidy_electricity_expense: 650 + spm_unit3: + members: ["person3"] + heating_type: "UNSPECIFIED" + fuel_oil_expense: 4_000 + spm_unit4: + members: ["person4"] + heating_type: "NONE" + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + household2: + members: ["person2"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + household3: + members: ["person3"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + household4: + members: ["person4"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + output: + nh_fap_heating_cost: [250, 3_971.395456, 0, 0] + +# Only the ten NH counties map to published agency HDD; actual-cost fallback remains available. +- name: "Case 9, unknown and outside counties do not generate an estimate." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + spm_unit2: + members: ["person2"] + heating_type: "FUEL_OIL" + fuel_oil_expense: 650 + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "UNKNOWN" + bedrooms: 4 + household2: + members: ["person2"] + state_code: "NH" + county_str: "SUFFOLK_COUNTY_MA" + bedrooms: 4 + output: + nh_fap_heating_cost: [0, 650] + +# State scope applies even when a supplied county string and bill would otherwise give a positive cost. +- name: "Case 10, the heating-cost component is limited to New Hampshire." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + fuel_oil_expense: 5_000 + households: + household1: + members: ["person1"] + state_code: "MA" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + output: + nh_fap_heating_cost: 0 + +# The adopted contract floors actual bills at zero and selects the better heating-cost basis. +- name: "Case 11, negative reported bills cannot reduce a positive estimate." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + fuel_oil_expense: -1_000 + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 4 + output: + nh_fap_heating_cost: 2_272.564431 + +# A negative bill floors at zero, and 0 bedrooms count as one room: +# 2000 * 1 * 7672 / 1,000,000 * 28.881 / .78 = 568.141108. +- name: "Case 12, a negative bill without bedrooms leaves the one-room estimate." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + fuel_oil_expense: -1_000 + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 0 + output: + nh_fap_heating_cost: 568.141108 + +# Omitted bedrooms default to 0, which counts as one room; the one-room estimate +# 568.141108 exceeds the 500 bill. +- name: "Case 13, omitted bedrooms give the one-room estimate above a smaller bill." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + fuel_oil_expense: 500 + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + output: + nh_fap_heating_cost: 568.141108 + +# Whole-household approximation: both units use two bedrooms; no inferred private-room allocation. Factor 1400 with Coos HDD 7672. +- name: "Case 14, SPM units reuse household bedrooms with their own fuel." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + person2: + age: 40 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "WOOD" + nh_fap_dwelling_type: "APARTMENT_CONDO_OR_DUPLEX" + spm_unit2: + members: ["person2"] + heating_type: "NATURAL_GAS" + nh_fap_dwelling_type: "APARTMENT_CONDO_OR_DUPLEX" + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + bedrooms: 2 + output: + nh_fap_heating_cost: [738.216889, 392.956098] + +# A homeless household has no dwelling to heat, so 0 bedrooms give no room and no +# estimate; the bill is also 0. +- name: "Case 15, a homeless household without bedrooms gets no one-room estimate." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + heating_type: "FUEL_OIL" + fuel_oil_expense: 0 + households: + household1: + members: ["person1"] + state_code: "NH" + county_str: "COOS_COUNTY_NH" + is_homeless: true + output: + nh_fap_heating_cost: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_household_size.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_household_size.yaml new file mode 100644 index 00000000000..ac071903d07 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_household_size.yaml @@ -0,0 +1,123 @@ +# Source: PY27 NH Fuel Assistance Program Procedures Manual. +# https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf +# Physical PDF pages: 12, 35, 36. +# Period 2027 represents the researched 2026-2027 schedule with 2026 FPG. +# Inputs are annual; SSI and FANF totals are explicitly supplied to isolate receipts. + +# Manual pp35-36 includes the reported qualified status regardless of entry date. +- name: "Case 1, citizen is a qualified household member." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + years_since_us_entry: 0 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_household_size: 1 + +# Manual pp35-36 includes the reported qualified status regardless of entry date. +- name: "Case 2, legal_permanent_resident is a qualified household member." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "LEGAL_PERMANENT_RESIDENT" + ssi: 0 + years_since_us_entry: 0 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_household_size: 1 + +# Manual pp35-36 and existing qualified-status mapping; income is tested separately. +- name: "Case 3, mixed status excludes ineligible members only from household size." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + person2: + age: 40 + immigration_status: "UNDOCUMENTED" + ssi: 0 + person3: + age: 40 + immigration_status: "DACA" + ssi: 0 + person4: + age: 40 + immigration_status: "TPS" + ssi: 0 + person5: + age: 40 + immigration_status: "REFUGEE" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4", "person5"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4", "person5"] + state_code: "NH" + output: + nh_fap_household_size: 2 + +# Manual p36 does not count an ineligible noncitizen for eligibility size. +- name: "Case 4, an entirely ineligible-status household has size zero." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "UNDOCUMENTED" + ssi: 0 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_household_size: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_income_limit.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_income_limit.yaml new file mode 100644 index 00000000000..f1f17864b03 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/doe/fap/nh_fap_income_limit.yaml @@ -0,0 +1,361 @@ +# Source: PY27 NH Fuel Assistance Program Procedures Manual. +# https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf +# Physical PDF pages: 17, 74. +# Period 2027 represents the researched 2026-2027 schedule with 2026 FPG. +# Inputs are annual; SSI and FANF totals are explicitly supplied to isolate receipts. + +# Manual p74 literal published annual maximum; the separate reconciliation documents inferred rounding. +- name: "Case 1, published annual ceiling for 1 qualified household member." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 48_713 + spm_units: + spm_unit1: + members: ["person1"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1"] + state_code: "NH" + output: + nh_fap_household_size: 1 + nh_fap_income_limit: 48_713 + +# Manual p74 literal published annual maximum; the separate reconciliation documents inferred rounding. +- name: "Case 2, published annual ceiling for 2 qualified household members." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 63_702 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2"] + state_code: "NH" + output: + nh_fap_household_size: 2 + nh_fap_income_limit: 63_702 + +# Manual p74 literal published annual maximum; the separate reconciliation documents inferred rounding. +- name: "Case 3, published annual ceiling for 3 qualified household members." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 78_691 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3"] + state_code: "NH" + output: + nh_fap_household_size: 3 + nh_fap_income_limit: 78_691 + +# Manual p74 literal published annual maximum; the separate reconciliation documents inferred rounding. +- name: "Case 4, published annual ceiling for 4 qualified household members." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 93_680 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4"] + state_code: "NH" + output: + nh_fap_household_size: 4 + nh_fap_income_limit: 93_680 + +# Manual p74 literal published annual maximum; the separate reconciliation documents inferred rounding. +- name: "Case 5, published annual ceiling for 5 qualified household members." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 108_668 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4", "person5"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4", "person5"] + state_code: "NH" + output: + nh_fap_household_size: 5 + nh_fap_income_limit: 108_668 + +# Manual p74 literal published annual maximum; the separate reconciliation documents inferred rounding. +- name: "Case 6, published annual ceiling for 6 qualified household members." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 123_657 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person6: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4", "person5", "person6"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4", "person5", "person6"] + state_code: "NH" + output: + nh_fap_household_size: 6 + nh_fap_income_limit: 123_657 + +# Manual p74 literal published annual maximum; the separate reconciliation documents inferred rounding. +- name: "Case 7, published annual ceiling for 7 qualified household members." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 126_468 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person6: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person7: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4", "person5", "person6", "person7"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4", "person5", "person6", "person7"] + state_code: "NH" + output: + nh_fap_household_size: 7 + nh_fap_income_limit: 126_468 + +# Manual p74 literal published annual maximum; the separate reconciliation documents inferred rounding. +- name: "Case 8, published annual ceiling for 8 qualified household members." + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 129_278 + person2: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person3: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person4: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person5: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person6: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person7: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + person8: + age: 40 + immigration_status: "CITIZEN" + ssi: 0 + employment_income: 0 + spm_units: + spm_unit1: + members: ["person1", "person2", "person3", "person4", "person5", "person6", "person7", "person8"] + nh_fanf: 0 + heating_type: "FUEL_OIL" + heat_expense_included_in_rent: false + receives_housing_assistance: false + fuel_oil_expense: 4_000 + households: + household1: + members: ["person1", "person2", "person3", "person4", "person5", "person6", "person7", "person8"] + state_code: "NH" + output: + nh_fap_household_size: 8 + nh_fap_income_limit: 129_278 diff --git a/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap.py b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap.py new file mode 100644 index 00000000000..2984eb3b25f --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap.py @@ -0,0 +1,78 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class nh_fap(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "New Hampshire Fuel Assistance Program benefit" + documentation = ( + "Regular heating award from the PY2027 schedule, using the larger of the " + "actual heating cost and the heating-cost estimate, with bedrooms (at " + "least one room for a dwelling) standing in for the room count. " + "Unsubsidized heat included in rent receives the ordinary schedule with " + "no further reduction. The PY2025 manual printed separate heat-in-rent " + "matrices (page 74), but the PY26 benefit matrix and the PY2027 schedule " + "(page 78) print none. On page 9, the FFY2027 draft state plan replaces " + "the FY2026 plan's 'eligible for a reduced benefit' with 'eligible for a " + "benefit', although its item 2.3 still describes reduced heat-in-rent " + "benefits. Verified against the PY2027 schedule; earlier results are " + "unverified historical estimates. Zero can mean an unsupported heating " + "cost or fuel classification rather than legal ineligibility." + ) + reference = ( + # PDF pages 10,17-21,57,74,76-78. + "https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=10", + # PDF pages 8-9: item 2.3 and the heat-in-rent benefit statement. + "https://liheapch.acf.gov/docs/2026/state-plans/NH_Plan_2026.pdf#page=8", + # PY2025 manual, Wayback Machine capture: heat-in-rent matrices. + "https://web.archive.org/web/20250523173906/https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=74", + "https://liheapch.acf.gov/docs/2026/benefits-matricies/NH_BenefitMatrix_2026.pdf#page=1", + # FFY2027 draft plan, PDF pages 8-9. + "https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/low-income-home-energy-assistance-detailed-model-plan.pdf#page=8", + ) + defined_for = "nh_fap_eligible" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nh.doe.fap + size = spm_unit("nh_fap_household_size", period) + state_group = spm_unit.household("state_group_str", period) + # Use the guideline at the start of the modeled heating season. + # Within-season February guideline changes are not separately modeled. + poverty_guideline = fpg( + size, state_group, period, parameters, year_lag=p.fpg_year_lag + ) + income = spm_unit("nh_fap_countable_income", period) + bounds = p.payment.income_band_upper_bound + income_band = select( + [ + income <= poverty_guideline * bounds.A, + income <= poverty_guideline * bounds.B, + income <= poverty_guideline * bounds.C, + income <= poverty_guideline * bounds.D, + income <= poverty_guideline * bounds.E, + ], + ["A", "B", "C", "D", "E"], + default="F", + ) + expense = spm_unit("nh_fap_heating_cost", period) + thresholds = p.payment.heating_cost_threshold + cost_band = select( + [expense < thresholds.CC, expense < thresholds.BB, expense < thresholds.AA], + ["DD", "CC", "BB"], + default="AA", + ) + delivered_benefit = p.payment.delivered_benefit[cost_band][income_band] + heating_type = spm_unit("heating_type", period) + multiplier = p.payment.benefit_multiplier[heating_type] + # Half-up whole dollars reproduce every utility matrix cell. + benefit = np.floor(delivered_benefit * multiplier + 0.5) + # Unsubsidized heat in rent receives this scheduled amount, with the + # fuel multiplier applied once, because the PY2027 schedule prints no + # heat-in-rent reduction (see the documentation). + # Unspecified and other fuels have no page 77 row; their zero + # multiplier marks an unsupported amount. + # The schedule is not capped at the household's actual heating cost. + return where(expense > 0, benefit, 0) diff --git a/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_countable_income.py b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_countable_income.py new file mode 100644 index 00000000000..7abe3728406 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_countable_income.py @@ -0,0 +1,78 @@ +from policyengine_us.model_api import * + + +class nh_fap_countable_income(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "New Hampshire FAP countable income" + reference = ( + # PDF pages 13-17,23,25-29,34-36. + "https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=13", + # Plan item 1.9: Social Security "Excluding MediCare deduction"; + # General Assistance benefits unchecked. + "https://liheapch.acf.gov/docs/2026/state-plans/NH_Plan_2026.pdf#page=6", + ) + defined_for = StateCode.NH + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nh.doe.fap.income + person = spm_unit.members + # Annual inputs approximate application-period income annualization. + # Separate business losses cannot offset positive sources. Existing + # net inputs lack depreciation, amortization and home-business addbacks; + # partnership/S-corporation inputs also lack FAP expense detail. + business_income = 0 + for source in p.business_sources: + business_income = business_income + max_(person(source, period), 0) + # Military basic pay is part of employment_income, the convention under + # which Virginia and Indiana subtract military_basic_pay from AGI, so it + # is not added again. + earned_income = max_(person("employment_income", period), 0) + business_income + # Secondary school also includes equivalent training in the model; + # this conjunction approximates the full-time high-school exclusion. + high_school_student = person("is_full_time_student", period) & person( + "is_in_secondary_school", period + ) + countable_earnings = spm_unit.sum(where(high_school_student, 0, earned_income)) + unearned_person = 0 + for source in p.unearned_sources: + # add() also sums monthly sources such as nh_ssp over the year. + unearned_person = unearned_person + max_(add(person, period, [source]), 0) + unearned_income = spm_unit.sum(unearned_person) + adult_ssi = spm_unit.sum( + where( + person("age", period) >= p.ssi_min_age, + person("ssi", period), + 0, + ) + ) + # Apply one exclusion to combined interest and dividends per SPM unit; + # the parameter comment gives the source basis. + interest = max_(add(spm_unit, period, ["interest_income"]), 0) + dividends = max_(add(spm_unit, period, ["ordinary_dividend_income"]), 0) + investment_income = max_(interest + dividends - p.investment_disregard, 0) + # Count received FANF once per SPM unit, respecting TANF take-up. + income = ( + countable_earnings + + unearned_income + + adult_ssi + + investment_income + + spm_unit("tanf", period) + ) + # Support-paid regularity and mileage reimbursements are not observed. + support_paid = add(spm_unit, period, ["child_support_expense"]) + # Page 17 deducts "Medicare deductions from Social Security or Railroad + # Retirement benefits (Part B and Part D)". Each member's out-of-pocket + # Part B premium (zero when not enrolled or when a Medicare Savings + # Program pays it) is deducted up to the Social Security and railroad + # retirement benefits it is withheld from. No Part D premium variable + # exists, so Part D is not deducted. + withholding_benefits = max_(person("social_security", period), 0) + max_( + person("railroad_benefits", period), 0 + ) + medicare_deduction = spm_unit.sum( + min_(person("medicare_part_b_premium", period), withholding_benefits) + ) + return max_(income - support_paid - medicare_deduction, 0) diff --git a/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_dwelling_type.py b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_dwelling_type.py new file mode 100644 index 00000000000..002e76b77c8 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_dwelling_type.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class NHFAPDwellingType(Enum): + MOBILE_HOME = "Mobile home" + APARTMENT_CONDO_OR_DUPLEX = "Apartment, condominium or duplex" + SINGLE_FAMILY_OR_MODULAR = "Single family or modular home" + + +class nh_fap_dwelling_type(Variable): + value_type = Enum + possible_values = NHFAPDwellingType + default_value = NHFAPDwellingType.SINGLE_FAMILY_OR_MODULAR + entity = SPMUnit + definition_period = YEAR + label = "New Hampshire FAP dwelling type" + reference = "https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=77" + # The single-family/modular default is a modeling assumption. Private + # rented rooms require room-use details absent from the bedroom proxy. diff --git a/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_eligible.py b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_eligible.py new file mode 100644 index 00000000000..83454f4a868 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_eligible.py @@ -0,0 +1,45 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.tax_unit_fpg import fpg + + +class nh_fap_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Eligible for New Hampshire FAP" + reference = ( + # PDF pages 10-12,17-18,21,34-36,57,74,76-77. + "https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=10", + "https://www.law.cornell.edu/uscode/text/42/8624#b_2_B", + ) + defined_for = StateCode.NH + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nh.doe.fap + size = spm_unit("nh_fap_household_size", period) + income = spm_unit("nh_fap_countable_income", period) + limit = spm_unit("nh_fap_income_limit", period) + state_group = spm_unit.household("state_group_str", period) + guideline = fpg(size, state_group, period, parameters, year_lag=p.fpg_year_lag) + floor_rate = parameters(period).gov.hhs.liheap.fpg_floor + # Federal law protects income strictly below this floor when SMI is lower. + federal_floor = np.round(guideline * floor_rate, 2) + income_eligible = (income <= limit) | (income < federal_floor) + 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) + heating_cost = spm_unit("nh_fap_heating_cost", period) + heating_type = spm_unit("heating_type", period) + fuel = heating_type.possible_values + # Subsidized heat-in-rent is excluded. Nonsubsidized heat-in-rent can + # qualify without a separately reported heating bill. + housing_eligible = ~(heat_in_rent & subsidized) + heating_eligible = (heating_cost > 0) | heat_in_rent + return ( + (size > 0) + & income_eligible + & housing_eligible + & heating_eligible + & (heating_type != fuel.NONE) + ) diff --git a/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_heating_cost.py b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_heating_cost.py new file mode 100644 index 00000000000..60a91f7ad67 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_heating_cost.py @@ -0,0 +1,60 @@ +from policyengine_us.model_api import * + + +class nh_fap_heating_cost(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "New Hampshire FAP annual heating cost using actual or estimated cost" + # PDF pages 17-18,76-77. + reference = "https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=17" + defined_for = StateCode.NH + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nh.doe.fap.heating_cost + bedrooms = spm_unit.household("bedrooms", period) + # No room-count input exists, so bedrooms stand in for the room count. + # Page 17 counts every room except hallways, unfinished basements, + # garages, attics and closets, and the application form also counts + # kitchen/dining and living/family rooms, so bedrooms understate rooms. + # A dwelling has at least one room, so a studio or an unreported + # bedroom count gets the one-room estimate. A homeless household has + # no dwelling to heat and keeps its reported count. + has_dwelling = ~spm_unit.household("is_homeless", period) + rooms = max_(bedrooms, where(has_dwelling, 1, 0)) + # Whole-household bedrooms approximate the SPM unit's dwelling; + # private, shared and business-only room adjustments are unobserved. + dwelling = spm_unit("nh_fap_dwelling_type", period) + county = spm_unit.household("county_str", period) + # Preserve the existing county input's geographic fallback. Explicit + # unknown/non-NH counties cannot establish an estimated heating cost. + county_key = where( + np.isin(county, list(p.heating_degree_days._children)), + county, + "UNAVAILABLE", + ) + fuel = spm_unit("heating_type", period).decode_to_str() + fuel_key = where( + np.isin(fuel, list(p.fuel_cost_per_mbtu._children)), + fuel, + "UNAVAILABLE", + ) + # WOOD approximates cordwood; pellets and bio-bricks cannot be + # distinguished with the existing heating type input. Winter blend, a + # heating-oil blend, is entered as FUEL_OIL or KEROSENE, so its own + # page 77 cost per MBTU is not used. An unsupported county or fuel + # gives no estimate, whatever the room count. + # The million divisor converts the heat-load quantity to MBTU. + estimated_cost = ( + p.dwelling_factor[dwelling] + * rooms + * p.heating_degree_days[county_key] + / 1_000_000 + * p.fuel_cost_per_mbtu[fuel_key] + / p.fuel_efficiency[fuel_key] + ) + actual_cost = max_(spm_unit("heating_expense", period), 0) + # The schedule is monotonic in cost, so the higher cost yields the + # better of the actual-cost and design-heat-load determinations. + return max_(actual_cost, estimated_cost) diff --git a/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_household_size.py b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_household_size.py new file mode 100644 index 00000000000..661f9d01af9 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_household_size.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class nh_fap_household_size(Variable): + value_type = int + entity = SPMUnit + definition_period = YEAR + label = "New Hampshire FAP household size" + documentation = "Number of citizens and qualified immigrants in the SPM unit. All members' otherwise countable income remains included." + # PDF pages 11-12,34-36. + reference = "https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=11" + defined_for = StateCode.NH + + # SPM composition approximates the shared residence and economic unit. + # Custody, foster-child, live-in-care-provider and finer immigration rules + # are not separately observed by the existing household/status inputs. + adds = ["is_citizen_or_legal_immigrant"] diff --git a/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_income_limit.py b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_income_limit.py new file mode 100644 index 00000000000..61fcdbc1958 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_income_limit.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * +from policyengine_us.variables.gov.hhs.hhs_smi import liheap_smi_limit + + +class nh_fap_income_limit(Variable): + value_type = float + entity = SPMUnit + definition_period = YEAR + unit = USD + label = "New Hampshire FAP income limit" + # PDF pages 17,74. + reference = "https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=17" + defined_for = StateCode.NH + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nh.doe.fap + size = spm_unit("nh_fap_household_size", period) + state = spm_unit.household("state_code_str", period) + # The HHS floor order reproduces all eight PY2027 published amounts. + # Federal size extensions are retained; NH rounding above eight is + # unverified. + limit = liheap_smi_limit(size, state, p.smi_rate, period, parameters) + # A household with no qualified member is ineligible. + return where(size > 0, limit, 0) diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index dfbda8868e1..9a78dfb50a2 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -4258,6 +4258,43 @@ candidates: prs: [] state: unreviewed note: Verify whether the still-listed ruling applies during these years despite its obsolete tax base. +- id: us-nh:fap-income-floor-vs-smi-limit + program: liheap + years: + from: 2027 + to: 2027 + type: program + note: New Hampshire Fuel Assistance Program year 2026-2027 (PY2027) + question: Can New Hampshire's 60% SMI limit exclude a large household whose income is below the federal 110% + poverty-guideline floor? + sources: + - kind: statute + citation: 42 U.S.C. 8624(b)(2)(B) + url: https://www.law.cornell.edu/uscode/text/42/8624 + - kind: plan + citation: FY2026 New Hampshire LIHEAP State Plan section 2.1, 60% SMI for all household sizes + url: https://liheapch.acf.gov/docs/2026/state-plans/NH_Plan_2026.pdf#page=8 + - kind: manual + citation: PY2027 New Hampshire Fuel Assistance Program Procedures Manual, Income Guidelines, 60% SMI printed for + sizes 1-8 + url: https://www.energy.nh.gov/sites/g/files/ehbemt551/files/inline-documents/sonh/fuel-assistance-program-procedures-manual.pdf#page=74 + readings: + statute: Income below 110% of the poverty guideline cannot by itself exclude the household. + other: The 60% SMI limit applies at every household size; with the federal SMI size adjustments it falls below + that floor starting at household size 28. + example: A 28-person household with $186,000 of countable income and a $2,000 fuel-oil heating cost exceeds the + $185,486 limit but is below the $186,252 floor and receives the $1,720 BB/C award in the PR. + pe_us: + follows: statute + code: + - policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_eligible.py + - policyengine_us/variables/gov/states/nh/doe/fap/nh_fap_income_limit.py + - policyengine_us/parameters/gov/states/nh/doe/fap/smi_rate.yaml + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10343 + state: unreviewed + note: The open PR applies the federal floor; verify the extended limits, since the manual prints 60% SMI amounts + only through eight persons. - id: us-nh:ssp-permanent-resident-forty-quarters program: ssi-state-supplement years: