diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..456fb93d4f9 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: minor + changes: + added: + - Indiana TANF program. diff --git a/policyengine_us/parameters/gov/states/in/fssa/README.md b/policyengine_us/parameters/gov/states/in/fssa/README.md new file mode 100644 index 00000000000..4ba77c232cc --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/fssa/README.md @@ -0,0 +1 @@ +# Family and Social Services Administration diff --git a/policyengine_us/parameters/gov/states/in/fssa/tanf/README.md b/policyengine_us/parameters/gov/states/in/fssa/tanf/README.md new file mode 100644 index 00000000000..eb8aeb3f951 --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/fssa/tanf/README.md @@ -0,0 +1 @@ +# Temporary Assistance for Needy Families diff --git a/policyengine_us/parameters/gov/states/in/fssa/tanf/eligibility/continuing/fpg_rate.yaml b/policyengine_us/parameters/gov/states/in/fssa/tanf/eligibility/continuing/fpg_rate.yaml new file mode 100644 index 00000000000..d567c1b88c6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/fssa/tanf/eligibility/continuing/fpg_rate.yaml @@ -0,0 +1,12 @@ +description: Indiana uses this multiplier of the federal poverty guideline for continuing eligibility under the Temporary Assistance for Needy Families program. + +values: + 2023-07-01: 1 + +metadata: + unit: /1 + period: month + label: Indiana TANF continuing eligibility FPG rate + reference: + - title: 470 IAC 10.3-4-1 + href: https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-1 diff --git a/policyengine_us/parameters/gov/states/in/fssa/tanf/income/deductions/benefit/earned_income_disregard/rate.yaml b/policyengine_us/parameters/gov/states/in/fssa/tanf/income/deductions/benefit/earned_income_disregard/rate.yaml new file mode 100644 index 00000000000..46cd8cb4c89 --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/fssa/tanf/income/deductions/benefit/earned_income_disregard/rate.yaml @@ -0,0 +1,12 @@ +description: Indiana excludes this share of earned income when calculating benefits under the Temporary Assistance for Needy Families program. + +values: + 2023-07-01: 0.75 + +metadata: + unit: /1 + period: month + label: Indiana TANF benefit earned income disregard rate + reference: + - title: 470 IAC 10.3-4-4(d)(1) + href: https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-4 diff --git a/policyengine_us/parameters/gov/states/in/fssa/tanf/income/deductions/eligibility/earned_income_disregard/rate.yaml b/policyengine_us/parameters/gov/states/in/fssa/tanf/income/deductions/eligibility/earned_income_disregard/rate.yaml new file mode 100644 index 00000000000..ed09c6ed7da --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/fssa/tanf/income/deductions/eligibility/earned_income_disregard/rate.yaml @@ -0,0 +1,12 @@ +description: Indiana excludes this share of earned income when determining eligibility under the Temporary Assistance for Needy Families program. + +values: + 2023-07-01: 0.33 + +metadata: + unit: /1 + period: month + label: Indiana TANF eligibility earned income disregard rate + reference: + - title: 470 IAC 10.3-4-4(c)(2) + href: https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-4 diff --git a/policyengine_us/parameters/gov/states/in/fssa/tanf/income/deductions/eligibility/flat_disregard/amount.yaml b/policyengine_us/parameters/gov/states/in/fssa/tanf/income/deductions/eligibility/flat_disregard/amount.yaml new file mode 100644 index 00000000000..202290bbaca --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/fssa/tanf/income/deductions/eligibility/flat_disregard/amount.yaml @@ -0,0 +1,12 @@ +description: Indiana deducts this amount from earned income when determining eligibility under the Temporary Assistance for Needy Families program. + +values: + 2023-07-01: 30 + +metadata: + unit: currency-USD + period: month + label: Indiana TANF eligibility flat disregard amount + reference: + - title: 470 IAC 10.3-4-4(c)(2) + href: https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-4 diff --git a/policyengine_us/parameters/gov/states/in/fssa/tanf/income/deductions/work_expense/amount.yaml b/policyengine_us/parameters/gov/states/in/fssa/tanf/income/deductions/work_expense/amount.yaml new file mode 100644 index 00000000000..a917a2db707 --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/fssa/tanf/income/deductions/work_expense/amount.yaml @@ -0,0 +1,12 @@ +description: Indiana deducts this amount from gross earned income as work-related expenses under the Temporary Assistance for Needy Families program. + +values: + 2023-07-01: 90 + +metadata: + unit: currency-USD + period: month + label: Indiana TANF work expense deduction amount + reference: + - title: 470 IAC 10.3-4-4(c)(1) + href: https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-4 diff --git a/policyengine_us/parameters/gov/states/in/fssa/tanf/resources/limit/at_application/amount.yaml b/policyengine_us/parameters/gov/states/in/fssa/tanf/resources/limit/at_application/amount.yaml new file mode 100644 index 00000000000..72170a781a0 --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/fssa/tanf/resources/limit/at_application/amount.yaml @@ -0,0 +1,12 @@ +description: Indiana limits resources to this amount when applying for the Temporary Assistance for Needy Families program. + +values: + 2023-07-01: 1_000 + +metadata: + unit: currency-USD + period: month + label: Indiana TANF resource limit at application amount + reference: + - title: 470 IAC 10.3-4-2 + href: https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-2 diff --git a/policyengine_us/parameters/gov/states/in/fssa/tanf/resources/limit/while_receiving/amount.yaml b/policyengine_us/parameters/gov/states/in/fssa/tanf/resources/limit/while_receiving/amount.yaml new file mode 100644 index 00000000000..72a58354fe9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/fssa/tanf/resources/limit/while_receiving/amount.yaml @@ -0,0 +1,12 @@ +description: Indiana limits resources to this amount while receiving the Temporary Assistance for Needy Families program. + +values: + 2023-07-01: 10_000 + +metadata: + unit: currency-USD + period: month + label: Indiana TANF resource limit while receiving amount + reference: + - title: IC 12-14-1-1(b) + href: https://iga.in.gov/laws/2025/ic/titles/12/#12-14-1-1 diff --git a/policyengine_us/parameters/gov/states/in/fssa/tanf/resources/vehicle_exemption/amount.yaml b/policyengine_us/parameters/gov/states/in/fssa/tanf/resources/vehicle_exemption/amount.yaml new file mode 100644 index 00000000000..d455bcbcd2d --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/fssa/tanf/resources/vehicle_exemption/amount.yaml @@ -0,0 +1,12 @@ +description: Indiana excludes this amount of vehicle equity from countable resources under the Temporary Assistance for Needy Families program. + +values: + 2023-07-01: 20_000 + +metadata: + unit: currency-USD + period: month + label: Indiana TANF vehicle exemption amount + reference: + - title: IC 12-14-2-1(b)(2) + href: https://iga.in.gov/laws/2025/ic/titles/12/#12-14-2-1 diff --git a/policyengine_us/parameters/gov/states/in/fssa/tanf/standard_of_need/amount.yaml b/policyengine_us/parameters/gov/states/in/fssa/tanf/standard_of_need/amount.yaml new file mode 100644 index 00000000000..d8193417ca0 --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/fssa/tanf/standard_of_need/amount.yaml @@ -0,0 +1,34 @@ +description: Indiana provides this amount as the standard of need under the Temporary Assistance for Needy Families program. + +1: + 2023-07-01: 155 +2: + 2023-07-01: 255 +3: + 2023-07-01: 320 +4: + 2023-07-01: 385 +5: + 2023-07-01: 450 +6: + 2023-07-01: 515 +7: + 2023-07-01: 580 +8: + 2023-07-01: 645 +9: + 2023-07-01: 710 +10: + 2023-07-01: 775 + +metadata: + unit: currency-USD + period: month + breakdown: + - range(1, 11) + label: Indiana TANF standard of need amount + reference: + - title: 470 IAC 10.3-4-3(a)(1) + href: https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-3 + - title: IC 12-14-2-5 + href: https://iga.in.gov/laws/2025/ic/titles/12/#12-14-2-5 diff --git a/policyengine_us/parameters/gov/states/in/fssa/tanf/standard_of_need/max_unit_size.yaml b/policyengine_us/parameters/gov/states/in/fssa/tanf/standard_of_need/max_unit_size.yaml new file mode 100644 index 00000000000..ba29895fdb6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/in/fssa/tanf/standard_of_need/max_unit_size.yaml @@ -0,0 +1,12 @@ +description: Indiana sets this as the maximum unit size for standard of need lookup under the Temporary Assistance for Needy Families program. + +values: + 2023-07-01: 10 + +metadata: + unit: person + period: year + label: Indiana TANF standard of need max unit size + reference: + - title: 470 IAC 10.3-4-3 + href: https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-3 diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/benefit/in_tanf_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/benefit/in_tanf_payment_standard.yaml new file mode 100644 index 00000000000..93c2c7a849f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/benefit/in_tanf_payment_standard.yaml @@ -0,0 +1,58 @@ +# Payment standard tests +# Post P.L. 103-2023 reform, payment standard = 100% of standard of need + +- name: Payment standard for family of 1 + period: 2024-01 + input: + spm_unit_size: 1 + state_code: IN + output: + in_tanf_payment_standard: 155 + +- name: Payment standard for family of 2 + period: 2024-01 + input: + spm_unit_size: 2 + state_code: IN + output: + in_tanf_payment_standard: 255 + +- name: Payment standard for family of 3 + period: 2024-01 + input: + spm_unit_size: 3 + state_code: IN + output: + in_tanf_payment_standard: 320 + +- name: Payment standard for family of 4 + period: 2024-01 + input: + spm_unit_size: 4 + state_code: IN + output: + in_tanf_payment_standard: 385 + +- name: Payment standard for family of 5 + period: 2024-01 + input: + spm_unit_size: 5 + state_code: IN + output: + in_tanf_payment_standard: 450 + +- name: Payment standard for family of 6 + period: 2024-01 + input: + spm_unit_size: 6 + state_code: IN + output: + in_tanf_payment_standard: 515 + +- name: Payment standard for family of 10 + period: 2024-01 + input: + spm_unit_size: 10 + state_code: IN + output: + in_tanf_payment_standard: 775 diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/eligibility/in_tanf_countable_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/eligibility/in_tanf_countable_income_eligible.yaml new file mode 100644 index 00000000000..8b51f3580fb --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/eligibility/in_tanf_countable_income_eligible.yaml @@ -0,0 +1,163 @@ +# Tests for in_tanf_countable_income_eligible +# Uses eligibility disregards: $90/earner, $30/unit, 1/3 of remainder +# Compares to standard of need (initial) or FPL (continuing) + +- name: Family of 3 with zero income - eligible + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 0 + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IN + output: + in_tanf_countable_income_for_eligibility: [0, 0, 0] + in_tanf_countable_income_eligible: [true, true, true] + # Countable income ($0) < standard of need ($320) → eligible + +- name: Family of 3 with low earned income - eligible + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 300 + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IN + output: + in_tanf_countable_earned_income_for_eligibility: [120.6, 120.6, 120.6] + # $300 - $90 (work expense) = $210 + # $210 - $30 (unit disregard) = $180 + # $180 * (1 - 0.33) = $120.60 + in_tanf_countable_income_for_eligibility: [120.6, 120.6, 120.6] + in_tanf_countable_income_eligible: [true, true, true] + # Countable ($120.60) < standard of need ($320) → eligible + +- name: Family of 3 with moderate earned income - not eligible + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 600 + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IN + output: + in_tanf_countable_earned_income_for_eligibility: [321.6, 321.6, 321.6] + # $600 - $90 = $510 + # $510 - $30 = $480 + # $480 * 0.67 = $321.60 + in_tanf_countable_income_for_eligibility: [321.6, 321.6, 321.6] + in_tanf_countable_income_eligible: [false, false, false] + # Countable ($321.60) >= standard of need ($320) → not eligible + +- name: Family of 2 with earned income at threshold - not eligible + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 500 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IN + output: + in_tanf_countable_earned_income_for_eligibility: [254.6, 254.6] + # $500 - $90 = $410 + # $410 - $30 = $380 + # $380 * 0.67 = $254.60 + in_tanf_countable_income_for_eligibility: [254.6, 254.6] + in_tanf_countable_income_eligible: [true, true] + # Countable ($254.60) < standard of need ($255) → eligible + +- name: Two earners - each gets $90 disregard + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 200 + person2: + age: 28 + tanf_gross_earned_income: 200 + person3: + age: 10 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IN + output: + in_tanf_countable_earned_income_for_eligibility: [127.3, 127.3, 127.3] + # Person1: $200 - $90 = $110 + # Person2: $200 - $90 = $110 + # Unit total: $220 + # $220 - $30 = $190 + # $190 * 0.67 = $127.30 + in_tanf_countable_income_for_eligibility: [127.3, 127.3, 127.3] + in_tanf_countable_income_eligible: [true, true, true] + # Countable ($127.30) < standard of need ($320) → eligible + +- name: Continuing eligibility uses FPL threshold + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 1_000 + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + is_tanf_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: IN + output: + in_tanf_countable_earned_income_for_eligibility: [589.6, 589.6, 589.6] + # $1000 - $90 = $910 + # $910 - $30 = $880 + # $880 * 0.67 = $589.60 + in_tanf_countable_income_for_eligibility: [589.6, 589.6, 589.6] + in_tanf_countable_income_eligible: [true, true, true] + # Countable ($589.60) < 100% FPL for 3 (~$1,988/mo) → eligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/eligibility/in_tanf_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/eligibility/in_tanf_eligible.yaml new file mode 100644 index 00000000000..ea41a289a94 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/eligibility/in_tanf_eligible.yaml @@ -0,0 +1,94 @@ +- name: Eligible - passes all tests + period: 2024-01 + input: + people: + person1: + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1] + is_demographic_tanf_eligible: true + in_tanf_countable_income_eligible: true + in_tanf_payment_eligible: true + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_eligible: true + +- name: Not eligible - fails countable income test + period: 2024-01 + input: + people: + person1: + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1] + is_demographic_tanf_eligible: true + in_tanf_countable_income_eligible: false + in_tanf_payment_eligible: true + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_eligible: false + +- name: Not eligible - fails benefit income test + period: 2024-01 + input: + people: + person1: + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1] + is_demographic_tanf_eligible: true + in_tanf_countable_income_eligible: true + in_tanf_payment_eligible: false + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_eligible: false + +- name: Not eligible - fails both income tests + period: 2024-01 + input: + people: + person1: + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1] + is_demographic_tanf_eligible: true + in_tanf_countable_income_eligible: false + in_tanf_payment_eligible: false + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_eligible: false + +- name: Not eligible - not a citizen or legal immigrant + period: 2024-01 + input: + people: + person1: + is_citizen_or_legal_immigrant: false + spm_units: + spm_unit: + members: [person1] + is_demographic_tanf_eligible: true + in_tanf_countable_income_eligible: true + in_tanf_payment_eligible: true + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/eligibility/in_tanf_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/eligibility/in_tanf_income_eligible.yaml new file mode 100644 index 00000000000..175b4cc3fee --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/eligibility/in_tanf_income_eligible.yaml @@ -0,0 +1,74 @@ +# Tests for in_tanf_income_eligible +# Combines countable income and benefit income tests + +- name: Passes both income tests + period: 2024-01 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + in_tanf_countable_income_eligible: true + in_tanf_payment_eligible: true + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_income_eligible: true + +- name: Fails countable income test only + period: 2024-01 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + in_tanf_countable_income_eligible: false + in_tanf_payment_eligible: true + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_income_eligible: false + +- name: Fails benefit income test only + period: 2024-01 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + in_tanf_countable_income_eligible: true + in_tanf_payment_eligible: false + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_income_eligible: false + +- name: Fails both income tests + period: 2024-01 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + in_tanf_countable_income_eligible: false + in_tanf_payment_eligible: false + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/eligibility/in_tanf_payment_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/eligibility/in_tanf_payment_eligible.yaml new file mode 100644 index 00000000000..939290a0d4f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/eligibility/in_tanf_payment_eligible.yaml @@ -0,0 +1,63 @@ +# Tests for in_tanf_payment_eligible +# Uses payment disregards: 75% earned income (only 25% counts) +# Compares to payment standard + +- name: Family of 3 with zero countable income - eligible + period: 2024-01 + input: + spm_unit_size: 3 + in_tanf_countable_income_for_payment: 0 + state_code: IN + output: + in_tanf_payment_eligible: true + # Countable income ($0) < standard of need ($320) → eligible + +- name: Family of 3 with income below standard of need - eligible + period: 2024-01 + input: + spm_unit_size: 3 + in_tanf_countable_income_for_payment: 300 + state_code: IN + output: + in_tanf_payment_eligible: true + # Countable income ($300) < standard of need ($320) → eligible + +- name: Family of 3 with income at standard of need - not eligible + period: 2024-01 + input: + spm_unit_size: 3 + in_tanf_countable_income_for_payment: 320 + state_code: IN + output: + in_tanf_payment_eligible: false + # Countable income ($320) >= standard of need ($320) → not eligible + +- name: Family of 3 with income above standard of need - not eligible + period: 2024-01 + input: + spm_unit_size: 3 + in_tanf_countable_income_for_payment: 400 + state_code: IN + output: + in_tanf_payment_eligible: false + # Countable income ($400) > standard of need ($320) → not eligible + +- name: Family of 1 below standard of need - eligible + period: 2024-01 + input: + spm_unit_size: 1 + in_tanf_countable_income_for_payment: 150 + state_code: IN + output: + in_tanf_payment_eligible: true + # Countable income ($150) < standard of need ($155) → eligible + +- name: Family of 2 below standard of need - eligible + period: 2024-01 + input: + spm_unit_size: 2 + in_tanf_countable_income_for_payment: 250 + state_code: IN + output: + in_tanf_payment_eligible: true + # Countable income ($250) < standard of need ($255) → eligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/in_tanf.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/in_tanf.yaml new file mode 100644 index 00000000000..49adcce45bd --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/in_tanf.yaml @@ -0,0 +1,64 @@ +- name: Family of 3 with no income receives maximum benefit + period: 2024-01 + input: + in_tanf_eligible: true + in_tanf_payment_standard: 513 + in_tanf_countable_income_for_payment: 0 + state_code: IN + output: + in_tanf: 513 + # Max benefit ($513) - countable income ($0) = $513 + +- name: Family of 3 with countable income receives reduced benefit + period: 2024-01 + input: + in_tanf_eligible: true + in_tanf_payment_standard: 513 + in_tanf_countable_income_for_payment: 200 + state_code: IN + output: + in_tanf: 313 + # Max benefit ($513) - countable income ($200) = $313 + +- name: Family of 2 with partial income + period: 2024-01 + input: + in_tanf_eligible: true + in_tanf_payment_standard: 409 + in_tanf_countable_income_for_payment: 100 + state_code: IN + output: + in_tanf: 309 + # Max benefit ($409) - countable income ($100) = $309 + +- name: Ineligible family receives no benefit + period: 2024-01 + input: + in_tanf_eligible: false + in_tanf_payment_standard: 513 + in_tanf_countable_income_for_payment: 100 + state_code: IN + output: + in_tanf: 0 + +- name: Family with countable income equal to payment standard + period: 2024-01 + input: + in_tanf_eligible: true + in_tanf_payment_standard: 513 + in_tanf_countable_income_for_payment: 513 + state_code: IN + output: + in_tanf: 0 + # Max benefit ($513) - countable income ($513) = $0 + +- name: Family with countable income exceeding payment standard + period: 2024-01 + input: + in_tanf_eligible: true + in_tanf_payment_standard: 513 + in_tanf_countable_income_for_payment: 600 + state_code: IN + output: + in_tanf: 0 + # max(513 - 600, 0) = 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/income/in_tanf_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/income/in_tanf_countable_earned_income.yaml new file mode 100644 index 00000000000..a900b37d635 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/income/in_tanf_countable_earned_income.yaml @@ -0,0 +1,83 @@ +- name: No earned income + period: 2024-01 + input: + people: + person1: + tanf_gross_earned_income: 0 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_countable_earned_income: 0 + +- name: Earned income with 75% disregard - $400 monthly + period: 2024-01 + input: + people: + person1: + tanf_gross_earned_income: 400 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_countable_earned_income: 100 + # 75% disregard: Only count 25% of $400 = $100 + +- name: Earned income with 75% disregard - $1000 monthly + period: 2024-01 + input: + people: + person1: + tanf_gross_earned_income: 1_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_countable_earned_income: 250 + # 75% disregard: Only count 25% of $1,000 = $250 + +- name: Earned income with 75% disregard - $500 monthly + period: 2024-01 + input: + people: + person1: + tanf_gross_earned_income: 500 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_countable_earned_income: 125 + # 75% disregard: Only count 25% of $500 = $125 + +- name: Low earned income - $200 monthly + period: 2024-01 + input: + people: + person1: + tanf_gross_earned_income: 200 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_countable_earned_income: 50 + # 75% disregard: Only count 25% of $200 = $50 diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/income/in_tanf_countable_earned_income_for_eligibility.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/income/in_tanf_countable_earned_income_for_eligibility.yaml new file mode 100644 index 00000000000..df24ab0de97 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/income/in_tanf_countable_earned_income_for_eligibility.yaml @@ -0,0 +1,112 @@ +# Tests for in_tanf_countable_earned_income_for_eligibility +# Applies: $90/earner (per person), then $30 + 1/3 per unit + +- name: Family of 3 with 1 earner - gets $90 work expense disregard + period: 2024-01 + input: + people: + parent1: + tanf_gross_earned_income: 400 + parent2: + tanf_gross_earned_income: 0 + child: + age: 10 + spm_units: + spm_unit: + members: [parent1, parent2, child] + households: + household: + members: [parent1, parent2, child] + state_code: IN + output: + in_tanf_countable_earned_income_for_eligibility: [187.6, 187.6, 187.6] + # 1 earner: $400 - $90 = $310 + # Unit total: $310 + # $310 - $30 = $280 + # $280 * 0.67 = $187.60 + +- name: Family of 3 with 2 earners - each gets $90 (total $180 disregard) + period: 2024-01 + input: + people: + parent1: + tanf_gross_earned_income: 200 + parent2: + tanf_gross_earned_income: 200 + child: + age: 10 + spm_units: + spm_unit: + members: [parent1, parent2, child] + households: + household: + members: [parent1, parent2, child] + state_code: IN + output: + in_tanf_countable_earned_income_for_eligibility: [127.3, 127.3, 127.3] + # Parent1: $200 - $90 = $110 + # Parent2: $200 - $90 = $110 + # Unit total: $220 (vs $310 if only 1 earner had $400) + # $220 - $30 = $190 + # $190 * 0.67 = $127.30 + # Key: 2 earners = $180 disregard, 1 earner = $90 disregard + +- name: Single earner with low income + period: 2024-01 + input: + people: + person1: + tanf_gross_earned_income: 300 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IN + output: + in_tanf_countable_earned_income_for_eligibility: [120.6, 120.6] + # $300 - $90 = $210 + # $210 - $30 = $180 + # $180 * 0.67 = $120.60 + +- name: Earner below work expense disregard + period: 2024-01 + input: + people: + person1: + tanf_gross_earned_income: 50 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IN + output: + in_tanf_countable_earned_income_for_eligibility: [0, 0] + # $50 - $90 = max(0, -40) = $0 + # $0 - $30 = max(0, -30) = $0 + # $0 * 0.67 = $0 + +- name: Zero income + period: 2024-01 + input: + people: + person1: + tanf_gross_earned_income: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IN + output: + in_tanf_countable_earned_income_for_eligibility: [0, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/income/in_tanf_countable_income_for_payment.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/income/in_tanf_countable_income_for_payment.yaml new file mode 100644 index 00000000000..a90f50df112 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/income/in_tanf_countable_income_for_payment.yaml @@ -0,0 +1,71 @@ +- name: No income + period: 2024-01 + input: + people: + person1: + tanf_gross_earned_income: 0 + tanf_gross_unearned_income: 0 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_countable_income_for_payment: 0 + +- name: Earned income only + period: 2024-01 + input: + people: + person1: + tanf_gross_earned_income: 400 + tanf_gross_unearned_income: 0 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_countable_income_for_payment: 100 + # $400 × 0.25 = $100 (75% disregard) + +- name: Unearned income only + period: 2024-01 + input: + people: + person1: + tanf_gross_earned_income: 0 + tanf_gross_unearned_income: 300 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_countable_income_for_payment: 300 + # Unearned income has no disregard + +- name: Mixed earned and unearned income + period: 2024-01 + input: + people: + person1: + tanf_gross_earned_income: 500 + tanf_gross_unearned_income: 200 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IN + output: + in_tanf_countable_income_for_payment: 325 + # $500 × 0.25 = $125 (earned with 75% disregard) + # $125 + $200 (unearned) = $325 diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/integration.yaml new file mode 100644 index 00000000000..fa34c564035 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/integration.yaml @@ -0,0 +1,249 @@ +# Indiana TANF Integration Tests +# Tests the full benefit calculation pipeline + +- name: Case 1 - Single parent with no income receives maximum benefit + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 0 + tanf_gross_unearned_income: 0 + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_cash_assets: 500 + households: + household: + members: [person1, person2, person3] + state_code: IN + output: + spm_unit_size: [3, 3, 3] + in_tanf_countable_earned_income_for_eligibility: [0, 0, 0] + in_tanf_countable_income_for_eligibility: [0, 0, 0] + in_tanf_countable_earned_income: [0, 0, 0] + in_tanf_countable_income_for_payment: [0, 0, 0] + in_tanf_countable_income_eligible: [true, true, true] + # Countable income ($0) < standard of need ($320) → eligible + in_tanf_payment_eligible: [true, true, true] + # Countable income ($0) < standard of need ($320) → eligible + in_tanf_payment_standard: [320, 320, 320] + # Family of 3 → $320 + in_tanf_eligible: [true, true, true] + in_tanf: [320, 320, 320] + # Max benefit ($320) - countable income ($0) = $320 + +- name: Case 2 - Single parent with earned income receives reduced benefit + period: 2024-01 + input: + people: + person1: + age: 28 + tanf_gross_earned_income: 200 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_cash_assets: 800 + households: + household: + members: [person1, person2] + state_code: IN + output: + spm_unit_size: [2, 2] + in_tanf_countable_earned_income_for_eligibility: [53.6, 53.6] + # $200 - $90 = $110 → $110 - $30 = $80 → $80 * 0.67 = $53.60 + in_tanf_countable_income_for_eligibility: [53.6, 53.6] + in_tanf_countable_earned_income: [50, 50] + # $200 × 0.25 (75% disregard) = $50 + in_tanf_countable_income_for_payment: [50, 50] + in_tanf_countable_income_eligible: [true, true] + # Countable for elig ($53.60) < standard of need ($255) → eligible + in_tanf_payment_eligible: [true, true] + # Countable for benefit ($50) < standard of need ($255) → eligible + in_tanf_payment_standard: [255, 255] + # Family of 2 → $255 + in_tanf_eligible: [true, true] + in_tanf: [205, 205] + # Max benefit ($255) - countable income ($50) = $205 + +- name: Case 3 - Family with mixed earned and unearned income + period: 2024-01 + input: + people: + person1: + age: 35 + tanf_gross_earned_income: 300 + person2: + age: 12 + tanf_gross_unearned_income: 100 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_cash_assets: 700 + households: + household: + members: [person1, person2] + state_code: IN + output: + spm_unit_size: [2, 2] + in_tanf_countable_earned_income_for_eligibility: [120.6, 120.6] + # $300 - $90 = $210 → $210 - $30 = $180 → $180 * 0.67 = $120.60 + in_tanf_countable_income_for_eligibility: [220.6, 220.6] + # $120.60 (earned) + $100 (unearned) = $220.60 + in_tanf_countable_earned_income: [75, 75] + # $300 × 0.25 = $75 + in_tanf_countable_income_for_payment: [175, 175] + # $75 (earned) + $100 (unearned) = $175 + in_tanf_countable_income_eligible: [true, true] + # Countable for elig ($220.60) < standard of need ($255) → eligible + in_tanf_payment_eligible: [true, true] + # Countable for benefit ($175) < standard of need ($255) → eligible + in_tanf_payment_standard: [255, 255] + in_tanf_eligible: [true, true] + in_tanf: [80, 80] + # Max benefit ($255) - countable income ($175) = $80 + +- name: Case 4 - High earner exceeds eligibility threshold + period: 2024-01 + input: + people: + person1: + age: 32 + tanf_gross_earned_income: 600 + person2: + age: 7 + person3: + age: 4 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_cash_assets: 900 + households: + household: + members: [person1, person2, person3] + state_code: IN + output: + spm_unit_size: [3, 3, 3] + in_tanf_countable_earned_income_for_eligibility: [321.6, 321.6, 321.6] + # $600 - $90 = $510 → $510 - $30 = $480 → $480 * 0.67 = $321.60 + in_tanf_countable_income_for_eligibility: [321.6, 321.6, 321.6] + in_tanf_countable_earned_income: [150, 150, 150] + # $600 × 0.25 = $150 + in_tanf_countable_income_for_payment: [150, 150, 150] + in_tanf_countable_income_eligible: [false, false, false] + # Countable for elig ($321.60) >= standard of need ($320) → NOT eligible + in_tanf_payment_eligible: [true, true, true] + # Countable for benefit ($150) < standard of need ($320) → eligible + in_tanf_payment_standard: [320, 320, 320] + in_tanf_eligible: [false, false, false] + # Failed countable income test + in_tanf: [0, 0, 0] + +- name: Case 5 - Two parent household with one working + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 300 + person2: + age: 29 + person3: + age: 6 + person4: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + spm_unit_cash_assets: 1_500 + households: + household: + members: [person1, person2, person3, person4] + state_code: IN + output: + spm_unit_size: [4, 4, 4, 4] + in_tanf_countable_earned_income_for_eligibility: [120.6, 120.6, 120.6, 120.6] + # $300 - $90 = $210 → $210 - $30 = $180 → $180 * 0.67 = $120.60 + in_tanf_countable_income_for_eligibility: [120.6, 120.6, 120.6, 120.6] + in_tanf_countable_earned_income: [75, 75, 75, 75] + # $300 × 0.25 = $75 + in_tanf_countable_income_for_payment: [75, 75, 75, 75] + in_tanf_countable_income_eligible: [true, true, true, true] + # Countable for elig ($120.60) < standard of need ($385) → eligible + in_tanf_payment_eligible: [true, true, true, true] + # Countable for benefit ($75) < standard of need ($385) → eligible + in_tanf_payment_standard: [385, 385, 385, 385] + # Family of 4 → $385 + in_tanf_eligible: [true, true, true, true] + in_tanf: [310, 310, 310, 310] + # Max benefit ($385) - countable income ($75) = $310 + +- name: Case 6 - Two earners both get $90 disregard + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 200 + person2: + age: 28 + tanf_gross_earned_income: 200 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_cash_assets: 500 + households: + household: + members: [person1, person2, person3] + state_code: IN + output: + spm_unit_size: [3, 3, 3] + in_tanf_countable_earned_income_for_eligibility: [127.3, 127.3, 127.3] + # Person1: $200 - $90 = $110 + # Person2: $200 - $90 = $110 + # Unit total: $220 - $30 = $190 → $190 * 0.67 = $127.30 + in_tanf_countable_income_for_eligibility: [127.3, 127.3, 127.3] + in_tanf_countable_earned_income: [100, 100, 100] + # ($200 + $200) × 0.25 = $100 + in_tanf_countable_income_for_payment: [100, 100, 100] + in_tanf_countable_income_eligible: [true, true, true] + # Countable for elig ($127.30) < standard of need ($320) → eligible + in_tanf_payment_eligible: [true, true, true] + # Countable for benefit ($100) < standard of need ($320) → eligible + in_tanf_payment_standard: [320, 320, 320] + in_tanf_eligible: [true, true, true] + in_tanf: [220, 220, 220] + # Max benefit ($320) - countable income ($100) = $220 + +- name: Case 7 - Single adult with no children (not demographically eligible) + period: 2024-01 + input: + people: + person1: + age: 25 + spm_units: + spm_unit: + members: [person1] + spm_unit_cash_assets: 300 + households: + household: + members: [person1] + state_code: IN + output: + spm_unit_size: 1 + in_tanf_countable_income_for_payment: 0 + in_tanf_countable_income_eligible: true + in_tanf_payment_eligible: true + in_tanf_payment_standard: 155 + # Family of 1 → $155 + in_tanf_eligible: false + # Single adult with no children → not demographically eligible + in_tanf: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/resources/in_tanf_countable_resources.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/resources/in_tanf_countable_resources.yaml new file mode 100644 index 00000000000..3de48c0a003 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/resources/in_tanf_countable_resources.yaml @@ -0,0 +1,38 @@ +- name: No assets means zero countable resources + period: 2024-01 + input: + state_code: IN + # SPM unit assets currently returns 0 in baseline + spm_unit_assets: 0 + output: + in_tanf_countable_resources: 0 + +- name: Non-vehicle assets are fully countable + period: 2024-01 + input: + state_code: IN + spm_unit_assets: 5_000 + household_vehicles_value: 0 # No vehicle + output: + in_tanf_countable_resources: 5_000 + # 5_000 - 0 vehicle exclusion = 5_000 + +- name: Vehicle exclusion reduces countable resources + period: 2024-01 + input: + state_code: IN + spm_unit_assets: 25_000 # Includes vehicle value + household_vehicles_value: 15_000 # Vehicle worth $15,000 + output: + in_tanf_countable_resources: 10_000 + # 25_000 - min(15_000, 20_000) = 25_000 - 15_000 = 10_000 + +- name: Vehicle exclusion capped at limit + period: 2024-01 + input: + state_code: IN + spm_unit_assets: 30_000 # Includes vehicle value + household_vehicles_value: 25_000 # Vehicle worth more than exclusion limit + output: + in_tanf_countable_resources: 10_000 + # 30_000 - min(25_000, 20_000) = 30_000 - 20_000 = 10_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/resources/in_tanf_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/resources/in_tanf_resources_eligible.yaml new file mode 100644 index 00000000000..0e5da21a6d4 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/resources/in_tanf_resources_eligible.yaml @@ -0,0 +1,60 @@ +- name: Resources below application limit passes eligibility + period: 2024-01 + input: + state_code: IN + in_tanf_countable_resources: 500 # Below $1_000 limit + is_tanf_enrolled: false # Not enrolled in TANF + output: + in_tanf_resources_eligible: true + # 500 <= 1_000 = true + +- name: Resources at application limit passes eligibility + period: 2024-01 + input: + state_code: IN + in_tanf_countable_resources: 1_000 # At $1_000 limit + is_tanf_enrolled: false # Not enrolled in TANF + output: + in_tanf_resources_eligible: true + # 1_000 <= 1_000 = true + +- name: Resources above application limit fails eligibility + period: 2024-01 + input: + state_code: IN + in_tanf_countable_resources: 1_500 # Above $1_000 limit + is_tanf_enrolled: false # Not enrolled in TANF + output: + in_tanf_resources_eligible: false + # 1_500 <= 1_000 = false + +- name: Resources below limit while enrolled passes eligibility + period: 2024-01 + input: + state_code: IN + in_tanf_countable_resources: 5_000 # Below $10_000 ongoing limit + is_tanf_enrolled: true # Currently enrolled in TANF + output: + in_tanf_resources_eligible: true + # Uses limit_while_receiving parameter: $10_000 + # 5_000 <= 10_000 = true + +- name: Resources above limit while enrolled fails eligibility + period: 2024-01 + input: + state_code: IN + in_tanf_countable_resources: 15_000 # Above $10_000 ongoing limit + is_tanf_enrolled: true # Currently enrolled in TANF + output: + in_tanf_resources_eligible: false + # 15_000 <= 10_000 = false + +- name: Zero resources always passes eligibility + period: 2024-01 + input: + state_code: IN + in_tanf_countable_resources: 0 + is_tanf_enrolled: false + output: + in_tanf_resources_eligible: true + # 0 <= 1_000 = true diff --git a/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/resources/integration_with_eligibility.yaml b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/resources/integration_with_eligibility.yaml new file mode 100644 index 00000000000..b7cad040313 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/in/fssa/tanf/resources/integration_with_eligibility.yaml @@ -0,0 +1,78 @@ +- name: Eligible with low resources and low income + period: 2024-01 + input: + people: + parent: + age: 30 + is_pregnant: false + employment_income: + 2024: 12_000 # $1_000/month + child: + age: 5 + spm_units: + spm_unit: + members: [parent, child] + spm_unit_assets: 500 # Below $1_000 limit + households: + household: + members: [parent, child] + state_code: IN + household_vehicles_value: 0 # No vehicle + output: + in_tanf_countable_resources: 500 # 500 - 0 vehicle exclusion = 500 + in_tanf_resources_eligible: true + in_tanf_eligible: true + # Meets all eligibility criteria + +- name: Ineligible due to excess resources despite low income + period: 2024-01 + input: + people: + parent: + age: 30 + is_pregnant: false + employment_income: + 2024: 12_000 # $1_000/month (low income) + child: + age: 5 + spm_units: + spm_unit: + members: [parent, child] + spm_unit_assets: 25_000 # Well above limits (includes vehicle) + households: + household: + members: [parent, child] + state_code: IN + household_vehicles_value: 20_000 # Vehicle at exclusion limit + output: + in_tanf_countable_resources: 5_000 # 25_000 - min(20_000, 20_000) = 5_000 + in_tanf_resources_eligible: false # 5_000 > 1_000 application limit + in_tanf_eligible: false # Fails resources test + # Income eligible but resources too high + +- name: Enrolled recipient can have higher resources + period: 2024-01 + input: + people: + parent: + age: 30 + is_pregnant: false + employment_income: + 2024: 12_000 + child: + age: 5 + spm_units: + spm_unit: + members: [parent, child] + spm_unit_assets: 25_000 # Above application limit but below ongoing (includes vehicle) + is_tanf_enrolled: true # Currently enrolled + households: + household: + members: [parent, child] + state_code: IN + household_vehicles_value: 20_000 # Vehicle at exclusion limit + output: + in_tanf_countable_resources: 5_000 # 25_000 - min(20_000, 20_000) = 5_000 + in_tanf_resources_eligible: true # 5_000 < 10_000 ongoing limit + in_tanf_eligible: true + # Uses higher limit for enrolled recipients diff --git a/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_countable_income_eligible.py b/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_countable_income_eligible.py new file mode 100644 index 00000000000..58fe12f038a --- /dev/null +++ b/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_countable_income_eligible.py @@ -0,0 +1,31 @@ +from policyengine_us.model_api import * + + +class in_tanf_countable_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Indiana TANF countable income eligible" + definition_period = MONTH + reference = ( + "https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-1", + "https://iga.in.gov/laws/2025/ic/titles/12/#12-14-1-1.7", + ) + defined_for = StateCode.IN + + def formula(spm_unit, period, parameters): + # Initial: standard of need; Continuing: FPL * rate + p = parameters(period).gov.states["in"].fssa.tanf + countable = spm_unit( + "in_tanf_countable_income_for_eligibility", period + ) + is_enrolled = spm_unit("is_tanf_enrolled", period) + + fpg = spm_unit("tanf_fpg", period) + continuing_threshold = fpg * p.eligibility.continuing.fpg_rate + + threshold = where( + is_enrolled, + continuing_threshold, + spm_unit("in_tanf_payment_standard", period), + ) + return countable < threshold diff --git a/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_eligible.py b/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_eligible.py new file mode 100644 index 00000000000..e7f793152e6 --- /dev/null +++ b/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_eligible.py @@ -0,0 +1,36 @@ +from policyengine_us.model_api import * + + +class in_tanf_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Indiana TANF eligible" + definition_period = MONTH + reference = "https://iar.iga.in.gov/code/2026/470/10.3" # 470 IAC 10.3 + defined_for = StateCode.IN + + def formula(spm_unit, period, parameters): + # Demographic eligibility - use federal baseline + # Per IC 12-14-1-0.5 and 470 IAC 10.3-3 + demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) + + # Immigration eligibility - must have at least one citizen or qualified noncitizen + # Per IC 12-14-1-1 + person = spm_unit.members + immigration_eligible = spm_unit.any( + person("is_citizen_or_legal_immigrant", period.this_year) + ) + + # Income eligibility - state-specific + income_eligible = spm_unit("in_tanf_income_eligible", period) + + # Resources eligibility - state-specific + # Per 470 IAC 10.3-3-6 + resources_eligible = spm_unit("in_tanf_resources_eligible", period) + + return ( + demographic_eligible + & immigration_eligible + & income_eligible + & resources_eligible + ) diff --git a/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_income_eligible.py b/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_income_eligible.py new file mode 100644 index 00000000000..34c6590150e --- /dev/null +++ b/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_income_eligible.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class in_tanf_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Indiana TANF income eligible" + definition_period = MONTH + reference = "https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4" # 470 IAC 10.3-4 + defined_for = StateCode.IN + + def formula(spm_unit, period, parameters): + # Indiana uses two income tests per 470 IAC 10.3-4: + # 1. Countable income test (with eligibility disregards) + # 2. Payment test (with payment disregards) + # Must pass both tests for fiscal eligibility. + countable_eligible = spm_unit( + "in_tanf_countable_income_eligible", period + ) + payment_eligible = spm_unit("in_tanf_payment_eligible", period) + return countable_eligible & payment_eligible diff --git a/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_payment_eligible.py b/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_payment_eligible.py new file mode 100644 index 00000000000..273a61a33c5 --- /dev/null +++ b/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_payment_eligible.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class in_tanf_payment_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Indiana TANF payment eligible" + definition_period = MONTH + reference = ( + "https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-3", + "https://iga.in.gov/laws/2025/ic/titles/12/#12-14-2-5", + ) + defined_for = StateCode.IN + + def formula(spm_unit, period, parameters): + countable = spm_unit("in_tanf_countable_income_for_payment", period) + payment_standard = spm_unit("in_tanf_payment_standard", period) + return countable < payment_standard diff --git a/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_resources_eligible.py b/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_resources_eligible.py new file mode 100644 index 00000000000..bf033a68739 --- /dev/null +++ b/policyengine_us/variables/gov/states/in/fssa/tanf/eligibility/in_tanf_resources_eligible.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class in_tanf_resources_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Indiana TANF resources eligible" + definition_period = MONTH + defined_for = StateCode.IN + reference = ( + "https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-2", + "https://iga.in.gov/laws/2025/ic/titles/12/#12-14-1-1", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states["in"].fssa.tanf.resources.limit + countable = spm_unit("in_tanf_countable_resources", period) + is_enrolled = spm_unit("is_tanf_enrolled", period) + + limit = where( + is_enrolled, + p.while_receiving.amount, + p.at_application.amount, + ) + return countable <= limit diff --git a/policyengine_us/variables/gov/states/in/fssa/tanf/in_tanf.py b/policyengine_us/variables/gov/states/in/fssa/tanf/in_tanf.py new file mode 100644 index 00000000000..19c08ad8858 --- /dev/null +++ b/policyengine_us/variables/gov/states/in/fssa/tanf/in_tanf.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class in_tanf(Variable): + value_type = float + entity = SPMUnit + label = "Indiana Temporary Assistance for Needy Families (TANF)" + unit = USD + definition_period = MONTH + reference = ( + "https://iga.in.gov/laws/2025/ic/titles/12/#12-14-2-5", + "https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-4", + ) + defined_for = "in_tanf_eligible" + + def formula(spm_unit, period, parameters): + payment_standard = spm_unit("in_tanf_payment_standard", period) + countable_income = spm_unit( + "in_tanf_countable_income_for_payment", period + ) + return max_(payment_standard - countable_income, 0) diff --git a/policyengine_us/variables/gov/states/in/fssa/tanf/in_tanf_payment_standard.py b/policyengine_us/variables/gov/states/in/fssa/tanf/in_tanf_payment_standard.py new file mode 100644 index 00000000000..61f745d799d --- /dev/null +++ b/policyengine_us/variables/gov/states/in/fssa/tanf/in_tanf_payment_standard.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class in_tanf_payment_standard(Variable): + value_type = float + entity = SPMUnit + label = "Indiana TANF payment standard" + unit = USD + definition_period = MONTH + reference = ( + "https://iga.in.gov/laws/2025/ic/titles/12/#12-14-2-5", + "https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-3", + ) + defined_for = StateCode.IN + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states["in"].fssa.tanf.standard_of_need + capped_size = min_(spm_unit("spm_unit_size", period), p.max_unit_size) + return p.amount[capped_size] diff --git a/policyengine_us/variables/gov/states/in/fssa/tanf/income/in_tanf_countable_earned_income.py b/policyengine_us/variables/gov/states/in/fssa/tanf/income/in_tanf_countable_earned_income.py new file mode 100644 index 00000000000..fd47cc3598c --- /dev/null +++ b/policyengine_us/variables/gov/states/in/fssa/tanf/income/in_tanf_countable_earned_income.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class in_tanf_countable_earned_income(Variable): + value_type = float + entity = SPMUnit + label = "Indiana TANF countable earned income" + unit = USD + definition_period = MONTH + reference = "https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-4" + defined_for = StateCode.IN + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states["in"].fssa.tanf.income.deductions + person = spm_unit.members + gross_earned = person("tanf_gross_earned_income", period) + # 75% disregard per 470 IAC 10.3-4-4(d)(1) + return spm_unit.sum( + gross_earned * (1 - p.benefit.earned_income_disregard.rate) + ) diff --git a/policyengine_us/variables/gov/states/in/fssa/tanf/income/in_tanf_countable_earned_income_for_eligibility.py b/policyengine_us/variables/gov/states/in/fssa/tanf/income/in_tanf_countable_earned_income_for_eligibility.py new file mode 100644 index 00000000000..d786d580ab7 --- /dev/null +++ b/policyengine_us/variables/gov/states/in/fssa/tanf/income/in_tanf_countable_earned_income_for_eligibility.py @@ -0,0 +1,33 @@ +from policyengine_us.model_api import * + + +class in_tanf_countable_earned_income_for_eligibility(Variable): + value_type = float + entity = SPMUnit + label = ( + "Indiana TANF countable earned income for eligibility determination" + ) + unit = USD + definition_period = MONTH + reference = ( + "https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-4", + "https://iga.in.gov/laws/2025/ic/titles/12/#12-14-2-3", + ) + defined_for = StateCode.IN + + def formula(spm_unit, period, parameters): + # NOTE: The $30 and 1/3 disregard only applies for the first 4 months + # of continuing eligibility. This simplified implementation always + # applies the disregard since PolicyEngine cannot track benefit history. + p = parameters(period).gov.states["in"].fssa.tanf.income.deductions + person = spm_unit.members + gross_earned = person("tanf_gross_earned_income", period) + + # $90 per earner, then $30 + 1/3 per unit (470 IAC 10.3-4-4(c)) + after_work_expense = spm_unit.sum( + max_(gross_earned - p.work_expense.amount, 0) + ) + after_flat = max_( + after_work_expense - p.eligibility.flat_disregard.amount, 0 + ) + return after_flat * (1 - p.eligibility.earned_income_disregard.rate) diff --git a/policyengine_us/variables/gov/states/in/fssa/tanf/income/in_tanf_countable_income_for_eligibility.py b/policyengine_us/variables/gov/states/in/fssa/tanf/income/in_tanf_countable_income_for_eligibility.py new file mode 100644 index 00000000000..6de2b9b6c98 --- /dev/null +++ b/policyengine_us/variables/gov/states/in/fssa/tanf/income/in_tanf_countable_income_for_eligibility.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class in_tanf_countable_income_for_eligibility(Variable): + value_type = float + entity = SPMUnit + label = "Indiana TANF countable income for eligibility determination" + unit = USD + definition_period = MONTH + reference = ( + "https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-4", + "https://iga.in.gov/laws/2025/ic/titles/12/#12-14-2-3", + ) + defined_for = StateCode.IN + + adds = [ + "in_tanf_countable_earned_income_for_eligibility", + "tanf_gross_unearned_income", + ] diff --git a/policyengine_us/variables/gov/states/in/fssa/tanf/income/in_tanf_countable_income_for_payment.py b/policyengine_us/variables/gov/states/in/fssa/tanf/income/in_tanf_countable_income_for_payment.py new file mode 100644 index 00000000000..2f7802b35ea --- /dev/null +++ b/policyengine_us/variables/gov/states/in/fssa/tanf/income/in_tanf_countable_income_for_payment.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class in_tanf_countable_income_for_payment(Variable): + value_type = float + entity = SPMUnit + label = "Indiana TANF countable income for payment calculation" + unit = USD + definition_period = MONTH + reference = "https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-4" + defined_for = StateCode.IN + + adds = ["in_tanf_countable_earned_income", "tanf_gross_unearned_income"] diff --git a/policyengine_us/variables/gov/states/in/fssa/tanf/resources/in_tanf_countable_resources.py b/policyengine_us/variables/gov/states/in/fssa/tanf/resources/in_tanf_countable_resources.py new file mode 100644 index 00000000000..4cf8fb64409 --- /dev/null +++ b/policyengine_us/variables/gov/states/in/fssa/tanf/resources/in_tanf_countable_resources.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class in_tanf_countable_resources(Variable): + value_type = float + entity = SPMUnit + label = "Indiana TANF countable resources" + unit = USD + definition_period = MONTH + defined_for = StateCode.IN + reference = ( + "https://iar.iga.in.gov/code/2026/470/10.3#470-10.3-4-2", + "https://iga.in.gov/laws/2025/ic/titles/12/#12-14-2-1", + ) + + def formula(spm_unit, period, parameters): + p = ( + parameters(period) + .gov.states["in"] + .fssa.tanf.resources.vehicle_exemption + ) + total_assets = spm_unit("spm_unit_assets", period.this_year) + vehicle_value = spm_unit.household( + "household_vehicles_value", period.this_year + ) + excluded_vehicle = min_(vehicle_value, p.amount) + return max_(total_assets - excluded_vehicle, 0)