From 0bc9a4e6b2555f5da7eae7cb2971daf7a649b425 Mon Sep 17 00:00:00 2001 From: Ziming Date: Sun, 28 Dec 2025 15:34:02 -0500 Subject: [PATCH 1/4] Initial commit for New Hampshire TANF implementation Starting implementation of New Hampshire TANF program. Documentation and parallel development will follow. Relates to #1480 From e74753522f557fd591ee3b1276dfc4ef869e3415 Mon Sep 17 00:00:00 2001 From: Ziming Date: Sun, 28 Dec 2025 16:16:14 -0500 Subject: [PATCH 2/4] Add New Hampshire FANF program MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Implements eligibility determination (income and resource tests) - Payment standard at 60% of Federal Poverty Guidelines - Earned income disregard (50% exclusion) - Benefit calculation as payment standard minus countable income 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- changelog_entry.yaml | 4 + .../income/earned_income_disregard_rate.yaml | 14 + .../dhhs/fanf/payment_standard/fpg_rate.yaml | 12 + .../states/nh/dhhs/fanf/resources/limit.yaml | 14 + policyengine_us/sources/working_references.md | 381 ++++++++++++++++++ .../gov/states/nh/dhhs/fanf/integration.yaml | 205 ++++++++++ .../gov/states/nh/dhhs/fanf/nh_fanf.yaml | 166 ++++++++ .../fanf/nh_fanf_countable_earned_income.yaml | 84 ++++ .../dhhs/fanf/nh_fanf_countable_income.yaml | 112 +++++ .../states/nh/dhhs/fanf/nh_fanf_eligible.yaml | 175 ++++++++ .../nh/dhhs/fanf/nh_fanf_income_eligible.yaml | 128 ++++++ .../dhhs/fanf/nh_fanf_payment_standard.yaml | 173 ++++++++ .../dhhs/fanf/nh_fanf_resources_eligible.yaml | 99 +++++ .../gov/states/nh/dhhs/fanf/nh_fanf.py | 19 + .../fanf/nh_fanf_countable_earned_income.py | 22 + .../nh/dhhs/fanf/nh_fanf_countable_income.py | 19 + .../states/nh/dhhs/fanf/nh_fanf_eligible.py | 29 ++ .../nh/dhhs/fanf/nh_fanf_income_eligible.py | 18 + .../nh/dhhs/fanf/nh_fanf_payment_standard.py | 16 + .../dhhs/fanf/nh_fanf_resources_eligible.py | 19 + 20 files changed, 1709 insertions(+) create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/fanf/payment_standard/fpg_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/limit.yaml create mode 100644 policyengine_us/sources/working_references.md create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/integration.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.yaml create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_eligible.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.py diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..7ed32c6dfca 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: minor + changes: + added: + - Add New Hampshire FANF (Financial Assistance to Needy Families) program with eligibility determination, payment standard (60% FPG), earned income disregards, and benefit calculation. diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard_rate.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard_rate.yaml new file mode 100644 index 00000000000..4d5aebeddb3 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard_rate.yaml @@ -0,0 +1,14 @@ +description: New Hampshire excludes this share of earnings from countable income under the Financial Assistance to Needy Families program. + +values: + 1997-02-01: 0.5 + +metadata: + unit: /1 + period: month + label: New Hampshire FANF earned income disregard rate + reference: + - title: SR 97-03 Dated 02/97 - TANF Implementation + href: https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm + - title: FAM 603 - Deductions and Disregards + href: https://www.dhhs.nh.gov/fam_htm/ diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/payment_standard/fpg_rate.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/payment_standard/fpg_rate.yaml new file mode 100644 index 00000000000..14cbf979aee --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/payment_standard/fpg_rate.yaml @@ -0,0 +1,12 @@ +description: New Hampshire uses this multiplier of the federal poverty guideline for the payment standard under the Financial Assistance to Needy Families program. + +values: + 2017-07-01: 0.6 + +metadata: + unit: /1 + period: month + label: New Hampshire FANF payment standard FPG rate + reference: + - title: RSA 167:77-g - Adjustment of TANF Financial Assistance + href: https://gc.nh.gov/rsa/html/xii/167/167-77-g.htm diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/limit.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/limit.yaml new file mode 100644 index 00000000000..b3f7ce383b9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/limit.yaml @@ -0,0 +1,14 @@ +description: New Hampshire limits resources to this amount under the Financial Assistance to Needy Families program. + +values: + 1997-02-01: 1_000 + +metadata: + unit: currency-USD + period: month + label: New Hampshire FANF resource limit + reference: + - title: FAM 403 - Resource Limits + href: https://www.dhhs.nh.gov/fam_htm/ + - title: SR 97-03 Dated 02/97 - TANF Implementation + href: https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm diff --git a/policyengine_us/sources/working_references.md b/policyengine_us/sources/working_references.md new file mode 100644 index 00000000000..8f6c70e93d2 --- /dev/null +++ b/policyengine_us/sources/working_references.md @@ -0,0 +1,381 @@ +# Collected Documentation + +## New Hampshire TANF (FANF) Implementation +**Collected**: 2025-12-28 +**Implementation Task**: Implement New Hampshire Financial Assistance to Needy Families (FANF) program + +--- + +## Official Program Name + +**Federal Program**: Temporary Assistance for Needy Families (TANF) +**State's Official Name**: Financial Assistance to Needy Families (FANF) +**Abbreviation**: FANF +**Source**: RSA 167:77 et seq.; He-W 601.04 + +**Variable Prefix**: `nh_fanf` (e.g., `nh_fanf_eligible`, `nh_fanf_countable_income`) + +**Sub-Programs Under FANF**: +- New Hampshire Employment Program (NHEP) - Work participation required +- Family Assistance Program (FAP) - No work requirements +- Interim Disabled Parent (IDP) - For families with disabled parents +- Families With Older Children (FWOC) - For 19-year-olds in high school + +All sub-programs have the same cash eligibility requirements and benefit limits. + +--- + +## Regulatory Authority + +### New Hampshire Revised Statutes (RSA) +- **RSA Chapter 167**: Public Assistance to Blind, Aged, or Disabled Persons, and to Dependent Children +- **RSA 167:77**: Statement of Purpose - NH Employment Program and Family Assistance Program +- **RSA 167:77-g**: Adjustment of TANF Financial Assistance (60% FPG provision) +- **RSA 167:79**: Employment Program; Eligibility + +**Source URLs**: +- https://gc.nh.gov/rsa/html/xii/167/167-77.htm +- https://gc.nh.gov/rsa/html/xii/167/167-77-g.htm +- https://gc.nh.gov/rsa/html/xii/167/167-79.htm + +### New Hampshire Administrative Rules +- **He-W 600**: Financial Assistance and Eligibility for Medical Care +- **He-W 601**: Definitions +- **He-W 606**: General Verification Requirements + +**Source URL**: https://gc.nh.gov/rules/state_agencies/he-w600.html + +### Family Assistance Manual (FAM) +- **FAM 203**: TANF (Temporary Assistance for Needy Families) +- **FAM 403**: Resource Limits +- **FAM 601**: Standards and Budget Tables +- **FAM 603**: Deductions and Disregards + +**Source URL**: https://www.dhhs.nh.gov/fam_htm/ + +--- + +## Demographic Eligibility + +### Age Requirements +- **Minor child age limit**: Under 18 years old +- **Full-time student age limit**: Under 19 years old (if enrolled full-time in high school or equivalency program) +- **FWOC program**: Age 19 up to 20 for full-time high school students + +**Source**: RSA 167:79(I); NH DHHS TANF website + +**Implementation approach**: +- [x] Use federal demographic eligibility (age 18/19 matches federal definition) + +### Deprivation Requirement +The dependent child must be deprived of parental support or care by reason of: +- Death of a parent +- Continued absence from the home +- Physical or mental incapacity of a parent +- Unemployment or underemployment of a parent + +**Source**: RSA 167:79(I) + +### Household Composition +The following must be included in the assistance group (if living in household or temporarily absent): +- Any dependent child +- All minor blood-related or step-relatives +- Parent or caretaker relative + +**Source**: RSA 167:79(II) + +--- + +## Immigration Eligibility + +### Citizenship Requirements +- Must be a United States citizen, OR +- Must meet the citizenship requirements established in PRWORA (Personal Responsibility and Work Opportunity Reconciliation Act), as amended + +**Source**: RSA 167:79(IV)(c) + +**Implementation approach**: +- [x] Use federal immigration eligibility (state follows federal PRWORA rules) + +--- + +## Income Eligibility Tests + +### Single Income Test +NH FANF uses a single income test comparing net countable income to the payment standard (60% FPG). + +**Formula**: Net Countable Income <= Payment Standard (60% FPG) + +**Source**: RSA 167:77-g; FAM 601 Table B + +### Payment Standard / Income Limit (60% FPG) +Per RSA 167:77-g, effective July 1, 2017: +> "The maximum monthly cash benefit under this subdivision shall be equal to 60 percent of the federal poverty guidelines, based upon the applicable household size and composition, as determined annually by the United States Department of Health and Human Services." + +**Implementation approach**: Store as rate (0.60), not dollar amounts. The payment standard = 60% of monthly FPG for household size. + +**2024 Payment Standards (60% FPG - Monthly)**: + +| Household Size | 60% FPG (Monthly) | +|----------------|-------------------| +| 1 | $753 | +| 2 | $1,022 | +| 3 | $1,291 | +| 4 | $1,560 | +| 5 | $1,829 | +| 6 | $2,098 | +| 7 | $2,367 | +| 8 | $2,636 | +| Each additional | +$269 | + +**Note**: These amounts update annually based on FPG published in the Federal Register. + +**Parameter**: Store as `fpg_rate: 0.60` and calculate from federal poverty guidelines. + +**Source**: +- RSA 167:77-g +- SR 24-07 Dated 03/24 +- https://law.justia.com/codes/new-hampshire/2022/title-xii/title-167/section-167-77-g/ + +--- + +## Income Deductions & Exemptions + +### For Applicants: 20% Employment Expense Disregard +A 20% disregard of gross earned income is applied as an employment expense disregard. + +**Formula**: Countable Earned Income = Gross Earned Income * (1 - 0.20) + +**Level**: Per PERSON (applies to each employed individual) + +**Source**: SR 97-03 Dated 02/97; FAM 603 + +### For Recipients: 50% Earned Income Disregard +Financial assistance recipients receive a continuing 50% earned income disregard (replaces the old $30 and 1/3 rule). + +**Formula**: Countable Earned Income = Gross Earned Income * (1 - 0.50) + +**Level**: Per PERSON (applies to each employed individual) + +**Who qualifies**: +- Current financial assistance recipients +- Applicants who have received TANF financial assistance in at least one of the last six months + +**Source**: SR 97-03 Dated 02/97; FAM 603 + +### WARNING: Time-Limited Disregard (Partially Simulatable) +The 50% earned income disregard for recipients vs 20% for applicants represents a time-based distinction that PolicyEngine cannot fully track. + +**Implementation Note**: Since PolicyEngine cannot track whether someone is a new applicant vs continuing recipient, we should implement the **50% disregard** as the standard (more favorable to recipients) and document the limitation. + +### Child Support Treatment +**CRITICAL**: The $50 child support disregard has been ELIMINATED. + +The full amount of direct child support is counted as unearned income in determining eligibility and benefit amounts. New Hampshire does not allow any child support funds to pass through to FANF recipients. + +**Source**: SR 97-03 Dated 02/97 + +### SSI Exclusion +SSI (Supplemental Security Income) is NOT counted as income for FANF eligibility purposes. + +**Source**: NH DHHS policy + +--- + +## Unearned Income +Unearned income is generally counted in full (no disregard) with the following exception: +- SSI is excluded entirely + +**Source**: FAM 603; SR 97-03 + +--- + +## Benefit Calculation + +### Formula +``` +Benefit = Payment Standard - Net Countable Income +``` + +Where: +- **Payment Standard** = 60% of FPG for household size (monthly) +- **Net Countable Income** = Countable Earned Income + Countable Unearned Income + +### Calculation Steps +1. Calculate gross earned income +2. Apply earned income disregard (50% for recipients, 20% for applicants) +3. Result = Countable Earned Income +4. Add Countable Unearned Income (full amount, excluding SSI) +5. Result = Net Countable Income +6. Get Payment Standard for household size (60% FPG) +7. If Net Countable Income <= Payment Standard: Eligible +8. Benefit = Payment Standard - Net Countable Income + +**Source**: SR 97-03 Dated 02/97; FAM 603 + +### Payment Method +FANF cash assistance is issued twice per month via: +- Electronic Funds Transfer (EFT) - direct deposit +- Electronic Benefit Transfer (EBT) - debit-style card + +--- + +## Resource / Asset Limits + +### Resource Limit +**Amount**: $1,000 countable resources + +**Source**: FAM 403; CLASP reports confirm NH has $1,000 TANF asset limit + +### Vehicle Exclusion +**Rule**: One vehicle per adult assistance group member is excluded, regardless of value or ownership. + +If the assistance group has more than one vehicle per adult member, they choose which vehicle(s) to exclude. + +**Source**: SR 97-03 Dated 02/97; SR 01-12 Dated 07/01 + +### Other Resource Exclusions +- Home (primary residence) +- Household furniture +- Life insurance equity value (excluded) + +**Source**: SR 97-03 Dated 02/97 + +--- + +## Non-Simulatable Rules (Architecture Limitation) + +### 60-Month Lifetime Limit +**Rule**: FANF recipients can receive cash assistance for a maximum of 60 months (consecutive or nonconsecutive). + +**CANNOT ENFORCE** - requires tracking benefit history across multiple periods. PolicyEngine uses single-period simulation. + +**Exception**: FAP cases (Family Assistance Program) are exempt from this lifetime limit. + +**Source**: RSA 167:82; NH DHHS TANF website + +### Work Requirements (NHEP) +**Rule**: NHEP participants must work, seek employment, or attend job readiness programs. + +**CANNOT TRACK** - requires tracking work participation over time. + +**Source**: RSA 167:82 + +### Applicant vs Recipient Status +**Rule**: Different earned income disregard rates apply: +- 20% for applicants +- 50% for recipients (or those who received TANF in past 6 months) + +**PARTIALLY SIMULATABLE** - Cannot track prior receipt. Implementation uses 50% disregard (recipient rate) as default. + +--- + +## Implementation Approach Summary + +### Use Federal Baseline Variables For: +- [x] Demographic eligibility (age 18/19 matches federal) +- [x] Immigration eligibility (follows federal PRWORA rules) +- [x] Gross earned income sources +- [x] Gross unearned income sources + +### Create State-Specific Variables For: +- [ ] `nh_fanf_countable_earned_income` - Apply 50% disregard +- [ ] `nh_fanf_countable_income` - Earned + Unearned (excluding SSI) +- [ ] `nh_fanf_payment_standard` - 60% FPG by household size +- [ ] `nh_fanf_income_eligible` - Compare income to payment standard +- [ ] `nh_fanf_resources_eligible` - $1,000 resource limit +- [ ] `nh_fanf_eligible` - Combine all eligibility tests +- [ ] `nh_fanf` - Final benefit calculation + +### Parameters Needed: +- `income/earned_income_disregard_rate` - 0.50 (50%) +- `payment_standard/fpg_rate` - 0.60 (60% of FPG) +- `resources/limit` - $1,000 + +--- + +## PDFs for Future Reference + +The following PDFs contain additional information but could not be extracted: + +1. **New Hampshire's Cash Assistance (TANF) policy - NCCP** + - URL: https://www.nccp.org/wp-content/uploads/2024/11/TANF-profile-New-Hampshire.pdf + - Expected content: Detailed TANF policy profile including income disregards, benefit amounts + +2. **Bureau of Family Assistance Fact Sheet** + - URL: https://www.dhhs.nh.gov/sites/g/files/ehbemt476/files/documents2/bfa-progam-fact-sheet.pdf + - Expected content: Current eligibility requirements, income limits, resource limits by program + +3. **BFA Program Net Monthly Income Limits** + - URL: https://www.dhhs.nh.gov/sites/g/files/ehbemt476/files/documents2/bfa-program-net-monthly-income-limits.pdf + - Expected content: Current income limit tables by household size for all BFA programs + +4. **New Hampshire TANF State Plan** + - URL: https://www.dhhs.nh.gov/sites/g/files/ehbemt476/files/documents2/tanf-state-plan.pdf + - Expected content: Official state plan submitted to ACF with program details + +5. **ACF Welfare Rules Databook (July 2023)** + - URL: https://acf.gov/sites/default/files/documents/opre/opre-graphical-overview-tanf-policies-dec2024.pdf + - Expected content: Comprehensive state-by-state TANF policy comparison + +6. **NH Bureau of Family Assistance Fact Sheet (2022)** + - URL: https://nhfv.org/wp-content/uploads/2022/06/fam-asst-fact-sheet-3-22.pdf + - Expected content: Older fact sheet with eligibility and benefit information + +--- + +## Key Online References + +### Official NH DHHS Sources +- NH DHHS TANF Main Page: https://www.dhhs.nh.gov/temporary-assistance-needy-families-tanf +- FAM Manual: https://www.dhhs.nh.gov/fam_htm/ +- Administrative Rules He-W 600: https://gc.nh.gov/rules/state_agencies/he-w600.html + +### Legal Sources +- RSA Chapter 167: https://www.gencourt.state.nh.us/rsa/html/nhtoc/nhtoc-xii-167.htm +- RSA 167:77-g (60% FPG): https://law.justia.com/codes/new-hampshire/2022/title-xii/title-167/section-167-77-g/ + +### Policy Updates (SR Documents) +- SR 25-09 (March 2025 updates): https://www.dhhs.nh.gov/sr_htm/html/sr_25-09_dated_03_25.htm +- SR 24-07 (March 2024 updates): https://www.dhhs.nh.gov/sr_htm/html/sr_24-07_dated_03_24.htm +- SR 97-03 (Original TANF implementation): https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm + +### Third-Party Analysis +- NH Fiscal Policy Institute analysis: https://nhfpi.org/blog/under-enrollment-in-key-aid-program-and-increased-available-funds-provide-opportunities-for-enhanced-outreach-and-assistance/ + +--- + +## References for Metadata + +### For Parameters: +```yaml +reference: + - title: RSA 167:77-g - Adjustment of TANF Financial Assistance + href: https://gc.nh.gov/rsa/html/xii/167/167-77-g.htm + - title: SR 24-07 Dated 03/24 - FPG Updates + href: https://www.dhhs.nh.gov/sr_htm/html/sr_24-07_dated_03_24.htm +``` + +### For Variables: +```python +reference = "https://gc.nh.gov/rsa/html/xii/167/167-77-g.htm" +# Or for multiple: +reference = ( + "https://gc.nh.gov/rsa/html/xii/167/167-77-g.htm", + "https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm", +) +``` + +--- + +## Validation Checklist + +- [x] URLs load and show actual values +- [x] Legal code references included (RSA 167:77-g, RSA 167:79) +- [x] Values match sources exactly +- [x] Effective dates documented (60% FPG effective July 1, 2017) +- [x] Identified all eligibility tests +- [x] Documented BOTH earned AND unearned income treatment +- [x] Flagged non-simulatable rules (60-month limit, work requirements) +- [x] Documented deduction levels (per PERSON) +- [x] Confirmed no child support disregard/passthrough diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/integration.yaml new file mode 100644 index 00000000000..724fe3e9467 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/integration.yaml @@ -0,0 +1,205 @@ +# Integration tests for NH FANF (Financial Assistance to Needy Families) +# Tests the complete benefit calculation pipeline with real-world scenarios +# Sources: RSA 167:77-g; FAM 601; FAM 603; SR 97-03 + +- name: Case 1, single parent with one child, no income, maximum benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 500 + households: + household: + members: [person1, person2] + state_code: NH + output: + # Payment Standard: FPG for 2 = 20,440, 60% = 12,264/12 = 1,022 + nh_fanf_payment_standard: 1_022 + nh_fanf_countable_income: 0 + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + nh_fanf_eligible: true + nh_fanf: 1_022 + +- name: Case 2, single parent with earnings, 50 percent disregard applied. + period: 2024-01 + input: + people: + person1: + age: 28 + # Annual employment income of $12,000 = $1,000/month + employment_income_before_lsr: 12_000 + person2: + age: 7 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 200 + households: + household: + members: [person1, person2] + state_code: NH + output: + # Payment Standard for 2 = 1,022 + nh_fanf_payment_standard: 1_022 + # person1 earned: 1,000/month * 0.50 = 500; person2 = 0 + nh_fanf_countable_earned_income: [500, 0] + nh_fanf_countable_income: 500 + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + nh_fanf_eligible: true + nh_fanf: 522 + +- name: Case 3, family of three with moderate income. + period: 2024-01 + input: + people: + person1: + age: 32 + # Annual employment income of $18,000 = $1,500/month + employment_income_before_lsr: 18_000 + person2: + age: 10 + person3: + age: 6 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 800 + households: + household: + members: [person1, person2, person3] + state_code: NH + output: + # Payment Standard for 3: FPG 25,820 * 0.60 / 12 = 1,291 + nh_fanf_payment_standard: 1_291 + # person1 earned: 1,500/month * 0.50 = 750; person2/3 = 0 + nh_fanf_countable_earned_income: [750, 0, 0] + nh_fanf_countable_income: 750 + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + nh_fanf_eligible: true + nh_fanf: 541 + +- name: Case 4, income above threshold, ineligible. + period: 2024-01 + input: + people: + person1: + age: 35 + # Annual employment income of $36,000 = $3,000/month + employment_income_before_lsr: 36_000 + person2: + age: 8 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 0 + households: + household: + members: [person1, person2] + state_code: NH + output: + nh_fanf_payment_standard: 1_022 + # person1 earned: 3,000/month * 0.50 = 1,500; person2 = 0 + nh_fanf_countable_earned_income: [1_500, 0] + nh_fanf_countable_income: 1_500 + nh_fanf_income_eligible: false + nh_fanf_resources_eligible: true + nh_fanf_eligible: false + nh_fanf: 0 + +- name: Case 5, SSI recipient excluded from income. + period: 2024-01 + input: + people: + person1: + age: 40 + # SSI is YEAR-defined, annual amount + ssi: 10_000 + employment_income_before_lsr: 0 + person2: + age: 12 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 300 + households: + household: + members: [person1, person2] + state_code: NH + output: + nh_fanf_payment_standard: 1_022 + # SSI excluded; no other income + nh_fanf_countable_earned_income: [0, 0] + nh_fanf_countable_income: 0 + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + nh_fanf_eligible: true + nh_fanf: 1_022 + +- name: Case 6, resources over limit, ineligible. + period: 2024-01 + input: + people: + person1: + age: 29 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 2_000 + households: + household: + members: [person1, person2] + state_code: NH + output: + nh_fanf_payment_standard: 1_022 + nh_fanf_countable_income: 0 + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: false + nh_fanf_eligible: false + nh_fanf: 0 + +- name: Case 7, family of four with both earned and unearned income. + period: 2024-01 + input: + people: + person1: + age: 38 + # Annual employment income of $9,600 = $800/month + employment_income_before_lsr: 9_600 + # Annual social security = $2,400 = $200/month + social_security: 2_400 + person2: + age: 36 + person3: + age: 14 + person4: + age: 10 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + spm_unit_assets: 900 + households: + household: + members: [person1, person2, person3, person4] + state_code: NH + output: + # Payment Standard for 4: FPG 31,200 * 0.60 / 12 = 1,560 + nh_fanf_payment_standard: 1_560 + # person1 earned: 800/month * 0.50 = 400; others = 0 + nh_fanf_countable_earned_income: [400, 0, 0, 0] + # 400 earned + 200 unearned = 600 + nh_fanf_countable_income: 600 + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + nh_fanf_eligible: true + nh_fanf: 960 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf.yaml new file mode 100644 index 00000000000..9d0b59cf165 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf.yaml @@ -0,0 +1,166 @@ +# Tests for NH FANF benefit calculation +# Formula: Benefit = max(Payment Standard - Net Countable Income, 0) +# Benefit is 0 if not eligible (handled by defined_for) +# Source: SR 97-03 Dated 02/97; FAM 603 + +- name: Case 1, maximum benefit with zero income. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: true + nh_fanf_payment_standard: 753 + nh_fanf_countable_income: 0 + output: + # 753 - 0 = 753 + nh_fanf: 753 + +- name: Case 2, partial benefit with some income. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: true + nh_fanf_payment_standard: 1_022 + nh_fanf_countable_income: 400 + output: + # 1,022 - 400 = 622 + nh_fanf: 622 + +- name: Case 3, income at payment standard yields zero benefit. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: true + nh_fanf_payment_standard: 753 + nh_fanf_countable_income: 753 + output: + # 753 - 753 = 0 + nh_fanf: 0 + +- name: Case 4, ineligible gets zero benefit. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: false + nh_fanf_payment_standard: 753 + nh_fanf_countable_income: 0 + output: + nh_fanf: 0 + +- name: Case 5, family of four with partial benefit. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: true + nh_fanf_payment_standard: 1_560 + nh_fanf_countable_income: 800 + output: + # 1,560 - 800 = 760 + nh_fanf: 760 + +# --- Edge Case Tests --- + +- name: Edge case, income one dollar below payment standard. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: true + nh_fanf_payment_standard: 753 + # Income is $752, one dollar below threshold + nh_fanf_countable_income: 752 + output: + # 753 - 752 = 1 (minimum positive benefit) + nh_fanf: 1 + +- name: Edge case, income one cent below payment standard. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: true + nh_fanf_payment_standard: 753 + # Income is $752.99 + nh_fanf_countable_income: 752.99 + output: + # 753 - 752.99 = 0.01 + nh_fanf: 0.01 + +- name: Edge case, max function handles income exceeding payment standard. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: true + nh_fanf_payment_standard: 753 + # Income exceeds payment standard + nh_fanf_countable_income: 800 + output: + # max(753 - 800, 0) = max(-47, 0) = 0 + nh_fanf: 0 + +- name: Edge case, large household maximum benefit. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: true + # 8-person payment standard + nh_fanf_payment_standard: 2_636 + nh_fanf_countable_income: 0 + output: + # Maximum benefit for large household + nh_fanf: 2_636 + +- name: Edge case, large household partial benefit. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: true + # 8-person payment standard + nh_fanf_payment_standard: 2_636 + nh_fanf_countable_income: 1_500 + output: + # 2,636 - 1,500 = 1,136 + nh_fanf: 1_136 + +- name: Edge case, fractional income results in fractional benefit. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: true + nh_fanf_payment_standard: 1_022 + nh_fanf_countable_income: 500.50 + output: + # 1,022 - 500.50 = 521.50 + nh_fanf: 521.50 + +- name: Edge case, very small benefit amount. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: true + nh_fanf_payment_standard: 753 + nh_fanf_countable_income: 750 + output: + # 753 - 750 = 3 + nh_fanf: 3 + +- name: Edge case, income far exceeds payment standard. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: true + nh_fanf_payment_standard: 753 + # Income is 10x the payment standard + nh_fanf_countable_income: 7_530 + output: + # max(753 - 7,530, 0) = 0 + nh_fanf: 0 + +- name: Edge case, half of payment standard as income. + period: 2024-01 + input: + state_code: NH + nh_fanf_eligible: true + nh_fanf_payment_standard: 1_022 + # Income is exactly half + nh_fanf_countable_income: 511 + output: + # 1,022 - 511 = 511 + nh_fanf: 511 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.yaml new file mode 100644 index 00000000000..caadbaf1b6d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.yaml @@ -0,0 +1,84 @@ +# Tests for NH FANF countable earned income +# NH applies a 50% earned income disregard for recipients +# Formula: Countable Earned Income = Gross Earned Income * (1 - 0.50) +# Source: SR 97-03 Dated 02/97; FAM 603 + +- name: Case 1, zero earned income. + period: 2024-01 + input: + state_code: NH + tanf_gross_earned_income: 0 + output: + nh_fanf_countable_earned_income: 0 + +- name: Case 2, earned income with 50 percent disregard. + period: 2024-01 + input: + state_code: NH + # $1,000/month gross earned income + tanf_gross_earned_income: 1_000 + output: + # 1,000 * (1 - 0.50) = 500 + nh_fanf_countable_earned_income: 500 + +- name: Case 3, higher earned income. + period: 2024-01 + input: + state_code: NH + # $2,000/month gross earned income + tanf_gross_earned_income: 2_000 + output: + # 2,000 * (1 - 0.50) = 1,000 + nh_fanf_countable_earned_income: 1_000 + +- name: Case 4, low earned income. + period: 2024-01 + input: + state_code: NH + # $200/month gross earned income + tanf_gross_earned_income: 200 + output: + # 200 * (1 - 0.50) = 100 + nh_fanf_countable_earned_income: 100 + +# --- Edge Case Tests --- + +- name: Edge case, minimum positive income. + period: 2024-01 + input: + state_code: NH + # $1/month gross earned income + tanf_gross_earned_income: 1 + output: + # 1 * (1 - 0.50) = 0.50 + nh_fanf_countable_earned_income: 0.50 + +- name: Edge case, odd dollar amount with decimal result. + period: 2024-01 + input: + state_code: NH + # $3/month gross earned income + tanf_gross_earned_income: 3 + output: + # 3 * (1 - 0.50) = 1.50 + nh_fanf_countable_earned_income: 1.50 + +- name: Edge case, large earned income. + period: 2024-01 + input: + state_code: NH + # $10,000/month gross earned income + tanf_gross_earned_income: 10_000 + output: + # 10,000 * (1 - 0.50) = 5,000 + nh_fanf_countable_earned_income: 5_000 + +- name: Edge case, very small fractional amount. + period: 2024-01 + input: + state_code: NH + # $0.02/month (2 cents) + tanf_gross_earned_income: 0.02 + output: + # 0.02 * 0.50 = 0.01 + nh_fanf_countable_earned_income: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.yaml new file mode 100644 index 00000000000..6ee2a3b762e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.yaml @@ -0,0 +1,112 @@ +# Tests for NH FANF countable income +# Formula: Countable Income = Countable Earned Income + Countable Unearned Income +# SSI is excluded from unearned income (federal TANF baseline excludes SSI) +# Source: FAM 603; SR 97-03 Dated 02/97 + +- name: Case 1, zero income. + period: 2024-01 + input: + state_code: NH + nh_fanf_countable_earned_income: 0 + tanf_gross_unearned_income: 0 + output: + nh_fanf_countable_income: 0 + +- name: Case 2, earned income only. + period: 2024-01 + input: + state_code: NH + nh_fanf_countable_earned_income: 500 + tanf_gross_unearned_income: 0 + output: + nh_fanf_countable_income: 500 + +- name: Case 3, unearned income only. + period: 2024-01 + input: + state_code: NH + nh_fanf_countable_earned_income: 0 + # Unearned income counted in full + tanf_gross_unearned_income: 300 + output: + nh_fanf_countable_income: 300 + +- name: Case 4, both earned and unearned income. + period: 2024-01 + input: + state_code: NH + # After 50% disregard + nh_fanf_countable_earned_income: 400 + # Unearned income counted in full + tanf_gross_unearned_income: 200 + output: + # 400 + 200 = 600 + nh_fanf_countable_income: 600 + +- name: Case 5, SSI excluded from unearned income. + period: 2024-01 + input: + people: + person1: + age: 35 + # SSI is YEAR-defined, input as annual + ssi: 10_000 + # No other unearned income + social_security: 0 + employment_income_before_lsr: 0 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NH + output: + # SSI is excluded from TANF unearned income sources + # Therefore countable income should be 0 + nh_fanf_countable_income: 0 + +# --- Edge Case Tests --- + +- name: Edge case, minimum positive income from both sources. + period: 2024-01 + input: + state_code: NH + # $1 from each source + nh_fanf_countable_earned_income: 1 + tanf_gross_unearned_income: 1 + output: + # 1 + 1 = 2 + nh_fanf_countable_income: 2 + +- name: Edge case, large combined income. + period: 2024-01 + input: + state_code: NH + # Large earned income (after 50% disregard) + nh_fanf_countable_earned_income: 5_000 + # Large unearned income + tanf_gross_unearned_income: 3_000 + output: + # 5,000 + 3,000 = 8,000 + nh_fanf_countable_income: 8_000 + +- name: Edge case, fractional amounts. + period: 2024-01 + input: + state_code: NH + nh_fanf_countable_earned_income: 0.50 + tanf_gross_unearned_income: 0.75 + output: + # 0.50 + 0.75 = 1.25 + nh_fanf_countable_income: 1.25 + +- name: Edge case, unearned income much higher than earned. + period: 2024-01 + input: + state_code: NH + nh_fanf_countable_earned_income: 100 + tanf_gross_unearned_income: 2_000 + output: + # 100 + 2,000 = 2,100 + nh_fanf_countable_income: 2_100 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_eligible.yaml new file mode 100644 index 00000000000..e80bc73bd37 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_eligible.yaml @@ -0,0 +1,175 @@ +# Tests for NH FANF overall eligibility +# Eligibility requires: income eligible AND resources eligible AND demographic eligible +# AND immigration eligible (at least one citizen or qualified noncitizen) +# Source: RSA 167:79; FAM 203 + +- name: Case 1, all criteria met is eligible. + period: 2024-01 + input: + state_code: NH + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + is_demographic_tanf_eligible: true + output: + nh_fanf_eligible: true + +- name: Case 2, income ineligible. + period: 2024-01 + input: + state_code: NH + nh_fanf_income_eligible: false + nh_fanf_resources_eligible: true + is_demographic_tanf_eligible: true + output: + nh_fanf_eligible: false + +- name: Case 3, resources ineligible. + period: 2024-01 + input: + state_code: NH + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: false + is_demographic_tanf_eligible: true + output: + nh_fanf_eligible: false + +- name: Case 4, demographic ineligible. + period: 2024-01 + input: + state_code: NH + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + is_demographic_tanf_eligible: false + output: + nh_fanf_eligible: false + +- name: Case 5, all criteria fail. + period: 2024-01 + input: + state_code: NH + nh_fanf_income_eligible: false + nh_fanf_resources_eligible: false + is_demographic_tanf_eligible: false + output: + nh_fanf_eligible: false + +# --- Edge Case Tests --- + +- name: Edge case, citizen parent with citizen child. + period: 2024-01 + input: + people: + person1: + age: 30 + immigration_status: CITIZEN + person2: + age: 5 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + households: + household: + members: [person1, person2] + state_code: NH + output: + # Both are citizens - immigration eligible + nh_fanf_eligible: true + +- name: Edge case, legal permanent resident parent with citizen child. + period: 2024-01 + input: + people: + person1: + age: 28 + immigration_status: LEGAL_PERMANENT_RESIDENT + person2: + age: 4 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2] + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + households: + household: + members: [person1, person2] + state_code: NH + output: + # At least one is a qualified immigrant - immigration eligible + nh_fanf_eligible: true + +- name: Edge case, refugee parent with child. + period: 2024-01 + input: + people: + person1: + age: 32 + immigration_status: REFUGEE + person2: + age: 7 + immigration_status: REFUGEE + spm_units: + spm_unit: + members: [person1, person2] + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + households: + household: + members: [person1, person2] + state_code: NH + output: + # Refugees are qualified noncitizens - eligible + nh_fanf_eligible: true + +- name: Edge case, income and resources both fail. + period: 2024-01 + input: + state_code: NH + nh_fanf_income_eligible: false + nh_fanf_resources_eligible: false + is_demographic_tanf_eligible: true + output: + nh_fanf_eligible: false + +- name: Edge case, only demographic fails. + period: 2024-01 + input: + state_code: NH + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + is_demographic_tanf_eligible: false + output: + nh_fanf_eligible: false + +- name: Edge case, full household scenario with all eligible criteria. + period: 2024-01 + input: + people: + person1: + age: 35 + immigration_status: CITIZEN + person2: + age: 12 + immigration_status: CITIZEN + person3: + age: 8 + immigration_status: CITIZEN + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 500 + nh_fanf_countable_income: 500 + households: + household: + members: [person1, person2, person3] + state_code: NH + output: + # Payment standard for 3 = 1,291 + # Income 500 <= 1,291 -> income eligible + # Resources 500 <= 1,000 -> resources eligible + # Has children under 18 -> demographic eligible + # All citizens -> immigration eligible + nh_fanf_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.yaml new file mode 100644 index 00000000000..7b05e937a7b --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.yaml @@ -0,0 +1,128 @@ +# Tests for NH FANF income eligibility +# Formula: Net Countable Income <= Payment Standard (60% FPG) +# Source: RSA 167:77-g; FAM 601 Table B + +- name: Case 1, zero income is eligible. + period: 2024-01 + input: + state_code: NH + nh_fanf_countable_income: 0 + nh_fanf_payment_standard: 753 + output: + nh_fanf_income_eligible: true + +- name: Case 2, income below payment standard is eligible. + period: 2024-01 + input: + state_code: NH + nh_fanf_countable_income: 500 + nh_fanf_payment_standard: 753 + output: + nh_fanf_income_eligible: true + +- name: Case 3, income equal to payment standard is eligible. + period: 2024-01 + input: + state_code: NH + nh_fanf_countable_income: 753 + nh_fanf_payment_standard: 753 + output: + nh_fanf_income_eligible: true + +- name: Case 4, income above payment standard is ineligible. + period: 2024-01 + input: + state_code: NH + nh_fanf_countable_income: 800 + nh_fanf_payment_standard: 753 + output: + nh_fanf_income_eligible: false + +- name: Case 5, family of three below threshold. + period: 2024-01 + input: + state_code: NH + nh_fanf_countable_income: 1_000 + nh_fanf_payment_standard: 1_291 + output: + nh_fanf_income_eligible: true + +- name: Case 6, family of three above threshold. + period: 2024-01 + input: + state_code: NH + nh_fanf_countable_income: 1_500 + nh_fanf_payment_standard: 1_291 + output: + nh_fanf_income_eligible: false + +# --- Edge Case Tests --- + +- name: Edge case, income one dollar below threshold. + period: 2024-01 + input: + state_code: NH + # $752 is $1 below threshold + nh_fanf_countable_income: 752 + nh_fanf_payment_standard: 753 + output: + nh_fanf_income_eligible: true + +- name: Edge case, income one dollar above threshold. + period: 2024-01 + input: + state_code: NH + # $754 is $1 above threshold + nh_fanf_countable_income: 754 + nh_fanf_payment_standard: 753 + output: + nh_fanf_income_eligible: false + +- name: Edge case, income one cent below threshold. + period: 2024-01 + input: + state_code: NH + # $752.99 is just below $753 + nh_fanf_countable_income: 752.99 + nh_fanf_payment_standard: 753 + output: + nh_fanf_income_eligible: true + +- name: Edge case, income one cent above threshold. + period: 2024-01 + input: + state_code: NH + # $753.01 is just above $753 + nh_fanf_countable_income: 753.01 + nh_fanf_payment_standard: 753 + output: + nh_fanf_income_eligible: false + +- name: Edge case, both income and threshold at high values. + period: 2024-01 + input: + state_code: NH + # Income exactly matches high payment standard (8-person) + nh_fanf_countable_income: 2_636 + nh_fanf_payment_standard: 2_636 + output: + nh_fanf_income_eligible: true + +- name: Edge case, high income slightly above high threshold. + period: 2024-01 + input: + state_code: NH + # Income $1 above 8-person payment standard + nh_fanf_countable_income: 2_637 + nh_fanf_payment_standard: 2_636 + output: + nh_fanf_income_eligible: false + +- name: Edge case, extremely high income. + period: 2024-01 + input: + state_code: NH + nh_fanf_countable_income: 10_000 + nh_fanf_payment_standard: 753 + output: + nh_fanf_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.yaml new file mode 100644 index 00000000000..415cf95cc3d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.yaml @@ -0,0 +1,173 @@ +# Tests for NH FANF payment standard +# Per RSA 167:77-g, the payment standard equals 60% of FPG for household size +# Formula: Payment Standard = FPG * 0.60 / 12 (monthly) +# 2024 FPG: First person = $15,060, Each additional = $5,380 +# Source: RSA 167:77-g; SR 24-07 Dated 03/24 + +- name: Case 1, single person household. + period: 2024-01 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NH + output: + # 15,060 * 0.60 / 12 = 753 + nh_fanf_payment_standard: 753 + +- name: Case 2, two person household. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NH + output: + # (15,060 + 5,380) * 0.60 / 12 = 20,440 * 0.60 / 12 = 1,022 + nh_fanf_payment_standard: 1_022 + +- name: Case 3, three person household. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 8 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NH + output: + # (15,060 + 5,380*2) * 0.60 / 12 = 25,820 * 0.60 / 12 = 1,291 + nh_fanf_payment_standard: 1_291 + +- name: Case 4, four person household. + period: 2024-01 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 10 + person4: + age: 7 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: NH + output: + # (15,060 + 5,380*3) * 0.60 / 12 = 31,200 * 0.60 / 12 = 1,560 + nh_fanf_payment_standard: 1_560 + +# --- Edge Case Tests --- + +- name: Edge case, large household with eight members. + period: 2024-01 + input: + people: + person1: + age: 40 + person2: + age: 38 + person3: + age: 16 + person4: + age: 14 + person5: + age: 12 + person6: + age: 10 + person7: + age: 8 + person8: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + state_code: NH + output: + # 8-person FPG: 15,060 + 5,380*7 = 52,720 + # 60% = 31,632 annual / 12 = 2,636 + nh_fanf_payment_standard: 2_636 + +- name: Edge case, five person household. + period: 2024-01 + input: + people: + person1: + age: 35 + person2: + age: 32 + person3: + age: 12 + person4: + age: 9 + person5: + age: 6 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: NH + output: + # 5-person FPG: 15,060 + 5,380*4 = 36,580 + # 60% = 21,948 annual / 12 = 1,829 + nh_fanf_payment_standard: 1_829 + +- name: Edge case, six person household. + period: 2024-01 + input: + people: + person1: + age: 38 + person2: + age: 36 + person3: + age: 15 + person4: + age: 13 + person5: + age: 11 + person6: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6] + households: + household: + members: [person1, person2, person3, person4, person5, person6] + state_code: NH + output: + # 6-person FPG: 15,060 + 5,380*5 = 41,960 + # 60% = 25,176 annual / 12 = 2,098 + nh_fanf_payment_standard: 2_098 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.yaml new file mode 100644 index 00000000000..474088188f7 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.yaml @@ -0,0 +1,99 @@ +# Tests for NH FANF resources eligibility +# Resource limit: $1,000 countable resources +# Source: FAM 403; CLASP reports + +- name: Case 1, zero resources is eligible. + period: 2024-01 + input: + state_code: NH + spm_unit_assets: 0 + output: + nh_fanf_resources_eligible: true + +- name: Case 2, resources below limit is eligible. + period: 2024-01 + input: + state_code: NH + spm_unit_assets: 500 + output: + nh_fanf_resources_eligible: true + +- name: Case 3, resources at limit is eligible. + period: 2024-01 + input: + state_code: NH + spm_unit_assets: 1_000 + output: + nh_fanf_resources_eligible: true + +- name: Case 4, resources above limit is ineligible. + period: 2024-01 + input: + state_code: NH + spm_unit_assets: 1_001 + output: + nh_fanf_resources_eligible: false + +- name: Case 5, high resources is ineligible. + period: 2024-01 + input: + state_code: NH + spm_unit_assets: 5_000 + output: + nh_fanf_resources_eligible: false + +# --- Edge Case Tests --- + +- name: Edge case, resources one dollar below limit. + period: 2024-01 + input: + state_code: NH + # $999 is $1 below the $1,000 limit + spm_unit_assets: 999 + output: + nh_fanf_resources_eligible: true + +- name: Edge case, resources one cent below limit. + period: 2024-01 + input: + state_code: NH + # $999.99 is 1 cent below the $1,000 limit + spm_unit_assets: 999.99 + output: + nh_fanf_resources_eligible: true + +- name: Edge case, resources one cent above limit. + period: 2024-01 + input: + state_code: NH + # $1,000.01 is 1 cent above the $1,000 limit + spm_unit_assets: 1_000.01 + output: + nh_fanf_resources_eligible: false + +- name: Edge case, minimum positive resources. + period: 2024-01 + input: + state_code: NH + # $1 in resources + spm_unit_assets: 1 + output: + nh_fanf_resources_eligible: true + +- name: Edge case, very high resources. + period: 2024-01 + input: + state_code: NH + # $100,000 in resources + spm_unit_assets: 100_000 + output: + nh_fanf_resources_eligible: false + +- name: Edge case, fractional resources well below limit. + period: 2024-01 + input: + state_code: NH + # $0.50 in resources + spm_unit_assets: 0.50 + output: + nh_fanf_resources_eligible: true diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf.py new file mode 100644 index 00000000000..6bc870bfdeb --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class nh_fanf(Variable): + value_type = float + entity = SPMUnit + label = "New Hampshire Financial Assistance to Needy Families" + unit = USD + definition_period = MONTH + reference = ( + "https://gc.nh.gov/rsa/html/xii/167/167-77-g.htm", + "https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm", + ) + defined_for = "nh_fanf_eligible" + + def formula(spm_unit, period, parameters): + payment_standard = spm_unit("nh_fanf_payment_standard", period) + countable_income = spm_unit("nh_fanf_countable_income", period) + return max_(payment_standard - countable_income, 0) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.py new file mode 100644 index 00000000000..0fc08e358ae --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class nh_fanf_countable_earned_income(Variable): + value_type = float + entity = Person + label = "New Hampshire FANF countable earned income" + unit = USD + definition_period = MONTH + reference = ( + "https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm", + "https://www.dhhs.nh.gov/fam_htm/", + ) + defined_for = StateCode.NH + + def formula(person, period, parameters): + # NOTE: NH has different disregard rates for applicants (20%) vs + # recipients (50%). PolicyEngine cannot track prior benefit receipt, + # so we apply the 50% recipient rate as it is more favorable. + p = parameters(period).gov.states.nh.dhhs.fanf.income + gross_earned = person("tanf_gross_earned_income", period) + return gross_earned * (1 - p.earned_income_disregard_rate) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.py new file mode 100644 index 00000000000..6cae4f704f5 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class nh_fanf_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "New Hampshire FANF countable income" + unit = USD + definition_period = MONTH + reference = ( + "https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm", + "https://www.dhhs.nh.gov/fam_htm/", + ) + defined_for = StateCode.NH + + adds = [ + "nh_fanf_countable_earned_income", + "tanf_gross_unearned_income", + ] diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_eligible.py new file mode 100644 index 00000000000..23f82ebed19 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_eligible.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class nh_fanf_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "New Hampshire FANF eligible" + definition_period = MONTH + reference = ( + "https://gc.nh.gov/rsa/html/xii/167/167-79.htm", + "https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm", + ) + defined_for = StateCode.NH + + def formula(spm_unit, period, parameters): + demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) + immigration_eligible = ( + add(spm_unit, period, ["is_citizen_or_legal_immigrant"]) > 0 + ) + income_eligible = spm_unit("nh_fanf_income_eligible", period) + resources_eligible = spm_unit( + "nh_fanf_resources_eligible", period.this_year + ) + return ( + demographic_eligible + & immigration_eligible + & income_eligible + & resources_eligible + ) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.py new file mode 100644 index 00000000000..c839c809002 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class nh_fanf_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "New Hampshire FANF income eligible" + definition_period = MONTH + reference = ( + "https://gc.nh.gov/rsa/html/xii/167/167-77-g.htm", + "https://www.dhhs.nh.gov/fam_htm/", + ) + defined_for = StateCode.NH + + def formula(spm_unit, period, parameters): + countable_income = spm_unit("nh_fanf_countable_income", period) + payment_standard = spm_unit("nh_fanf_payment_standard", period) + return countable_income <= payment_standard diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.py new file mode 100644 index 00000000000..3ab62c20f0f --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class nh_fanf_payment_standard(Variable): + value_type = float + entity = SPMUnit + label = "New Hampshire FANF payment standard" + unit = USD + definition_period = MONTH + reference = "https://gc.nh.gov/rsa/html/xii/167/167-77-g.htm" + defined_for = StateCode.NH + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nh.dhhs.fanf.payment_standard + annual_fpg = spm_unit("spm_unit_fpg", period.this_year) + return annual_fpg * p.fpg_rate / MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.py new file mode 100644 index 00000000000..12085d52c9a --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class nh_fanf_resources_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "New Hampshire FANF resources eligible" + definition_period = YEAR + reference = ( + "https://www.dhhs.nh.gov/fam_htm/", + "https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm", + ) + defined_for = StateCode.NH + + def formula(spm_unit, period, parameters): + # NOTE: One vehicle per adult is excluded regardless of value. + p = parameters(period).gov.states.nh.dhhs.fanf.resources + resources = spm_unit("spm_unit_assets", period) + return resources <= p.limit From 96511ba2e1a562a809f17046795d3d7284f6d6d1 Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 29 Dec 2025 16:12:29 -0500 Subject: [PATCH 3/4] draft --- .../income/earned_income_disregard_rate.yaml | 4 +- .../states/nh/dhhs/fanf/resources/limit.yaml | 4 +- .../gov/states/nh/dhhs/fanf/integration.yaml | 98 +++++++++++++++++++ .../dhhs/fanf/nh_fanf_payment_standard.yaml | 30 ++++++ .../fanf/nh_fanf_countable_earned_income.py | 2 +- .../nh/dhhs/fanf/nh_fanf_countable_income.py | 2 +- .../nh/dhhs/fanf/nh_fanf_income_eligible.py | 2 +- .../dhhs/fanf/nh_fanf_resources_eligible.py | 2 +- 8 files changed, 136 insertions(+), 8 deletions(-) diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard_rate.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard_rate.yaml index 4d5aebeddb3..72cdebc7c40 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard_rate.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard_rate.yaml @@ -8,7 +8,7 @@ metadata: period: month label: New Hampshire FANF earned income disregard rate reference: + - title: FAM 603.01 - Earned Income Disregards (EID) + href: https://www.dhhs.nh.gov/famar_htm/html/603_01_earned_income_disregards_eid_sr_97-03_02_97_fam_a.htm - title: SR 97-03 Dated 02/97 - TANF Implementation href: https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm - - title: FAM 603 - Deductions and Disregards - href: https://www.dhhs.nh.gov/fam_htm/ diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/limit.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/limit.yaml index b3f7ce383b9..9629acecd71 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/limit.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/limit.yaml @@ -8,7 +8,7 @@ metadata: period: month label: New Hampshire FANF resource limit reference: - - title: FAM 403 - Resource Limits - href: https://www.dhhs.nh.gov/fam_htm/ - title: SR 97-03 Dated 02/97 - TANF Implementation href: https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm + - title: FAM 403 - Resource Limits + href: https://www.dhhs.nh.gov/fam_htm/newfam.htm diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/integration.yaml index 724fe3e9467..da0a2a2ac8f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/integration.yaml @@ -203,3 +203,101 @@ nh_fanf_resources_eligible: true nh_fanf_eligible: true nh_fanf: 960 + +- name: Case 8, SSI recipient with earnings, SSI excluded but earnings counted. + period: 2024-01 + input: + people: + person1: + age: 35 + # SSI should be excluded from income + ssi: 10_000 + # Annual employment income of $6,000 = $500/month + employment_income_before_lsr: 6_000 + person2: + age: 8 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 300 + households: + household: + members: [person1, person2] + state_code: NH + output: + nh_fanf_payment_standard: 1_022 + # person1 earned: 500/month * 0.50 = 250; person2 = 0 + # SSI excluded from unearned income + nh_fanf_countable_earned_income: [250, 0] + nh_fanf_countable_income: 250 + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + nh_fanf_eligible: true + # 1,022 - 250 = 772 + nh_fanf: 772 + +- name: Case 9, two parents both with earnings, disregard applies to each. + period: 2024-01 + input: + people: + person1: + age: 35 + # Annual $6,000 = $500/month + employment_income_before_lsr: 6_000 + person2: + age: 33 + # Annual $4,800 = $400/month + employment_income_before_lsr: 4_800 + person3: + age: 10 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 400 + households: + household: + members: [person1, person2, person3] + state_code: NH + output: + # Payment Standard for 3: 1,291 + nh_fanf_payment_standard: 1_291 + # person1: 500 * 0.50 = 250; person2: 400 * 0.50 = 200; person3 = 0 + nh_fanf_countable_earned_income: [250, 200, 0] + # 250 + 200 = 450 total countable + nh_fanf_countable_income: 450 + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + nh_fanf_eligible: true + # 1,291 - 450 = 841 + nh_fanf: 841 + +- name: Case 10, unearned income only, no earned income disregard applies. + period: 2024-01 + input: + people: + person1: + age: 38 + employment_income_before_lsr: 0 + # Annual social security = $4,800 = $400/month + social_security: 4_800 + person2: + age: 12 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 200 + households: + household: + members: [person1, person2] + state_code: NH + output: + nh_fanf_payment_standard: 1_022 + # No earned income, so no disregard applies + nh_fanf_countable_earned_income: [0, 0] + # Unearned counted in full: 400 + nh_fanf_countable_income: 400 + nh_fanf_income_eligible: true + nh_fanf_resources_eligible: true + nh_fanf_eligible: true + # 1,022 - 400 = 622 + nh_fanf: 622 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.yaml index 415cf95cc3d..5b99d21444e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.yaml @@ -171,3 +171,33 @@ # 6-person FPG: 15,060 + 5,380*5 = 41,960 # 60% = 25,176 annual / 12 = 2,098 nh_fanf_payment_standard: 2_098 + +- name: Edge case, seven person household. + period: 2024-01 + input: + people: + person1: + age: 40 + person2: + age: 38 + person3: + age: 16 + person4: + age: 14 + person5: + age: 12 + person6: + age: 10 + person7: + age: 7 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7] + state_code: NH + output: + # 7-person FPG: 15,060 + 5,380*6 = 47,340 + # 60% = 28,404 annual / 12 = 2,367 + nh_fanf_payment_standard: 2_367 diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.py index 0fc08e358ae..0570725778d 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.py @@ -8,8 +8,8 @@ class nh_fanf_countable_earned_income(Variable): unit = USD definition_period = MONTH reference = ( + "https://www.dhhs.nh.gov/famar_htm/html/603_01_earned_income_disregards_eid_sr_97-03_02_97_fam_a.htm", "https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm", - "https://www.dhhs.nh.gov/fam_htm/", ) defined_for = StateCode.NH diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.py index 6cae4f704f5..60971681a8a 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.py @@ -9,7 +9,7 @@ class nh_fanf_countable_income(Variable): definition_period = MONTH reference = ( "https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm", - "https://www.dhhs.nh.gov/fam_htm/", + "https://www.dhhs.nh.gov/fam_htm/newfam.htm", ) defined_for = StateCode.NH diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.py index c839c809002..4d4e324f316 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.py @@ -8,7 +8,7 @@ class nh_fanf_income_eligible(Variable): definition_period = MONTH reference = ( "https://gc.nh.gov/rsa/html/xii/167/167-77-g.htm", - "https://www.dhhs.nh.gov/fam_htm/", + "https://www.dhhs.nh.gov/fam_htm/newfam.htm", ) defined_for = StateCode.NH diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.py index 12085d52c9a..2d8f42fe27d 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.py @@ -7,8 +7,8 @@ class nh_fanf_resources_eligible(Variable): label = "New Hampshire FANF resources eligible" definition_period = YEAR reference = ( - "https://www.dhhs.nh.gov/fam_htm/", "https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm", + "https://www.dhhs.nh.gov/fam_htm/newfam.htm", ) defined_for = StateCode.NH From 7936518cdd711411edd9bd5e57620a4838480a89 Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 29 Dec 2025 21:37:02 -0500 Subject: [PATCH 4/4] adjustments --- .../child_care_deduction/full_time.yaml | 24 ++ .../full_time_threshold.yaml | 12 + .../child_care_deduction/part_time.yaml | 24 ++ .../applicant_rate.yaml} | 6 +- .../recipient_rate.yaml | 17 + .../dhhs/fanf/resources/applicant_limit.yaml | 14 + .../states/nh/dhhs/fanf/resources/limit.yaml | 14 - .../dhhs/fanf/resources/recipient_limit.yaml | 15 + policyengine_us/sources/working_references.md | 381 ------------------ .../gov/states/nh/dhhs/fanf/integration.yaml | 371 +++++++++++------ .../gov/states/nh/dhhs/fanf/nh_fanf.yaml | 112 +---- .../fanf/nh_fanf_child_care_deduction.yaml | 258 ++++++++++++ .../fanf/nh_fanf_countable_earned_income.yaml | 143 ++++--- .../dhhs/fanf/nh_fanf_countable_income.yaml | 112 ----- .../states/nh/dhhs/fanf/nh_fanf_eligible.yaml | 100 ++--- .../nh/dhhs/fanf/nh_fanf_income_eligible.yaml | 89 ---- .../dhhs/fanf/nh_fanf_payment_standard.yaml | 97 +---- .../dhhs/fanf/nh_fanf_resources_eligible.yaml | 69 ++-- .../{ => eligibility}/nh_fanf_eligible.py | 0 .../nh_fanf_income_eligible.py | 0 .../nh_fanf_resources_eligible.py | 6 +- .../income/nh_fanf_child_care_deduction.py | 40 ++ .../income/nh_fanf_countable_earned_income.py | 33 ++ .../{ => income}/nh_fanf_countable_income.py | 5 +- .../fanf/nh_fanf_countable_earned_income.py | 22 - 25 files changed, 847 insertions(+), 1117 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/child_care_deduction/full_time.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/child_care_deduction/full_time_threshold.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/child_care_deduction/part_time.yaml rename policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/{earned_income_disregard_rate.yaml => earned_income_disregard/applicant_rate.yaml} (70%) create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard/recipient_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/applicant_limit.yaml delete mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/limit.yaml create mode 100644 policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/recipient_limit.yaml delete mode 100644 policyengine_us/sources/working_references.md create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_child_care_deduction.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.yaml rename policyengine_us/variables/gov/states/nh/dhhs/fanf/{ => eligibility}/nh_fanf_eligible.py (100%) rename policyengine_us/variables/gov/states/nh/dhhs/fanf/{ => eligibility}/nh_fanf_income_eligible.py (100%) rename policyengine_us/variables/gov/states/nh/dhhs/fanf/{ => eligibility}/nh_fanf_resources_eligible.py (63%) create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/fanf/income/nh_fanf_child_care_deduction.py create mode 100644 policyengine_us/variables/gov/states/nh/dhhs/fanf/income/nh_fanf_countable_earned_income.py rename policyengine_us/variables/gov/states/nh/dhhs/fanf/{ => income}/nh_fanf_countable_income.py (80%) delete mode 100644 policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.py diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/child_care_deduction/full_time.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/child_care_deduction/full_time.yaml new file mode 100644 index 00000000000..3038aea2d40 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/child_care_deduction/full_time.yaml @@ -0,0 +1,24 @@ +description: New Hampshire deducts up to this amount of child care expenses per child from countable income for full-time employees under the Financial Assistance to Needy Families program, depending on child age. + +metadata: + period: month + label: New Hampshire FANF child care deduction full-time per child + type: single_amount + threshold_unit: year + amount_unit: currency-USD + reference: + - title: FAM 603.05 - Child/Dependent Care Deduction (SR 12-04) + href: https://www.dhhs.nh.gov/famar_htm/html/603_05_child_dependent_care_deduction_sr_12-04_07_12_fam_a.htm + - title: New Hampshire TANF State Plan - Policy Changes (BFA SR 22-18) + href: https://www.dhhs.nh.gov/sites/g/files/ehbemt476/files/documents2/tanf-state-plan.pdf#page=25 + +brackets: + - threshold: + 2012-07-01: 0 + amount: + 2012-07-01: 200 + - threshold: + 2012-07-01: 2 + 2022-07-01: 6 + amount: + 2012-07-01: 175 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/child_care_deduction/full_time_threshold.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/child_care_deduction/full_time_threshold.yaml new file mode 100644 index 00000000000..6cd3bf4fb06 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/child_care_deduction/full_time_threshold.yaml @@ -0,0 +1,12 @@ +description: New Hampshire sets this earnings threshold to distinguish full-time from part-time employment for the child care deduction under the Financial Assistance to Needy Families program. + +values: + 2012-07-01: 377 + +metadata: + unit: currency-USD + period: month + label: New Hampshire FANF child care deduction full-time earnings threshold + reference: + - title: FAM 603.05 - Child/Dependent Care Deduction + href: https://www.dhhs.nh.gov/famar_htm/index.htm#html/603_05_child_dependent_care_deduction_sr_12-04_07_12_fam_a.htm diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/child_care_deduction/part_time.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/child_care_deduction/part_time.yaml new file mode 100644 index 00000000000..719a685fa01 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/child_care_deduction/part_time.yaml @@ -0,0 +1,24 @@ +description: New Hampshire deducts up to this amount of child care expenses per child from countable income for part-time employees under the Financial Assistance to Needy Families program, depending on child age. + +metadata: + period: month + label: New Hampshire FANF child care deduction part-time per child + type: single_amount + threshold_unit: year + amount_unit: currency-USD + reference: + - title: FAM 603.05 - Child/Dependent Care Deduction (SR 12-04) + href: https://www.dhhs.nh.gov/famar_htm/html/603_05_child_dependent_care_deduction_sr_12-04_07_12_fam_a.htm + - title: New Hampshire TANF State Plan - Policy Changes (BFA SR 22-18) + href: https://www.dhhs.nh.gov/sites/g/files/ehbemt476/files/documents2/tanf-state-plan.pdf#page=25 + +brackets: + - threshold: + 2012-07-01: 0 + amount: + 2012-07-01: 100 + - threshold: + 2012-07-01: 2 + 2022-07-01: 6 + amount: + 2012-07-01: 87.5 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard_rate.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard/applicant_rate.yaml similarity index 70% rename from policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard_rate.yaml rename to policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard/applicant_rate.yaml index 72cdebc7c40..675b88ffe21 100644 --- a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard_rate.yaml +++ b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard/applicant_rate.yaml @@ -1,12 +1,12 @@ -description: New Hampshire excludes this share of earnings from countable income under the Financial Assistance to Needy Families program. +description: New Hampshire excludes this share of earnings from countable income for applicants under the Financial Assistance to Needy Families program. values: - 1997-02-01: 0.5 + 1997-02-01: 0.2 metadata: unit: /1 period: month - label: New Hampshire FANF earned income disregard rate + label: New Hampshire FANF applicant earned income disregard rate reference: - title: FAM 603.01 - Earned Income Disregards (EID) href: https://www.dhhs.nh.gov/famar_htm/html/603_01_earned_income_disregards_eid_sr_97-03_02_97_fam_a.htm diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard/recipient_rate.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard/recipient_rate.yaml new file mode 100644 index 00000000000..54a48f9b3aa --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/income/earned_income_disregard/recipient_rate.yaml @@ -0,0 +1,17 @@ +description: New Hampshire excludes this share of earnings from countable income for recipients under the Financial Assistance to Needy Families program. + +values: + 1997-02-01: 0.5 + 2022-09-01: 0.75 + +metadata: + unit: /1 + period: month + label: New Hampshire FANF recipient earned income disregard rate + reference: + - title: FAM 603.01 - Earned Income Disregards (EID) + href: https://www.dhhs.nh.gov/famar_htm/html/603_01_earned_income_disregards_eid_sr_97-03_02_97_fam_a.htm + - title: SR 97-03 Dated 02/97 - TANF Implementation + href: https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm + - title: New Hampshire TANF State Plan - Cliff Effect Initiative + href: https://www.dhhs.nh.gov/sites/g/files/ehbemt476/files/documents2/tanf-state-plan.pdf#page=29 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/applicant_limit.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/applicant_limit.yaml new file mode 100644 index 00000000000..42bb90698af --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/applicant_limit.yaml @@ -0,0 +1,14 @@ +description: New Hampshire limits resources to this amount for applicants under the Financial Assistance to Needy Families program. + +values: + 1997-02-01: 1_000 + +metadata: + unit: currency-USD + period: month + label: New Hampshire FANF applicant resource limit + reference: + - title: SR 97-03 Dated 02/97 - TANF Implementation + href: https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm + - title: New Hampshire TANF State Plan - Policy Changes (BFA SR 22-17) + href: https://www.dhhs.nh.gov/sites/g/files/ehbemt476/files/documents2/tanf-state-plan.pdf#page=25 diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/limit.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/limit.yaml deleted file mode 100644 index 9629acecd71..00000000000 --- a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/limit.yaml +++ /dev/null @@ -1,14 +0,0 @@ -description: New Hampshire limits resources to this amount under the Financial Assistance to Needy Families program. - -values: - 1997-02-01: 1_000 - -metadata: - unit: currency-USD - period: month - label: New Hampshire FANF resource limit - reference: - - title: SR 97-03 Dated 02/97 - TANF Implementation - href: https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm - - title: FAM 403 - Resource Limits - href: https://www.dhhs.nh.gov/fam_htm/newfam.htm diff --git a/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/recipient_limit.yaml b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/recipient_limit.yaml new file mode 100644 index 00000000000..01672b4d163 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nh/dhhs/fanf/resources/recipient_limit.yaml @@ -0,0 +1,15 @@ +description: New Hampshire limits resources to this amount for recipients under the Financial Assistance to Needy Families program. + +values: + 1997-02-01: 2_000 + 2022-07-01: 5_000 + +metadata: + unit: currency-USD + period: month + label: New Hampshire FANF recipient resource limit + reference: + - title: SR 97-03 Dated 02/97 - TANF Implementation + href: https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm + - title: New Hampshire TANF State Plan - Policy Changes (BFA SR 22-17) + href: https://www.dhhs.nh.gov/sites/g/files/ehbemt476/files/documents2/tanf-state-plan.pdf#page=25 diff --git a/policyengine_us/sources/working_references.md b/policyengine_us/sources/working_references.md deleted file mode 100644 index 8f6c70e93d2..00000000000 --- a/policyengine_us/sources/working_references.md +++ /dev/null @@ -1,381 +0,0 @@ -# Collected Documentation - -## New Hampshire TANF (FANF) Implementation -**Collected**: 2025-12-28 -**Implementation Task**: Implement New Hampshire Financial Assistance to Needy Families (FANF) program - ---- - -## Official Program Name - -**Federal Program**: Temporary Assistance for Needy Families (TANF) -**State's Official Name**: Financial Assistance to Needy Families (FANF) -**Abbreviation**: FANF -**Source**: RSA 167:77 et seq.; He-W 601.04 - -**Variable Prefix**: `nh_fanf` (e.g., `nh_fanf_eligible`, `nh_fanf_countable_income`) - -**Sub-Programs Under FANF**: -- New Hampshire Employment Program (NHEP) - Work participation required -- Family Assistance Program (FAP) - No work requirements -- Interim Disabled Parent (IDP) - For families with disabled parents -- Families With Older Children (FWOC) - For 19-year-olds in high school - -All sub-programs have the same cash eligibility requirements and benefit limits. - ---- - -## Regulatory Authority - -### New Hampshire Revised Statutes (RSA) -- **RSA Chapter 167**: Public Assistance to Blind, Aged, or Disabled Persons, and to Dependent Children -- **RSA 167:77**: Statement of Purpose - NH Employment Program and Family Assistance Program -- **RSA 167:77-g**: Adjustment of TANF Financial Assistance (60% FPG provision) -- **RSA 167:79**: Employment Program; Eligibility - -**Source URLs**: -- https://gc.nh.gov/rsa/html/xii/167/167-77.htm -- https://gc.nh.gov/rsa/html/xii/167/167-77-g.htm -- https://gc.nh.gov/rsa/html/xii/167/167-79.htm - -### New Hampshire Administrative Rules -- **He-W 600**: Financial Assistance and Eligibility for Medical Care -- **He-W 601**: Definitions -- **He-W 606**: General Verification Requirements - -**Source URL**: https://gc.nh.gov/rules/state_agencies/he-w600.html - -### Family Assistance Manual (FAM) -- **FAM 203**: TANF (Temporary Assistance for Needy Families) -- **FAM 403**: Resource Limits -- **FAM 601**: Standards and Budget Tables -- **FAM 603**: Deductions and Disregards - -**Source URL**: https://www.dhhs.nh.gov/fam_htm/ - ---- - -## Demographic Eligibility - -### Age Requirements -- **Minor child age limit**: Under 18 years old -- **Full-time student age limit**: Under 19 years old (if enrolled full-time in high school or equivalency program) -- **FWOC program**: Age 19 up to 20 for full-time high school students - -**Source**: RSA 167:79(I); NH DHHS TANF website - -**Implementation approach**: -- [x] Use federal demographic eligibility (age 18/19 matches federal definition) - -### Deprivation Requirement -The dependent child must be deprived of parental support or care by reason of: -- Death of a parent -- Continued absence from the home -- Physical or mental incapacity of a parent -- Unemployment or underemployment of a parent - -**Source**: RSA 167:79(I) - -### Household Composition -The following must be included in the assistance group (if living in household or temporarily absent): -- Any dependent child -- All minor blood-related or step-relatives -- Parent or caretaker relative - -**Source**: RSA 167:79(II) - ---- - -## Immigration Eligibility - -### Citizenship Requirements -- Must be a United States citizen, OR -- Must meet the citizenship requirements established in PRWORA (Personal Responsibility and Work Opportunity Reconciliation Act), as amended - -**Source**: RSA 167:79(IV)(c) - -**Implementation approach**: -- [x] Use federal immigration eligibility (state follows federal PRWORA rules) - ---- - -## Income Eligibility Tests - -### Single Income Test -NH FANF uses a single income test comparing net countable income to the payment standard (60% FPG). - -**Formula**: Net Countable Income <= Payment Standard (60% FPG) - -**Source**: RSA 167:77-g; FAM 601 Table B - -### Payment Standard / Income Limit (60% FPG) -Per RSA 167:77-g, effective July 1, 2017: -> "The maximum monthly cash benefit under this subdivision shall be equal to 60 percent of the federal poverty guidelines, based upon the applicable household size and composition, as determined annually by the United States Department of Health and Human Services." - -**Implementation approach**: Store as rate (0.60), not dollar amounts. The payment standard = 60% of monthly FPG for household size. - -**2024 Payment Standards (60% FPG - Monthly)**: - -| Household Size | 60% FPG (Monthly) | -|----------------|-------------------| -| 1 | $753 | -| 2 | $1,022 | -| 3 | $1,291 | -| 4 | $1,560 | -| 5 | $1,829 | -| 6 | $2,098 | -| 7 | $2,367 | -| 8 | $2,636 | -| Each additional | +$269 | - -**Note**: These amounts update annually based on FPG published in the Federal Register. - -**Parameter**: Store as `fpg_rate: 0.60` and calculate from federal poverty guidelines. - -**Source**: -- RSA 167:77-g -- SR 24-07 Dated 03/24 -- https://law.justia.com/codes/new-hampshire/2022/title-xii/title-167/section-167-77-g/ - ---- - -## Income Deductions & Exemptions - -### For Applicants: 20% Employment Expense Disregard -A 20% disregard of gross earned income is applied as an employment expense disregard. - -**Formula**: Countable Earned Income = Gross Earned Income * (1 - 0.20) - -**Level**: Per PERSON (applies to each employed individual) - -**Source**: SR 97-03 Dated 02/97; FAM 603 - -### For Recipients: 50% Earned Income Disregard -Financial assistance recipients receive a continuing 50% earned income disregard (replaces the old $30 and 1/3 rule). - -**Formula**: Countable Earned Income = Gross Earned Income * (1 - 0.50) - -**Level**: Per PERSON (applies to each employed individual) - -**Who qualifies**: -- Current financial assistance recipients -- Applicants who have received TANF financial assistance in at least one of the last six months - -**Source**: SR 97-03 Dated 02/97; FAM 603 - -### WARNING: Time-Limited Disregard (Partially Simulatable) -The 50% earned income disregard for recipients vs 20% for applicants represents a time-based distinction that PolicyEngine cannot fully track. - -**Implementation Note**: Since PolicyEngine cannot track whether someone is a new applicant vs continuing recipient, we should implement the **50% disregard** as the standard (more favorable to recipients) and document the limitation. - -### Child Support Treatment -**CRITICAL**: The $50 child support disregard has been ELIMINATED. - -The full amount of direct child support is counted as unearned income in determining eligibility and benefit amounts. New Hampshire does not allow any child support funds to pass through to FANF recipients. - -**Source**: SR 97-03 Dated 02/97 - -### SSI Exclusion -SSI (Supplemental Security Income) is NOT counted as income for FANF eligibility purposes. - -**Source**: NH DHHS policy - ---- - -## Unearned Income -Unearned income is generally counted in full (no disregard) with the following exception: -- SSI is excluded entirely - -**Source**: FAM 603; SR 97-03 - ---- - -## Benefit Calculation - -### Formula -``` -Benefit = Payment Standard - Net Countable Income -``` - -Where: -- **Payment Standard** = 60% of FPG for household size (monthly) -- **Net Countable Income** = Countable Earned Income + Countable Unearned Income - -### Calculation Steps -1. Calculate gross earned income -2. Apply earned income disregard (50% for recipients, 20% for applicants) -3. Result = Countable Earned Income -4. Add Countable Unearned Income (full amount, excluding SSI) -5. Result = Net Countable Income -6. Get Payment Standard for household size (60% FPG) -7. If Net Countable Income <= Payment Standard: Eligible -8. Benefit = Payment Standard - Net Countable Income - -**Source**: SR 97-03 Dated 02/97; FAM 603 - -### Payment Method -FANF cash assistance is issued twice per month via: -- Electronic Funds Transfer (EFT) - direct deposit -- Electronic Benefit Transfer (EBT) - debit-style card - ---- - -## Resource / Asset Limits - -### Resource Limit -**Amount**: $1,000 countable resources - -**Source**: FAM 403; CLASP reports confirm NH has $1,000 TANF asset limit - -### Vehicle Exclusion -**Rule**: One vehicle per adult assistance group member is excluded, regardless of value or ownership. - -If the assistance group has more than one vehicle per adult member, they choose which vehicle(s) to exclude. - -**Source**: SR 97-03 Dated 02/97; SR 01-12 Dated 07/01 - -### Other Resource Exclusions -- Home (primary residence) -- Household furniture -- Life insurance equity value (excluded) - -**Source**: SR 97-03 Dated 02/97 - ---- - -## Non-Simulatable Rules (Architecture Limitation) - -### 60-Month Lifetime Limit -**Rule**: FANF recipients can receive cash assistance for a maximum of 60 months (consecutive or nonconsecutive). - -**CANNOT ENFORCE** - requires tracking benefit history across multiple periods. PolicyEngine uses single-period simulation. - -**Exception**: FAP cases (Family Assistance Program) are exempt from this lifetime limit. - -**Source**: RSA 167:82; NH DHHS TANF website - -### Work Requirements (NHEP) -**Rule**: NHEP participants must work, seek employment, or attend job readiness programs. - -**CANNOT TRACK** - requires tracking work participation over time. - -**Source**: RSA 167:82 - -### Applicant vs Recipient Status -**Rule**: Different earned income disregard rates apply: -- 20% for applicants -- 50% for recipients (or those who received TANF in past 6 months) - -**PARTIALLY SIMULATABLE** - Cannot track prior receipt. Implementation uses 50% disregard (recipient rate) as default. - ---- - -## Implementation Approach Summary - -### Use Federal Baseline Variables For: -- [x] Demographic eligibility (age 18/19 matches federal) -- [x] Immigration eligibility (follows federal PRWORA rules) -- [x] Gross earned income sources -- [x] Gross unearned income sources - -### Create State-Specific Variables For: -- [ ] `nh_fanf_countable_earned_income` - Apply 50% disregard -- [ ] `nh_fanf_countable_income` - Earned + Unearned (excluding SSI) -- [ ] `nh_fanf_payment_standard` - 60% FPG by household size -- [ ] `nh_fanf_income_eligible` - Compare income to payment standard -- [ ] `nh_fanf_resources_eligible` - $1,000 resource limit -- [ ] `nh_fanf_eligible` - Combine all eligibility tests -- [ ] `nh_fanf` - Final benefit calculation - -### Parameters Needed: -- `income/earned_income_disregard_rate` - 0.50 (50%) -- `payment_standard/fpg_rate` - 0.60 (60% of FPG) -- `resources/limit` - $1,000 - ---- - -## PDFs for Future Reference - -The following PDFs contain additional information but could not be extracted: - -1. **New Hampshire's Cash Assistance (TANF) policy - NCCP** - - URL: https://www.nccp.org/wp-content/uploads/2024/11/TANF-profile-New-Hampshire.pdf - - Expected content: Detailed TANF policy profile including income disregards, benefit amounts - -2. **Bureau of Family Assistance Fact Sheet** - - URL: https://www.dhhs.nh.gov/sites/g/files/ehbemt476/files/documents2/bfa-progam-fact-sheet.pdf - - Expected content: Current eligibility requirements, income limits, resource limits by program - -3. **BFA Program Net Monthly Income Limits** - - URL: https://www.dhhs.nh.gov/sites/g/files/ehbemt476/files/documents2/bfa-program-net-monthly-income-limits.pdf - - Expected content: Current income limit tables by household size for all BFA programs - -4. **New Hampshire TANF State Plan** - - URL: https://www.dhhs.nh.gov/sites/g/files/ehbemt476/files/documents2/tanf-state-plan.pdf - - Expected content: Official state plan submitted to ACF with program details - -5. **ACF Welfare Rules Databook (July 2023)** - - URL: https://acf.gov/sites/default/files/documents/opre/opre-graphical-overview-tanf-policies-dec2024.pdf - - Expected content: Comprehensive state-by-state TANF policy comparison - -6. **NH Bureau of Family Assistance Fact Sheet (2022)** - - URL: https://nhfv.org/wp-content/uploads/2022/06/fam-asst-fact-sheet-3-22.pdf - - Expected content: Older fact sheet with eligibility and benefit information - ---- - -## Key Online References - -### Official NH DHHS Sources -- NH DHHS TANF Main Page: https://www.dhhs.nh.gov/temporary-assistance-needy-families-tanf -- FAM Manual: https://www.dhhs.nh.gov/fam_htm/ -- Administrative Rules He-W 600: https://gc.nh.gov/rules/state_agencies/he-w600.html - -### Legal Sources -- RSA Chapter 167: https://www.gencourt.state.nh.us/rsa/html/nhtoc/nhtoc-xii-167.htm -- RSA 167:77-g (60% FPG): https://law.justia.com/codes/new-hampshire/2022/title-xii/title-167/section-167-77-g/ - -### Policy Updates (SR Documents) -- SR 25-09 (March 2025 updates): https://www.dhhs.nh.gov/sr_htm/html/sr_25-09_dated_03_25.htm -- SR 24-07 (March 2024 updates): https://www.dhhs.nh.gov/sr_htm/html/sr_24-07_dated_03_24.htm -- SR 97-03 (Original TANF implementation): https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm - -### Third-Party Analysis -- NH Fiscal Policy Institute analysis: https://nhfpi.org/blog/under-enrollment-in-key-aid-program-and-increased-available-funds-provide-opportunities-for-enhanced-outreach-and-assistance/ - ---- - -## References for Metadata - -### For Parameters: -```yaml -reference: - - title: RSA 167:77-g - Adjustment of TANF Financial Assistance - href: https://gc.nh.gov/rsa/html/xii/167/167-77-g.htm - - title: SR 24-07 Dated 03/24 - FPG Updates - href: https://www.dhhs.nh.gov/sr_htm/html/sr_24-07_dated_03_24.htm -``` - -### For Variables: -```python -reference = "https://gc.nh.gov/rsa/html/xii/167/167-77-g.htm" -# Or for multiple: -reference = ( - "https://gc.nh.gov/rsa/html/xii/167/167-77-g.htm", - "https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm", -) -``` - ---- - -## Validation Checklist - -- [x] URLs load and show actual values -- [x] Legal code references included (RSA 167:77-g, RSA 167:79) -- [x] Values match sources exactly -- [x] Effective dates documented (60% FPG effective July 1, 2017) -- [x] Identified all eligibility tests -- [x] Documented BOTH earned AND unearned income treatment -- [x] Flagged non-simulatable rules (60-month limit, work requirements) -- [x] Documented deduction levels (per PERSON) -- [x] Confirmed no child support disregard/passthrough diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/integration.yaml index da0a2a2ac8f..be5a4b069f4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/integration.yaml @@ -1,6 +1,8 @@ # Integration tests for NH FANF (Financial Assistance to Needy Families) # Tests the complete benefit calculation pipeline with real-world scenarios -# Sources: RSA 167:77-g; FAM 601; FAM 603; SR 97-03 +# Note: Tests default to applicant status (20% earned income disregard) +# Recipients get 75% disregard per Cliff Effect Initiative (Sept 2022) +# Sources: RSA 167:77-g; FAM 601; FAM 603; SR 97-03; BFA SR 22-28 - name: Case 1, single parent with one child, no income, maximum benefit. period: 2024-01 @@ -19,22 +21,21 @@ members: [person1, person2] state_code: NH output: - # Payment Standard: FPG for 2 = 20,440, 60% = 12,264/12 = 1,022 nh_fanf_payment_standard: 1_022 + nh_fanf_countable_earned_income: 0 nh_fanf_countable_income: 0 nh_fanf_income_eligible: true nh_fanf_resources_eligible: true nh_fanf_eligible: true nh_fanf: 1_022 -- name: Case 2, single parent with earnings, 50 percent disregard applied. +- name: Case 2, applicant with earnings, 20 percent disregard. period: 2024-01 input: people: person1: age: 28 - # Annual employment income of $12,000 = $1,000/month - employment_income_before_lsr: 12_000 + employment_income_before_lsr: 12_000 # $1,000/month person2: age: 7 spm_units: @@ -46,72 +47,60 @@ members: [person1, person2] state_code: NH output: - # Payment Standard for 2 = 1,022 nh_fanf_payment_standard: 1_022 - # person1 earned: 1,000/month * 0.50 = 500; person2 = 0 - nh_fanf_countable_earned_income: [500, 0] - nh_fanf_countable_income: 500 + # Applicant: 1,000 * 0.80 = 800 + nh_fanf_countable_earned_income: 800 + nh_fanf_countable_income: 800 nh_fanf_income_eligible: true nh_fanf_resources_eligible: true nh_fanf_eligible: true - nh_fanf: 522 + # 1,022 - 800 = 222 + nh_fanf: 222 -- name: Case 3, family of three with moderate income. +- name: Case 3, income above threshold, ineligible. period: 2024-01 input: people: person1: - age: 32 - # Annual employment income of $18,000 = $1,500/month - employment_income_before_lsr: 18_000 + age: 35 + employment_income_before_lsr: 36_000 # $3,000/month person2: - age: 10 - person3: - age: 6 + age: 8 spm_units: spm_unit: - members: [person1, person2, person3] - spm_unit_assets: 800 + members: [person1, person2] + spm_unit_assets: 0 households: household: - members: [person1, person2, person3] + members: [person1, person2] state_code: NH output: - # Payment Standard for 3: FPG 25,820 * 0.60 / 12 = 1,291 - nh_fanf_payment_standard: 1_291 - # person1 earned: 1,500/month * 0.50 = 750; person2/3 = 0 - nh_fanf_countable_earned_income: [750, 0, 0] - nh_fanf_countable_income: 750 - nh_fanf_income_eligible: true - nh_fanf_resources_eligible: true - nh_fanf_eligible: true - nh_fanf: 541 + nh_fanf_payment_standard: 1_022 + # Applicant: 3,000 * 0.80 = 2,400 > 1,022 + nh_fanf_countable_earned_income: 2_400 + nh_fanf_countable_income: 2_400 + nh_fanf_income_eligible: false + nh_fanf_eligible: false + nh_fanf: 0 -- name: Case 4, income above threshold, ineligible. +- name: Case 4, resources over limit, ineligible. period: 2024-01 input: people: person1: - age: 35 - # Annual employment income of $36,000 = $3,000/month - employment_income_before_lsr: 36_000 + age: 29 person2: - age: 8 + age: 4 spm_units: spm_unit: members: [person1, person2] - spm_unit_assets: 0 + spm_unit_assets: 2_000 households: household: members: [person1, person2] state_code: NH output: - nh_fanf_payment_standard: 1_022 - # person1 earned: 3,000/month * 0.50 = 1,500; person2 = 0 - nh_fanf_countable_earned_income: [1_500, 0] - nh_fanf_countable_income: 1_500 - nh_fanf_income_eligible: false - nh_fanf_resources_eligible: true + nh_fanf_resources_eligible: false nh_fanf_eligible: false nh_fanf: 0 @@ -121,9 +110,7 @@ people: person1: age: 40 - # SSI is YEAR-defined, annual amount ssi: 10_000 - employment_income_before_lsr: 0 person2: age: 12 spm_units: @@ -135,169 +122,297 @@ members: [person1, person2] state_code: NH output: - nh_fanf_payment_standard: 1_022 - # SSI excluded; no other income - nh_fanf_countable_earned_income: [0, 0] + # SSI excluded nh_fanf_countable_income: 0 - nh_fanf_income_eligible: true + nh_fanf_eligible: true + nh_fanf: 1_022 + +- name: Case 6, earned and unearned income combined. + period: 2024-01 + input: + people: + person1: + age: 38 + employment_income_before_lsr: 9_600 # $800/month + social_security: 2_400 # $200/month + person2: + age: 36 + person3: + age: 14 + person4: + age: 10 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + spm_unit_assets: 900 + households: + household: + members: [person1, person2, person3, person4] + state_code: NH + output: + nh_fanf_payment_standard: 1_560 + # Applicant: 800 * 0.80 = 640 earned + 200 unearned = 840 + nh_fanf_countable_earned_income: 640 + nh_fanf_countable_income: 840 + nh_fanf_eligible: true + # 1,560 - 840 = 720 + nh_fanf: 720 + +- name: Case 7, recipient with 75 percent earned income disregard. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 500 + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NH + output: + # Recipient: 1,000 * 0.25 = 250 + nh_fanf_countable_earned_income: 250 + nh_fanf_countable_income: 250 + nh_fanf_eligible: true + # 1,022 - 250 = 772 + nh_fanf: 772 + +- name: Case 8, recipient with higher resource limit. + period: 2024-01 + input: + people: + person1: + age: 35 + person2: + age: 8 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 3_000 + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NH + output: + # Recipient limit: $5,000; assets $3,000 passes nh_fanf_resources_eligible: true nh_fanf_eligible: true nh_fanf: 1_022 -- name: Case 6, resources over limit, ineligible. +- name: Case 9, recipient with child care deduction. period: 2024-01 input: people: person1: - age: 29 + age: 30 + employment_income_before_lsr: 24_000 # $2,000/month person2: - age: 4 + age: 3 spm_units: spm_unit: members: [person1, person2] - spm_unit_assets: 2_000 + spm_unit_assets: 500 + is_tanf_enrolled: true + childcare_expenses: 3_600 households: household: members: [person1, person2] state_code: NH output: - nh_fanf_payment_standard: 1_022 - nh_fanf_countable_income: 0 - nh_fanf_income_eligible: true - nh_fanf_resources_eligible: false - nh_fanf_eligible: false - nh_fanf: 0 + # Recipient: 2,000 * 0.25 = 500 + # Child care: $200 + # Countable: 500 - 200 = 300 + nh_fanf_child_care_deduction: 200 + nh_fanf_countable_earned_income: 300 + nh_fanf_countable_income: 300 + nh_fanf_eligible: true + # 1,022 - 300 = 722 + nh_fanf: 722 -- name: Case 7, family of four with both earned and unearned income. +- name: Case 10, large 8-person household. period: 2024-01 input: people: person1: - age: 38 - # Annual employment income of $9,600 = $800/month - employment_income_before_lsr: 9_600 - # Annual social security = $2,400 = $200/month - social_security: 2_400 + age: 40 person2: - age: 36 + age: 38 person3: - age: 14 + age: 16 person4: + age: 14 + person5: + age: 12 + person6: age: 10 + person7: + age: 8 + person8: + age: 5 spm_units: spm_unit: - members: [person1, person2, person3, person4] - spm_unit_assets: 900 + members: [person1, person2, person3, person4, person5, person6, person7, person8] + spm_unit_assets: 800 households: household: - members: [person1, person2, person3, person4] + members: [person1, person2, person3, person4, person5, person6, person7, person8] state_code: NH output: - # Payment Standard for 4: FPG 31,200 * 0.60 / 12 = 1,560 - nh_fanf_payment_standard: 1_560 - # person1 earned: 800/month * 0.50 = 400; others = 0 - nh_fanf_countable_earned_income: [400, 0, 0, 0] - # 400 earned + 200 unearned = 600 - nh_fanf_countable_income: 600 - nh_fanf_income_eligible: true - nh_fanf_resources_eligible: true + # 8-person payment standard: 2,636 + nh_fanf_payment_standard: 2_636 nh_fanf_eligible: true - nh_fanf: 960 + nh_fanf: 2_636 -- name: Case 8, SSI recipient with earnings, SSI excluded but earnings counted. +- name: Case 11, applicant with child care deduction. period: 2024-01 input: people: person1: - age: 35 - # SSI should be excluded from income - ssi: 10_000 - # Annual employment income of $6,000 = $500/month - employment_income_before_lsr: 6_000 + age: 30 + employment_income_before_lsr: 24_000 # $2,000/month person2: - age: 8 + age: 3 + person3: + age: 7 spm_units: spm_unit: - members: [person1, person2] - spm_unit_assets: 300 + members: [person1, person2, person3] + spm_unit_assets: 500 + is_tanf_enrolled: false + childcare_expenses: 6_000 households: household: - members: [person1, person2] + members: [person1, person2, person3] state_code: NH output: - nh_fanf_payment_standard: 1_022 - # person1 earned: 500/month * 0.50 = 250; person2 = 0 - # SSI excluded from unearned income - nh_fanf_countable_earned_income: [250, 0] - nh_fanf_countable_income: 250 - nh_fanf_income_eligible: true - nh_fanf_resources_eligible: true + nh_fanf_payment_standard: 1_291 + # Applicant: 2,000 * 0.80 = 1,600 + # Child care: $200 (age 3) + $175 (age 7) = $375 + # Countable: 1,600 - 375 = 1,225 + nh_fanf_child_care_deduction: 375 + nh_fanf_countable_earned_income: 1_225 + nh_fanf_countable_income: 1_225 nh_fanf_eligible: true - # 1,022 - 250 = 772 - nh_fanf: 772 + # 1,291 - 1,225 = 66 + nh_fanf: 66 -- name: Case 9, two parents both with earnings, disregard applies to each. +- name: Case 12, child care deduction brings countable to zero. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 2_400 # $200/month + person2: + age: 3 + person3: + age: 4 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 500 + is_tanf_enrolled: true + childcare_expenses: 4_800 + households: + household: + members: [person1, person2, person3] + state_code: NH + output: + nh_fanf_payment_standard: 1_291 + # Recipient: 200 * 0.25 = 50 + # Child care (part-time): 2 * $100 = $200 + # Countable: max(50 - 200, 0) = 0 + nh_fanf_child_care_deduction: 200 + nh_fanf_countable_earned_income: 0 + nh_fanf_countable_income: 0 + nh_fanf_eligible: true + nh_fanf: 1_291 + +- name: Case 13, multiple earners in household. period: 2024-01 input: people: person1: age: 35 - # Annual $6,000 = $500/month - employment_income_before_lsr: 6_000 + employment_income_before_lsr: 6_000 # $500/month person2: age: 33 - # Annual $4,800 = $400/month - employment_income_before_lsr: 4_800 + employment_income_before_lsr: 6_000 # $500/month person3: - age: 10 + age: 8 spm_units: spm_unit: members: [person1, person2, person3] - spm_unit_assets: 400 + spm_unit_assets: 500 households: household: members: [person1, person2, person3] state_code: NH output: - # Payment Standard for 3: 1,291 nh_fanf_payment_standard: 1_291 - # person1: 500 * 0.50 = 250; person2: 400 * 0.50 = 200; person3 = 0 - nh_fanf_countable_earned_income: [250, 200, 0] - # 250 + 200 = 450 total countable - nh_fanf_countable_income: 450 - nh_fanf_income_eligible: true - nh_fanf_resources_eligible: true + # Applicant: (500 + 500) * 0.80 = 800 + nh_fanf_countable_earned_income: 800 + nh_fanf_countable_income: 800 nh_fanf_eligible: true - # 1,291 - 450 = 841 - nh_fanf: 841 + # 1,291 - 800 = 491 + nh_fanf: 491 -- name: Case 10, unearned income only, no earned income disregard applies. +- name: Case 14, applicant with $1000 per month earnings. period: 2024-01 input: people: person1: - age: 38 - employment_income_before_lsr: 0 - # Annual social security = $4,800 = $400/month - social_security: 4_800 + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month person2: - age: 12 + age: 5 spm_units: spm_unit: members: [person1, person2] - spm_unit_assets: 200 + spm_unit_assets: 500 + is_tanf_enrolled: false households: household: members: [person1, person2] state_code: NH output: - nh_fanf_payment_standard: 1_022 - # No earned income, so no disregard applies - nh_fanf_countable_earned_income: [0, 0] - # Unearned counted in full: 400 - nh_fanf_countable_income: 400 - nh_fanf_income_eligible: true - nh_fanf_resources_eligible: true + # Applicant: 1,000 * 0.80 = 800 + nh_fanf_countable_earned_income: 800 + nh_fanf_countable_income: 800 + nh_fanf_eligible: true + # 1,022 - 800 = 222 + nh_fanf: 222 + +- name: Case 15, recipient with same $1000 per month earnings. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 500 + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: NH + output: + # Recipient: 1,000 * 0.25 = 250 (75% disregard) + nh_fanf_countable_earned_income: 250 + nh_fanf_countable_income: 250 nh_fanf_eligible: true - # 1,022 - 400 = 622 - nh_fanf: 622 + # 1,022 - 250 = 772 (vs 222 for applicant - $550 more benefit!) + nh_fanf: 772 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf.yaml index 9d0b59cf165..36de82bba88 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf.yaml @@ -46,121 +46,13 @@ output: nh_fanf: 0 -- name: Case 5, family of four with partial benefit. - period: 2024-01 - input: - state_code: NH - nh_fanf_eligible: true - nh_fanf_payment_standard: 1_560 - nh_fanf_countable_income: 800 - output: - # 1,560 - 800 = 760 - nh_fanf: 760 - -# --- Edge Case Tests --- - -- name: Edge case, income one dollar below payment standard. - period: 2024-01 - input: - state_code: NH - nh_fanf_eligible: true - nh_fanf_payment_standard: 753 - # Income is $752, one dollar below threshold - nh_fanf_countable_income: 752 - output: - # 753 - 752 = 1 (minimum positive benefit) - nh_fanf: 1 - -- name: Edge case, income one cent below payment standard. - period: 2024-01 - input: - state_code: NH - nh_fanf_eligible: true - nh_fanf_payment_standard: 753 - # Income is $752.99 - nh_fanf_countable_income: 752.99 - output: - # 753 - 752.99 = 0.01 - nh_fanf: 0.01 - -- name: Edge case, max function handles income exceeding payment standard. +- name: Case 5, income exceeds payment standard, capped at zero. period: 2024-01 input: state_code: NH nh_fanf_eligible: true nh_fanf_payment_standard: 753 - # Income exceeds payment standard nh_fanf_countable_income: 800 output: - # max(753 - 800, 0) = max(-47, 0) = 0 - nh_fanf: 0 - -- name: Edge case, large household maximum benefit. - period: 2024-01 - input: - state_code: NH - nh_fanf_eligible: true - # 8-person payment standard - nh_fanf_payment_standard: 2_636 - nh_fanf_countable_income: 0 - output: - # Maximum benefit for large household - nh_fanf: 2_636 - -- name: Edge case, large household partial benefit. - period: 2024-01 - input: - state_code: NH - nh_fanf_eligible: true - # 8-person payment standard - nh_fanf_payment_standard: 2_636 - nh_fanf_countable_income: 1_500 - output: - # 2,636 - 1,500 = 1,136 - nh_fanf: 1_136 - -- name: Edge case, fractional income results in fractional benefit. - period: 2024-01 - input: - state_code: NH - nh_fanf_eligible: true - nh_fanf_payment_standard: 1_022 - nh_fanf_countable_income: 500.50 - output: - # 1,022 - 500.50 = 521.50 - nh_fanf: 521.50 - -- name: Edge case, very small benefit amount. - period: 2024-01 - input: - state_code: NH - nh_fanf_eligible: true - nh_fanf_payment_standard: 753 - nh_fanf_countable_income: 750 - output: - # 753 - 750 = 3 - nh_fanf: 3 - -- name: Edge case, income far exceeds payment standard. - period: 2024-01 - input: - state_code: NH - nh_fanf_eligible: true - nh_fanf_payment_standard: 753 - # Income is 10x the payment standard - nh_fanf_countable_income: 7_530 - output: - # max(753 - 7,530, 0) = 0 + # max(753 - 800, 0) = 0 nh_fanf: 0 - -- name: Edge case, half of payment standard as income. - period: 2024-01 - input: - state_code: NH - nh_fanf_eligible: true - nh_fanf_payment_standard: 1_022 - # Income is exactly half - nh_fanf_countable_income: 511 - output: - # 1,022 - 511 = 511 - nh_fanf: 511 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_child_care_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_child_care_deduction.yaml new file mode 100644 index 00000000000..5774df75b1e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_child_care_deduction.yaml @@ -0,0 +1,258 @@ +# Tests for NH FANF child care deduction +# Age threshold changed from 2 to 6 per BFA SR 22-18 (Eff: 07/01/22) +# Under 6: $200 FT / $100 PT +# 6+: $175 FT / $87.50 PT +# Full-time threshold: $377/month earned income +# Source: FAM 603.05; BFA SR 22-18 + +- name: Case 1, no child care expenses. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NH + output: + nh_fanf_child_care_deduction: 0 + +- name: Case 2, full-time parent with child under 6. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 # $500/month, above $377 threshold + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 3_600 # $300/month + households: + household: + members: [person1, person2] + state_code: NH + output: + # Max for full-time, under 6: $200/month + nh_fanf_child_care_deduction: 200 + +- name: Case 3, full-time parent with child age 6 plus. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 + person2: + age: 7 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 3_600 + households: + household: + members: [person1, person2] + state_code: NH + output: + # Max for full-time, age 6+: $175/month + nh_fanf_child_care_deduction: 175 + +- name: Case 4, part-time parent with child under 6. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 3_600 # $300/month, below $377 threshold + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 2_400 + households: + household: + members: [person1, person2] + state_code: NH + output: + # Max for part-time, under 6: $100/month + nh_fanf_child_care_deduction: 100 + +- name: Case 5, part-time parent with child age 6 plus. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 3_600 + person2: + age: 8 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 2_400 + households: + household: + members: [person1, person2] + state_code: NH + output: + # Max for part-time, age 6+: $87.50/month + nh_fanf_child_care_deduction: 87.5 + +- name: Case 6, child exactly age 6 gets 6 plus rate. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 + person2: + age: 6 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 3_600 + households: + household: + members: [person1, person2] + state_code: NH + output: + # Age 6 triggers age 6+ bracket: $175 + nh_fanf_child_care_deduction: 175 + +- name: Case 7, earnings exactly at 377 threshold is full-time. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 4_524 # $377/month exactly + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 3_600 + households: + household: + members: [person1, person2] + state_code: NH + output: + # $377 >= $377 threshold = full-time rate + nh_fanf_child_care_deduction: 200 + +- name: Case 8, two children with mixed ages. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 6_000 + person2: + age: 3 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + childcare_expenses: 6_000 + households: + household: + members: [person1, person2, person3] + state_code: NH + output: + # Full-time: $200 (under 6) + $175 (6+) = $375 + nh_fanf_child_care_deduction: 375 + +- name: Case 9, expenses less than maximum. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 1_200 # $100/month + households: + household: + members: [person1, person2] + state_code: NH + output: + # Actual expenses: $100, max: $200 -> $100 + nh_fanf_child_care_deduction: 100 + +- name: Case 10, no children in household. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 + person2: + age: 25 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 2_400 + households: + household: + members: [person1, person2] + state_code: NH + output: + # No children - no deduction + nh_fanf_child_care_deduction: 0 + +- name: Case 11, earnings $376 per month is part-time. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 4_512 # $376/month, one dollar below $377 threshold + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 3_600 + households: + household: + members: [person1, person2] + state_code: NH + output: + # $376 < $377 threshold = part-time rate ($100 for under 6) + nh_fanf_child_care_deduction: 100 + +- name: Case 12, zero earnings with childcare expenses. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 2_400 + households: + household: + members: [person1, person2] + state_code: NH + output: + # Zero earnings = part-time rate ($100 for under 6) + nh_fanf_child_care_deduction: 100 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.yaml index caadbaf1b6d..5fd10457415 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.yaml @@ -1,84 +1,129 @@ # Tests for NH FANF countable earned income -# NH applies a 50% earned income disregard for recipients -# Formula: Countable Earned Income = Gross Earned Income * (1 - 0.50) -# Source: SR 97-03 Dated 02/97; FAM 603 +# NH applies different earned income disregard rates: +# - Applicants: 20% disregard (keep 80%) +# - Recipients: 75% disregard (keep 25%) as of Sept 2022 Cliff Effect Initiative +# Child care deduction is also applied to earned income +# Source: SR 97-03; FAM 603.01; BFA SR 22-28 - name: Case 1, zero earned income. period: 2024-01 input: state_code: NH - tanf_gross_earned_income: 0 output: nh_fanf_countable_earned_income: 0 -- name: Case 2, earned income with 50 percent disregard. +- name: Case 2, applicant with earned income, 20 percent disregard. period: 2024-01 input: state_code: NH - # $1,000/month gross earned income + is_tanf_enrolled: false tanf_gross_earned_income: 1_000 output: - # 1,000 * (1 - 0.50) = 500 - nh_fanf_countable_earned_income: 500 + # Applicant: 1,000 * (1 - 0.20) = 800 + nh_fanf_countable_earned_income: 800 -- name: Case 3, higher earned income. +- name: Case 3, recipient with earned income, 75 percent disregard. period: 2024-01 input: state_code: NH - # $2,000/month gross earned income - tanf_gross_earned_income: 2_000 + is_tanf_enrolled: true + tanf_gross_earned_income: 1_000 output: - # 2,000 * (1 - 0.50) = 1,000 - nh_fanf_countable_earned_income: 1_000 + # Recipient: 1,000 * (1 - 0.75) = 250 + nh_fanf_countable_earned_income: 250 -- name: Case 4, low earned income. +- name: Case 4, applicant with child care deduction. period: 2024-01 input: - state_code: NH - # $200/month gross earned income - tanf_gross_earned_income: 200 + people: + person1: + age: 30 + employment_income_before_lsr: 24_000 # $2,000/month gross + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: false + childcare_expenses: 3_600 # $300/month + households: + household: + members: [person1, person2] + state_code: NH output: - # 200 * (1 - 0.50) = 100 - nh_fanf_countable_earned_income: 100 + # Applicant: 2,000 * (1 - 0.20) = 1,600 + # Child care max (under 6, full-time): $200 + # Countable: 1,600 - 200 = 1,400 + nh_fanf_countable_earned_income: 1_400 -# --- Edge Case Tests --- - -- name: Edge case, minimum positive income. +- name: Case 5, recipient with child care deduction. period: 2024-01 input: - state_code: NH - # $1/month gross earned income - tanf_gross_earned_income: 1 + people: + person1: + age: 30 + employment_income_before_lsr: 24_000 + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + childcare_expenses: 3_600 + households: + household: + members: [person1, person2] + state_code: NH output: - # 1 * (1 - 0.50) = 0.50 - nh_fanf_countable_earned_income: 0.50 + # Recipient: 2,000 * (1 - 0.75) = 500 + # Child care: $200 + # Countable: 500 - 200 = 300 + nh_fanf_countable_earned_income: 300 -- name: Edge case, odd dollar amount with decimal result. +- name: Case 6, child care deduction exceeds income, capped at zero. period: 2024-01 input: - state_code: NH - # $3/month gross earned income - tanf_gross_earned_income: 3 + people: + person1: + age: 30 + employment_income_before_lsr: 2_400 # $200/month gross + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + childcare_expenses: 2_400 + households: + household: + members: [person1, person2] + state_code: NH output: - # 3 * (1 - 0.50) = 1.50 - nh_fanf_countable_earned_income: 1.50 - -- name: Edge case, large earned income. - period: 2024-01 - input: - state_code: NH - # $10,000/month gross earned income - tanf_gross_earned_income: 10_000 - output: - # 10,000 * (1 - 0.50) = 5,000 - nh_fanf_countable_earned_income: 5_000 + # Recipient: 200 * (1 - 0.75) = 50 + # Child care (part-time): $100 + # Countable: max(50 - 100, 0) = 0 + nh_fanf_countable_earned_income: 0 -- name: Edge case, very small fractional amount. +- name: Case 7, child care deduction exactly equals after-disregard income. period: 2024-01 input: - state_code: NH - # $0.02/month (2 cents) - tanf_gross_earned_income: 0.02 + people: + person1: + age: 30 + employment_income_before_lsr: 9_600 # $800/month gross + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + is_tanf_enrolled: true + childcare_expenses: 3_600 + households: + household: + members: [person1, person2] + state_code: NH output: - # 0.02 * 0.50 = 0.01 - nh_fanf_countable_earned_income: 0.01 + # Recipient: 800 * (1 - 0.75) = 200 + # Child care (full-time, under 6): $200 + # Countable: 200 - 200 = 0 + nh_fanf_countable_earned_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.yaml deleted file mode 100644 index 6ee2a3b762e..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.yaml +++ /dev/null @@ -1,112 +0,0 @@ -# Tests for NH FANF countable income -# Formula: Countable Income = Countable Earned Income + Countable Unearned Income -# SSI is excluded from unearned income (federal TANF baseline excludes SSI) -# Source: FAM 603; SR 97-03 Dated 02/97 - -- name: Case 1, zero income. - period: 2024-01 - input: - state_code: NH - nh_fanf_countable_earned_income: 0 - tanf_gross_unearned_income: 0 - output: - nh_fanf_countable_income: 0 - -- name: Case 2, earned income only. - period: 2024-01 - input: - state_code: NH - nh_fanf_countable_earned_income: 500 - tanf_gross_unearned_income: 0 - output: - nh_fanf_countable_income: 500 - -- name: Case 3, unearned income only. - period: 2024-01 - input: - state_code: NH - nh_fanf_countable_earned_income: 0 - # Unearned income counted in full - tanf_gross_unearned_income: 300 - output: - nh_fanf_countable_income: 300 - -- name: Case 4, both earned and unearned income. - period: 2024-01 - input: - state_code: NH - # After 50% disregard - nh_fanf_countable_earned_income: 400 - # Unearned income counted in full - tanf_gross_unearned_income: 200 - output: - # 400 + 200 = 600 - nh_fanf_countable_income: 600 - -- name: Case 5, SSI excluded from unearned income. - period: 2024-01 - input: - people: - person1: - age: 35 - # SSI is YEAR-defined, input as annual - ssi: 10_000 - # No other unearned income - social_security: 0 - employment_income_before_lsr: 0 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: NH - output: - # SSI is excluded from TANF unearned income sources - # Therefore countable income should be 0 - nh_fanf_countable_income: 0 - -# --- Edge Case Tests --- - -- name: Edge case, minimum positive income from both sources. - period: 2024-01 - input: - state_code: NH - # $1 from each source - nh_fanf_countable_earned_income: 1 - tanf_gross_unearned_income: 1 - output: - # 1 + 1 = 2 - nh_fanf_countable_income: 2 - -- name: Edge case, large combined income. - period: 2024-01 - input: - state_code: NH - # Large earned income (after 50% disregard) - nh_fanf_countable_earned_income: 5_000 - # Large unearned income - tanf_gross_unearned_income: 3_000 - output: - # 5,000 + 3,000 = 8,000 - nh_fanf_countable_income: 8_000 - -- name: Edge case, fractional amounts. - period: 2024-01 - input: - state_code: NH - nh_fanf_countable_earned_income: 0.50 - tanf_gross_unearned_income: 0.75 - output: - # 0.50 + 0.75 = 1.25 - nh_fanf_countable_income: 1.25 - -- name: Edge case, unearned income much higher than earned. - period: 2024-01 - input: - state_code: NH - nh_fanf_countable_earned_income: 100 - tanf_gross_unearned_income: 2_000 - output: - # 100 + 2,000 = 2,100 - nh_fanf_countable_income: 2_100 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_eligible.yaml index e80bc73bd37..a1ceea052fd 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_eligible.yaml @@ -1,6 +1,5 @@ # Tests for NH FANF overall eligibility # Eligibility requires: income eligible AND resources eligible AND demographic eligible -# AND immigration eligible (at least one citizen or qualified noncitizen) # Source: RSA 167:79; FAM 203 - name: Case 1, all criteria met is eligible. @@ -43,133 +42,92 @@ output: nh_fanf_eligible: false -- name: Case 5, all criteria fail. - period: 2024-01 - input: - state_code: NH - nh_fanf_income_eligible: false - nh_fanf_resources_eligible: false - is_demographic_tanf_eligible: false - output: - nh_fanf_eligible: false - -# --- Edge Case Tests --- - -- name: Edge case, citizen parent with citizen child. +- name: Case 5, adults only household, no children. period: 2024-01 input: people: person1: - age: 30 + age: 35 immigration_status: CITIZEN person2: - age: 5 + age: 30 immigration_status: CITIZEN spm_units: spm_unit: members: [person1, person2] - nh_fanf_income_eligible: true - nh_fanf_resources_eligible: true + spm_unit_assets: 500 + nh_fanf_countable_income: 0 households: household: members: [person1, person2] state_code: NH output: - # Both are citizens - immigration eligible - nh_fanf_eligible: true + # No children - demographic ineligible + nh_fanf_eligible: false -- name: Edge case, legal permanent resident parent with citizen child. +- name: Case 6, child exactly age 17 is still a child. period: 2024-01 input: people: person1: - age: 28 - immigration_status: LEGAL_PERMANENT_RESIDENT + age: 40 + immigration_status: CITIZEN person2: - age: 4 + age: 17 immigration_status: CITIZEN spm_units: spm_unit: members: [person1, person2] - nh_fanf_income_eligible: true - nh_fanf_resources_eligible: true + spm_unit_assets: 500 + nh_fanf_countable_income: 0 households: household: members: [person1, person2] state_code: NH output: - # At least one is a qualified immigrant - immigration eligible + # Age 17 < 18 is still a child nh_fanf_eligible: true -- name: Edge case, refugee parent with child. +- name: Case 7, child exactly age 18 is no longer a child. period: 2024-01 input: people: person1: - age: 32 - immigration_status: REFUGEE + age: 45 + immigration_status: CITIZEN person2: - age: 7 - immigration_status: REFUGEE + age: 18 + immigration_status: CITIZEN spm_units: spm_unit: members: [person1, person2] - nh_fanf_income_eligible: true - nh_fanf_resources_eligible: true + spm_unit_assets: 500 + nh_fanf_countable_income: 0 households: household: members: [person1, person2] state_code: NH output: - # Refugees are qualified noncitizens - eligible - nh_fanf_eligible: true - -- name: Edge case, income and resources both fail. - period: 2024-01 - input: - state_code: NH - nh_fanf_income_eligible: false - nh_fanf_resources_eligible: false - is_demographic_tanf_eligible: true - output: + # Age 18 is an adult - no dependent children nh_fanf_eligible: false -- name: Edge case, only demographic fails. - period: 2024-01 - input: - state_code: NH - nh_fanf_income_eligible: true - nh_fanf_resources_eligible: true - is_demographic_tanf_eligible: false - output: - nh_fanf_eligible: false - -- name: Edge case, full household scenario with all eligible criteria. +- name: Case 8, pregnant woman with no children is eligible. period: 2024-01 input: people: person1: - age: 35 - immigration_status: CITIZEN - person2: - age: 12 - immigration_status: CITIZEN - person3: - age: 8 + age: 25 + is_pregnant: true immigration_status: CITIZEN spm_units: spm_unit: - members: [person1, person2, person3] + members: [person1] spm_unit_assets: 500 - nh_fanf_countable_income: 500 + nh_fanf_countable_income: 0 households: household: - members: [person1, person2, person3] + members: [person1] state_code: NH output: - # Payment standard for 3 = 1,291 - # Income 500 <= 1,291 -> income eligible - # Resources 500 <= 1,000 -> resources eligible - # Has children under 18 -> demographic eligible - # All citizens -> immigration eligible + # Pregnant woman qualifies for demographic eligibility nh_fanf_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.yaml index 7b05e937a7b..45e9af82c3d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.yaml @@ -33,96 +33,7 @@ period: 2024-01 input: state_code: NH - nh_fanf_countable_income: 800 - nh_fanf_payment_standard: 753 - output: - nh_fanf_income_eligible: false - -- name: Case 5, family of three below threshold. - period: 2024-01 - input: - state_code: NH - nh_fanf_countable_income: 1_000 - nh_fanf_payment_standard: 1_291 - output: - nh_fanf_income_eligible: true - -- name: Case 6, family of three above threshold. - period: 2024-01 - input: - state_code: NH - nh_fanf_countable_income: 1_500 - nh_fanf_payment_standard: 1_291 - output: - nh_fanf_income_eligible: false - -# --- Edge Case Tests --- - -- name: Edge case, income one dollar below threshold. - period: 2024-01 - input: - state_code: NH - # $752 is $1 below threshold - nh_fanf_countable_income: 752 - nh_fanf_payment_standard: 753 - output: - nh_fanf_income_eligible: true - -- name: Edge case, income one dollar above threshold. - period: 2024-01 - input: - state_code: NH - # $754 is $1 above threshold nh_fanf_countable_income: 754 nh_fanf_payment_standard: 753 output: nh_fanf_income_eligible: false - -- name: Edge case, income one cent below threshold. - period: 2024-01 - input: - state_code: NH - # $752.99 is just below $753 - nh_fanf_countable_income: 752.99 - nh_fanf_payment_standard: 753 - output: - nh_fanf_income_eligible: true - -- name: Edge case, income one cent above threshold. - period: 2024-01 - input: - state_code: NH - # $753.01 is just above $753 - nh_fanf_countable_income: 753.01 - nh_fanf_payment_standard: 753 - output: - nh_fanf_income_eligible: false - -- name: Edge case, both income and threshold at high values. - period: 2024-01 - input: - state_code: NH - # Income exactly matches high payment standard (8-person) - nh_fanf_countable_income: 2_636 - nh_fanf_payment_standard: 2_636 - output: - nh_fanf_income_eligible: true - -- name: Edge case, high income slightly above high threshold. - period: 2024-01 - input: - state_code: NH - # Income $1 above 8-person payment standard - nh_fanf_countable_income: 2_637 - nh_fanf_payment_standard: 2_636 - output: - nh_fanf_income_eligible: false - -- name: Edge case, extremely high income. - period: 2024-01 - input: - state_code: NH - nh_fanf_countable_income: 10_000 - nh_fanf_payment_standard: 753 - output: - nh_fanf_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.yaml index 5b99d21444e..15239a9a9aa 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_payment_standard.yaml @@ -37,7 +37,7 @@ members: [person1, person2] state_code: NH output: - # (15,060 + 5,380) * 0.60 / 12 = 20,440 * 0.60 / 12 = 1,022 + # (15,060 + 5,380) * 0.60 / 12 = 1,022 nh_fanf_payment_standard: 1_022 - name: Case 3, three person household. @@ -58,7 +58,7 @@ members: [person1, person2, person3] state_code: NH output: - # (15,060 + 5,380*2) * 0.60 / 12 = 25,820 * 0.60 / 12 = 1,291 + # (15,060 + 5,380*2) * 0.60 / 12 = 1,291 nh_fanf_payment_standard: 1_291 - name: Case 4, four person household. @@ -81,12 +81,10 @@ members: [person1, person2, person3, person4] state_code: NH output: - # (15,060 + 5,380*3) * 0.60 / 12 = 31,200 * 0.60 / 12 = 1,560 + # (15,060 + 5,380*3) * 0.60 / 12 = 1,560 nh_fanf_payment_standard: 1_560 -# --- Edge Case Tests --- - -- name: Edge case, large household with eight members. +- name: Case 5, large 8-person household. period: 2024-01 input: people: @@ -114,90 +112,5 @@ members: [person1, person2, person3, person4, person5, person6, person7, person8] state_code: NH output: - # 8-person FPG: 15,060 + 5,380*7 = 52,720 - # 60% = 31,632 annual / 12 = 2,636 + # (15,060 + 5,380*7) * 0.60 / 12 = 2,636 nh_fanf_payment_standard: 2_636 - -- name: Edge case, five person household. - period: 2024-01 - input: - people: - person1: - age: 35 - person2: - age: 32 - person3: - age: 12 - person4: - age: 9 - person5: - age: 6 - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5] - households: - household: - members: [person1, person2, person3, person4, person5] - state_code: NH - output: - # 5-person FPG: 15,060 + 5,380*4 = 36,580 - # 60% = 21,948 annual / 12 = 1,829 - nh_fanf_payment_standard: 1_829 - -- name: Edge case, six person household. - period: 2024-01 - input: - people: - person1: - age: 38 - person2: - age: 36 - person3: - age: 15 - person4: - age: 13 - person5: - age: 11 - person6: - age: 8 - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5, person6] - households: - household: - members: [person1, person2, person3, person4, person5, person6] - state_code: NH - output: - # 6-person FPG: 15,060 + 5,380*5 = 41,960 - # 60% = 25,176 annual / 12 = 2,098 - nh_fanf_payment_standard: 2_098 - -- name: Edge case, seven person household. - period: 2024-01 - input: - people: - person1: - age: 40 - person2: - age: 38 - person3: - age: 16 - person4: - age: 14 - person5: - age: 12 - person6: - age: 10 - person7: - age: 7 - spm_units: - spm_unit: - members: [person1, person2, person3, person4, person5, person6, person7] - households: - household: - members: [person1, person2, person3, person4, person5, person6, person7] - state_code: NH - output: - # 7-person FPG: 15,060 + 5,380*6 = 47,340 - # 60% = 28,404 annual / 12 = 2,367 - nh_fanf_payment_standard: 2_367 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.yaml index 474088188f7..07179837a73 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.yaml @@ -1,6 +1,8 @@ # Tests for NH FANF resources eligibility -# Resource limit: $1,000 countable resources -# Source: FAM 403; CLASP reports +# Resource limits differ for applicants vs recipients: +# - Applicants: $1,000 (since 1997) +# - Recipients: $5,000 (since 07/01/22, was $2,000 before) +# Source: FAM 403; SR 97-03; BFA SR 22-17 - name: Case 1, zero resources is eligible. period: 2024-01 @@ -10,90 +12,75 @@ output: nh_fanf_resources_eligible: true -- name: Case 2, resources below limit is eligible. - period: 2024-01 - input: - state_code: NH - spm_unit_assets: 500 - output: - nh_fanf_resources_eligible: true - -- name: Case 3, resources at limit is eligible. +- name: Case 2, applicant resources at limit is eligible. period: 2024-01 input: state_code: NH + is_tanf_enrolled: false spm_unit_assets: 1_000 output: nh_fanf_resources_eligible: true -- name: Case 4, resources above limit is ineligible. +- name: Case 3, applicant resources above limit is ineligible. period: 2024-01 input: state_code: NH + is_tanf_enrolled: false spm_unit_assets: 1_001 output: nh_fanf_resources_eligible: false -- name: Case 5, high resources is ineligible. +- name: Case 4, recipient resources at limit is eligible. period: 2024-01 input: state_code: NH + is_tanf_enrolled: true spm_unit_assets: 5_000 - output: - nh_fanf_resources_eligible: false - -# --- Edge Case Tests --- - -- name: Edge case, resources one dollar below limit. - period: 2024-01 - input: - state_code: NH - # $999 is $1 below the $1,000 limit - spm_unit_assets: 999 output: nh_fanf_resources_eligible: true -- name: Edge case, resources one cent below limit. +- name: Case 5, recipient resources above limit is ineligible. period: 2024-01 input: state_code: NH - # $999.99 is 1 cent below the $1,000 limit - spm_unit_assets: 999.99 + is_tanf_enrolled: true + spm_unit_assets: 5_001 output: - nh_fanf_resources_eligible: true + nh_fanf_resources_eligible: false -- name: Edge case, resources one cent above limit. +- name: Case 6, resources between applicant and recipient limits, applicant fails. period: 2024-01 input: state_code: NH - # $1,000.01 is 1 cent above the $1,000 limit - spm_unit_assets: 1_000.01 + is_tanf_enrolled: false + spm_unit_assets: 3_000 output: nh_fanf_resources_eligible: false -- name: Edge case, minimum positive resources. +- name: Case 7, resources between applicant and recipient limits, recipient passes. period: 2024-01 input: state_code: NH - # $1 in resources - spm_unit_assets: 1 + is_tanf_enrolled: true + spm_unit_assets: 3_000 output: nh_fanf_resources_eligible: true -- name: Edge case, very high resources. +- name: Case 8, recipient zero resources is eligible. period: 2024-01 input: state_code: NH - # $100,000 in resources - spm_unit_assets: 100_000 + is_tanf_enrolled: true + spm_unit_assets: 0 output: - nh_fanf_resources_eligible: false + nh_fanf_resources_eligible: true -- name: Edge case, fractional resources well below limit. +- name: Case 9, applicant at $999 is eligible. period: 2024-01 input: state_code: NH - # $0.50 in resources - spm_unit_assets: 0.50 + is_tanf_enrolled: false + spm_unit_assets: 999 output: + # $999 < $1,000 limit = eligible nh_fanf_resources_eligible: true diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/eligibility/nh_fanf_eligible.py similarity index 100% rename from policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_eligible.py rename to policyengine_us/variables/gov/states/nh/dhhs/fanf/eligibility/nh_fanf_eligible.py diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/eligibility/nh_fanf_income_eligible.py similarity index 100% rename from policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_income_eligible.py rename to policyengine_us/variables/gov/states/nh/dhhs/fanf/eligibility/nh_fanf_income_eligible.py diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/eligibility/nh_fanf_resources_eligible.py similarity index 63% rename from policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.py rename to policyengine_us/variables/gov/states/nh/dhhs/fanf/eligibility/nh_fanf_resources_eligible.py index 2d8f42fe27d..8f1a36146d2 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_resources_eligible.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/eligibility/nh_fanf_resources_eligible.py @@ -9,11 +9,15 @@ class nh_fanf_resources_eligible(Variable): reference = ( "https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm", "https://www.dhhs.nh.gov/fam_htm/newfam.htm", + "https://www.dhhs.nh.gov/sites/g/files/ehbemt476/files/documents2/tanf-state-plan.pdf#page=25", ) defined_for = StateCode.NH def formula(spm_unit, period, parameters): # NOTE: One vehicle per adult is excluded regardless of value. + # Resource limits differ for applicants ($1,000) vs recipients ($5,000 as of 07/01/22) p = parameters(period).gov.states.nh.dhhs.fanf.resources resources = spm_unit("spm_unit_assets", period) - return resources <= p.limit + is_enrolled = spm_unit("is_tanf_enrolled", period) + limit = where(is_enrolled, p.recipient_limit, p.applicant_limit) + return resources <= limit diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/income/nh_fanf_child_care_deduction.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/income/nh_fanf_child_care_deduction.py new file mode 100644 index 00000000000..cac87672be9 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/income/nh_fanf_child_care_deduction.py @@ -0,0 +1,40 @@ +from policyengine_us.model_api import * + + +class nh_fanf_child_care_deduction(Variable): + value_type = float + entity = SPMUnit + label = "New Hampshire FANF child/dependent care deduction" + unit = USD + definition_period = MONTH + reference = "https://www.dhhs.nh.gov/famar_htm/index.htm#html/603_05_child_dependent_care_deduction_sr_12-04_07_12_fam_a.htm" + defined_for = StateCode.NH + + def formula(spm_unit, period, parameters): + p = parameters( + period + ).gov.states.nh.dhhs.fanf.income.child_care_deduction + person = spm_unit.members + + # Determine if any earner is full-time (≥$377/month) + earned_income = person("tanf_gross_earned_income", period) + is_full_time = earned_income >= p.full_time_threshold + any_full_time = spm_unit.any(is_full_time) + + # Get child age and status + age = person("age", period.this_year) + is_child = person("is_child", period) + + # Calculate max deduction per child based on employment status and age + full_time_max = p.full_time.calc(age) + part_time_max = p.part_time.calc(age) + max_per_child = where(any_full_time, full_time_max, part_time_max) + + # Only count children + max_deduction_per_child = max_per_child * is_child + total_max_deduction = spm_unit.sum(max_deduction_per_child) + + # Cap at actual childcare expenses + childcare_expenses = spm_unit("childcare_expenses", period) + + return min_(childcare_expenses, total_max_deduction) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/income/nh_fanf_countable_earned_income.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/income/nh_fanf_countable_earned_income.py new file mode 100644 index 00000000000..1a06a44afa7 --- /dev/null +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/income/nh_fanf_countable_earned_income.py @@ -0,0 +1,33 @@ +from policyengine_us.model_api import * + + +class nh_fanf_countable_earned_income(Variable): + value_type = float + entity = SPMUnit + label = "New Hampshire FANF countable earned income" + unit = USD + definition_period = MONTH + reference = ( + "https://www.dhhs.nh.gov/famar_htm/html/603_01_earned_income_disregards_eid_sr_97-03_02_97_fam_a.htm", + "https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm", + "https://www.dhhs.nh.gov/sites/g/files/ehbemt476/files/documents2/tanf-state-plan.pdf#page=29", + ) + defined_for = StateCode.NH + + def formula(spm_unit, period, parameters): + # NH has different disregard rates for applicants (20%) vs recipients + # Recipients: 50% (1997) → 75% (Sept 2022 Cliff Effect Initiative) + # Note: A 100% disregard exists for high-demand jobs (per NH Workforce + # Innovation Opportunities Act board) with medical benefits offered, + # but this is not implemented due to lack of job classification data. + p = parameters( + period + ).gov.states.nh.dhhs.fanf.income.earned_income_disregard + gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) + is_enrolled = spm_unit("is_tanf_enrolled", period) + disregard_rate = where(is_enrolled, p.recipient_rate, p.applicant_rate) + after_disregard = gross_earned * (1 - disregard_rate) + + # Child care deduction applies to earned income (FAM 603.05) + child_care_deduction = spm_unit("nh_fanf_child_care_deduction", period) + return max_(after_disregard - child_care_deduction, 0) diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/income/nh_fanf_countable_income.py similarity index 80% rename from policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.py rename to policyengine_us/variables/gov/states/nh/dhhs/fanf/income/nh_fanf_countable_income.py index 60971681a8a..d705529ae2f 100644 --- a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_income.py +++ b/policyengine_us/variables/gov/states/nh/dhhs/fanf/income/nh_fanf_countable_income.py @@ -13,7 +13,4 @@ class nh_fanf_countable_income(Variable): ) defined_for = StateCode.NH - adds = [ - "nh_fanf_countable_earned_income", - "tanf_gross_unearned_income", - ] + adds = ["nh_fanf_countable_earned_income", "tanf_gross_unearned_income"] diff --git a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.py b/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.py deleted file mode 100644 index 0570725778d..00000000000 --- a/policyengine_us/variables/gov/states/nh/dhhs/fanf/nh_fanf_countable_earned_income.py +++ /dev/null @@ -1,22 +0,0 @@ -from policyengine_us.model_api import * - - -class nh_fanf_countable_earned_income(Variable): - value_type = float - entity = Person - label = "New Hampshire FANF countable earned income" - unit = USD - definition_period = MONTH - reference = ( - "https://www.dhhs.nh.gov/famar_htm/html/603_01_earned_income_disregards_eid_sr_97-03_02_97_fam_a.htm", - "https://www.dhhs.nh.gov/sr_htm/html/sr_97-03_dated_02_97.htm", - ) - defined_for = StateCode.NH - - def formula(person, period, parameters): - # NOTE: NH has different disregard rates for applicants (20%) vs - # recipients (50%). PolicyEngine cannot track prior benefit receipt, - # so we apply the 50% recipient rate as it is more favorable. - p = parameters(period).gov.states.nh.dhhs.fanf.income - gross_earned = person("tanf_gross_earned_income", period) - return gross_earned * (1 - p.earned_income_disregard_rate)