diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..0c3db51c72b 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: minor + changes: + added: + - Add Alabama Family Assistance (TANF) program. diff --git a/policyengine_us/parameters/gov/states/al/dhs/tanf/income/work_expense_rate.yaml b/policyengine_us/parameters/gov/states/al/dhs/tanf/income/work_expense_rate.yaml new file mode 100644 index 00000000000..2a956e7e380 --- /dev/null +++ b/policyengine_us/parameters/gov/states/al/dhs/tanf/income/work_expense_rate.yaml @@ -0,0 +1,12 @@ +description: Alabama deducts this share of miscellaneous expenses from earned income under the Temporary Assistance for Needy Families program. + +values: + 2002-01-01: 0.2 + +metadata: + unit: /1 + period: month + label: Alabama TANF work expense deduction rate + reference: + - title: Alabama DHR Public Assistance Payment Manual - Section 3215.B Work Expenses + href: https://dhr.alabama.gov/wp-content/uploads/2022/04/Appendix-N-Sec-2-Public-Assistance-Payment-Manual.pdf#page=37 diff --git a/policyengine_us/parameters/gov/states/al/dhs/tanf/max_unit_size.yaml b/policyengine_us/parameters/gov/states/al/dhs/tanf/max_unit_size.yaml new file mode 100644 index 00000000000..e3743ccdd59 --- /dev/null +++ b/policyengine_us/parameters/gov/states/al/dhs/tanf/max_unit_size.yaml @@ -0,0 +1,14 @@ +description: Alabama limits assistance unit size to this number of persons under the Temporary Assistance for Needy Families program. + +values: + 2002-01-01: 16 + +metadata: + unit: person + period: year + label: Alabama TANF maximum unit size + reference: + - title: Alabama 2021 TANF State Plan - Attachment E Payment Standards + href: https://dhr.alabama.gov/wp-content/uploads/2021/09/2021-TANF-State-Plan.pdf#page=21 + - title: Alabama 2024 TANF State Plan - Payment Standards (60% increase effective October 2023) + href: https://dhr.alabama.gov/wp-content/uploads/2024/09/2024-State-Plan-TANF.pdf#page=23 diff --git a/policyengine_us/parameters/gov/states/al/dhs/tanf/payment_standard.yaml b/policyengine_us/parameters/gov/states/al/dhs/tanf/payment_standard.yaml new file mode 100644 index 00000000000..af2f8791694 --- /dev/null +++ b/policyengine_us/parameters/gov/states/al/dhs/tanf/payment_standard.yaml @@ -0,0 +1,64 @@ +description: Alabama provides this amount as the payment standard under the Temporary Assistance for Needy Families program. + +metadata: + unit: currency-USD + period: month + breakdown: + - range(1, 17) + breakdown_label: + - Assistance unit size + label: Alabama TANF payment standard + reference: + - title: Alabama 2021 TANF State Plan - Attachment E Payment Standards + href: https://dhr.alabama.gov/wp-content/uploads/2021/09/2021-TANF-State-Plan.pdf#page=21 + - title: Alabama 2024 TANF State Plan - Payment Standards (60% increase effective October 2023) + href: https://dhr.alabama.gov/wp-content/uploads/2024/09/2024-State-Plan-TANF.pdf#page=23 + +1: + 2002-01-01: 165 + 2023-10-01: 264 +2: + 2002-01-01: 190 + 2023-10-01: 304 +3: + 2002-01-01: 215 + 2023-10-01: 344 +4: + 2002-01-01: 245 + 2023-10-01: 392 +5: + 2002-01-01: 275 + 2023-10-01: 440 +6: + 2002-01-01: 305 + 2023-10-01: 488 +7: + 2002-01-01: 335 + 2023-10-01: 536 +8: + 2002-01-01: 365 + 2023-10-01: 584 +9: + 2002-01-01: 395 + 2023-10-01: 632 +10: + 2002-01-01: 425 + 2023-10-01: 680 +11: + 2002-01-01: 455 + 2023-10-01: 728 +12: + 2002-01-01: 485 + 2023-10-01: 776 +13: + 2002-01-01: 515 + 2023-10-01: 824 +14: + 2002-01-01: 545 + 2023-10-01: 872 +15: + 2002-01-01: 575 + 2023-10-01: 920 +16: + 2002-01-01: 605 + 2023-10-01: 968 diff --git a/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf.yaml b/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf.yaml new file mode 100644 index 00000000000..71a45357d80 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf.yaml @@ -0,0 +1,308 @@ +# Unit tests for Alabama TANF benefit amount +# Reference: https://dhr.alabama.gov/wp-content/uploads/2022/04/Appendix-N-Sec-2-Public-Assistance-Payment-Manual.pdf#page=37 +# Benefit = max(payment_standard - countable_income, 0) +# Payment standards: $264 (1), $304 (2), $344 (3), $392 (4), $440 (5), $488 (6), etc. + +- name: Case 1, no income - full benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Family of 2: payment standard = $304 + # Countable income: $0 + # Benefit: $304 - $0 = $304 + al_tanf: 304 + +- name: Case 2, partial benefit with earned income. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 2_400 # $200/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly employment: $200 + # Work expense deduction (20%): $200 * 0.20 = $40 + # Countable earned: $200 - $40 = $160 + # Payment standard (2 persons): $304 + # Benefit: $304 - $160 = $144 + al_tanf: 144 + +- name: Case 3, income exceeds threshold - zero benefit. + 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] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly employment: $1,000 + # Work expense deduction (20%): $1,000 * 0.20 = $200 + # Countable earned: $1,000 - $200 = $800 + # Payment standard (2 persons): $304 + # Ineligible: countable > payment standard + # Benefit: $0 + al_tanf: 0 + +- name: Case 4, family of 3 with partial benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 3_000 # $250/month + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: AL + output: + # Monthly employment: $250 + # Work expense deduction (20%): $250 * 0.20 = $50 + # Countable earned: $250 - $50 = $200 + # Payment standard (3 persons): $344 + # Benefit: $344 - $200 = $144 + al_tanf: 144 + +- name: Case 5, family of 4 full benefit. + period: 2024-01 + input: + people: + person1: + age: 35 + person2: + age: 32 + person3: + age: 10 + person4: + age: 7 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: AL + output: + # No income + # Payment standard (4 persons): $392 + # Benefit: $392 + al_tanf: 392 + +- name: Case 6, family of 5 partial benefit. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 3_600 # $300/month + person2: + age: 32 + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: AL + output: + # Monthly employment: $300 + # Work expense deduction (20%): $300 * 0.20 = $60 + # Countable earned: $300 - $60 = $240 + # Payment standard (5 persons): $440 + # Benefit: $440 - $240 = $200 + al_tanf: 200 + +- name: Case 7, self-employment income. + period: 2024-01 + input: + people: + person1: + age: 30 + self_employment_income_before_lsr: 3_600 # $300/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly self-employment: $300 + # Work expense deduction (20%): $300 * 0.20 = $60 + # Countable earned: $300 - $60 = $240 + # Payment standard (2 persons): $304 + # Benefit: $304 - $240 = $64 + al_tanf: 64 + +- name: Case 8, unearned income. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 2_400 # $200/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Unearned (child support): $200/month + # No deductions on unearned income + # Countable income: $200 + # Payment standard (2 persons): $304 + # Benefit: $304 - $200 = $104 + al_tanf: 104 + +- name: Case 9, childcare expense deduction. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 # $500/month + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 3_600 # $300/month + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly employment: $500 + # Work expense deduction (20%): $500 * 0.20 = $100 + # After work expense: $400 + # Childcare deduction: $300 + # Countable earned: max($400 - $300, 0) = $100 + # Payment standard (2 persons): $304 + # Benefit: $304 - $100 = $204 + al_tanf: 204 + +- name: Case 10, single pregnant person full benefit. + period: 2024-01 + input: + people: + person1: + age: 25 + is_pregnant: true + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: AL + output: + # No income + # Payment standard (1 person): $264 + # Benefit: $264 + al_tanf: 264 + +# ============================================================================ +# Edge Case Tests +# ============================================================================ + +- name: Edge Case 1, childcare enabling larger benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 5_400 # $450/month + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 2_400 # $200/month + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly employment: $450 + # Work expense deduction (20%): $450 * 0.20 = $90 + # After work expense: $450 - $90 = $360 + # Childcare deduction: $200 + # Countable earned: max($360 - $200, 0) = $160 + # Payment standard (2 persons): $304 + # Benefit: $304 - $160 = $144 + al_tanf: 144 + +- name: Edge Case 2, eligible with zero benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 4_560 # $380/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Family of 2: payment standard = $304 + # Monthly employment: $380 + # Work expense deduction (20%): $380 * 0.20 = $76 + # Countable earned: $380 - $76 = $304 + # Countable income: $304 + # $304 <= $304, eligible (tests <= boundary) + # Benefit: $304 - $304 = $0 + al_tanf: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf_countable_earned_income.yaml new file mode 100644 index 00000000000..2655d66e8b2 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf_countable_earned_income.yaml @@ -0,0 +1,221 @@ +# Unit tests for Alabama TANF countable earned income +# Reference: https://dhr.alabama.gov/wp-content/uploads/2022/04/Appendix-N-Sec-2-Public-Assistance-Payment-Manual.pdf#page=37 +# Countable earned = max(gross_earned - work_expense - childcare, 0) +# Work expense = gross_earned * 0.20 + +- name: Case 1, no earned income. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + al_tanf_countable_earned_income: 0 + +- name: Case 2, employment income only. + 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] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly employment income: $1,000 + # Work expense deduction: $1,000 * 0.20 = $200 + # Countable earned: $1,000 - $200 = $800 + al_tanf_countable_earned_income: 800 + +- name: Case 3, self-employment income only. + period: 2024-01 + input: + people: + person1: + age: 30 + self_employment_income_before_lsr: 12_000 # $1,000/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly self-employment income: $1,000 + # Work expense deduction: $1,000 * 0.20 = $200 + # Countable earned: $1,000 - $200 = $800 + al_tanf_countable_earned_income: 800 + +- name: Case 4, combined employment and self-employment. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 # $500/month + self_employment_income_before_lsr: 6_000 # $500/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly earned: $500 + $500 = $1,000 + # Work expense deduction: $1,000 * 0.20 = $200 + # Countable earned: $1,000 - $200 = $800 + al_tanf_countable_earned_income: 800 + +- name: Case 5, low income. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 600 # $50/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly employment income: $50 + # Work expense deduction: $50 * 0.20 = $10 + # Countable earned: $50 - $10 = $40 + al_tanf_countable_earned_income: 40 + +- name: Case 6, two earners in household. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 12_000 # $1,000/month + person2: + age: 32 + employment_income_before_lsr: 6_000 # $500/month + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: AL + output: + # Person1: $1,000/month, Person2: $500/month + # Total earned: $1,500 + # Work expense deduction: $1,500 * 0.20 = $300 + # Countable earned: $1,500 - $300 = $1,200 + al_tanf_countable_earned_income: 1_200 + +- name: Case 7, with childcare expenses. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 # $500/month + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 3_600 # $300/month + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly employment: $500 + # Work expense deduction: $500 * 0.20 = $100 + # After work expense: $500 - $100 = $400 + # Childcare: $300/month + # Countable earned: max($400 - $300, 0) = $100 + al_tanf_countable_earned_income: 100 + +- name: Case 8, childcare exceeds earnings after work expense. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 2_400 # $200/month + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 3_600 # $300/month + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly employment: $200 + # Work expense deduction: $200 * 0.20 = $40 + # After work expense: $200 - $40 = $160 + # Childcare: $300/month + # Countable earned: max($160 - $300, 0) = max(-$140, 0) = $0 + al_tanf_countable_earned_income: 0 + +# ============================================================================ +# Edge Case Tests +# ============================================================================ + +- name: Edge Case 1, two earners with childcare expenses. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 3_000 # $250/month + person2: + age: 32 + employment_income_before_lsr: 2_400 # $200/month + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + childcare_expenses: 2_400 # $200/month + households: + household: + members: [person1, person2, person3] + state_code: AL + output: + # Person1: $250/month, Person2: $200/month + # Total gross earned: $450 + # Work expense deduction: $450 * 0.20 = $90 + # After work expense: $450 - $90 = $360 + # Childcare: $200/month + # Countable earned: max($360 - $200, 0) = $160 + al_tanf_countable_earned_income: 160 diff --git a/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf_eligible.yaml new file mode 100644 index 00000000000..69ee0a26592 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf_eligible.yaml @@ -0,0 +1,260 @@ +# Unit tests for Alabama TANF eligibility +# Reference: https://dhr.alabama.gov/wp-content/uploads/2022/04/Appendix-N-Sec-2-Public-Assistance-Payment-Manual.pdf#page=37 +# Eligibility requires: demographic eligible (minor child or pregnant), +# immigration eligible (citizen or qualified noncitizen), and income eligible +# Alabama has NO asset limit for TANF + +- name: Case 1, eligible family with minor child and no income. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Demographic: has minor child (age 5) + # Immigration: default is CITIZEN + # Income: $0 <= $304 payment standard + al_tanf_eligible: true + +- name: Case 2, eligible pregnant woman. + period: 2024-01 + input: + people: + person1: + age: 25 + employment_income_before_lsr: 2_400 # $200/month + is_pregnant: true + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: AL + output: + # Demographic: pregnant + # Immigration: default is CITIZEN + # Income: $200 - $40 (20% work expense) = $160 <= $264 payment standard + al_tanf_eligible: true + +- name: Case 3, ineligible due to no minor child and not pregnant. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 19 # Not a minor child + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Demographic: no minor child (age 19), not pregnant + # Fails demographic eligibility + al_tanf_eligible: false + +- name: Case 4, ineligible due to high income. + 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] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Demographic: has minor child + # Immigration: default is CITIZEN + # Income: $1,000 - $200 (20% work expense) = $800 > $304 payment standard + al_tanf_eligible: false + +- name: Case 5, legal permanent resident eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 2_400 # $200/month + immigration_status: LEGAL_PERMANENT_RESIDENT + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Demographic: has minor child + # Immigration: Legal Permanent Resident is qualified noncitizen + # Income: $200 - $40 (20% work expense) = $160 <= $304 payment standard + al_tanf_eligible: true + +- name: Case 6, undocumented immigrant with citizen child - eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 2_400 # $200/month + immigration_status: UNDOCUMENTED + person2: + age: 5 + immigration_status: CITIZEN # Child is citizen + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Demographic: has minor child + # Immigration: at least one citizen in unit (child) + # Income: $200 - $40 (20% work expense) = $160 <= $304 payment standard + al_tanf_eligible: true + +- name: Case 7, family of 4 with childcare expenses. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 6_000 # $500/month + person2: + age: 32 + person3: + age: 5 + person4: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + childcare_expenses: 3_600 # $300/month + households: + household: + members: [person1, person2, person3, person4] + state_code: AL + output: + # Demographic: has minor children + # Immigration: default is CITIZEN + # Income: $500 - $100 (work expense) - $300 (childcare) = $100 <= $392 + al_tanf_eligible: true + +- name: Case 8, refugee family eligible. + period: 2024-01 + input: + people: + person1: + age: 28 + employment_income_before_lsr: 3_000 # $250/month + immigration_status: REFUGEE + person2: + age: 6 + immigration_status: REFUGEE + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Demographic: has minor child + # Immigration: Refugee is qualified noncitizen + # Income: $250 - $50 (20% work expense) = $200 <= $304 payment standard + al_tanf_eligible: true + +# ============================================================================ +# Edge Case Tests +# ============================================================================ + +- name: Edge Case 1, child at age 17 - minor child boundary. + period: 2024-01 + input: + people: + person1: + age: 40 + person2: + age: 17 # Last year as minor + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Demographic: age 17 is still minor under federal TANF rules + # Immigration: default is CITIZEN + # Income: $0 <= $304 payment standard + al_tanf_eligible: true + +- name: Edge Case 2, all undocumented household - ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + immigration_status: UNDOCUMENTED + person2: + age: 5 + immigration_status: UNDOCUMENTED + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Demographic: has minor child + # Immigration: NO citizen or qualified noncitizen in household + # Fails immigration eligibility + al_tanf_eligible: false + +- name: Edge Case 3, pregnant woman at exact income threshold. + period: 2024-01 + input: + people: + person1: + age: 25 + is_pregnant: true + employment_income_before_lsr: 3_960 # $330/month + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: AL + output: + # Demographic: pregnant + # Immigration: default is CITIZEN + # Income: $330 - $66 (20% work expense) = $264 + # Payment standard (1 person): $264 + # $264 <= $264, eligible (tests <= at exact boundary) + al_tanf_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf_income_eligible.yaml new file mode 100644 index 00000000000..de5917a6870 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf_income_eligible.yaml @@ -0,0 +1,238 @@ +# Unit tests for Alabama TANF income eligibility +# Reference: https://dhr.alabama.gov/wp-content/uploads/2022/04/Appendix-N-Sec-2-Public-Assistance-Payment-Manual.pdf#page=37 +# Income eligible if countable income <= payment standard +# Payment standards: $264 (1 person), $304 (2), $344 (3), $392 (4), $440 (5) + +- name: Case 1, no income - eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Family of 2: payment standard = $304 + # Countable income: $0 + # $0 <= $304, eligible + al_tanf_income_eligible: true + +- name: Case 2, income below payment standard - eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 3_000 # $250/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly employment: $250 + # Work expense deduction (20%): $250 * 0.20 = $50 + # Countable earned: $250 - $50 = $200 + # Payment standard (2 persons): $304 + # $200 <= $304, eligible + al_tanf_income_eligible: true + +- name: Case 3, income at payment standard - eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 4_560 # $380/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly employment: $380 + # Work expense deduction (20%): $380 * 0.20 = $76 + # Countable earned: $380 - $76 = $304 + # Payment standard (2 persons): $304 + # $304 <= $304, eligible + al_tanf_income_eligible: true + +- name: Case 4, income exceeds payment standard - ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 # $500/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly employment: $500 + # Work expense deduction (20%): $500 * 0.20 = $100 + # Countable earned: $500 - $100 = $400 + # Payment standard (2 persons): $304 + # $400 > $304, ineligible + al_tanf_income_eligible: false + +- name: Case 5, family of 3 below threshold - eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 4_200 # $350/month + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: AL + output: + # Monthly employment: $350 + # Work expense deduction (20%): $350 * 0.20 = $70 + # Countable earned: $350 - $70 = $280 + # Payment standard (3 persons): $344 + # $280 <= $344, eligible + al_tanf_income_eligible: true + +- name: Case 6, family of 4 with childcare expenses - eligible. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 6_000 # $500/month + person2: + age: 32 + person3: + age: 5 + person4: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + childcare_expenses: 3_600 # $300/month + households: + household: + members: [person1, person2, person3, person4] + state_code: AL + output: + # Monthly employment: $500 + # Work expense deduction (20%): $500 * 0.20 = $100 + # After work expense: $400 + # Childcare deduction: $300 + # Countable earned: max($400 - $300, 0) = $100 + # Payment standard (4 persons): $392 + # $100 <= $392, eligible + al_tanf_income_eligible: true + +- name: Case 7, family of 5 with unearned income - ineligible. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 6_000 # $500/month + child_support_received: 1_200 # $100/month + person2: + age: 32 + person3: + age: 10 + person4: + age: 7 + person5: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: AL + output: + # Monthly employment: $500 + # Work expense deduction (20%): $500 * 0.20 = $100 + # Countable earned: $500 - $100 = $400 + # Unearned: $100/month + # Countable income: $400 + $100 = $500 + # Payment standard (5 persons): $440 + # $500 > $440, ineligible + al_tanf_income_eligible: false + +- name: Case 8, single person household - eligible. + period: 2024-01 + input: + people: + person1: + age: 25 + employment_income_before_lsr: 2_400 # $200/month + is_pregnant: true + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: AL + output: + # Monthly employment: $200 + # Work expense deduction (20%): $200 * 0.20 = $40 + # Countable earned: $200 - $40 = $160 + # Payment standard (1 person): $264 + # $160 <= $264, eligible + al_tanf_income_eligible: true + +# ============================================================================ +# Edge Case Tests +# ============================================================================ + +- name: Edge Case 1, income one dollar over payment standard - ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 3_660 # $305/month unearned (no work expense deduction) + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Family of 2: payment standard = $304 + # Monthly unearned income: $305 (no deductions on unearned) + # Countable income: $305 + # $305 > $304, ineligible (tests > boundary, one dollar over) + al_tanf_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf_payment_standard.yaml new file mode 100644 index 00000000000..ab62d60a7f3 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/al_tanf_payment_standard.yaml @@ -0,0 +1,43 @@ +# Unit tests for Alabama TANF payment standard +# Reference: https://dhr.alabama.gov/wp-content/uploads/2021/09/2021-TANF-State-Plan.pdf#page=21 +# Payment standards by family size (capped at 16) + +- name: Case 1, single person household. + period: 2018-01 + input: + spm_unit_size: 1 + state_code: AL + output: + al_tanf_payment_standard: 165 + +- name: Case 2, family of 3. + period: 2018-01 + input: + spm_unit_size: 3 + state_code: AL + output: + al_tanf_payment_standard: 215 + +- name: Case 3, family of 5. + period: 2018-01 + input: + spm_unit_size: 5 + state_code: AL + output: + al_tanf_payment_standard: 275 + +- name: Case 4, family of 6. + period: 2024-01 + input: + spm_unit_size: 6 + state_code: AL + output: + al_tanf_payment_standard: 488 + +- name: Case 5, family of 18. + period: 2024-01 + input: + spm_unit_size: 18 + state_code: AL + output: + al_tanf_payment_standard: 968 diff --git a/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/integration.yaml new file mode 100644 index 00000000000..161f067c808 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/al/dhs/tanf/integration.yaml @@ -0,0 +1,365 @@ +# Integration tests for Alabama TANF - full pipeline testing +# Tests realistic family scenarios with complete eligibility and benefit calculations +# Reference: https://dhr.alabama.gov/wp-content/uploads/2022/04/Appendix-N-Sec-2-Public-Assistance-Payment-Manual.pdf#page=37 +# Key rules: +# - Work expense deduction: 20% of earned income +# - Childcare is deducted directly from earned income +# - No asset limit in Alabama + +- name: Scenario 1 - Single parent with 2 children, no income - full benefit. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: AL + output: + # Family size: 3 + # Countable earned income: $0 + # Countable income: $0 + # Payment standard (family of 3): $344 + # Benefit: $344 - $0 = $344 + is_person_demographic_tanf_eligible: [false, true, true] + al_tanf_countable_earned_income: 0 + al_tanf_countable_income: 0 + al_tanf_income_eligible: true + al_tanf_eligible: true + al_tanf: 344 + +- name: Scenario 2 - Family of 2 with $600 monthly employment earnings. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 28 + employment_income_before_lsr: 7_200 # $600/month + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Family size: 2 + # Monthly gross earned income: $600 + # Work expense deduction: $600 * 0.20 = $120 + # Countable earned income: $600 - $120 = $480 + # Countable income: $480 + # Payment standard (family of 2): $304 + # Ineligible: $480 > $304 + # Benefit: $0 + is_person_demographic_tanf_eligible: [false, true] + al_tanf_countable_earned_income: 480 + al_tanf_countable_income: 480 + al_tanf_income_eligible: false + al_tanf_eligible: false + al_tanf: 0 + +- name: Scenario 3 - Family of 3 with $400 monthly earnings - partial benefit. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 32 + employment_income_before_lsr: 4_800 # $400/month + person2: + age: 7 + person3: + age: 4 + spm_units: + spm_unit: + members: [person1, person2, person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: AL + output: + # Family size: 3 + # Monthly gross earned income: $400 + # Work expense deduction: $400 * 0.20 = $80 + # Countable earned income: $400 - $80 = $320 + # Countable income: $320 + # Payment standard (family of 3): $344 + # $320 <= $344, eligible + # Benefit: $344 - $320 = $24 + is_person_demographic_tanf_eligible: [false, true, true] + al_tanf_countable_earned_income: 320 + al_tanf_countable_income: 320 + al_tanf_income_eligible: true + al_tanf_eligible: true + al_tanf: 24 + +- name: Scenario 4 - Family of 4 with self-employment income. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 38 + self_employment_income_before_lsr: 4_800 # $400/month self-employment + person2: + age: 35 + person3: + age: 12 + person4: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: AL + output: + # Family size: 4 + # Monthly self-employment: $400 + # Work expense deduction: $400 * 0.20 = $80 + # Countable earned income: $400 - $80 = $320 + # Countable income: $320 + # Payment standard (family of 4): $392 + # $320 <= $392, eligible + # Benefit: $392 - $320 = $72 + is_person_demographic_tanf_eligible: [false, false, true, true] + al_tanf_countable_earned_income: 320 + al_tanf_countable_income: 320 + al_tanf_income_eligible: true + al_tanf_eligible: true + al_tanf: 72 + +- name: Scenario 5 - Family with combined earned and unearned income. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 29 + employment_income_before_lsr: 3_600 # $300/month earned + child_support_received: 600 # $50/month unearned + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Family size: 2 + # Monthly gross earned income: $300 + # Work expense deduction: $300 * 0.20 = $60 + # Countable earned: $300 - $60 = $240 + # Monthly unearned: $50 + # Countable income: $240 + $50 = $290 + # Payment standard (family of 2): $304 + # $290 <= $304, eligible + # Benefit: $304 - $290 = $14 + is_person_demographic_tanf_eligible: [false, true] + al_tanf_countable_earned_income: 240 + al_tanf_countable_income: 290 + al_tanf_income_eligible: true + al_tanf_eligible: true + al_tanf: 14 + +- name: Scenario 6 - Family of 5 with childcare expenses. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 36 + employment_income_before_lsr: 7_200 # $600/month + person2: + age: 34 + person3: + age: 10 + person4: + age: 6 + person5: + age: 2 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + childcare_expenses: 2_400 # $200/month childcare + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: AL + output: + # Family size: 5 + # Monthly gross earned income: $600 + # Work expense deduction: $600 * 0.20 = $120 + # After work expense: $600 - $120 = $480 + # Childcare: $200 + # Countable earned: max($480 - $200, 0) = $280 + # Countable income: $280 + # Payment standard (family of 5): $440 + # $280 <= $440, eligible + # Benefit: $440 - $280 = $160 + is_person_demographic_tanf_eligible: [false, false, true, true, true] + al_tanf_countable_earned_income: 280 + al_tanf_countable_income: 280 + al_tanf_income_eligible: true + al_tanf_eligible: true + al_tanf: 160 + +- name: Scenario 7 - Refugee family eligible. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 28 + employment_income_before_lsr: 2_400 # $200/month + immigration_status: REFUGEE + person2: + age: 6 + immigration_status: REFUGEE + spm_units: + spm_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Family size: 2 + # Monthly gross earned income: $200 + # Work expense deduction: $200 * 0.20 = $40 + # Countable earned: $200 - $40 = $160 + # Countable income: $160 + # Payment standard (family of 2): $304 + # $160 <= $304, eligible + # Benefit: $304 - $160 = $144 + is_person_demographic_tanf_eligible: [false, true] + al_tanf_countable_earned_income: 160 + al_tanf_countable_income: 160 + al_tanf_income_eligible: true + al_tanf_eligible: true + al_tanf: 144 + +# ============================================================================ +# Edge Case Tests +# ============================================================================ + +- name: Edge Case 1 - Family of 8 with partial benefit. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 42 + employment_income_before_lsr: 4_800 # $400/month + person2: + age: 40 + 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] + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + state_code: AL + output: + # Family size: 8 + # Monthly gross earned income: $400 + # Work expense deduction: $400 * 0.20 = $80 + # Countable earned income: $400 - $80 = $320 + # Countable income: $320 + # Payment standard (family of 8): $584 + # $320 <= $584, eligible + # Benefit: $584 - $320 = $264 + is_person_demographic_tanf_eligible: [false, false, true, true, true, true, true, true] + al_tanf_countable_earned_income: 320 + al_tanf_countable_income: 320 + al_tanf_income_eligible: true + al_tanf_eligible: true + al_tanf: 264 + +- name: Edge Case 2 - Childcare exceeds after-work-expense income. + period: 2024-01 + absolute_error_margin: 0.5 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 3_600 # $300/month + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 3_600 # $300/month + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: AL + output: + # Monthly employment: $300 + # Work expense deduction: $300 * 0.20 = $60 + # After work expense: $240 + # Childcare: $300 + # Countable earned: max($240 - $300, 0) = max(-$60, 0) = $0 + # Payment standard (2 persons): $304 + # Benefit: $304 - $0 = $304 + is_person_demographic_tanf_eligible: [false, true] + al_tanf_countable_earned_income: 0 + al_tanf_countable_income: 0 + al_tanf_income_eligible: true + al_tanf_eligible: true + al_tanf: 304 diff --git a/policyengine_us/variables/gov/states/al/dhs/tanf/al_tanf.py b/policyengine_us/variables/gov/states/al/dhs/tanf/al_tanf.py new file mode 100644 index 00000000000..4325048e3b7 --- /dev/null +++ b/policyengine_us/variables/gov/states/al/dhs/tanf/al_tanf.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class al_tanf(Variable): + value_type = float + entity = SPMUnit + label = "Alabama TANF" + unit = USD + definition_period = MONTH + reference = "https://dhr.alabama.gov/wp-content/uploads/2023/10/DHR-FAD-595-Oct.23.pdf#page=2" + defined_for = "al_tanf_eligible" + + def formula(spm_unit, period, parameters): + payment_standard = spm_unit("al_tanf_payment_standard", period) + countable_income = spm_unit("al_tanf_countable_income", period) + return max_(payment_standard - countable_income, 0) diff --git a/policyengine_us/variables/gov/states/al/dhs/tanf/al_tanf_payment_standard.py b/policyengine_us/variables/gov/states/al/dhs/tanf/al_tanf_payment_standard.py new file mode 100644 index 00000000000..91aa8a334ab --- /dev/null +++ b/policyengine_us/variables/gov/states/al/dhs/tanf/al_tanf_payment_standard.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class al_tanf_payment_standard(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Alabama TANF payment standard" + definition_period = MONTH + reference = ( + "https://dhr.alabama.gov/wp-content/uploads/2024/09/2024-State-Plan-TANF.pdf#page=23", + ) + defined_for = StateCode.AL + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.al.dhs.tanf + unit_size = spm_unit("spm_unit_size", period) + capped_unit_size = min_(unit_size, p.max_unit_size) + return p.payment_standard[capped_unit_size] diff --git a/policyengine_us/variables/gov/states/al/dhs/tanf/eligibility/al_tanf_eligible.py b/policyengine_us/variables/gov/states/al/dhs/tanf/eligibility/al_tanf_eligible.py new file mode 100644 index 00000000000..b19e71f8b71 --- /dev/null +++ b/policyengine_us/variables/gov/states/al/dhs/tanf/eligibility/al_tanf_eligible.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class al_tanf_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Alabama TANF eligibility" + definition_period = MONTH + reference = "https://dhr.alabama.gov/wp-content/uploads/2023/10/DHR-FAD-595-Oct.23.pdf#page=1" + defined_for = StateCode.AL + + def formula(spm_unit, period, parameters): + # Use federal demographic eligibility (minor child or pregnant) + demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) + # Must be US citizen or qualified noncitizen + immigration_eligible = ( + add(spm_unit, period, ["is_citizen_or_legal_immigrant"]) > 0 + ) + income_eligible = spm_unit("al_tanf_income_eligible", period) + # Alabama has NO asset limit for TANF + + return demographic_eligible & immigration_eligible & income_eligible diff --git a/policyengine_us/variables/gov/states/al/dhs/tanf/eligibility/al_tanf_income_eligible.py b/policyengine_us/variables/gov/states/al/dhs/tanf/eligibility/al_tanf_income_eligible.py new file mode 100644 index 00000000000..8f30ba86fff --- /dev/null +++ b/policyengine_us/variables/gov/states/al/dhs/tanf/eligibility/al_tanf_income_eligible.py @@ -0,0 +1,15 @@ +from policyengine_us.model_api import * + + +class al_tanf_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Alabama TANF income eligibility" + definition_period = MONTH + reference = "https://dhr.alabama.gov/wp-content/uploads/2023/10/DHR-FAD-595-Oct.23.pdf#page=2" + defined_for = StateCode.AL + + def formula(spm_unit, period, parameters): + countable_income = spm_unit("al_tanf_countable_income", period) + payment_standard = spm_unit("al_tanf_payment_standard", period) + return countable_income <= payment_standard diff --git a/policyengine_us/variables/gov/states/al/dhs/tanf/income/al_tanf_countable_earned_income.py b/policyengine_us/variables/gov/states/al/dhs/tanf/income/al_tanf_countable_earned_income.py new file mode 100644 index 00000000000..811c7f07973 --- /dev/null +++ b/policyengine_us/variables/gov/states/al/dhs/tanf/income/al_tanf_countable_earned_income.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class al_tanf_countable_earned_income(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Alabama TANF countable earned income" + definition_period = MONTH + reference = "https://dhr.alabama.gov/wp-content/uploads/2022/04/Appendix-N-Sec-2-Public-Assistance-Payment-Manual.pdf#page=37" + defined_for = StateCode.AL + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.al.dhs.tanf.income + gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) + work_expense = gross_earned * p.work_expense_rate + # Child care is deducted from earned income per Section 3115.B + childcare_expenses = spm_unit("childcare_expenses", period) + return max_(gross_earned - work_expense - childcare_expenses, 0) diff --git a/policyengine_us/variables/gov/states/al/dhs/tanf/income/al_tanf_countable_income.py b/policyengine_us/variables/gov/states/al/dhs/tanf/income/al_tanf_countable_income.py new file mode 100644 index 00000000000..2a65fc3e767 --- /dev/null +++ b/policyengine_us/variables/gov/states/al/dhs/tanf/income/al_tanf_countable_income.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class al_tanf_countable_income(Variable): + value_type = float + entity = SPMUnit + unit = USD + label = "Alabama TANF countable income" + definition_period = MONTH + reference = "https://dhr.alabama.gov/wp-content/uploads/2022/04/Appendix-N-Sec-2-Public-Assistance-Payment-Manual.pdf#page=37" + defined_for = StateCode.AL + + adds = ["al_tanf_countable_earned_income", "tanf_gross_unearned_income"]