From 8e82222679b7c0c33f9adbf61182dd0e1487091b Mon Sep 17 00:00:00 2001 From: Ziming Date: Sun, 14 Dec 2025 13:07:07 -0500 Subject: [PATCH 1/8] Initial commit for Arkansas TANF implementation Starting implementation of Arkansas Transitional Employment Assistance (TEA). Documentation and parallel development will follow. From 0bfe68d227f8d0d76ef8a0311c8f0f169ee81af6 Mon Sep 17 00:00:00 2001 From: Ziming Date: Sun, 14 Dec 2025 13:36:13 -0500 Subject: [PATCH 2/8] Add Arkansas TANF implementation with changelog entry - Add AR TANF variables: eligibility, income, maximum benefit, resources - Add parameters: payment standards, income deductions, resource limits - Add comprehensive unit tests and integration tests - Add changelog entry for the implementation Closes #6970 --- changelog_entry.yaml | 4 + .../income/deductions/work_expense/rate.yaml | 14 + .../deductions/work_incentive/rate.yaml | 14 + .../income/eligibility_standard/amount.yaml | 14 + .../income/gross_income_trigger/amount.yaml | 14 + .../gross_income_trigger/reduction_rate.yaml | 12 + .../ar/dhs/tanf/payment_standard/amount.yaml | 52 ++++ .../tanf/payment_standard/max_unit_size.yaml | 12 + .../states/ar/dhs/tanf/resources/limit.yaml | 14 + .../gov/states/ar/dhs/tanf/ar_tanf.yaml | 140 +++++++++ .../tanf/ar_tanf_countable_earned_income.yaml | 100 ++++++ .../ar/dhs/tanf/ar_tanf_countable_income.yaml | 98 ++++++ .../states/ar/dhs/tanf/ar_tanf_eligible.yaml | 100 ++++++ .../ar/dhs/tanf/ar_tanf_income_eligible.yaml | 93 ++++++ .../ar/dhs/tanf/ar_tanf_maximum_benefit.yaml | 181 +++++++++++ .../dhs/tanf/ar_tanf_resources_eligible.yaml | 97 ++++++ .../gov/states/ar/dhs/tanf/integration.yaml | 288 ++++++++++++++++++ .../gov/states/ar/dhs/tanf/ar_tanf.py | 35 +++ .../tanf/ar_tanf_countable_earned_income.py | 24 ++ .../ar/dhs/tanf/ar_tanf_countable_income.py | 16 + .../states/ar/dhs/tanf/ar_tanf_eligible.py | 17 ++ .../ar/dhs/tanf/ar_tanf_income_eligible.py | 19 ++ .../ar/dhs/tanf/ar_tanf_maximum_benefit.py | 18 ++ .../ar/dhs/tanf/ar_tanf_resources_eligible.py | 17 ++ 24 files changed, 1393 insertions(+) create mode 100644 policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_expense/rate.yaml create mode 100644 policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_incentive/rate.yaml create mode 100644 policyengine_us/parameters/gov/states/ar/dhs/tanf/income/eligibility_standard/amount.yaml create mode 100644 policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/amount.yaml create mode 100644 policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/reduction_rate.yaml create mode 100644 policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/amount.yaml create mode 100644 policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/max_unit_size.yaml create mode 100644 policyengine_us/parameters/gov/states/ar/dhs/tanf/resources/limit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/integration.yaml create mode 100644 policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf.py create mode 100644 policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.py create mode 100644 policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_income.py create mode 100644 policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_eligible.py create mode 100644 policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.py create mode 100644 policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.py diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..4dfbc07cdc2 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: minor + changes: + added: + - Implement Arkansas Transitional Employment Assistance (TEA/TANF) program diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_expense/rate.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_expense/rate.yaml new file mode 100644 index 00000000000..afba2e3f679 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_expense/rate.yaml @@ -0,0 +1,14 @@ +description: Arkansas deducts this share of gross earned income as work-related expenses under the Transitional Employment Assistance program. + +values: + 1997-09-01: 0.2 + +metadata: + unit: /1 + period: month + label: Arkansas TANF work expense deduction rate + reference: + - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Eligibility Standard + href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 + - title: 016.20.98-041 Ark. Code R. - TEA Policy 2352-2362, Work Expense Deduction + href: https://regulations.justia.com/states/arkansas/agency-016/division-20/rule-016-20-98-041/ diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_incentive/rate.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_incentive/rate.yaml new file mode 100644 index 00000000000..84c8ff11d98 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_incentive/rate.yaml @@ -0,0 +1,14 @@ +description: Arkansas deducts this share of remaining earned income as a work incentive under the Transitional Employment Assistance program. + +values: + 1997-09-01: 0.6 + +metadata: + unit: /1 + period: month + label: Arkansas TANF work incentive deduction rate + reference: + - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Eligibility Standard + href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 + - title: 016.20.98-041 Ark. Code R. - TEA Policy 2352-2362, Work Incentive Deduction + href: https://regulations.justia.com/states/arkansas/agency-016/division-20/rule-016-20-98-041/ diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/eligibility_standard/amount.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/eligibility_standard/amount.yaml new file mode 100644 index 00000000000..1b6527b7690 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/eligibility_standard/amount.yaml @@ -0,0 +1,14 @@ +description: Arkansas limits countable income to this amount for eligibility under the Transitional Employment Assistance program. + +values: + 1997-09-01: 223 + +metadata: + unit: currency-USD + period: month + label: Arkansas TANF income eligibility standard + reference: + - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Eligibility Standard + href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 + - title: Arkansas TEA/Work Pays Program + href: https://humanservices.arkansas.gov/divisions-shared-services/county-operations/temporary-assistance-for-needy-families/transitional-employment-assistance-tea-work-pays/ diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/amount.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/amount.yaml new file mode 100644 index 00000000000..f58fb7c53ae --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/amount.yaml @@ -0,0 +1,14 @@ +description: Arkansas reduces the payment by half when gross income equals or exceeds this amount under the Transitional Employment Assistance program. + +values: + 1997-09-01: 446 + +metadata: + unit: currency-USD + period: month + label: Arkansas TANF gross income trigger threshold + reference: + - title: 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - Payment Standards + href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 + - title: Arkansas TEA/Work Pays Program + href: https://humanservices.arkansas.gov/divisions-shared-services/county-operations/temporary-assistance-for-needy-families/transitional-employment-assistance-tea-work-pays/ diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/reduction_rate.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/reduction_rate.yaml new file mode 100644 index 00000000000..a2a5af4906a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/reduction_rate.yaml @@ -0,0 +1,12 @@ +description: Arkansas reduces the payment by this share when gross income equals or exceeds the trigger amount under the Transitional Employment Assistance program. + +values: + 1997-09-01: 0.5 + +metadata: + unit: /1 + period: month + label: Arkansas TANF gross income trigger payment reduction rate + reference: + - title: 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - Payment Standards + href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/amount.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/amount.yaml new file mode 100644 index 00000000000..b92a8eb8c6c --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/amount.yaml @@ -0,0 +1,52 @@ +description: Arkansas provides this amount as the maximum monthly payment under the Transitional Employment Assistance program. + +metadata: + unit: currency-USD + period: month + breakdown: + - range(1, 20) + label: Arkansas TANF payment standard amount + reference: + - title: 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - Payment Standards + href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 + - title: Arkansas TEA/Work Pays Program + href: https://humanservices.arkansas.gov/divisions-shared-services/county-operations/temporary-assistance-for-needy-families/transitional-employment-assistance-tea-work-pays/ + +1: + 1997-09-01: 81 +2: + 1997-09-01: 162 +3: + 1997-09-01: 204 +4: + 1997-09-01: 247 +5: + 1997-09-01: 286 +6: + 1997-09-01: 331 +7: + 1997-09-01: 373 +8: + 1997-09-01: 415 +9: + 1997-09-01: 457 +10: + 1997-09-01: 457 +11: + 1997-09-01: 457 +12: + 1997-09-01: 457 +13: + 1997-09-01: 457 +14: + 1997-09-01: 457 +15: + 1997-09-01: 457 +16: + 1997-09-01: 457 +17: + 1997-09-01: 457 +18: + 1997-09-01: 457 +19: + 1997-09-01: 457 diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/max_unit_size.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/max_unit_size.yaml new file mode 100644 index 00000000000..9746a97b928 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/max_unit_size.yaml @@ -0,0 +1,12 @@ +description: Arkansas provides increased payment amounts for households with up to this number of members under the Transitional Employment Assistance program. + +values: + 1997-09-01: 9 + +metadata: + unit: int + period: month + label: Arkansas TANF payment standard max unit size + reference: + - title: 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - Payment Standards + href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/resources/limit.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tanf/resources/limit.yaml new file mode 100644 index 00000000000..ab4295e168a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/dhs/tanf/resources/limit.yaml @@ -0,0 +1,14 @@ +description: Arkansas limits countable resources to this amount for eligibility under the Transitional Employment Assistance program. + +values: + 1997-09-01: 3_000 + +metadata: + unit: currency-USD + period: month + label: Arkansas TANF resource limit + reference: + - title: 208.00.13 Ark. Code R. Section 001, Section 3.4 - Resource Limits + href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 + - title: Arkansas TEA/Work Pays Program + href: https://humanservices.arkansas.gov/divisions-shared-services/county-operations/temporary-assistance-for-needy-families/transitional-employment-assistance-tea-work-pays/ diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf.yaml new file mode 100644 index 00000000000..ac06cddccfa --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf.yaml @@ -0,0 +1,140 @@ +# Unit tests for ar_tanf (final benefit amount) +# Benefit calculation: +# 1. If not eligible: $0 +# 2. If gross income < $446: benefit = max(payment_standard - countable_income, 0) +# 3. If gross income >= $446: benefit = max(payment_standard * 0.5 - countable_income, 0) + +- name: Case 1, ineligible receives zero. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 0 + tanf_gross_unearned_income: 0 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_eligible: false + ar_tanf_maximum_benefit: 204 + ar_tanf_countable_income: 0 + output: + ar_tanf: 0 + # Not eligible -> no benefit + +- name: Case 2, eligible with zero income receives full benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 0 + tanf_gross_unearned_income: 0 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_eligible: true + ar_tanf_maximum_benefit: 204 + ar_tanf_countable_income: 0 + output: + ar_tanf: 204 + # max(204 - 0, 0) = 204 + +- name: Case 3, eligible with countable income below payment standard. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 400 + tanf_gross_unearned_income: 0 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_eligible: true + ar_tanf_maximum_benefit: 204 + ar_tanf_countable_income: 128 + output: + ar_tanf: 76 + # Gross income 400 < 446 trigger, so full payment standard applies + # max(204 - 128, 0) = 76 + +- name: Case 4, gross income at trigger causes 50 percent reduction. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 446 + tanf_gross_unearned_income: 0 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_eligible: true + ar_tanf_maximum_benefit: 204 + ar_tanf_countable_income: 0 + output: + ar_tanf: 102 + # Gross income 446 >= 446 trigger, so 50% reduction + # max(204 * 0.5 - 0, 0) = max(102 - 0, 0) = 102 + +- name: Case 5, gross income above trigger with countable income. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 500 + tanf_gross_unearned_income: 0 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_eligible: true + ar_tanf_maximum_benefit: 162 + ar_tanf_countable_income: 50 + output: + ar_tanf: 31 + # Gross income 500 >= 446 trigger, so 50% reduction + # max(162 * 0.5 - 50, 0) = max(81 - 50, 0) = 31 + +- name: Case 6, benefit would be negative clipped to zero. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 0 + tanf_gross_unearned_income: 0 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_eligible: true + ar_tanf_maximum_benefit: 81 + ar_tanf_countable_income: 100 + output: + ar_tanf: 0 + # max(81 - 100, 0) = max(-19, 0) = 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.yaml new file mode 100644 index 00000000000..a6bd0904b35 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.yaml @@ -0,0 +1,100 @@ +# Unit tests for ar_tanf_countable_earned_income +# Arkansas TEA applies sequential earned income deductions: +# Step 1: 20% work-related expense deduction +# Step 2: 60% work incentive deduction on remainder +# Combined: Net = Gross x 0.80 x 0.40 = Gross x 0.32 + +- name: Case 1, zero earned income. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 0 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + output: + ar_tanf_countable_earned_income: 0 + # Calculation: 0 * 0.32 = 0 + +- name: Case 2, single earner with low income. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 300 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + output: + ar_tanf_countable_earned_income: 96 + # Step 1: 300 * 0.80 = 240 (after 20% work expense) + # Step 2: 240 * 0.40 = 96 (after 60% work incentive) + +- name: Case 3, documentation example with 550 gross earnings. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 550 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + output: + ar_tanf_countable_earned_income: 176 + # Step 1: 550 * 0.80 = 440 (after 20% work expense) + # Step 2: 440 * 0.40 = 176 (after 60% work incentive) + +- name: Case 4, gross income at trigger threshold. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 446 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + output: + ar_tanf_countable_earned_income: 142.72 + # Step 1: 446 * 0.80 = 356.8 (after 20% work expense) + # Step 2: 356.8 * 0.40 = 142.72 (after 60% work incentive) + +- name: Case 5, higher earnings yielding net above eligibility standard. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 800 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + output: + ar_tanf_countable_earned_income: 256 + # Step 1: 800 * 0.80 = 640 (after 20% work expense) + # Step 2: 640 * 0.40 = 256 (after 60% work incentive) + # Note: 256 > 223 eligibility standard, so would be income ineligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_income.yaml new file mode 100644 index 00000000000..63d2fda252c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_income.yaml @@ -0,0 +1,98 @@ +# Unit tests for ar_tanf_countable_income +# Total countable income = countable earned income + unearned income +# Note: Earned income has already been reduced by 20% + 60% deductions +# Unearned income has no deductions applied + +- name: Case 1, zero income. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_unearned_income: 0 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_countable_earned_income: 0 + output: + ar_tanf_countable_income: 0 + +- name: Case 2, only earned income. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_unearned_income: 0 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_countable_earned_income: 176 + output: + ar_tanf_countable_income: 176 + # 176 (earned after disregards) + 0 (unearned) = 176 + +- name: Case 3, only unearned income. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_unearned_income: 150 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_countable_earned_income: 0 + output: + ar_tanf_countable_income: 150 + # 0 (earned) + 150 (unearned) = 150 + +- name: Case 4, mixed earned and unearned income. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_unearned_income: 100 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_countable_earned_income: 96 + output: + ar_tanf_countable_income: 196 + # 96 (earned after disregards) + 100 (unearned) = 196 + +- name: Case 5, income at eligibility threshold. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_unearned_income: 100 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_countable_earned_income: 123 + output: + ar_tanf_countable_income: 223 + # 123 + 100 = 223 (exactly at $223 income eligibility standard) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_eligible.yaml new file mode 100644 index 00000000000..7374aeb83b6 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_eligible.yaml @@ -0,0 +1,100 @@ +# Unit tests for ar_tanf_eligible +# Overall eligibility requires: +# 1. Income eligibility (countable income <= $223) +# 2. Resource eligibility (resources <= $3,000) +# 3. Demographic eligibility (from federal baseline - SPM unit level) + +- name: Case 1, all requirements met. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_income_eligible: true + ar_tanf_resources_eligible: true + is_demographic_tanf_eligible: true + output: + ar_tanf_eligible: true + +- name: Case 2, income ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_income_eligible: false + ar_tanf_resources_eligible: true + is_demographic_tanf_eligible: true + output: + ar_tanf_eligible: false + +- name: Case 3, resources ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_income_eligible: true + ar_tanf_resources_eligible: false + is_demographic_tanf_eligible: true + output: + ar_tanf_eligible: false + +- name: Case 4, demographic ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_income_eligible: true + ar_tanf_resources_eligible: true + is_demographic_tanf_eligible: false + output: + ar_tanf_eligible: false + +- name: Case 5, multiple requirements not met. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_income_eligible: false + ar_tanf_resources_eligible: false + is_demographic_tanf_eligible: true + output: + ar_tanf_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.yaml new file mode 100644 index 00000000000..440f3fb6fba --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.yaml @@ -0,0 +1,93 @@ +# Unit tests for ar_tanf_income_eligible +# Arkansas TEA has a fixed income eligibility standard of $223/month for ALL family sizes +# A household is income eligible if countable income <= $223 + +- name: Case 1, zero income is eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_countable_income: 0 + output: + ar_tanf_income_eligible: true + # 0 <= 223 -> eligible + +- name: Case 2, income below threshold. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_countable_income: 150 + output: + ar_tanf_income_eligible: true + # 150 <= 223 -> eligible + +- name: Case 3, income exactly at threshold. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_countable_income: 223 + output: + ar_tanf_income_eligible: true + # 223 <= 223 -> eligible (at threshold is still eligible) + +- name: Case 4, income one dollar over threshold. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_countable_income: 224 + output: + ar_tanf_income_eligible: false + # 224 > 223 -> ineligible + +- name: Case 5, income well above threshold. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tanf_countable_income: 500 + output: + ar_tanf_income_eligible: false + # 500 > 223 -> ineligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.yaml new file mode 100644 index 00000000000..fada13af330 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.yaml @@ -0,0 +1,181 @@ +# Unit tests for ar_tanf_maximum_benefit +# Arkansas TEA payment standards by family size (full payment, before 50% reduction): +# 1: $81, 2: $162, 3: $204, 4: $247, 5: $286 +# 6: $331, 7: $373, 8: $415, 9+: $457 + +- name: Case 1, family size 1. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + spm_unit_size: 1 + output: + ar_tanf_maximum_benefit: 81 + +- name: Case 2, family size 2. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 10 + households: + household: + members: [person1, person2] + state_code: AR + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_size: 2 + output: + ar_tanf_maximum_benefit: 162 + +- name: Case 3, family size 3. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 10 + person3: + age: 8 + households: + household: + members: [person1, person2, person3] + state_code: AR + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_size: 3 + output: + ar_tanf_maximum_benefit: 204 + +- name: Case 4, family size 4. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + spm_unit_size: 4 + output: + ar_tanf_maximum_benefit: 247 + +- name: Case 5, family size 5. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + spm_unit_size: 5 + output: + ar_tanf_maximum_benefit: 286 + +- name: Case 6, family size 6. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + spm_unit_size: 6 + output: + ar_tanf_maximum_benefit: 331 + +- name: Case 7, family size 7. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + spm_unit_size: 7 + output: + ar_tanf_maximum_benefit: 373 + +- name: Case 8, family size 8. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + spm_unit_size: 8 + output: + ar_tanf_maximum_benefit: 415 + +- name: Case 9, family size 9 or more. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + spm_unit_size: 9 + output: + ar_tanf_maximum_benefit: 457 + +- name: Case 10, family size 10 capped at 9 rate. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + spm_unit_size: 10 + output: + ar_tanf_maximum_benefit: 457 + # Family sizes 9+ all receive $457 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.yaml new file mode 100644 index 00000000000..afe26d7bfe1 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.yaml @@ -0,0 +1,97 @@ +# Unit tests for ar_tanf_resources_eligible +# Arkansas TEA has a fixed resource limit of $3,000 for ALL family sizes +# Countable resources exclude: +# - Family homestead (residence) +# - One operable vehicle +# - Household goods and personal effects +# - Resources of SSI recipients + +- name: Case 1, zero resources is eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 0 + output: + ar_tanf_resources_eligible: true + # 0 <= 3,000 -> eligible + +- name: Case 2, resources well below limit. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 1_500 + output: + ar_tanf_resources_eligible: true + # 1,500 <= 3,000 -> eligible + +- name: Case 3, resources exactly at limit. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 3_000 + output: + ar_tanf_resources_eligible: true + # 3,000 <= 3,000 -> eligible (at limit is still eligible) + +- name: Case 4, resources one dollar over limit. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 3_001 + output: + ar_tanf_resources_eligible: false + # 3,001 > 3,000 -> ineligible + +- name: Case 5, resources well above limit. + period: 2024-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 10_000 + output: + ar_tanf_resources_eligible: false + # 10,000 > 3,000 -> ineligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/integration.yaml new file mode 100644 index 00000000000..214ddf33d15 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/integration.yaml @@ -0,0 +1,288 @@ +# Integration tests for Arkansas TANF (TEA - Transitional Employment Assistance) +# These tests verify the complete benefit calculation pipeline from inputs to final benefit + +- name: Case 1, family of 3 with no income receives full benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + # Income calculation chain + tanf_gross_earned_income: [0, 0, 0] + # No earned income for any member + ar_tanf_countable_earned_income: 0 + # 0 * 0.32 = 0 (after 20% + 60% deductions) + ar_tanf_countable_income: 0 + # 0 (earned) + 0 (unearned) = 0 + + # Eligibility chain + ar_tanf_income_eligible: true + # 0 <= 223 -> eligible + ar_tanf_resources_eligible: true + # 1,000 <= 3,000 -> eligible + ar_tanf_eligible: true + + # Benefit calculation + ar_tanf_maximum_benefit: 204 + # Family size 3 -> $204 payment standard + ar_tanf: 204 + # Gross income 0 < 446, so full payment + # max(204 - 0, 0) = 204 + +- name: Case 2, family of 3 with earned income below trigger receives partial benefit. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 4_800 + # Annual $4,800 = $400/month + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 500 + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + # Income calculation chain + tanf_gross_earned_income: [400, 0, 0] + # Person1: 4,800 / 12 = 400/month + ar_tanf_countable_earned_income: 128 + # Step 1: 400 * 0.80 = 320 (after 20% work expense) + # Step 2: 320 * 0.40 = 128 (after 60% work incentive) + ar_tanf_countable_income: 128 + # 128 (earned) + 0 (unearned) = 128 + + # Eligibility chain + ar_tanf_income_eligible: true + # 128 <= 223 -> eligible + ar_tanf_resources_eligible: true + # 500 <= 3,000 -> eligible + ar_tanf_eligible: true + + # Benefit calculation + ar_tanf_maximum_benefit: 204 + # Family size 3 -> $204 + ar_tanf: 76 + # Gross income 400 < 446, so full payment standard + # max(204 - 128, 0) = 76 + +- name: Case 3, family of 2 with earnings at gross income trigger. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 5_352 + # Annual $5,352 = $446/month (at trigger threshold) + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 2_000 + households: + household: + members: [person1, person2] + state_code: AR + output: + # Income calculation chain + tanf_gross_earned_income: [446, 0] + # Person1: 5,352 / 12 = 446/month + ar_tanf_countable_earned_income: 142.72 + # 446 * 0.80 * 0.40 = 142.72 + ar_tanf_countable_income: 142.72 + + # Eligibility chain + ar_tanf_income_eligible: true + # 142.72 <= 223 -> eligible + ar_tanf_resources_eligible: true + # 2,000 <= 3,000 -> eligible + ar_tanf_eligible: true + + # Benefit calculation + ar_tanf_maximum_benefit: 162 + # Family size 2 -> $162 + ar_tanf: 0 + # Gross income 446 >= 446, so 50% reduction applies + # Reduced payment = 162 * 0.5 = 81 + # max(81 - 142.72, 0) = max(-61.72, 0) = 0 + +- name: Case 4, family of 4 with earnings above trigger but still eligible. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 + # Annual $6,000 = $500/month + person2: + age: 28 + employment_income_before_lsr: 0 + person3: + age: 10 + person4: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + spm_unit_assets: 1_500 + households: + household: + members: [person1, person2, person3, person4] + state_code: AR + output: + # Income calculation chain + tanf_gross_earned_income: [500, 0, 0, 0] + # Person1: 6,000 / 12 = 500/month + ar_tanf_countable_earned_income: 160 + # 500 * 0.80 * 0.40 = 160 + ar_tanf_countable_income: 160 + + # Eligibility chain + ar_tanf_income_eligible: true + # 160 <= 223 -> eligible + ar_tanf_eligible: true + + # Benefit calculation + ar_tanf_maximum_benefit: 247 + # Family size 4 -> $247 + ar_tanf: 0 + # Gross income 500 >= 446, so 50% reduction + # Reduced payment = 247 * 0.5 = 123.5 + # max(123.5 - 160, 0) = 0 + +- name: Case 5, documentation example 550 gross earnings. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_600 + # Annual $6,600 = $550/month (from documentation) + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 500 + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + # Income calculation chain (per documentation example) + tanf_gross_earned_income: [550, 0, 0] + # Person1: 6,600 / 12 = 550/month + ar_tanf_countable_earned_income: 176 + # Step 1: 550 * 0.80 = 440 (after 20% work expense) + # Step 2: 440 * 0.40 = 176 (after 60% work incentive) + ar_tanf_countable_income: 176 + + # Eligibility chain + ar_tanf_income_eligible: true + # 176 <= 223 -> eligible + ar_tanf_eligible: true + + # Benefit calculation + ar_tanf_maximum_benefit: 204 + ar_tanf: 0 + # Gross income 550 >= 446, so 50% reduction + # Reduced payment = 204 * 0.5 = 102 + # max(102 - 176, 0) = 0 + +- name: Case 6, income exceeds eligibility standard making family ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 9_600 + # Annual $9,600 = $800/month + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 1_000 + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + # Income calculation chain + tanf_gross_earned_income: [800, 0, 0] + ar_tanf_countable_earned_income: 256 + # 800 * 0.80 * 0.40 = 256 + ar_tanf_countable_income: 256 + + # Eligibility chain + ar_tanf_income_eligible: false + # 256 > 223 -> INELIGIBLE + ar_tanf_eligible: false + + # Benefit calculation + ar_tanf_maximum_benefit: 204 + ar_tanf: 0 + # Ineligible -> no benefit + +- name: Case 7, resources exceed limit making family ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 5_000 + # Exceeds $3,000 resource limit + households: + household: + members: [person1, person2] + state_code: AR + output: + # Income calculation chain + ar_tanf_countable_income: 0 + + # Eligibility chain + ar_tanf_income_eligible: true + # 0 <= 223 -> income eligible + ar_tanf_resources_eligible: false + # 5,000 > 3,000 -> RESOURCES INELIGIBLE + ar_tanf_eligible: false + + # Benefit calculation + ar_tanf_maximum_benefit: 162 + ar_tanf: 0 + # Ineligible -> no benefit diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf.py b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf.py new file mode 100644 index 00000000000..bafda45ad69 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf.py @@ -0,0 +1,35 @@ +from policyengine_us.model_api import * + + +class ar_tanf(Variable): + value_type = float + entity = SPMUnit + label = "Arkansas Transitional Employment Assistance (TANF)" + unit = USD + definition_period = MONTH + reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" + defined_for = "ar_tanf_eligible" + + def formula(spm_unit, period, parameters): + # Per 208.00.13 Ark. Code R. Section 001, Section 6.1.1 + p = parameters(period).gov.states.ar.dhs.tanf + + maximum_benefit = spm_unit("ar_tanf_maximum_benefit", period) + countable_income = spm_unit("ar_tanf_countable_income", period) + + # Check if gross income triggers 50% payment reduction + gross_earned = spm_unit("tanf_gross_earned_income", period) + unearned = spm_unit("tanf_gross_unearned_income", period) + gross_income = gross_earned + unearned + + trigger = p.income.gross_income_trigger + above_trigger = gross_income >= trigger.amount + + # Apply 50% reduction to maximum payment when above trigger + effective_maximum = where( + above_trigger, + maximum_benefit * (1 - trigger.reduction_rate), + maximum_benefit, + ) + + return max_(effective_maximum - countable_income, 0) diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.py b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.py new file mode 100644 index 00000000000..6f3b24e0c0c --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class ar_tanf_countable_earned_income(Variable): + value_type = float + entity = SPMUnit + label = "Arkansas TANF countable earned income" + unit = USD + definition_period = MONTH + reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" + defined_for = StateCode.AR + + def formula(spm_unit, period, parameters): + # Per 208.00.13 Ark. Code R. Section 001, Section 3.3 + p = parameters(period).gov.states.ar.dhs.tanf.income.deductions + gross_earned = spm_unit("tanf_gross_earned_income", period) + + # Step 1: Apply 20% work expense deduction + after_work_expense = gross_earned * (1 - p.work_expense.rate) + + # Step 2: Apply 60% work incentive deduction + countable_earned = after_work_expense * (1 - p.work_incentive.rate) + + return max_(countable_earned, 0) diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_income.py b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_income.py new file mode 100644 index 00000000000..3055957f537 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_income.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class ar_tanf_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "Arkansas TANF countable income" + unit = USD + definition_period = MONTH + reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" + defined_for = StateCode.AR + + def formula(spm_unit, period, parameters): + countable_earned = spm_unit("ar_tanf_countable_earned_income", period) + unearned = spm_unit("tanf_gross_unearned_income", period) + return countable_earned + unearned diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_eligible.py b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_eligible.py new file mode 100644 index 00000000000..28ef9dd848b --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ar_tanf_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Arkansas TANF eligible" + definition_period = MONTH + reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" + defined_for = StateCode.AR + + def formula(spm_unit, period, parameters): + income_eligible = spm_unit("ar_tanf_income_eligible", period) + resources_eligible = spm_unit("ar_tanf_resources_eligible", period) + # Use federal demographic eligibility (already SPM unit-level) + demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) + return income_eligible & resources_eligible & demographic_eligible diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.py b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.py new file mode 100644 index 00000000000..99605c95a14 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class ar_tanf_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Arkansas TANF income eligible" + definition_period = MONTH + reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" + defined_for = StateCode.AR + + def formula(spm_unit, period, parameters): + # Per 208.00.13 Ark. Code R. Section 001, Section 3.3 + # Income eligibility standard is $223/month for ALL family sizes + p = parameters( + period + ).gov.states.ar.dhs.tanf.income.eligibility_standard + countable_income = spm_unit("ar_tanf_countable_income", period) + return countable_income <= p.amount diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.py b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.py new file mode 100644 index 00000000000..26b90840481 --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class ar_tanf_maximum_benefit(Variable): + value_type = float + entity = SPMUnit + label = "Arkansas TANF maximum benefit" + unit = USD + definition_period = MONTH + reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" + defined_for = StateCode.AR + + def formula(spm_unit, period, parameters): + # Per 208.00.13 Ark. Code R. Section 001, Section 6.1.1 + p = parameters(period).gov.states.ar.dhs.tanf.payment_standard + unit_size = spm_unit("spm_unit_size", period.this_year) + capped_size = min_(unit_size, p.max_unit_size) + return p.amount[capped_size] diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.py b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.py new file mode 100644 index 00000000000..50ea36a47ed --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ar_tanf_resources_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Arkansas TANF resources eligible" + definition_period = MONTH + reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" + defined_for = StateCode.AR + + def formula(spm_unit, period, parameters): + # Per 208.00.13 Ark. Code R. Section 001, Section 3.4 + p = parameters(period).gov.states.ar.dhs.tanf.resources + # Use federal asset calculation for SPM unit + resources = spm_unit("spm_unit_assets", period.this_year) + return resources <= p.limit From 297542b7d6dc447ab0c7e6c38f0c25171a3bd510 Mon Sep 17 00:00:00 2001 From: Ziming Date: Sun, 14 Dec 2025 13:37:47 -0500 Subject: [PATCH 3/8] Update uv.lock --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index 728df755b14..bef6217d61e 100644 --- a/uv.lock +++ b/uv.lock @@ -2327,11 +2327,11 @@ wheels = [ [[package]] name = "tzdata" -version = "2025.2" +version = "2025.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380, upload-time = "2025-03-23T13:54:43.652Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839, upload-time = "2025-03-23T13:54:41.845Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, ] [[package]] From e3ba9199b82072ebfacaf5b30b7154b294788681 Mon Sep 17 00:00:00 2001 From: Ziming Date: Sun, 14 Dec 2025 17:54:49 -0500 Subject: [PATCH 4/8] adjustment --- .../tanf/income/gross_income_limit/rate.yaml | 14 +++ .../tanf/ar_tanf_countable_earned_income.yaml | 61 +++++++-- .../ar/dhs/tanf/ar_tanf_income_eligible.yaml | 93 ++++++++++++-- .../gov/states/ar/dhs/tanf/integration.yaml | 118 ++++++++++++++++-- .../tanf/ar_tanf_countable_earned_income.py | 16 ++- .../ar/dhs/tanf/ar_tanf_income_eligible.py | 21 +++- 6 files changed, 279 insertions(+), 44 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_limit/rate.yaml diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_limit/rate.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_limit/rate.yaml new file mode 100644 index 00000000000..16a4a5d0531 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_limit/rate.yaml @@ -0,0 +1,14 @@ +description: Arkansas limits gross income to this share of the federal poverty guideline under the Transitional Employment Assistance program. + +values: + 1997-09-01: 1.85 + +metadata: + unit: /1 + period: month + label: Arkansas TANF gross income limit rate + reference: + - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Eligibility Standard + href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 + - title: Arkansas TEA/Work Pays Program + href: https://humanservices.arkansas.gov/divisions-shared-services/county-operations/temporary-assistance-for-needy-families/transitional-employment-assistance-tea-work-pays/ diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.yaml index a6bd0904b35..d1c579efd3f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.yaml @@ -1,10 +1,10 @@ # Unit tests for ar_tanf_countable_earned_income # Arkansas TEA applies sequential earned income deductions: -# Step 1: 20% work-related expense deduction -# Step 2: 60% work incentive deduction on remainder -# Combined: Net = Gross x 0.80 x 0.40 = Gross x 0.32 +# - Initial applicants (not enrolled): 20% work-related expense deduction only +# - Ongoing recipients (enrolled): 20% work expense + 60% work incentive deduction +# Combined for ongoing: Net = Gross x 0.80 x 0.40 = Gross x 0.32 -- name: Case 1, zero earned income. +- name: Case 1, zero earned income (initial applicant). period: 2024-01 input: people: @@ -18,11 +18,11 @@ spm_units: spm_unit: members: [person1] + is_tanf_enrolled: false output: ar_tanf_countable_earned_income: 0 - # Calculation: 0 * 0.32 = 0 -- name: Case 2, single earner with low income. +- name: Case 2, initial applicant with low income (20% deduction only). period: 2024-01 input: people: @@ -36,12 +36,33 @@ spm_units: spm_unit: members: [person1] + is_tanf_enrolled: false + output: + ar_tanf_countable_earned_income: 240 + # Initial applicant: 300 * 0.80 = 240 (only 20% work expense) + +- name: Case 3, ongoing recipient with low income (20% + 60% deductions). + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 300 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + is_tanf_enrolled: true output: ar_tanf_countable_earned_income: 96 + # Ongoing recipient: # Step 1: 300 * 0.80 = 240 (after 20% work expense) # Step 2: 240 * 0.40 = 96 (after 60% work incentive) -- name: Case 3, documentation example with 550 gross earnings. +- name: Case 4, ongoing recipient documentation example with 550 gross earnings. period: 2024-01 input: people: @@ -55,12 +76,32 @@ spm_units: spm_unit: members: [person1] + is_tanf_enrolled: true output: ar_tanf_countable_earned_income: 176 # Step 1: 550 * 0.80 = 440 (after 20% work expense) # Step 2: 440 * 0.40 = 176 (after 60% work incentive) -- name: Case 4, gross income at trigger threshold. +- name: Case 5, initial applicant with 550 gross earnings. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 550 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + is_tanf_enrolled: false + output: + ar_tanf_countable_earned_income: 440 + # Initial applicant: 550 * 0.80 = 440 (only 20% work expense) + +- name: Case 6, ongoing recipient with gross income at trigger threshold. period: 2024-01 input: people: @@ -74,12 +115,13 @@ spm_units: spm_unit: members: [person1] + is_tanf_enrolled: true output: ar_tanf_countable_earned_income: 142.72 # Step 1: 446 * 0.80 = 356.8 (after 20% work expense) # Step 2: 356.8 * 0.40 = 142.72 (after 60% work incentive) -- name: Case 5, higher earnings yielding net above eligibility standard. +- name: Case 7, ongoing recipient higher earnings yielding net above eligibility standard. period: 2024-01 input: people: @@ -93,6 +135,7 @@ spm_units: spm_unit: members: [person1] + is_tanf_enrolled: true output: ar_tanf_countable_earned_income: 256 # Step 1: 800 * 0.80 = 640 (after 20% work expense) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.yaml index 440f3fb6fba..dab78d4d96a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.yaml @@ -1,13 +1,16 @@ # Unit tests for ar_tanf_income_eligible -# Arkansas TEA has a fixed income eligibility standard of $223/month for ALL family sizes -# A household is income eligible if countable income <= $223 +# Arkansas TEA has two income tests: +# 1. Gross income test: Gross income must be < 185% FPL +# 2. Net income test: Countable income must be <= $223/month (all family sizes) -- name: Case 1, zero income is eligible. +- name: Case 1, zero income passes both tests. period: 2024-01 input: people: person1: age: 30 + tanf_gross_earned_income: 0 + tanf_gross_unearned_income: 0 households: household: members: [person1] @@ -18,14 +21,17 @@ ar_tanf_countable_income: 0 output: ar_tanf_income_eligible: true - # 0 <= 223 -> eligible + # Gross: 0 < 185% FPL -> pass + # Net: 0 <= 223 -> pass -- name: Case 2, income below threshold. +- name: Case 2, low income passes both tests. period: 2024-01 input: people: person1: age: 30 + tanf_gross_earned_income: 300 + tanf_gross_unearned_income: 0 households: household: members: [person1] @@ -36,14 +42,17 @@ ar_tanf_countable_income: 150 output: ar_tanf_income_eligible: true - # 150 <= 223 -> eligible + # Gross: 300 < 185% FPL (~$2,322 for size 1) -> pass + # Net: 150 <= 223 -> pass -- name: Case 3, income exactly at threshold. +- name: Case 3, net income at threshold passes. period: 2024-01 input: people: person1: age: 30 + tanf_gross_earned_income: 500 + tanf_gross_unearned_income: 0 households: household: members: [person1] @@ -54,14 +63,17 @@ ar_tanf_countable_income: 223 output: ar_tanf_income_eligible: true - # 223 <= 223 -> eligible (at threshold is still eligible) + # Gross: 500 < 185% FPL -> pass + # Net: 223 <= 223 -> pass (at threshold is still eligible) -- name: Case 4, income one dollar over threshold. +- name: Case 4, net income one dollar over threshold fails. period: 2024-01 input: people: person1: age: 30 + tanf_gross_earned_income: 500 + tanf_gross_unearned_income: 0 households: household: members: [person1] @@ -72,14 +84,17 @@ ar_tanf_countable_income: 224 output: ar_tanf_income_eligible: false - # 224 > 223 -> ineligible + # Gross: 500 < 185% FPL -> pass + # Net: 224 > 223 -> FAIL -- name: Case 5, income well above threshold. +- name: Case 5, gross income above 185% FPL fails. period: 2024-01 input: people: person1: age: 30 + tanf_gross_earned_income: 2_500 + tanf_gross_unearned_income: 0 households: household: members: [person1] @@ -87,7 +102,59 @@ spm_units: spm_unit: members: [person1] - ar_tanf_countable_income: 500 + ar_tanf_countable_income: 100 output: ar_tanf_income_eligible: false - # 500 > 223 -> ineligible + # 185% FPL for size 1 in 2024: $15,060 * 1.85 / 12 = $2,321.75 + # Gross: 2,500 >= 2,321.75 -> FAIL (even though net income would pass) + +- name: Case 6, family of 3 gross income below 185% FPL. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 3_000 + tanf_gross_unearned_income: 0 + person2: + age: 10 + person3: + age: 8 + households: + household: + members: [person1, person2, person3] + state_code: AR + spm_units: + spm_unit: + members: [person1, person2, person3] + ar_tanf_countable_income: 150 + output: + ar_tanf_income_eligible: true + # 185% FPL for size 3 in 2024: $25,820 * 1.85 / 12 = $3,980.58 + # Gross: 3,000 < 3,980.58 -> pass + # Net: 150 <= 223 -> pass + +- name: Case 7, family of 3 gross income above 185% FPL. + period: 2024-01 + input: + people: + person1: + age: 30 + tanf_gross_earned_income: 4_500 + tanf_gross_unearned_income: 0 + person2: + age: 10 + person3: + age: 8 + households: + household: + members: [person1, person2, person3] + state_code: AR + spm_units: + spm_unit: + members: [person1, person2, person3] + ar_tanf_countable_income: 100 + output: + ar_tanf_income_eligible: false + # 185% FPL for size 3 in 2024: $25,820 * 1.85 / 12 = $3,980.58 + # Gross: 4,500 >= 3,980.58 -> FAIL diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/integration.yaml index 214ddf33d15..3c590d9178a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/integration.yaml @@ -1,5 +1,6 @@ # Integration tests for Arkansas TANF (TEA - Transitional Employment Assistance) # These tests verify the complete benefit calculation pipeline from inputs to final benefit +# Note: These tests use is_tanf_enrolled: true to simulate ongoing recipients - name: Case 1, family of 3 with no income receives full benefit. period: 2024-01 @@ -16,6 +17,7 @@ spm_unit: members: [person1, person2, person3] spm_unit_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2, person3] @@ -31,7 +33,8 @@ # Eligibility chain ar_tanf_income_eligible: true - # 0 <= 223 -> eligible + # Gross: 0 < 185% FPL -> pass + # Net: 0 <= 223 -> pass ar_tanf_resources_eligible: true # 1,000 <= 3,000 -> eligible ar_tanf_eligible: true @@ -43,7 +46,7 @@ # Gross income 0 < 446, so full payment # max(204 - 0, 0) = 204 -- name: Case 2, family of 3 with earned income below trigger receives partial benefit. +- name: Case 2, ongoing family of 3 with earned income below trigger receives partial benefit. period: 2024-01 absolute_error_margin: 0.01 input: @@ -60,6 +63,7 @@ spm_unit: members: [person1, person2, person3] spm_unit_assets: 500 + is_tanf_enrolled: true households: household: members: [person1, person2, person3] @@ -76,7 +80,8 @@ # Eligibility chain ar_tanf_income_eligible: true - # 128 <= 223 -> eligible + # Gross: 400 < 185% FPL -> pass + # Net: 128 <= 223 -> pass ar_tanf_resources_eligible: true # 500 <= 3,000 -> eligible ar_tanf_eligible: true @@ -88,7 +93,7 @@ # Gross income 400 < 446, so full payment standard # max(204 - 128, 0) = 76 -- name: Case 3, family of 2 with earnings at gross income trigger. +- name: Case 3, ongoing family of 2 with earnings at gross income trigger. period: 2024-01 absolute_error_margin: 0.01 input: @@ -103,6 +108,7 @@ spm_unit: members: [person1, person2] spm_unit_assets: 2_000 + is_tanf_enrolled: true households: household: members: [person1, person2] @@ -117,7 +123,8 @@ # Eligibility chain ar_tanf_income_eligible: true - # 142.72 <= 223 -> eligible + # Gross: 446 < 185% FPL -> pass + # Net: 142.72 <= 223 -> pass ar_tanf_resources_eligible: true # 2,000 <= 3,000 -> eligible ar_tanf_eligible: true @@ -130,7 +137,7 @@ # Reduced payment = 162 * 0.5 = 81 # max(81 - 142.72, 0) = max(-61.72, 0) = 0 -- name: Case 4, family of 4 with earnings above trigger but still eligible. +- name: Case 4, ongoing family of 4 with earnings above trigger but still eligible. period: 2024-01 absolute_error_margin: 0.01 input: @@ -150,6 +157,7 @@ spm_unit: members: [person1, person2, person3, person4] spm_unit_assets: 1_500 + is_tanf_enrolled: true households: household: members: [person1, person2, person3, person4] @@ -164,7 +172,8 @@ # Eligibility chain ar_tanf_income_eligible: true - # 160 <= 223 -> eligible + # Gross: 500 < 185% FPL -> pass + # Net: 160 <= 223 -> pass ar_tanf_eligible: true # Benefit calculation @@ -175,7 +184,7 @@ # Reduced payment = 247 * 0.5 = 123.5 # max(123.5 - 160, 0) = 0 -- name: Case 5, documentation example 550 gross earnings. +- name: Case 5, ongoing recipient documentation example 550 gross earnings. period: 2024-01 input: people: @@ -191,6 +200,7 @@ spm_unit: members: [person1, person2, person3] spm_unit_assets: 500 + is_tanf_enrolled: true households: household: members: [person1, person2, person3] @@ -206,7 +216,8 @@ # Eligibility chain ar_tanf_income_eligible: true - # 176 <= 223 -> eligible + # Gross: 550 < 185% FPL -> pass + # Net: 176 <= 223 -> pass ar_tanf_eligible: true # Benefit calculation @@ -216,7 +227,7 @@ # Reduced payment = 204 * 0.5 = 102 # max(102 - 176, 0) = 0 -- name: Case 6, income exceeds eligibility standard making family ineligible. +- name: Case 6, ongoing recipient income exceeds net eligibility standard making family ineligible. period: 2024-01 input: people: @@ -232,6 +243,7 @@ spm_unit: members: [person1, person2, person3] spm_unit_assets: 1_000 + is_tanf_enrolled: true households: household: members: [person1, person2, person3] @@ -245,7 +257,8 @@ # Eligibility chain ar_tanf_income_eligible: false - # 256 > 223 -> INELIGIBLE + # Gross: 800 < 185% FPL -> pass + # Net: 256 > 223 -> FAIL ar_tanf_eligible: false # Benefit calculation @@ -266,6 +279,7 @@ spm_unit: members: [person1, person2] spm_unit_assets: 5_000 + is_tanf_enrolled: true # Exceeds $3,000 resource limit households: household: @@ -277,7 +291,8 @@ # Eligibility chain ar_tanf_income_eligible: true - # 0 <= 223 -> income eligible + # Gross: 0 < 185% FPL -> pass + # Net: 0 <= 223 -> pass ar_tanf_resources_eligible: false # 5,000 > 3,000 -> RESOURCES INELIGIBLE ar_tanf_eligible: false @@ -286,3 +301,82 @@ ar_tanf_maximum_benefit: 162 ar_tanf: 0 # Ineligible -> no benefit + +- name: Case 8, initial applicant family of 3 (20% deduction only). + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 4_800 + # Annual $4,800 = $400/month + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 500 + is_tanf_enrolled: false + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + # Income calculation chain - initial applicant gets only 20% deduction + tanf_gross_earned_income: [400, 0, 0] + ar_tanf_countable_earned_income: 320 + # Initial applicant: 400 * 0.80 = 320 (only 20% work expense) + ar_tanf_countable_income: 320 + # 320 (earned) + 0 (unearned) = 320 + + # Eligibility chain + ar_tanf_income_eligible: false + # Gross: 400 < 185% FPL -> pass + # Net: 320 > 223 -> FAIL (initial applicant has higher countable income) + ar_tanf_eligible: false + + # Benefit calculation + ar_tanf_maximum_benefit: 204 + ar_tanf: 0 + # Ineligible -> no benefit + +- name: Case 9, gross income above 185% FPL makes family ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 54_000 + # Annual $54,000 = $4,500/month + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 500 + is_tanf_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + # Income calculation chain + tanf_gross_earned_income: [4_500, 0, 0] + ar_tanf_countable_earned_income: 1_440 + # 4,500 * 0.80 * 0.40 = 1,440 + ar_tanf_countable_income: 1_440 + + # Eligibility chain + ar_tanf_income_eligible: false + # 185% FPL for size 3 in 2024: $25,820 * 1.85 / 12 = $3,980.58 + # Gross: 4,500 >= 3,980.58 -> FAIL + ar_tanf_eligible: false + + # Benefit calculation + ar_tanf_maximum_benefit: 204 + ar_tanf: 0 + # Ineligible -> no benefit diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.py b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.py index 6f3b24e0c0c..a4985dd6eaa 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.py @@ -13,12 +13,18 @@ class ar_tanf_countable_earned_income(Variable): def formula(spm_unit, period, parameters): # Per 208.00.13 Ark. Code R. Section 001, Section 3.3 p = parameters(period).gov.states.ar.dhs.tanf.income.deductions - gross_earned = spm_unit("tanf_gross_earned_income", period) + gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) - # Step 1: Apply 20% work expense deduction + # Step 1: Apply 20% work expense deduction (applies to all) after_work_expense = gross_earned * (1 - p.work_expense.rate) - # Step 2: Apply 60% work incentive deduction - countable_earned = after_work_expense * (1 - p.work_incentive.rate) + # Step 2: Apply 60% work incentive deduction (only for ongoing recipients) + is_enrolled = spm_unit("is_tanf_enrolled", period) - return max_(countable_earned, 0) + # For initial applicants: only 20% work expense deduction + # For ongoing recipients: 20% work expense + 60% work incentive + return where( + is_enrolled, + after_work_expense * (1 - p.work_incentive.rate), + after_work_expense, + ) diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.py b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.py index 99605c95a14..95da1c79b81 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.py @@ -11,9 +11,20 @@ class ar_tanf_income_eligible(Variable): def formula(spm_unit, period, parameters): # Per 208.00.13 Ark. Code R. Section 001, Section 3.3 - # Income eligibility standard is $223/month for ALL family sizes - p = parameters( - period - ).gov.states.ar.dhs.tanf.income.eligibility_standard + p = parameters(period).gov.states.ar.dhs.tanf.income + + # Step 1: Gross income test - must be below 185% FPL + fpg = spm_unit("spm_unit_fpg", period) + gross_income_limit = fpg * p.gross_income_limit.rate + + gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) + gross_unearned = add(spm_unit, period, ["tanf_gross_unearned_income"]) + gross_income = gross_earned + gross_unearned + + passes_gross_test = gross_income < gross_income_limit + + # Step 2: Net income test - countable income must be at or below $223 countable_income = spm_unit("ar_tanf_countable_income", period) - return countable_income <= p.amount + passes_net_test = countable_income <= p.eligibility_standard.amount + + return passes_gross_test & passes_net_test From 2b9857c7262ba13778cf31fee142208365a2c175 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 17 Dec 2025 13:37:56 -0500 Subject: [PATCH 5/8] rename --- .../income/gross_income/limit_rate.yaml} | 4 +- .../income/income_limit.yaml} | 4 +- .../income/work_deduction/expense_rate.yaml} | 4 +- .../work_deduction/incentive_rate.yaml} | 4 +- .../payment_standard/amount.yaml | 2 +- .../payment_standard/max_unit_size.yaml | 2 +- .../payment_standard/trigger}/amount.yaml | 2 +- .../trigger}/reduction_rate.yaml | 2 +- .../ar/dhs/{tanf => tea}/resources/limit.yaml | 2 +- .../{tanf/ar_tanf.yaml => tea/ar_tea.yaml} | 50 ++++---- .../ar_tea_countable_earned_income.yaml} | 16 +-- .../ar_tea_countable_income.yaml} | 22 ++-- .../ar_tea_eligible.yaml} | 32 ++--- .../ar_tea_income_eligible.yaml} | 30 ++--- .../ar_tea_maximum_benefit.yaml} | 22 ++-- .../ar_tea_resources_eligible.yaml} | 12 +- .../ar/dhs/{tanf => tea}/integration.yaml | 114 +++++++++--------- .../ar/dhs/{tanf/ar_tanf.py => tea/ar_tea.py} | 17 ++- .../ar_tea_countable_earned_income.py} | 10 +- .../ar_tea_countable_income.py} | 6 +- .../ar_tea_eligible.py} | 8 +- .../ar_tea_income_eligible.py} | 12 +- .../ar_tea_maximum_benefit.py} | 6 +- .../ar_tea_resources_eligible.py} | 6 +- 24 files changed, 194 insertions(+), 195 deletions(-) rename policyengine_us/parameters/gov/states/ar/dhs/{tanf/income/gross_income_limit/rate.yaml => tea/income/gross_income/limit_rate.yaml} (89%) rename policyengine_us/parameters/gov/states/ar/dhs/{tanf/income/eligibility_standard/amount.yaml => tea/income/income_limit.yaml} (88%) rename policyengine_us/parameters/gov/states/ar/dhs/{tanf/income/deductions/work_expense/rate.yaml => tea/income/work_deduction/expense_rate.yaml} (87%) rename policyengine_us/parameters/gov/states/ar/dhs/{tanf/income/deductions/work_incentive/rate.yaml => tea/income/work_deduction/incentive_rate.yaml} (87%) rename policyengine_us/parameters/gov/states/ar/dhs/{tanf => tea}/payment_standard/amount.yaml (95%) rename policyengine_us/parameters/gov/states/ar/dhs/{tanf => tea}/payment_standard/max_unit_size.yaml (88%) rename policyengine_us/parameters/gov/states/ar/dhs/{tanf/income/gross_income_trigger => tea/payment_standard/trigger}/amount.yaml (92%) rename policyengine_us/parameters/gov/states/ar/dhs/{tanf/income/gross_income_trigger => tea/payment_standard/trigger}/reduction_rate.yaml (86%) rename policyengine_us/parameters/gov/states/ar/dhs/{tanf => tea}/resources/limit.yaml (94%) rename policyengine_us/tests/policy/baseline/gov/states/ar/dhs/{tanf/ar_tanf.yaml => tea/ar_tea.yaml} (78%) rename policyengine_us/tests/policy/baseline/gov/states/ar/dhs/{tanf/ar_tanf_countable_earned_income.yaml => tea/ar_tea_countable_earned_income.yaml} (91%) rename policyengine_us/tests/policy/baseline/gov/states/ar/dhs/{tanf/ar_tanf_countable_income.yaml => tea/ar_tea_countable_income.yaml} (81%) rename policyengine_us/tests/policy/baseline/gov/states/ar/dhs/{tanf/ar_tanf_eligible.yaml => tea/ar_tea_eligible.yaml} (75%) rename policyengine_us/tests/policy/baseline/gov/states/ar/dhs/{tanf/ar_tanf_income_eligible.yaml => tea/ar_tea_income_eligible.yaml} (86%) rename policyengine_us/tests/policy/baseline/gov/states/ar/dhs/{tanf/ar_tanf_maximum_benefit.yaml => tea/ar_tea_maximum_benefit.yaml} (89%) rename policyengine_us/tests/policy/baseline/gov/states/ar/dhs/{tanf/ar_tanf_resources_eligible.yaml => tea/ar_tea_resources_eligible.yaml} (89%) rename policyengine_us/tests/policy/baseline/gov/states/ar/dhs/{tanf => tea}/integration.yaml (83%) rename policyengine_us/variables/gov/states/ar/dhs/{tanf/ar_tanf.py => tea/ar_tea.py} (62%) rename policyengine_us/variables/gov/states/ar/dhs/{tanf/ar_tanf_countable_earned_income.py => tea/ar_tea_countable_earned_income.py} (73%) rename policyengine_us/variables/gov/states/ar/dhs/{tanf/ar_tanf_countable_income.py => tea/ar_tea_countable_income.py} (71%) rename policyengine_us/variables/gov/states/ar/dhs/{tanf/ar_tanf_eligible.py => tea/ar_tea_eligible.py} (70%) rename policyengine_us/variables/gov/states/ar/dhs/{tanf/ar_tanf_income_eligible.py => tea/ar_tea_income_eligible.py} (70%) rename policyengine_us/variables/gov/states/ar/dhs/{tanf/ar_tanf_maximum_benefit.py => tea/ar_tea_maximum_benefit.py} (77%) rename policyengine_us/variables/gov/states/ar/dhs/{tanf/ar_tanf_resources_eligible.py => tea/ar_tea_resources_eligible.py} (76%) diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_limit/rate.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/gross_income/limit_rate.yaml similarity index 89% rename from policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_limit/rate.yaml rename to policyengine_us/parameters/gov/states/ar/dhs/tea/income/gross_income/limit_rate.yaml index 16a4a5d0531..51aff3ccbec 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_limit/rate.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/gross_income/limit_rate.yaml @@ -6,9 +6,9 @@ values: metadata: unit: /1 period: month - label: Arkansas TANF gross income limit rate + label: Arkansas TEA gross income limit rate reference: - - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Eligibility Standard + - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Limit href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 - title: Arkansas TEA/Work Pays Program href: https://humanservices.arkansas.gov/divisions-shared-services/county-operations/temporary-assistance-for-needy-families/transitional-employment-assistance-tea-work-pays/ diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/eligibility_standard/amount.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/income_limit.yaml similarity index 88% rename from policyengine_us/parameters/gov/states/ar/dhs/tanf/income/eligibility_standard/amount.yaml rename to policyengine_us/parameters/gov/states/ar/dhs/tea/income/income_limit.yaml index 1b6527b7690..7ae6bc3cc43 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/eligibility_standard/amount.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/income_limit.yaml @@ -6,9 +6,9 @@ values: metadata: unit: currency-USD period: month - label: Arkansas TANF income eligibility standard + label: Arkansas TEA income limit reference: - - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Eligibility Standard + - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Limit href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 - title: Arkansas TEA/Work Pays Program href: https://humanservices.arkansas.gov/divisions-shared-services/county-operations/temporary-assistance-for-needy-families/transitional-employment-assistance-tea-work-pays/ diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_expense/rate.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/expense_rate.yaml similarity index 87% rename from policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_expense/rate.yaml rename to policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/expense_rate.yaml index afba2e3f679..2f609993f4a 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_expense/rate.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/expense_rate.yaml @@ -6,9 +6,9 @@ values: metadata: unit: /1 period: month - label: Arkansas TANF work expense deduction rate + label: Arkansas TEA work expense deduction rate reference: - - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Eligibility Standard + - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Limit href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 - title: 016.20.98-041 Ark. Code R. - TEA Policy 2352-2362, Work Expense Deduction href: https://regulations.justia.com/states/arkansas/agency-016/division-20/rule-016-20-98-041/ diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_incentive/rate.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/incentive_rate.yaml similarity index 87% rename from policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_incentive/rate.yaml rename to policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/incentive_rate.yaml index 84c8ff11d98..5151fa3e2ed 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/deductions/work_incentive/rate.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/incentive_rate.yaml @@ -6,9 +6,9 @@ values: metadata: unit: /1 period: month - label: Arkansas TANF work incentive deduction rate + label: Arkansas TEA work incentive deduction rate reference: - - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Eligibility Standard + - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Limit href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 - title: 016.20.98-041 Ark. Code R. - TEA Policy 2352-2362, Work Incentive Deduction href: https://regulations.justia.com/states/arkansas/agency-016/division-20/rule-016-20-98-041/ diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/amount.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/amount.yaml similarity index 95% rename from policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/amount.yaml rename to policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/amount.yaml index b92a8eb8c6c..3d8c7868774 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/amount.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/amount.yaml @@ -5,7 +5,7 @@ metadata: period: month breakdown: - range(1, 20) - label: Arkansas TANF payment standard amount + label: Arkansas TEA payment standard amount reference: - title: 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - Payment Standards href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/max_unit_size.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/max_unit_size.yaml similarity index 88% rename from policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/max_unit_size.yaml rename to policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/max_unit_size.yaml index 9746a97b928..e5726f24eba 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tanf/payment_standard/max_unit_size.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/max_unit_size.yaml @@ -6,7 +6,7 @@ values: metadata: unit: int period: month - label: Arkansas TANF payment standard max unit size + label: Arkansas TEA payment standard max unit size reference: - title: 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - Payment Standards href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/amount.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/amount.yaml similarity index 92% rename from policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/amount.yaml rename to policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/amount.yaml index f58fb7c53ae..587bb9f9528 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/amount.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/amount.yaml @@ -6,7 +6,7 @@ values: metadata: unit: currency-USD period: month - label: Arkansas TANF gross income trigger threshold + label: Arkansas TEA gross income trigger threshold reference: - title: 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - Payment Standards href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/reduction_rate.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/reduction_rate.yaml similarity index 86% rename from policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/reduction_rate.yaml rename to policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/reduction_rate.yaml index a2a5af4906a..0b3f243aa57 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tanf/income/gross_income_trigger/reduction_rate.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/reduction_rate.yaml @@ -6,7 +6,7 @@ values: metadata: unit: /1 period: month - label: Arkansas TANF gross income trigger payment reduction rate + label: Arkansas TEA gross income trigger payment reduction rate reference: - title: 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - Payment Standards href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tanf/resources/limit.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/resources/limit.yaml similarity index 94% rename from policyengine_us/parameters/gov/states/ar/dhs/tanf/resources/limit.yaml rename to policyengine_us/parameters/gov/states/ar/dhs/tea/resources/limit.yaml index ab4295e168a..c6dbd22edc0 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tanf/resources/limit.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/resources/limit.yaml @@ -6,7 +6,7 @@ values: metadata: unit: currency-USD period: month - label: Arkansas TANF resource limit + label: Arkansas TEA resource limit reference: - title: 208.00.13 Ark. Code R. Section 001, Section 3.4 - Resource Limits href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea.yaml similarity index 78% rename from policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf.yaml rename to policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea.yaml index ac06cddccfa..3eed1515fef 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea.yaml @@ -1,4 +1,4 @@ -# Unit tests for ar_tanf (final benefit amount) +# Unit tests for ar_tea (final benefit amount) # Benefit calculation: # 1. If not eligible: $0 # 2. If gross income < $446: benefit = max(payment_standard - countable_income, 0) @@ -19,11 +19,11 @@ spm_units: spm_unit: members: [person1] - ar_tanf_eligible: false - ar_tanf_maximum_benefit: 204 - ar_tanf_countable_income: 0 + ar_tea_eligible: false + ar_tea_maximum_benefit: 204 + ar_tea_countable_income: 0 output: - ar_tanf: 0 + ar_tea: 0 # Not eligible -> no benefit - name: Case 2, eligible with zero income receives full benefit. @@ -41,11 +41,11 @@ spm_units: spm_unit: members: [person1] - ar_tanf_eligible: true - ar_tanf_maximum_benefit: 204 - ar_tanf_countable_income: 0 + ar_tea_eligible: true + ar_tea_maximum_benefit: 204 + ar_tea_countable_income: 0 output: - ar_tanf: 204 + ar_tea: 204 # max(204 - 0, 0) = 204 - name: Case 3, eligible with countable income below payment standard. @@ -63,11 +63,11 @@ spm_units: spm_unit: members: [person1] - ar_tanf_eligible: true - ar_tanf_maximum_benefit: 204 - ar_tanf_countable_income: 128 + ar_tea_eligible: true + ar_tea_maximum_benefit: 204 + ar_tea_countable_income: 128 output: - ar_tanf: 76 + ar_tea: 76 # Gross income 400 < 446 trigger, so full payment standard applies # max(204 - 128, 0) = 76 @@ -86,11 +86,11 @@ spm_units: spm_unit: members: [person1] - ar_tanf_eligible: true - ar_tanf_maximum_benefit: 204 - ar_tanf_countable_income: 0 + ar_tea_eligible: true + ar_tea_maximum_benefit: 204 + ar_tea_countable_income: 0 output: - ar_tanf: 102 + ar_tea: 102 # Gross income 446 >= 446 trigger, so 50% reduction # max(204 * 0.5 - 0, 0) = max(102 - 0, 0) = 102 @@ -109,11 +109,11 @@ spm_units: spm_unit: members: [person1] - ar_tanf_eligible: true - ar_tanf_maximum_benefit: 162 - ar_tanf_countable_income: 50 + ar_tea_eligible: true + ar_tea_maximum_benefit: 162 + ar_tea_countable_income: 50 output: - ar_tanf: 31 + ar_tea: 31 # Gross income 500 >= 446 trigger, so 50% reduction # max(162 * 0.5 - 50, 0) = max(81 - 50, 0) = 31 @@ -132,9 +132,9 @@ spm_units: spm_unit: members: [person1] - ar_tanf_eligible: true - ar_tanf_maximum_benefit: 81 - ar_tanf_countable_income: 100 + ar_tea_eligible: true + ar_tea_maximum_benefit: 81 + ar_tea_countable_income: 100 output: - ar_tanf: 0 + ar_tea: 0 # max(81 - 100, 0) = max(-19, 0) = 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_countable_earned_income.yaml similarity index 91% rename from policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.yaml rename to policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_countable_earned_income.yaml index d1c579efd3f..15413fc615d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_countable_earned_income.yaml @@ -1,4 +1,4 @@ -# Unit tests for ar_tanf_countable_earned_income +# Unit tests for ar_tea_countable_earned_income # Arkansas TEA applies sequential earned income deductions: # - Initial applicants (not enrolled): 20% work-related expense deduction only # - Ongoing recipients (enrolled): 20% work expense + 60% work incentive deduction @@ -20,7 +20,7 @@ members: [person1] is_tanf_enrolled: false output: - ar_tanf_countable_earned_income: 0 + ar_tea_countable_earned_income: 0 - name: Case 2, initial applicant with low income (20% deduction only). period: 2024-01 @@ -38,7 +38,7 @@ members: [person1] is_tanf_enrolled: false output: - ar_tanf_countable_earned_income: 240 + ar_tea_countable_earned_income: 240 # Initial applicant: 300 * 0.80 = 240 (only 20% work expense) - name: Case 3, ongoing recipient with low income (20% + 60% deductions). @@ -57,7 +57,7 @@ members: [person1] is_tanf_enrolled: true output: - ar_tanf_countable_earned_income: 96 + ar_tea_countable_earned_income: 96 # Ongoing recipient: # Step 1: 300 * 0.80 = 240 (after 20% work expense) # Step 2: 240 * 0.40 = 96 (after 60% work incentive) @@ -78,7 +78,7 @@ members: [person1] is_tanf_enrolled: true output: - ar_tanf_countable_earned_income: 176 + ar_tea_countable_earned_income: 176 # Step 1: 550 * 0.80 = 440 (after 20% work expense) # Step 2: 440 * 0.40 = 176 (after 60% work incentive) @@ -98,7 +98,7 @@ members: [person1] is_tanf_enrolled: false output: - ar_tanf_countable_earned_income: 440 + ar_tea_countable_earned_income: 440 # Initial applicant: 550 * 0.80 = 440 (only 20% work expense) - name: Case 6, ongoing recipient with gross income at trigger threshold. @@ -117,7 +117,7 @@ members: [person1] is_tanf_enrolled: true output: - ar_tanf_countable_earned_income: 142.72 + ar_tea_countable_earned_income: 142.72 # Step 1: 446 * 0.80 = 356.8 (after 20% work expense) # Step 2: 356.8 * 0.40 = 142.72 (after 60% work incentive) @@ -137,7 +137,7 @@ members: [person1] is_tanf_enrolled: true output: - ar_tanf_countable_earned_income: 256 + ar_tea_countable_earned_income: 256 # Step 1: 800 * 0.80 = 640 (after 20% work expense) # Step 2: 640 * 0.40 = 256 (after 60% work incentive) # Note: 256 > 223 eligibility standard, so would be income ineligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_countable_income.yaml similarity index 81% rename from policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_income.yaml rename to policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_countable_income.yaml index 63d2fda252c..8756a0af27b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_countable_income.yaml @@ -1,4 +1,4 @@ -# Unit tests for ar_tanf_countable_income +# Unit tests for ar_tea_countable_income # Total countable income = countable earned income + unearned income # Note: Earned income has already been reduced by 20% + 60% deductions # Unearned income has no deductions applied @@ -17,9 +17,9 @@ spm_units: spm_unit: members: [person1] - ar_tanf_countable_earned_income: 0 + ar_tea_countable_earned_income: 0 output: - ar_tanf_countable_income: 0 + ar_tea_countable_income: 0 - name: Case 2, only earned income. period: 2024-01 @@ -35,9 +35,9 @@ spm_units: spm_unit: members: [person1] - ar_tanf_countable_earned_income: 176 + ar_tea_countable_earned_income: 176 output: - ar_tanf_countable_income: 176 + ar_tea_countable_income: 176 # 176 (earned after disregards) + 0 (unearned) = 176 - name: Case 3, only unearned income. @@ -54,9 +54,9 @@ spm_units: spm_unit: members: [person1] - ar_tanf_countable_earned_income: 0 + ar_tea_countable_earned_income: 0 output: - ar_tanf_countable_income: 150 + ar_tea_countable_income: 150 # 0 (earned) + 150 (unearned) = 150 - name: Case 4, mixed earned and unearned income. @@ -73,9 +73,9 @@ spm_units: spm_unit: members: [person1] - ar_tanf_countable_earned_income: 96 + ar_tea_countable_earned_income: 96 output: - ar_tanf_countable_income: 196 + ar_tea_countable_income: 196 # 96 (earned after disregards) + 100 (unearned) = 196 - name: Case 5, income at eligibility threshold. @@ -92,7 +92,7 @@ spm_units: spm_unit: members: [person1] - ar_tanf_countable_earned_income: 123 + ar_tea_countable_earned_income: 123 output: - ar_tanf_countable_income: 223 + ar_tea_countable_income: 223 # 123 + 100 = 223 (exactly at $223 income eligibility standard) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_eligible.yaml similarity index 75% rename from policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_eligible.yaml rename to policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_eligible.yaml index 7374aeb83b6..0d1ec4d9fc6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_eligible.yaml @@ -1,4 +1,4 @@ -# Unit tests for ar_tanf_eligible +# Unit tests for ar_tea_eligible # Overall eligibility requires: # 1. Income eligibility (countable income <= $223) # 2. Resource eligibility (resources <= $3,000) @@ -17,11 +17,11 @@ spm_units: spm_unit: members: [person1] - ar_tanf_income_eligible: true - ar_tanf_resources_eligible: true + ar_tea_income_eligible: true + ar_tea_resources_eligible: true is_demographic_tanf_eligible: true output: - ar_tanf_eligible: true + ar_tea_eligible: true - name: Case 2, income ineligible. period: 2024-01 @@ -36,11 +36,11 @@ spm_units: spm_unit: members: [person1] - ar_tanf_income_eligible: false - ar_tanf_resources_eligible: true + ar_tea_income_eligible: false + ar_tea_resources_eligible: true is_demographic_tanf_eligible: true output: - ar_tanf_eligible: false + ar_tea_eligible: false - name: Case 3, resources ineligible. period: 2024-01 @@ -55,11 +55,11 @@ spm_units: spm_unit: members: [person1] - ar_tanf_income_eligible: true - ar_tanf_resources_eligible: false + ar_tea_income_eligible: true + ar_tea_resources_eligible: false is_demographic_tanf_eligible: true output: - ar_tanf_eligible: false + ar_tea_eligible: false - name: Case 4, demographic ineligible. period: 2024-01 @@ -74,11 +74,11 @@ spm_units: spm_unit: members: [person1] - ar_tanf_income_eligible: true - ar_tanf_resources_eligible: true + ar_tea_income_eligible: true + ar_tea_resources_eligible: true is_demographic_tanf_eligible: false output: - ar_tanf_eligible: false + ar_tea_eligible: false - name: Case 5, multiple requirements not met. period: 2024-01 @@ -93,8 +93,8 @@ spm_units: spm_unit: members: [person1] - ar_tanf_income_eligible: false - ar_tanf_resources_eligible: false + ar_tea_income_eligible: false + ar_tea_resources_eligible: false is_demographic_tanf_eligible: true output: - ar_tanf_eligible: false + ar_tea_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_income_eligible.yaml similarity index 86% rename from policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.yaml rename to policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_income_eligible.yaml index dab78d4d96a..a13fe2300a0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_income_eligible.yaml @@ -1,4 +1,4 @@ -# Unit tests for ar_tanf_income_eligible +# Unit tests for ar_tea_income_eligible # Arkansas TEA has two income tests: # 1. Gross income test: Gross income must be < 185% FPL # 2. Net income test: Countable income must be <= $223/month (all family sizes) @@ -18,9 +18,9 @@ spm_units: spm_unit: members: [person1] - ar_tanf_countable_income: 0 + ar_tea_countable_income: 0 output: - ar_tanf_income_eligible: true + ar_tea_income_eligible: true # Gross: 0 < 185% FPL -> pass # Net: 0 <= 223 -> pass @@ -39,9 +39,9 @@ spm_units: spm_unit: members: [person1] - ar_tanf_countable_income: 150 + ar_tea_countable_income: 150 output: - ar_tanf_income_eligible: true + ar_tea_income_eligible: true # Gross: 300 < 185% FPL (~$2,322 for size 1) -> pass # Net: 150 <= 223 -> pass @@ -60,9 +60,9 @@ spm_units: spm_unit: members: [person1] - ar_tanf_countable_income: 223 + ar_tea_countable_income: 223 output: - ar_tanf_income_eligible: true + ar_tea_income_eligible: true # Gross: 500 < 185% FPL -> pass # Net: 223 <= 223 -> pass (at threshold is still eligible) @@ -81,9 +81,9 @@ spm_units: spm_unit: members: [person1] - ar_tanf_countable_income: 224 + ar_tea_countable_income: 224 output: - ar_tanf_income_eligible: false + ar_tea_income_eligible: false # Gross: 500 < 185% FPL -> pass # Net: 224 > 223 -> FAIL @@ -102,9 +102,9 @@ spm_units: spm_unit: members: [person1] - ar_tanf_countable_income: 100 + ar_tea_countable_income: 100 output: - ar_tanf_income_eligible: false + ar_tea_income_eligible: false # 185% FPL for size 1 in 2024: $15,060 * 1.85 / 12 = $2,321.75 # Gross: 2,500 >= 2,321.75 -> FAIL (even though net income would pass) @@ -127,9 +127,9 @@ spm_units: spm_unit: members: [person1, person2, person3] - ar_tanf_countable_income: 150 + ar_tea_countable_income: 150 output: - ar_tanf_income_eligible: true + ar_tea_income_eligible: true # 185% FPL for size 3 in 2024: $25,820 * 1.85 / 12 = $3,980.58 # Gross: 3,000 < 3,980.58 -> pass # Net: 150 <= 223 -> pass @@ -153,8 +153,8 @@ spm_units: spm_unit: members: [person1, person2, person3] - ar_tanf_countable_income: 100 + ar_tea_countable_income: 100 output: - ar_tanf_income_eligible: false + ar_tea_income_eligible: false # 185% FPL for size 3 in 2024: $25,820 * 1.85 / 12 = $3,980.58 # Gross: 4,500 >= 3,980.58 -> FAIL diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_maximum_benefit.yaml similarity index 89% rename from policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.yaml rename to policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_maximum_benefit.yaml index fada13af330..218afcf5196 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_maximum_benefit.yaml @@ -1,4 +1,4 @@ -# Unit tests for ar_tanf_maximum_benefit +# Unit tests for ar_tea_maximum_benefit # Arkansas TEA payment standards by family size (full payment, before 50% reduction): # 1: $81, 2: $162, 3: $204, 4: $247, 5: $286 # 6: $331, 7: $373, 8: $415, 9+: $457 @@ -18,7 +18,7 @@ members: [person1] spm_unit_size: 1 output: - ar_tanf_maximum_benefit: 81 + ar_tea_maximum_benefit: 81 - name: Case 2, family size 2. period: 2024-01 @@ -37,7 +37,7 @@ members: [person1, person2] spm_unit_size: 2 output: - ar_tanf_maximum_benefit: 162 + ar_tea_maximum_benefit: 162 - name: Case 3, family size 3. period: 2024-01 @@ -58,7 +58,7 @@ members: [person1, person2, person3] spm_unit_size: 3 output: - ar_tanf_maximum_benefit: 204 + ar_tea_maximum_benefit: 204 - name: Case 4, family size 4. period: 2024-01 @@ -75,7 +75,7 @@ members: [person1] spm_unit_size: 4 output: - ar_tanf_maximum_benefit: 247 + ar_tea_maximum_benefit: 247 - name: Case 5, family size 5. period: 2024-01 @@ -92,7 +92,7 @@ members: [person1] spm_unit_size: 5 output: - ar_tanf_maximum_benefit: 286 + ar_tea_maximum_benefit: 286 - name: Case 6, family size 6. period: 2024-01 @@ -109,7 +109,7 @@ members: [person1] spm_unit_size: 6 output: - ar_tanf_maximum_benefit: 331 + ar_tea_maximum_benefit: 331 - name: Case 7, family size 7. period: 2024-01 @@ -126,7 +126,7 @@ members: [person1] spm_unit_size: 7 output: - ar_tanf_maximum_benefit: 373 + ar_tea_maximum_benefit: 373 - name: Case 8, family size 8. period: 2024-01 @@ -143,7 +143,7 @@ members: [person1] spm_unit_size: 8 output: - ar_tanf_maximum_benefit: 415 + ar_tea_maximum_benefit: 415 - name: Case 9, family size 9 or more. period: 2024-01 @@ -160,7 +160,7 @@ members: [person1] spm_unit_size: 9 output: - ar_tanf_maximum_benefit: 457 + ar_tea_maximum_benefit: 457 - name: Case 10, family size 10 capped at 9 rate. period: 2024-01 @@ -177,5 +177,5 @@ members: [person1] spm_unit_size: 10 output: - ar_tanf_maximum_benefit: 457 + ar_tea_maximum_benefit: 457 # Family sizes 9+ all receive $457 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_resources_eligible.yaml similarity index 89% rename from policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.yaml rename to policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_resources_eligible.yaml index afe26d7bfe1..1e49e14a4e4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_resources_eligible.yaml @@ -1,4 +1,4 @@ -# Unit tests for ar_tanf_resources_eligible +# Unit tests for ar_tea_resources_eligible # Arkansas TEA has a fixed resource limit of $3,000 for ALL family sizes # Countable resources exclude: # - Family homestead (residence) @@ -21,7 +21,7 @@ members: [person1] spm_unit_assets: 0 output: - ar_tanf_resources_eligible: true + ar_tea_resources_eligible: true # 0 <= 3,000 -> eligible - name: Case 2, resources well below limit. @@ -39,7 +39,7 @@ members: [person1] spm_unit_assets: 1_500 output: - ar_tanf_resources_eligible: true + ar_tea_resources_eligible: true # 1,500 <= 3,000 -> eligible - name: Case 3, resources exactly at limit. @@ -57,7 +57,7 @@ members: [person1] spm_unit_assets: 3_000 output: - ar_tanf_resources_eligible: true + ar_tea_resources_eligible: true # 3,000 <= 3,000 -> eligible (at limit is still eligible) - name: Case 4, resources one dollar over limit. @@ -75,7 +75,7 @@ members: [person1] spm_unit_assets: 3_001 output: - ar_tanf_resources_eligible: false + ar_tea_resources_eligible: false # 3,001 > 3,000 -> ineligible - name: Case 5, resources well above limit. @@ -93,5 +93,5 @@ members: [person1] spm_unit_assets: 10_000 output: - ar_tanf_resources_eligible: false + ar_tea_resources_eligible: false # 10,000 > 3,000 -> ineligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/integration.yaml similarity index 83% rename from policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/integration.yaml rename to policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/integration.yaml index 3c590d9178a..950f4b0c3d6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tanf/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/integration.yaml @@ -26,23 +26,23 @@ # Income calculation chain tanf_gross_earned_income: [0, 0, 0] # No earned income for any member - ar_tanf_countable_earned_income: 0 + ar_tea_countable_earned_income: 0 # 0 * 0.32 = 0 (after 20% + 60% deductions) - ar_tanf_countable_income: 0 + ar_tea_countable_income: 0 # 0 (earned) + 0 (unearned) = 0 # Eligibility chain - ar_tanf_income_eligible: true + ar_tea_income_eligible: true # Gross: 0 < 185% FPL -> pass # Net: 0 <= 223 -> pass - ar_tanf_resources_eligible: true + ar_tea_resources_eligible: true # 1,000 <= 3,000 -> eligible - ar_tanf_eligible: true + ar_tea_eligible: true # Benefit calculation - ar_tanf_maximum_benefit: 204 + ar_tea_maximum_benefit: 204 # Family size 3 -> $204 payment standard - ar_tanf: 204 + ar_tea: 204 # Gross income 0 < 446, so full payment # max(204 - 0, 0) = 204 @@ -72,24 +72,24 @@ # Income calculation chain tanf_gross_earned_income: [400, 0, 0] # Person1: 4,800 / 12 = 400/month - ar_tanf_countable_earned_income: 128 + ar_tea_countable_earned_income: 128 # Step 1: 400 * 0.80 = 320 (after 20% work expense) # Step 2: 320 * 0.40 = 128 (after 60% work incentive) - ar_tanf_countable_income: 128 + ar_tea_countable_income: 128 # 128 (earned) + 0 (unearned) = 128 # Eligibility chain - ar_tanf_income_eligible: true + ar_tea_income_eligible: true # Gross: 400 < 185% FPL -> pass # Net: 128 <= 223 -> pass - ar_tanf_resources_eligible: true + ar_tea_resources_eligible: true # 500 <= 3,000 -> eligible - ar_tanf_eligible: true + ar_tea_eligible: true # Benefit calculation - ar_tanf_maximum_benefit: 204 + ar_tea_maximum_benefit: 204 # Family size 3 -> $204 - ar_tanf: 76 + ar_tea: 76 # Gross income 400 < 446, so full payment standard # max(204 - 128, 0) = 76 @@ -117,22 +117,22 @@ # Income calculation chain tanf_gross_earned_income: [446, 0] # Person1: 5,352 / 12 = 446/month - ar_tanf_countable_earned_income: 142.72 + ar_tea_countable_earned_income: 142.72 # 446 * 0.80 * 0.40 = 142.72 - ar_tanf_countable_income: 142.72 + ar_tea_countable_income: 142.72 # Eligibility chain - ar_tanf_income_eligible: true + ar_tea_income_eligible: true # Gross: 446 < 185% FPL -> pass # Net: 142.72 <= 223 -> pass - ar_tanf_resources_eligible: true + ar_tea_resources_eligible: true # 2,000 <= 3,000 -> eligible - ar_tanf_eligible: true + ar_tea_eligible: true # Benefit calculation - ar_tanf_maximum_benefit: 162 + ar_tea_maximum_benefit: 162 # Family size 2 -> $162 - ar_tanf: 0 + ar_tea: 0 # Gross income 446 >= 446, so 50% reduction applies # Reduced payment = 162 * 0.5 = 81 # max(81 - 142.72, 0) = max(-61.72, 0) = 0 @@ -166,20 +166,20 @@ # Income calculation chain tanf_gross_earned_income: [500, 0, 0, 0] # Person1: 6,000 / 12 = 500/month - ar_tanf_countable_earned_income: 160 + ar_tea_countable_earned_income: 160 # 500 * 0.80 * 0.40 = 160 - ar_tanf_countable_income: 160 + ar_tea_countable_income: 160 # Eligibility chain - ar_tanf_income_eligible: true + ar_tea_income_eligible: true # Gross: 500 < 185% FPL -> pass # Net: 160 <= 223 -> pass - ar_tanf_eligible: true + ar_tea_eligible: true # Benefit calculation - ar_tanf_maximum_benefit: 247 + ar_tea_maximum_benefit: 247 # Family size 4 -> $247 - ar_tanf: 0 + ar_tea: 0 # Gross income 500 >= 446, so 50% reduction # Reduced payment = 247 * 0.5 = 123.5 # max(123.5 - 160, 0) = 0 @@ -209,20 +209,20 @@ # Income calculation chain (per documentation example) tanf_gross_earned_income: [550, 0, 0] # Person1: 6,600 / 12 = 550/month - ar_tanf_countable_earned_income: 176 + ar_tea_countable_earned_income: 176 # Step 1: 550 * 0.80 = 440 (after 20% work expense) # Step 2: 440 * 0.40 = 176 (after 60% work incentive) - ar_tanf_countable_income: 176 + ar_tea_countable_income: 176 # Eligibility chain - ar_tanf_income_eligible: true + ar_tea_income_eligible: true # Gross: 550 < 185% FPL -> pass # Net: 176 <= 223 -> pass - ar_tanf_eligible: true + ar_tea_eligible: true # Benefit calculation - ar_tanf_maximum_benefit: 204 - ar_tanf: 0 + ar_tea_maximum_benefit: 204 + ar_tea: 0 # Gross income 550 >= 446, so 50% reduction # Reduced payment = 204 * 0.5 = 102 # max(102 - 176, 0) = 0 @@ -251,19 +251,19 @@ output: # Income calculation chain tanf_gross_earned_income: [800, 0, 0] - ar_tanf_countable_earned_income: 256 + ar_tea_countable_earned_income: 256 # 800 * 0.80 * 0.40 = 256 - ar_tanf_countable_income: 256 + ar_tea_countable_income: 256 # Eligibility chain - ar_tanf_income_eligible: false + ar_tea_income_eligible: false # Gross: 800 < 185% FPL -> pass # Net: 256 > 223 -> FAIL - ar_tanf_eligible: false + ar_tea_eligible: false # Benefit calculation - ar_tanf_maximum_benefit: 204 - ar_tanf: 0 + ar_tea_maximum_benefit: 204 + ar_tea: 0 # Ineligible -> no benefit - name: Case 7, resources exceed limit making family ineligible. @@ -287,19 +287,19 @@ state_code: AR output: # Income calculation chain - ar_tanf_countable_income: 0 + ar_tea_countable_income: 0 # Eligibility chain - ar_tanf_income_eligible: true + ar_tea_income_eligible: true # Gross: 0 < 185% FPL -> pass # Net: 0 <= 223 -> pass - ar_tanf_resources_eligible: false + ar_tea_resources_eligible: false # 5,000 > 3,000 -> RESOURCES INELIGIBLE - ar_tanf_eligible: false + ar_tea_eligible: false # Benefit calculation - ar_tanf_maximum_benefit: 162 - ar_tanf: 0 + ar_tea_maximum_benefit: 162 + ar_tea: 0 # Ineligible -> no benefit - name: Case 8, initial applicant family of 3 (20% deduction only). @@ -326,20 +326,20 @@ output: # Income calculation chain - initial applicant gets only 20% deduction tanf_gross_earned_income: [400, 0, 0] - ar_tanf_countable_earned_income: 320 + ar_tea_countable_earned_income: 320 # Initial applicant: 400 * 0.80 = 320 (only 20% work expense) - ar_tanf_countable_income: 320 + ar_tea_countable_income: 320 # 320 (earned) + 0 (unearned) = 320 # Eligibility chain - ar_tanf_income_eligible: false + ar_tea_income_eligible: false # Gross: 400 < 185% FPL -> pass # Net: 320 > 223 -> FAIL (initial applicant has higher countable income) - ar_tanf_eligible: false + ar_tea_eligible: false # Benefit calculation - ar_tanf_maximum_benefit: 204 - ar_tanf: 0 + ar_tea_maximum_benefit: 204 + ar_tea: 0 # Ineligible -> no benefit - name: Case 9, gross income above 185% FPL makes family ineligible. @@ -366,17 +366,17 @@ output: # Income calculation chain tanf_gross_earned_income: [4_500, 0, 0] - ar_tanf_countable_earned_income: 1_440 + ar_tea_countable_earned_income: 1_440 # 4,500 * 0.80 * 0.40 = 1,440 - ar_tanf_countable_income: 1_440 + ar_tea_countable_income: 1_440 # Eligibility chain - ar_tanf_income_eligible: false + ar_tea_income_eligible: false # 185% FPL for size 3 in 2024: $25,820 * 1.85 / 12 = $3,980.58 # Gross: 4,500 >= 3,980.58 -> FAIL - ar_tanf_eligible: false + ar_tea_eligible: false # Benefit calculation - ar_tanf_maximum_benefit: 204 - ar_tanf: 0 + ar_tea_maximum_benefit: 204 + ar_tea: 0 # Ineligible -> no benefit diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf.py b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea.py similarity index 62% rename from policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf.py rename to policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea.py index bafda45ad69..0c3037fbfac 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea.py @@ -1,34 +1,33 @@ from policyengine_us.model_api import * -class ar_tanf(Variable): +class ar_tea(Variable): value_type = float entity = SPMUnit - label = "Arkansas Transitional Employment Assistance (TANF)" + label = "Arkansas Transitional Employment Assistance" unit = USD definition_period = MONTH reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" - defined_for = "ar_tanf_eligible" + defined_for = "ar_tea_eligible" def formula(spm_unit, period, parameters): # Per 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - p = parameters(period).gov.states.ar.dhs.tanf + p = parameters(period).gov.states.ar.dhs.tea - maximum_benefit = spm_unit("ar_tanf_maximum_benefit", period) - countable_income = spm_unit("ar_tanf_countable_income", period) + maximum_benefit = spm_unit("ar_tea_maximum_benefit", period) + countable_income = spm_unit("ar_tea_countable_income", period) # Check if gross income triggers 50% payment reduction gross_earned = spm_unit("tanf_gross_earned_income", period) unearned = spm_unit("tanf_gross_unearned_income", period) gross_income = gross_earned + unearned - trigger = p.income.gross_income_trigger - above_trigger = gross_income >= trigger.amount + above_trigger = gross_income >= p.payment_standard.trigger.amount # Apply 50% reduction to maximum payment when above trigger effective_maximum = where( above_trigger, - maximum_benefit * (1 - trigger.reduction_rate), + maximum_benefit * (1 - p.payment_standard.trigger.reduction_rate), maximum_benefit, ) diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.py b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_countable_earned_income.py similarity index 73% rename from policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.py rename to policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_countable_earned_income.py index a4985dd6eaa..378b2fe7c4f 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_countable_earned_income.py @@ -1,10 +1,10 @@ from policyengine_us.model_api import * -class ar_tanf_countable_earned_income(Variable): +class ar_tea_countable_earned_income(Variable): value_type = float entity = SPMUnit - label = "Arkansas TANF countable earned income" + label = "Arkansas TEA countable earned income" unit = USD definition_period = MONTH reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" @@ -12,11 +12,11 @@ class ar_tanf_countable_earned_income(Variable): def formula(spm_unit, period, parameters): # Per 208.00.13 Ark. Code R. Section 001, Section 3.3 - p = parameters(period).gov.states.ar.dhs.tanf.income.deductions + p = parameters(period).gov.states.ar.dhs.tea.income gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) # Step 1: Apply 20% work expense deduction (applies to all) - after_work_expense = gross_earned * (1 - p.work_expense.rate) + after_work_expense = gross_earned * (1 - p.work_deduction.expense_rate) # Step 2: Apply 60% work incentive deduction (only for ongoing recipients) is_enrolled = spm_unit("is_tanf_enrolled", period) @@ -25,6 +25,6 @@ def formula(spm_unit, period, parameters): # For ongoing recipients: 20% work expense + 60% work incentive return where( is_enrolled, - after_work_expense * (1 - p.work_incentive.rate), + after_work_expense * (1 - p.work_deduction.incentive_rate), after_work_expense, ) diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_income.py b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_countable_income.py similarity index 71% rename from policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_income.py rename to policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_countable_income.py index 3055957f537..f85f4aefdac 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_countable_income.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_countable_income.py @@ -1,16 +1,16 @@ from policyengine_us.model_api import * -class ar_tanf_countable_income(Variable): +class ar_tea_countable_income(Variable): value_type = float entity = SPMUnit - label = "Arkansas TANF countable income" + label = "Arkansas TEA countable income" unit = USD definition_period = MONTH reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" defined_for = StateCode.AR def formula(spm_unit, period, parameters): - countable_earned = spm_unit("ar_tanf_countable_earned_income", period) + countable_earned = spm_unit("ar_tea_countable_earned_income", period) unearned = spm_unit("tanf_gross_unearned_income", period) return countable_earned + unearned diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_eligible.py b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_eligible.py similarity index 70% rename from policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_eligible.py rename to policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_eligible.py index 28ef9dd848b..186b3909242 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_eligible.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_eligible.py @@ -1,17 +1,17 @@ from policyengine_us.model_api import * -class ar_tanf_eligible(Variable): +class ar_tea_eligible(Variable): value_type = bool entity = SPMUnit - label = "Arkansas TANF eligible" + label = "Arkansas TEA eligible" definition_period = MONTH reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" defined_for = StateCode.AR def formula(spm_unit, period, parameters): - income_eligible = spm_unit("ar_tanf_income_eligible", period) - resources_eligible = spm_unit("ar_tanf_resources_eligible", period) + income_eligible = spm_unit("ar_tea_income_eligible", period) + resources_eligible = spm_unit("ar_tea_resources_eligible", period) # Use federal demographic eligibility (already SPM unit-level) demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) return income_eligible & resources_eligible & demographic_eligible diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.py b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_income_eligible.py similarity index 70% rename from policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.py rename to policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_income_eligible.py index 95da1c79b81..13addc077e5 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_income_eligible.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_income_eligible.py @@ -1,21 +1,21 @@ from policyengine_us.model_api import * -class ar_tanf_income_eligible(Variable): +class ar_tea_income_eligible(Variable): value_type = bool entity = SPMUnit - label = "Arkansas TANF income eligible" + label = "Arkansas TEA income eligible" definition_period = MONTH reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" defined_for = StateCode.AR def formula(spm_unit, period, parameters): # Per 208.00.13 Ark. Code R. Section 001, Section 3.3 - p = parameters(period).gov.states.ar.dhs.tanf.income + p = parameters(period).gov.states.ar.dhs.tea.income # Step 1: Gross income test - must be below 185% FPL fpg = spm_unit("spm_unit_fpg", period) - gross_income_limit = fpg * p.gross_income_limit.rate + gross_income_limit = fpg * p.gross_income.limit_rate gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) gross_unearned = add(spm_unit, period, ["tanf_gross_unearned_income"]) @@ -24,7 +24,7 @@ def formula(spm_unit, period, parameters): passes_gross_test = gross_income < gross_income_limit # Step 2: Net income test - countable income must be at or below $223 - countable_income = spm_unit("ar_tanf_countable_income", period) - passes_net_test = countable_income <= p.eligibility_standard.amount + countable_income = spm_unit("ar_tea_countable_income", period) + passes_net_test = countable_income <= p.income_limit return passes_gross_test & passes_net_test diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.py b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_maximum_benefit.py similarity index 77% rename from policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.py rename to policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_maximum_benefit.py index 26b90840481..9deda8d1d67 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_maximum_benefit.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_maximum_benefit.py @@ -1,10 +1,10 @@ from policyengine_us.model_api import * -class ar_tanf_maximum_benefit(Variable): +class ar_tea_maximum_benefit(Variable): value_type = float entity = SPMUnit - label = "Arkansas TANF maximum benefit" + label = "Arkansas TEA maximum benefit" unit = USD definition_period = MONTH reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" @@ -12,7 +12,7 @@ class ar_tanf_maximum_benefit(Variable): def formula(spm_unit, period, parameters): # Per 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - p = parameters(period).gov.states.ar.dhs.tanf.payment_standard + p = parameters(period).gov.states.ar.dhs.tea.payment_standard unit_size = spm_unit("spm_unit_size", period.this_year) capped_size = min_(unit_size, p.max_unit_size) return p.amount[capped_size] diff --git a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.py b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_resources_eligible.py similarity index 76% rename from policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.py rename to policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_resources_eligible.py index 50ea36a47ed..ae11cb313c7 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tanf/ar_tanf_resources_eligible.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_resources_eligible.py @@ -1,17 +1,17 @@ from policyengine_us.model_api import * -class ar_tanf_resources_eligible(Variable): +class ar_tea_resources_eligible(Variable): value_type = bool entity = SPMUnit - label = "Arkansas TANF resources eligible" + label = "Arkansas TEA resources eligible" definition_period = MONTH reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" defined_for = StateCode.AR def formula(spm_unit, period, parameters): # Per 208.00.13 Ark. Code R. Section 001, Section 3.4 - p = parameters(period).gov.states.ar.dhs.tanf.resources + p = parameters(period).gov.states.ar.dhs.tea.resources # Use federal asset calculation for SPM unit resources = spm_unit("spm_unit_assets", period.this_year) return resources <= p.limit From 1d4cd86458ad2db7f9c77cfffd745b53a1c2d963 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 17 Dec 2025 22:34:21 -0500 Subject: [PATCH 6/8] adjustments --- .../tea/income/gross_income/limit_rate.yaml | 14 - .../ar/dhs/tea/income/income_limit.yaml | 9 +- .../income/work_deduction/expense_rate.yaml | 4 +- .../income/work_deduction/incentive_rate.yaml | 4 +- .../ar/dhs/tea/payment_standard/amount.yaml | 44 +-- .../tea/payment_standard/max_unit_size.yaml | 2 +- .../tea/payment_standard/trigger/amount.yaml | 5 +- .../trigger/reduction_rate.yaml | 4 +- .../states/ar/dhs/tea/resources/limit.yaml | 6 +- .../gov/states/ar/dhs/tea/ar_tea.yaml | 24 +- .../ar/dhs/tea/ar_tea_countable_income.yaml | 98 ------- .../ar/dhs/tea/ar_tea_income_eligible.yaml | 107 ++++--- .../gov/states/ar/dhs/tea/integration.yaml | 272 +++++++++++++----- .../variables/gov/states/ar/dhs/tea/ar_tea.py | 16 +- .../ar/dhs/tea/ar_tea_income_eligible.py | 30 -- .../tea/{ => eligibility}/ar_tea_eligible.py | 12 +- .../tea/eligibility/ar_tea_income_eligible.py | 17 ++ .../ar_tea_resources_eligible.py | 0 .../ar_tea_countable_earned_income.py | 6 +- .../{ => income}/ar_tea_countable_income.py | 5 +- 20 files changed, 339 insertions(+), 340 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/ar/dhs/tea/income/gross_income/limit_rate.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_countable_income.yaml delete mode 100644 policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_income_eligible.py rename policyengine_us/variables/gov/states/ar/dhs/tea/{ => eligibility}/ar_tea_eligible.py (62%) create mode 100644 policyengine_us/variables/gov/states/ar/dhs/tea/eligibility/ar_tea_income_eligible.py rename policyengine_us/variables/gov/states/ar/dhs/tea/{ => eligibility}/ar_tea_resources_eligible.py (100%) rename policyengine_us/variables/gov/states/ar/dhs/tea/{ => income}/ar_tea_countable_earned_income.py (82%) rename policyengine_us/variables/gov/states/ar/dhs/tea/{ => income}/ar_tea_countable_income.py (59%) diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tea/income/gross_income/limit_rate.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/gross_income/limit_rate.yaml deleted file mode 100644 index 51aff3ccbec..00000000000 --- a/policyengine_us/parameters/gov/states/ar/dhs/tea/income/gross_income/limit_rate.yaml +++ /dev/null @@ -1,14 +0,0 @@ -description: Arkansas limits gross income to this share of the federal poverty guideline under the Transitional Employment Assistance program. - -values: - 1997-09-01: 1.85 - -metadata: - unit: /1 - period: month - label: Arkansas TEA gross income limit rate - reference: - - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Limit - href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 - - title: Arkansas TEA/Work Pays Program - href: https://humanservices.arkansas.gov/divisions-shared-services/county-operations/temporary-assistance-for-needy-families/transitional-employment-assistance-tea-work-pays/ diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tea/income/income_limit.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/income_limit.yaml index 7ae6bc3cc43..797b09d8b31 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tea/income/income_limit.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/income_limit.yaml @@ -1,7 +1,8 @@ description: Arkansas limits countable income to this amount for eligibility under the Transitional Employment Assistance program. values: - 1997-09-01: 223 + 1999-09-01: 223 + 2023-01-01: 513 metadata: unit: currency-USD @@ -10,5 +11,7 @@ metadata: reference: - title: 208.00.13 Ark. Code R. Section 001, Section 3.3 - Income Limit href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 - - title: Arkansas TEA/Work Pays Program - href: https://humanservices.arkansas.gov/divisions-shared-services/county-operations/temporary-assistance-for-needy-families/transitional-employment-assistance-tea-work-pays/ + - title: Arkansas TEA Policy Manual Sec 2101 + href: https://humanservices.arkansas.gov/wp-content/uploads/TEA_MANUAL-10.1.24.pdf#page=13 + - title: Quick Reference Transitional Employment Assistance (2024) + href: https://humanservices.arkansas.gov/wp-content/uploads/TEA-Quick-Reference-Guide-4.2024.pdf diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/expense_rate.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/expense_rate.yaml index 2f609993f4a..ce049d7fbf9 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/expense_rate.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/expense_rate.yaml @@ -1,7 +1,7 @@ description: Arkansas deducts this share of gross earned income as work-related expenses under the Transitional Employment Assistance program. values: - 1997-09-01: 0.2 + 1999-09-01: 0.2 metadata: unit: /1 @@ -12,3 +12,5 @@ metadata: href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 - title: 016.20.98-041 Ark. Code R. - TEA Policy 2352-2362, Work Expense Deduction href: https://regulations.justia.com/states/arkansas/agency-016/division-20/rule-016-20-98-041/ + - title: Arkansas TEA Policy Manual Sec 2352 + href: https://humanservices.arkansas.gov/wp-content/uploads/TEA_MANUAL-10.1.24.pdf#page=89 diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/incentive_rate.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/incentive_rate.yaml index 5151fa3e2ed..9bc0bcee465 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/incentive_rate.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/incentive_rate.yaml @@ -1,7 +1,7 @@ description: Arkansas deducts this share of remaining earned income as a work incentive under the Transitional Employment Assistance program. values: - 1997-09-01: 0.6 + 1999-09-01: 0.6 metadata: unit: /1 @@ -12,3 +12,5 @@ metadata: href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 - title: 016.20.98-041 Ark. Code R. - TEA Policy 2352-2362, Work Incentive Deduction href: https://regulations.justia.com/states/arkansas/agency-016/division-20/rule-016-20-98-041/ + - title: Arkansas TEA Policy Manual Sec 2352 + href: https://humanservices.arkansas.gov/wp-content/uploads/TEA_MANUAL-10.1.24.pdf#page=13 diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/amount.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/amount.yaml index 3d8c7868774..e327fc2cd6b 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/amount.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/amount.yaml @@ -7,46 +7,26 @@ metadata: - range(1, 20) label: Arkansas TEA payment standard amount reference: - - title: 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - Payment Standards + - title: 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - Monthly Cash Assistance Payment Amount href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 - - title: Arkansas TEA/Work Pays Program - href: https://humanservices.arkansas.gov/divisions-shared-services/county-operations/temporary-assistance-for-needy-families/transitional-employment-assistance-tea-work-pays/ + - title: Arkansas TEA Policy Manual Sec 2361 + href: https://humanservices.arkansas.gov/wp-content/uploads/TEA_MANUAL-10.1.24.pdf#page=92 1: - 1997-09-01: 81 + 2012-01-01: 81 2: - 1997-09-01: 162 + 2012-01-01: 162 3: - 1997-09-01: 204 + 2012-01-01: 204 4: - 1997-09-01: 247 + 2012-01-01: 247 5: - 1997-09-01: 286 + 2012-01-01: 286 6: - 1997-09-01: 331 + 2012-01-01: 331 7: - 1997-09-01: 373 + 2012-01-01: 373 8: - 1997-09-01: 415 + 2012-01-01: 415 9: - 1997-09-01: 457 -10: - 1997-09-01: 457 -11: - 1997-09-01: 457 -12: - 1997-09-01: 457 -13: - 1997-09-01: 457 -14: - 1997-09-01: 457 -15: - 1997-09-01: 457 -16: - 1997-09-01: 457 -17: - 1997-09-01: 457 -18: - 1997-09-01: 457 -19: - 1997-09-01: 457 + 2012-01-01: 457 diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/max_unit_size.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/max_unit_size.yaml index e5726f24eba..31dc1005f54 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/max_unit_size.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/max_unit_size.yaml @@ -1,7 +1,7 @@ description: Arkansas provides increased payment amounts for households with up to this number of members under the Transitional Employment Assistance program. values: - 1997-09-01: 9 + 1999-09-01: 9 metadata: unit: int diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/amount.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/amount.yaml index 587bb9f9528..57b71413d6c 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/amount.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/amount.yaml @@ -1,7 +1,8 @@ description: Arkansas reduces the payment by half when gross income equals or exceeds this amount under the Transitional Employment Assistance program. values: - 1997-09-01: 446 + 1999-09-01: 446 + 2023-01-01: 1_026 metadata: unit: currency-USD @@ -12,3 +13,5 @@ metadata: href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 - title: Arkansas TEA/Work Pays Program href: https://humanservices.arkansas.gov/divisions-shared-services/county-operations/temporary-assistance-for-needy-families/transitional-employment-assistance-tea-work-pays/ + - title: Arkansas TEA Policy Manual Sec 2362 + href: https://humanservices.arkansas.gov/wp-content/uploads/TEA_MANUAL-10.1.24.pdf#page=93 diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/reduction_rate.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/reduction_rate.yaml index 0b3f243aa57..afa20cc3a97 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/reduction_rate.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/trigger/reduction_rate.yaml @@ -1,7 +1,7 @@ description: Arkansas reduces the payment by this share when gross income equals or exceeds the trigger amount under the Transitional Employment Assistance program. values: - 1997-09-01: 0.5 + 1999-09-01: 0.5 metadata: unit: /1 @@ -10,3 +10,5 @@ metadata: reference: - title: 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - Payment Standards href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 + - title: Arkansas TEA Policy Manual Sec 2362 + href: https://humanservices.arkansas.gov/wp-content/uploads/TEA_MANUAL-10.1.24.pdf#page=93 diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tea/resources/limit.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/resources/limit.yaml index c6dbd22edc0..313040c6892 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tea/resources/limit.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/resources/limit.yaml @@ -1,7 +1,7 @@ description: Arkansas limits countable resources to this amount for eligibility under the Transitional Employment Assistance program. values: - 1997-09-01: 3_000 + 1999-09-01: 3_000 metadata: unit: currency-USD @@ -10,5 +10,5 @@ metadata: reference: - title: 208.00.13 Ark. Code R. Section 001, Section 3.4 - Resource Limits href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 - - title: Arkansas TEA/Work Pays Program - href: https://humanservices.arkansas.gov/divisions-shared-services/county-operations/temporary-assistance-for-needy-families/transitional-employment-assistance-tea-work-pays/ + - title: Arkansas TEA Policy Manual Sec 2101 + href: https://humanservices.arkansas.gov/wp-content/uploads/TEA_MANUAL-10.1.24.pdf#page=13 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea.yaml index 3eed1515fef..31d6394bb38 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea.yaml @@ -1,8 +1,8 @@ # Unit tests for ar_tea (final benefit amount) -# Benefit calculation: +# Benefit calculation (per TEA Manual Section 2362, effective 01/01/2023): # 1. If not eligible: $0 -# 2. If gross income < $446: benefit = max(payment_standard - countable_income, 0) -# 3. If gross income >= $446: benefit = max(payment_standard * 0.5 - countable_income, 0) +# 2. If gross income < $1026: benefit = max(payment_standard - countable_income, 0) +# 3. If gross income >= $1026: benefit = payment_standard * 0.5 (no subtraction) - name: Case 1, ineligible receives zero. period: 2024-01 @@ -68,7 +68,7 @@ ar_tea_countable_income: 128 output: ar_tea: 76 - # Gross income 400 < 446 trigger, so full payment standard applies + # Gross income 400 < 1026 trigger, so full payment standard applies # max(204 - 128, 0) = 76 - name: Case 4, gross income at trigger causes 50 percent reduction. @@ -77,7 +77,7 @@ people: person1: age: 30 - tanf_gross_earned_income: 446 + tanf_gross_earned_income: 1_026 tanf_gross_unearned_income: 0 households: household: @@ -91,8 +91,8 @@ ar_tea_countable_income: 0 output: ar_tea: 102 - # Gross income 446 >= 446 trigger, so 50% reduction - # max(204 * 0.5 - 0, 0) = max(102 - 0, 0) = 102 + # Gross income 1,026 >= 1,026 trigger, so 50% reduction + # 204 * 0.5 = 102 (no subtraction when above trigger) - name: Case 5, gross income above trigger with countable income. period: 2024-01 @@ -100,7 +100,7 @@ people: person1: age: 30 - tanf_gross_earned_income: 500 + tanf_gross_earned_income: 1_200 tanf_gross_unearned_income: 0 households: household: @@ -111,11 +111,11 @@ members: [person1] ar_tea_eligible: true ar_tea_maximum_benefit: 162 - ar_tea_countable_income: 50 + ar_tea_countable_income: 384 output: - ar_tea: 31 - # Gross income 500 >= 446 trigger, so 50% reduction - # max(162 * 0.5 - 50, 0) = max(81 - 50, 0) = 31 + ar_tea: 81 + # Gross income 1,200 >= 1,026 trigger, so 50% reduction + # 162 * 0.5 = 81 (no subtraction when above trigger) - name: Case 6, benefit would be negative clipped to zero. period: 2024-01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_countable_income.yaml deleted file mode 100644 index 8756a0af27b..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_countable_income.yaml +++ /dev/null @@ -1,98 +0,0 @@ -# Unit tests for ar_tea_countable_income -# Total countable income = countable earned income + unearned income -# Note: Earned income has already been reduced by 20% + 60% deductions -# Unearned income has no deductions applied - -- name: Case 1, zero income. - period: 2024-01 - input: - people: - person1: - age: 30 - tanf_gross_unearned_income: 0 - households: - household: - members: [person1] - state_code: AR - spm_units: - spm_unit: - members: [person1] - ar_tea_countable_earned_income: 0 - output: - ar_tea_countable_income: 0 - -- name: Case 2, only earned income. - period: 2024-01 - input: - people: - person1: - age: 30 - tanf_gross_unearned_income: 0 - households: - household: - members: [person1] - state_code: AR - spm_units: - spm_unit: - members: [person1] - ar_tea_countable_earned_income: 176 - output: - ar_tea_countable_income: 176 - # 176 (earned after disregards) + 0 (unearned) = 176 - -- name: Case 3, only unearned income. - period: 2024-01 - input: - people: - person1: - age: 30 - tanf_gross_unearned_income: 150 - households: - household: - members: [person1] - state_code: AR - spm_units: - spm_unit: - members: [person1] - ar_tea_countable_earned_income: 0 - output: - ar_tea_countable_income: 150 - # 0 (earned) + 150 (unearned) = 150 - -- name: Case 4, mixed earned and unearned income. - period: 2024-01 - input: - people: - person1: - age: 30 - tanf_gross_unearned_income: 100 - households: - household: - members: [person1] - state_code: AR - spm_units: - spm_unit: - members: [person1] - ar_tea_countable_earned_income: 96 - output: - ar_tea_countable_income: 196 - # 96 (earned after disregards) + 100 (unearned) = 196 - -- name: Case 5, income at eligibility threshold. - period: 2024-01 - input: - people: - person1: - age: 30 - tanf_gross_unearned_income: 100 - households: - household: - members: [person1] - state_code: AR - spm_units: - spm_unit: - members: [person1] - ar_tea_countable_earned_income: 123 - output: - ar_tea_countable_income: 223 - # 123 + 100 = 223 (exactly at $223 income eligibility standard) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_income_eligible.yaml index a13fe2300a0..93f916bccc0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/ar_tea_income_eligible.yaml @@ -1,16 +1,13 @@ # Unit tests for ar_tea_income_eligible -# Arkansas TEA has two income tests: -# 1. Gross income test: Gross income must be < 185% FPL -# 2. Net income test: Countable income must be <= $223/month (all family sizes) +# Arkansas TEA income eligibility: Countable income must be <= $513/month (all family sizes) +# Income limit increased from $223 to $513 effective 01/01/2023 -- name: Case 1, zero income passes both tests. +- name: Case 1, zero income is eligible. period: 2024-01 input: people: person1: age: 30 - tanf_gross_earned_income: 0 - tanf_gross_unearned_income: 0 households: household: members: [person1] @@ -21,17 +18,14 @@ ar_tea_countable_income: 0 output: ar_tea_income_eligible: true - # Gross: 0 < 185% FPL -> pass - # Net: 0 <= 223 -> pass + # 0 <= 513 -> eligible -- name: Case 2, low income passes both tests. +- name: Case 2, countable income below limit is eligible. period: 2024-01 input: people: person1: age: 30 - tanf_gross_earned_income: 300 - tanf_gross_unearned_income: 0 households: household: members: [person1] @@ -39,20 +33,17 @@ spm_units: spm_unit: members: [person1] - ar_tea_countable_income: 150 + ar_tea_countable_income: 400 output: ar_tea_income_eligible: true - # Gross: 300 < 185% FPL (~$2,322 for size 1) -> pass - # Net: 150 <= 223 -> pass + # 400 <= 513 -> eligible -- name: Case 3, net income at threshold passes. +- name: Case 3, countable income at threshold is eligible. period: 2024-01 input: people: person1: age: 30 - tanf_gross_earned_income: 500 - tanf_gross_unearned_income: 0 households: household: members: [person1] @@ -60,20 +51,17 @@ spm_units: spm_unit: members: [person1] - ar_tea_countable_income: 223 + ar_tea_countable_income: 513 output: ar_tea_income_eligible: true - # Gross: 500 < 185% FPL -> pass - # Net: 223 <= 223 -> pass (at threshold is still eligible) + # 513 <= 513 -> eligible (at threshold is still eligible) -- name: Case 4, net income one dollar over threshold fails. +- name: Case 4, countable income one dollar over threshold is ineligible. period: 2024-01 input: people: person1: age: 30 - tanf_gross_earned_income: 500 - tanf_gross_unearned_income: 0 households: household: members: [person1] @@ -81,20 +69,17 @@ spm_units: spm_unit: members: [person1] - ar_tea_countable_income: 224 + ar_tea_countable_income: 514 output: ar_tea_income_eligible: false - # Gross: 500 < 185% FPL -> pass - # Net: 224 > 223 -> FAIL + # 514 > 513 -> ineligible -- name: Case 5, gross income above 185% FPL fails. +- name: Case 5, countable income well above threshold is ineligible. period: 2024-01 input: people: person1: age: 30 - tanf_gross_earned_income: 2_500 - tanf_gross_unearned_income: 0 households: household: members: [person1] @@ -102,59 +87,63 @@ spm_units: spm_unit: members: [person1] - ar_tea_countable_income: 100 + ar_tea_countable_income: 700 output: ar_tea_income_eligible: false - # 185% FPL for size 1 in 2024: $15,060 * 1.85 / 12 = $2,321.75 - # Gross: 2,500 >= 2,321.75 -> FAIL (even though net income would pass) + # 700 > 513 -> ineligible -- name: Case 6, family of 3 gross income below 185% FPL. - period: 2024-01 +# 2022 tests - using old $223 income limit (before 01/01/2023 increase) + +- name: Case 6, 2022 countable income at old threshold is eligible. + period: 2022-01 input: people: person1: age: 30 - tanf_gross_earned_income: 3_000 - tanf_gross_unearned_income: 0 - person2: - age: 10 - person3: - age: 8 households: household: - members: [person1, person2, person3] + members: [person1] state_code: AR spm_units: spm_unit: - members: [person1, person2, person3] - ar_tea_countable_income: 150 + members: [person1] + ar_tea_countable_income: 223 output: ar_tea_income_eligible: true - # 185% FPL for size 3 in 2024: $25,820 * 1.85 / 12 = $3,980.58 - # Gross: 3,000 < 3,980.58 -> pass - # Net: 150 <= 223 -> pass + # 223 <= 223 -> eligible (at old threshold) -- name: Case 7, family of 3 gross income above 185% FPL. - period: 2024-01 +- name: Case 7, 2022 countable income one dollar over old threshold is ineligible. + period: 2022-01 input: people: person1: age: 30 - tanf_gross_earned_income: 4_500 - tanf_gross_unearned_income: 0 - person2: - age: 10 - person3: - age: 8 households: household: - members: [person1, person2, person3] + members: [person1] state_code: AR spm_units: spm_unit: - members: [person1, person2, person3] - ar_tea_countable_income: 100 + members: [person1] + ar_tea_countable_income: 224 + output: + ar_tea_income_eligible: false + # 224 > 223 -> ineligible (old threshold) + +- name: Case 8, 2022 countable income of 400 is ineligible under old limit. + period: 2022-01 + input: + people: + person1: + age: 30 + households: + household: + members: [person1] + state_code: AR + spm_units: + spm_unit: + members: [person1] + ar_tea_countable_income: 400 output: ar_tea_income_eligible: false - # 185% FPL for size 3 in 2024: $25,820 * 1.85 / 12 = $3,980.58 - # Gross: 4,500 >= 3,980.58 -> FAIL + # 400 > 223 -> ineligible (but would be eligible under 2024 $513 limit) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/integration.yaml index 950f4b0c3d6..647d852aaea 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/integration.yaml @@ -1,4 +1,4 @@ -# Integration tests for Arkansas TANF (TEA - Transitional Employment Assistance) +# Integration tests for Arkansas TEA (Transitional Employment Assistance) # These tests verify the complete benefit calculation pipeline from inputs to final benefit # Note: These tests use is_tanf_enrolled: true to simulate ongoing recipients @@ -25,16 +25,12 @@ output: # Income calculation chain tanf_gross_earned_income: [0, 0, 0] - # No earned income for any member ar_tea_countable_earned_income: 0 - # 0 * 0.32 = 0 (after 20% + 60% deductions) ar_tea_countable_income: 0 - # 0 (earned) + 0 (unearned) = 0 # Eligibility chain ar_tea_income_eligible: true - # Gross: 0 < 185% FPL -> pass - # Net: 0 <= 223 -> pass + # 0 <= 513 -> eligible ar_tea_resources_eligible: true # 1,000 <= 3,000 -> eligible ar_tea_eligible: true @@ -71,29 +67,24 @@ output: # Income calculation chain tanf_gross_earned_income: [400, 0, 0] - # Person1: 4,800 / 12 = 400/month ar_tea_countable_earned_income: 128 # Step 1: 400 * 0.80 = 320 (after 20% work expense) # Step 2: 320 * 0.40 = 128 (after 60% work incentive) ar_tea_countable_income: 128 - # 128 (earned) + 0 (unearned) = 128 # Eligibility chain ar_tea_income_eligible: true - # Gross: 400 < 185% FPL -> pass - # Net: 128 <= 223 -> pass + # 128 <= 513 -> eligible ar_tea_resources_eligible: true - # 500 <= 3,000 -> eligible ar_tea_eligible: true # Benefit calculation ar_tea_maximum_benefit: 204 - # Family size 3 -> $204 ar_tea: 76 # Gross income 400 < 446, so full payment standard # max(204 - 128, 0) = 76 -- name: Case 3, ongoing family of 2 with earnings at gross income trigger. +- name: Case 3, ongoing family of 2 with earnings below trigger. period: 2024-01 absolute_error_margin: 0.01 input: @@ -101,7 +92,7 @@ person1: age: 30 employment_income_before_lsr: 5_352 - # Annual $5,352 = $446/month (at trigger threshold) + # Annual $5,352 = $446/month person2: age: 10 spm_units: @@ -116,28 +107,23 @@ output: # Income calculation chain tanf_gross_earned_income: [446, 0] - # Person1: 5,352 / 12 = 446/month ar_tea_countable_earned_income: 142.72 # 446 * 0.80 * 0.40 = 142.72 ar_tea_countable_income: 142.72 # Eligibility chain ar_tea_income_eligible: true - # Gross: 446 < 185% FPL -> pass - # Net: 142.72 <= 223 -> pass + # 142.72 <= 513 -> eligible ar_tea_resources_eligible: true - # 2,000 <= 3,000 -> eligible ar_tea_eligible: true # Benefit calculation ar_tea_maximum_benefit: 162 - # Family size 2 -> $162 - ar_tea: 0 - # Gross income 446 >= 446, so 50% reduction applies - # Reduced payment = 162 * 0.5 = 81 - # max(81 - 142.72, 0) = max(-61.72, 0) = 0 + ar_tea: 19.28 + # Gross income 446 < 1026, so no reduction + # max(162 - 142.72, 0) = 19.28 -- name: Case 4, ongoing family of 4 with earnings above trigger but still eligible. +- name: Case 4, ongoing family of 4 with earnings below trigger. period: 2024-01 absolute_error_margin: 0.01 input: @@ -165,33 +151,29 @@ output: # Income calculation chain tanf_gross_earned_income: [500, 0, 0, 0] - # Person1: 6,000 / 12 = 500/month ar_tea_countable_earned_income: 160 # 500 * 0.80 * 0.40 = 160 ar_tea_countable_income: 160 # Eligibility chain ar_tea_income_eligible: true - # Gross: 500 < 185% FPL -> pass - # Net: 160 <= 223 -> pass + # 160 <= 513 -> eligible ar_tea_eligible: true # Benefit calculation ar_tea_maximum_benefit: 247 - # Family size 4 -> $247 - ar_tea: 0 - # Gross income 500 >= 446, so 50% reduction - # Reduced payment = 247 * 0.5 = 123.5 - # max(123.5 - 160, 0) = 0 + ar_tea: 87 + # Gross income 500 < 1026, so no reduction + # max(247 - 160, 0) = 87 -- name: Case 5, ongoing recipient documentation example 550 gross earnings. +- name: Case 5, ongoing recipient with 550 gross earnings below trigger. period: 2024-01 input: people: person1: age: 30 employment_income_before_lsr: 6_600 - # Annual $6,600 = $550/month (from documentation) + # Annual $6,600 = $550/month person2: age: 10 person3: @@ -206,9 +188,8 @@ members: [person1, person2, person3] state_code: AR output: - # Income calculation chain (per documentation example) + # Income calculation chain tanf_gross_earned_income: [550, 0, 0] - # Person1: 6,600 / 12 = 550/month ar_tea_countable_earned_income: 176 # Step 1: 550 * 0.80 = 440 (after 20% work expense) # Step 2: 440 * 0.40 = 176 (after 60% work incentive) @@ -216,18 +197,16 @@ # Eligibility chain ar_tea_income_eligible: true - # Gross: 550 < 185% FPL -> pass - # Net: 176 <= 223 -> pass + # 176 <= 513 -> eligible ar_tea_eligible: true # Benefit calculation ar_tea_maximum_benefit: 204 - ar_tea: 0 - # Gross income 550 >= 446, so 50% reduction - # Reduced payment = 204 * 0.5 = 102 - # max(102 - 176, 0) = 0 + ar_tea: 28 + # Gross income 550 < 1026, so no reduction + # max(204 - 176, 0) = 28 -- name: Case 6, ongoing recipient income exceeds net eligibility standard making family ineligible. +- name: Case 6, ongoing recipient with high earnings but still income eligible. period: 2024-01 input: people: @@ -256,15 +235,16 @@ ar_tea_countable_income: 256 # Eligibility chain - ar_tea_income_eligible: false - # Gross: 800 < 185% FPL -> pass - # Net: 256 > 223 -> FAIL - ar_tea_eligible: false + ar_tea_income_eligible: true + # 256 <= 513 -> eligible + ar_tea_eligible: true # Benefit calculation ar_tea_maximum_benefit: 204 ar_tea: 0 - # Ineligible -> no benefit + # Gross income 800 >= 446, so 50% reduction + # Reduced payment = 204 * 0.5 = 102 + # max(102 - 256, 0) = 0 - name: Case 7, resources exceed limit making family ineligible. period: 2024-01 @@ -280,7 +260,6 @@ members: [person1, person2] spm_unit_assets: 5_000 is_tanf_enrolled: true - # Exceeds $3,000 resource limit households: household: members: [person1, person2] @@ -291,10 +270,9 @@ # Eligibility chain ar_tea_income_eligible: true - # Gross: 0 < 185% FPL -> pass - # Net: 0 <= 223 -> pass + # 0 <= 513 -> eligible ar_tea_resources_eligible: false - # 5,000 > 3,000 -> RESOURCES INELIGIBLE + # 5,000 > 3,000 -> ineligible ar_tea_eligible: false # Benefit calculation @@ -329,27 +307,26 @@ ar_tea_countable_earned_income: 320 # Initial applicant: 400 * 0.80 = 320 (only 20% work expense) ar_tea_countable_income: 320 - # 320 (earned) + 0 (unearned) = 320 # Eligibility chain - ar_tea_income_eligible: false - # Gross: 400 < 185% FPL -> pass - # Net: 320 > 223 -> FAIL (initial applicant has higher countable income) - ar_tea_eligible: false + ar_tea_income_eligible: true + # 320 <= 513 -> eligible + ar_tea_eligible: true # Benefit calculation ar_tea_maximum_benefit: 204 ar_tea: 0 - # Ineligible -> no benefit + # Gross income 400 < 446, so full payment standard + # max(204 - 320, 0) = 0 -- name: Case 9, gross income above 185% FPL makes family ineligible. +- name: Case 9, ongoing recipient with gross income above trigger. period: 2024-01 input: people: person1: age: 30 - employment_income_before_lsr: 54_000 - # Annual $54,000 = $4,500/month + employment_income_before_lsr: 19_200 + # Annual $19,200 = $1,600/month person2: age: 10 person3: @@ -357,7 +334,46 @@ spm_units: spm_unit: members: [person1, person2, person3] - spm_unit_assets: 500 + spm_unit_assets: 1_000 + is_tanf_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + # Income calculation chain + tanf_gross_earned_income: [1_600, 0, 0] + ar_tea_countable_earned_income: 512 + # 1,600 * 0.80 * 0.40 = 512 + ar_tea_countable_income: 512 + + # Eligibility chain + ar_tea_income_eligible: true + # 512 <= 513 -> eligible (just under threshold) + ar_tea_eligible: true + + # Benefit calculation + ar_tea_maximum_benefit: 204 + ar_tea: 102 + # Gross income 1,600 >= 1,026, so 50% reduction + # 204 * 0.5 = 102 (no subtraction when above trigger) + +- name: Case 10, ongoing recipient income exceeds $513 limit making family ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 19_500 + # Annual $19,500 = $1,625/month + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 1_000 is_tanf_enrolled: true households: household: @@ -365,18 +381,138 @@ state_code: AR output: # Income calculation chain - tanf_gross_earned_income: [4_500, 0, 0] - ar_tea_countable_earned_income: 1_440 - # 4,500 * 0.80 * 0.40 = 1,440 - ar_tea_countable_income: 1_440 + tanf_gross_earned_income: [1_625, 0, 0] + ar_tea_countable_earned_income: 520 + # 1,625 * 0.80 * 0.40 = 520 + ar_tea_countable_income: 520 # Eligibility chain ar_tea_income_eligible: false - # 185% FPL for size 3 in 2024: $25,820 * 1.85 / 12 = $3,980.58 - # Gross: 4,500 >= 3,980.58 -> FAIL + # 520 > 513 -> ineligible ar_tea_eligible: false # Benefit calculation ar_tea_maximum_benefit: 204 ar_tea: 0 # Ineligible -> no benefit + +# TEA Manual Examples (Section 2353.1) + +- name: TEA Manual Example 1, Ms. Jones with unearned income exceeding $513 limit. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + unemployment_compensation: 6_501 + # Annual $6,501 = $541.75/month ($125/week UI) + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + is_tanf_enrolled: false + households: + household: + members: [person1, person2] + state_code: AR + output: + # Income calculation chain (per TEA Manual Example #1) + tanf_gross_earned_income: [0, 0] + tanf_gross_unearned_income: [541.75, 0] + ar_tea_countable_earned_income: 0 + ar_tea_countable_income: 541.75 + + # Eligibility chain + ar_tea_income_eligible: false + # 541.75 > 513 -> ineligible + ar_tea_eligible: false + + # Benefit calculation + ar_tea_maximum_benefit: 162 + ar_tea: 0 + # Ineligible -> no benefit + +- name: TEA Manual Example 2, Miller family initial applicant with earned income below $513. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 5_720.88 + # Annual $5,720.88 = $476.74/month (10 hrs/week × $11/hr × 4.33 weeks) + person2: + age: 28 + person3: + age: 10 + person4: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + spm_unit_assets: 1_000 + is_tanf_enrolled: false + households: + household: + members: [person1, person2, person3, person4] + state_code: AR + output: + # Income calculation chain (per TEA Manual Example #2 Section 2353.1) + tanf_gross_earned_income: [476.74, 0, 0, 0] + ar_tea_countable_earned_income: 381.39 + # Initial applicant: 476.74 * 0.80 = 381.39 (manual says 381.40) + ar_tea_countable_income: 381.39 + + # Eligibility chain + ar_tea_income_eligible: true + # 381.39 <= 513 -> eligible + ar_tea_eligible: true + + # Benefit calculation + ar_tea_maximum_benefit: 247 + ar_tea: 0 + # Gross income 476.74 < 1026, so no reduction + # max(247 - 381.39, 0) = 0 + +# TEA Manual Section 2362 Examples (Gross Income Trigger) + +- name: TEA Manual Example 2362-2, Ms. Brown ongoing recipient above trigger. + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 14_400 + # Annual $14,400 = $1,200/month gross + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: AR + output: + # Income calculation chain (per TEA Manual Section 2362 Example #2) + tanf_gross_earned_income: [1_200, 0] + ar_tea_countable_earned_income: 384 + # Ongoing recipient: 1,200 * 0.80 * 0.40 = 384 + ar_tea_countable_income: 384 + + # Eligibility chain + ar_tea_income_eligible: true + # 384 <= 513 -> eligible + ar_tea_eligible: true + + # Benefit calculation + ar_tea_maximum_benefit: 162 + ar_tea: 81 + # Gross income 1,200 >= 1,026, so 50% reduction + # 162 * 0.5 = 81 (per manual: "payment is 50% of the maximum") diff --git a/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea.py b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea.py index 0c3037fbfac..23fa27d8bfe 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea.py @@ -11,7 +11,7 @@ class ar_tea(Variable): defined_for = "ar_tea_eligible" def formula(spm_unit, period, parameters): - # Per 208.00.13 Ark. Code R. Section 001, Section 6.1.1 + # Per TEA Manual Section 2362 - Reduced Payment - Gross Income Trigger p = parameters(period).gov.states.ar.dhs.tea maximum_benefit = spm_unit("ar_tea_maximum_benefit", period) @@ -23,12 +23,14 @@ def formula(spm_unit, period, parameters): gross_income = gross_earned + unearned above_trigger = gross_income >= p.payment_standard.trigger.amount + reduced_payment = maximum_benefit * ( + 1 - p.payment_standard.trigger.reduction_rate + ) - # Apply 50% reduction to maximum payment when above trigger - effective_maximum = where( + # When gross income >= trigger: payment is 50% of max (no subtraction) + # When gross income < trigger: payment is max - countable income + return where( above_trigger, - maximum_benefit * (1 - p.payment_standard.trigger.reduction_rate), - maximum_benefit, + reduced_payment, + max_(maximum_benefit - countable_income, 0), ) - - return max_(effective_maximum - countable_income, 0) diff --git a/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_income_eligible.py b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_income_eligible.py deleted file mode 100644 index 13addc077e5..00000000000 --- a/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_income_eligible.py +++ /dev/null @@ -1,30 +0,0 @@ -from policyengine_us.model_api import * - - -class ar_tea_income_eligible(Variable): - value_type = bool - entity = SPMUnit - label = "Arkansas TEA income eligible" - definition_period = MONTH - reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" - defined_for = StateCode.AR - - def formula(spm_unit, period, parameters): - # Per 208.00.13 Ark. Code R. Section 001, Section 3.3 - p = parameters(period).gov.states.ar.dhs.tea.income - - # Step 1: Gross income test - must be below 185% FPL - fpg = spm_unit("spm_unit_fpg", period) - gross_income_limit = fpg * p.gross_income.limit_rate - - gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) - gross_unearned = add(spm_unit, period, ["tanf_gross_unearned_income"]) - gross_income = gross_earned + gross_unearned - - passes_gross_test = gross_income < gross_income_limit - - # Step 2: Net income test - countable income must be at or below $223 - countable_income = spm_unit("ar_tea_countable_income", period) - passes_net_test = countable_income <= p.income_limit - - return passes_gross_test & passes_net_test diff --git a/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_eligible.py b/policyengine_us/variables/gov/states/ar/dhs/tea/eligibility/ar_tea_eligible.py similarity index 62% rename from policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_eligible.py rename to policyengine_us/variables/gov/states/ar/dhs/tea/eligibility/ar_tea_eligible.py index 186b3909242..e3a8f5ca672 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_eligible.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/eligibility/ar_tea_eligible.py @@ -12,6 +12,14 @@ class ar_tea_eligible(Variable): def formula(spm_unit, period, parameters): income_eligible = spm_unit("ar_tea_income_eligible", period) resources_eligible = spm_unit("ar_tea_resources_eligible", period) - # Use federal demographic eligibility (already SPM unit-level) demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) - return income_eligible & resources_eligible & demographic_eligible + # Must have at least one U.S. citizen or qualified immigrant + immigration_eligible = ( + add(spm_unit, period, ["is_citizen_or_legal_immigrant"]) > 0 + ) + return ( + income_eligible + & resources_eligible + & demographic_eligible + & immigration_eligible + ) diff --git a/policyengine_us/variables/gov/states/ar/dhs/tea/eligibility/ar_tea_income_eligible.py b/policyengine_us/variables/gov/states/ar/dhs/tea/eligibility/ar_tea_income_eligible.py new file mode 100644 index 00000000000..e8f1f3f7b8a --- /dev/null +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/eligibility/ar_tea_income_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ar_tea_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Arkansas TEA income eligible" + definition_period = MONTH + reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" + defined_for = StateCode.AR + + def formula(spm_unit, period, parameters): + # Per 208.00.13 Ark. Code R. Section 001, Section 3.3 + p = parameters(period).gov.states.ar.dhs.tea.income + # Countable income must be at or below $223 + countable_income = spm_unit("ar_tea_countable_income", period) + return countable_income <= p.income_limit diff --git a/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_resources_eligible.py b/policyengine_us/variables/gov/states/ar/dhs/tea/eligibility/ar_tea_resources_eligible.py similarity index 100% rename from policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_resources_eligible.py rename to policyengine_us/variables/gov/states/ar/dhs/tea/eligibility/ar_tea_resources_eligible.py diff --git a/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_countable_earned_income.py b/policyengine_us/variables/gov/states/ar/dhs/tea/income/ar_tea_countable_earned_income.py similarity index 82% rename from policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_countable_earned_income.py rename to policyengine_us/variables/gov/states/ar/dhs/tea/income/ar_tea_countable_earned_income.py index 378b2fe7c4f..2a717e1e0c0 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/income/ar_tea_countable_earned_income.py @@ -12,11 +12,11 @@ class ar_tea_countable_earned_income(Variable): def formula(spm_unit, period, parameters): # Per 208.00.13 Ark. Code R. Section 001, Section 3.3 - p = parameters(period).gov.states.ar.dhs.tea.income + p = parameters(period).gov.states.ar.dhs.tea.income.work_deduction gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) # Step 1: Apply 20% work expense deduction (applies to all) - after_work_expense = gross_earned * (1 - p.work_deduction.expense_rate) + after_work_expense = gross_earned * (1 - p.expense_rate) # Step 2: Apply 60% work incentive deduction (only for ongoing recipients) is_enrolled = spm_unit("is_tanf_enrolled", period) @@ -25,6 +25,6 @@ def formula(spm_unit, period, parameters): # For ongoing recipients: 20% work expense + 60% work incentive return where( is_enrolled, - after_work_expense * (1 - p.work_deduction.incentive_rate), + after_work_expense * (1 - p.incentive_rate), after_work_expense, ) diff --git a/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_countable_income.py b/policyengine_us/variables/gov/states/ar/dhs/tea/income/ar_tea_countable_income.py similarity index 59% rename from policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_countable_income.py rename to policyengine_us/variables/gov/states/ar/dhs/tea/income/ar_tea_countable_income.py index f85f4aefdac..a8d646e81f4 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea_countable_income.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/income/ar_tea_countable_income.py @@ -10,7 +10,4 @@ class ar_tea_countable_income(Variable): reference = "https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001" defined_for = StateCode.AR - def formula(spm_unit, period, parameters): - countable_earned = spm_unit("ar_tea_countable_earned_income", period) - unearned = spm_unit("tanf_gross_unearned_income", period) - return countable_earned + unearned + adds = ["ar_tea_countable_earned_income", "tanf_gross_unearned_income"] From 926ebe2d4b6ede115977b347e429ebeb140833c6 Mon Sep 17 00:00:00 2001 From: Ziming Date: Fri, 19 Dec 2025 14:50:01 -0500 Subject: [PATCH 7/8] pr fix --- .../income/work_deduction/incentive_rate.yaml | 2 +- .../tea/payment_standard/max_unit_size.yaml | 2 + .../gov/states/ar/dhs/tea/integration.yaml | 171 +++++++++++++++++- .../variables/gov/states/ar/dhs/tea/ar_tea.py | 8 +- .../tea/eligibility/ar_tea_income_eligible.py | 2 +- 5 files changed, 174 insertions(+), 11 deletions(-) diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/incentive_rate.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/incentive_rate.yaml index 9bc0bcee465..424c8ef57b3 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/incentive_rate.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/income/work_deduction/incentive_rate.yaml @@ -13,4 +13,4 @@ metadata: - title: 016.20.98-041 Ark. Code R. - TEA Policy 2352-2362, Work Incentive Deduction href: https://regulations.justia.com/states/arkansas/agency-016/division-20/rule-016-20-98-041/ - title: Arkansas TEA Policy Manual Sec 2352 - href: https://humanservices.arkansas.gov/wp-content/uploads/TEA_MANUAL-10.1.24.pdf#page=13 + href: https://humanservices.arkansas.gov/wp-content/uploads/TEA_MANUAL-10.1.24.pdf#page=89 diff --git a/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/max_unit_size.yaml b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/max_unit_size.yaml index 31dc1005f54..c0b4351fec0 100644 --- a/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/max_unit_size.yaml +++ b/policyengine_us/parameters/gov/states/ar/dhs/tea/payment_standard/max_unit_size.yaml @@ -10,3 +10,5 @@ metadata: reference: - title: 208.00.13 Ark. Code R. Section 001, Section 6.1.1 - Payment Standards href: https://www.law.cornell.edu/regulations/arkansas/208-00-13-Ark-Code-R-SS-001 + - title: Arkansas TEA Policy Manual Sec 2361 + href: https://humanservices.arkansas.gov/wp-content/uploads/TEA_MANUAL-10.1.24.pdf#page=92 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/integration.yaml index 647d852aaea..9b1b53598f5 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ar/dhs/tea/integration.yaml @@ -39,7 +39,7 @@ ar_tea_maximum_benefit: 204 # Family size 3 -> $204 payment standard ar_tea: 204 - # Gross income 0 < 446, so full payment + # Gross income 0 < 1,026, so no reduction # max(204 - 0, 0) = 204 - name: Case 2, ongoing family of 3 with earned income below trigger receives partial benefit. @@ -81,7 +81,7 @@ # Benefit calculation ar_tea_maximum_benefit: 204 ar_tea: 76 - # Gross income 400 < 446, so full payment standard + # Gross income 400 < 1,026, so no reduction # max(204 - 128, 0) = 76 - name: Case 3, ongoing family of 2 with earnings below trigger. @@ -242,9 +242,8 @@ # Benefit calculation ar_tea_maximum_benefit: 204 ar_tea: 0 - # Gross income 800 >= 446, so 50% reduction - # Reduced payment = 204 * 0.5 = 102 - # max(102 - 256, 0) = 0 + # Gross income 800 < 1,026, so no reduction + # max(204 - 256, 0) = 0 (countable income exceeds maximum benefit) - name: Case 7, resources exceed limit making family ineligible. period: 2024-01 @@ -316,7 +315,7 @@ # Benefit calculation ar_tea_maximum_benefit: 204 ar_tea: 0 - # Gross income 400 < 446, so full payment standard + # Gross income 400 < 1,026, so no reduction # max(204 - 320, 0) = 0 - name: Case 9, ongoing recipient with gross income above trigger. @@ -516,3 +515,163 @@ ar_tea: 81 # Gross income 1,200 >= 1,026, so 50% reduction # 162 * 0.5 = 81 (per manual: "payment is 50% of the maximum") + +# Gross Income Trigger Boundary Tests + +- name: Boundary test, gross income $1,025 (one below trigger - no reduction). + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_300 + # Annual $12,300 = $1,025/month + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 1_000 + is_tanf_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + # Income calculation chain + tanf_gross_earned_income: [1_025, 0, 0] + ar_tea_countable_earned_income: 328 + # 1,025 * 0.80 * 0.40 = 328 + ar_tea_countable_income: 328 + + # Eligibility chain + ar_tea_income_eligible: true + # 328 <= 513 -> eligible + ar_tea_eligible: true + + # Benefit calculation + ar_tea_maximum_benefit: 204 + ar_tea: 0 + # Gross income 1,025 < 1,026, so NO reduction + # max(204 - 328, 0) = 0 (countable income exceeds maximum benefit) + +- name: Boundary test, gross income $1,027 (one above trigger - 50% reduction). + period: 2024-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_324 + # Annual $12,324 = $1,027/month + person2: + age: 10 + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 1_000 + is_tanf_enrolled: true + households: + household: + members: [person1, person2, person3] + state_code: AR + output: + # Income calculation chain + tanf_gross_earned_income: [1_027, 0, 0] + ar_tea_countable_earned_income: 328.64 + # 1,027 * 0.80 * 0.40 = 328.64 + ar_tea_countable_income: 328.64 + + # Eligibility chain + ar_tea_income_eligible: true + # 328.64 <= 513 -> eligible + ar_tea_eligible: true + + # Benefit calculation + ar_tea_maximum_benefit: 204 + ar_tea: 102 + # Gross income 1,027 >= 1,026, so 50% reduction + # 204 * 0.5 = 102 (no subtraction when above trigger) + +# Historical Trigger Tests (2022 - $446 threshold) + +- name: Historical test 2022, ongoing recipient below $446 trigger. + period: 2022-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 5_340 + # Annual $5,340 = $445/month (one below trigger) + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: AR + output: + # Income calculation chain + tanf_gross_earned_income: [445, 0] + ar_tea_countable_earned_income: 142.4 + # 445 * 0.80 * 0.40 = 142.4 + ar_tea_countable_income: 142.4 + + # Eligibility chain + ar_tea_income_eligible: true + # 142.4 <= 223 -> eligible (2022 income limit) + ar_tea_eligible: true + + # Benefit calculation + ar_tea_maximum_benefit: 162 + ar_tea: 19.6 + # Gross income 445 < 446, so NO reduction + # max(162 - 142.4, 0) = 19.6 + +- name: Historical test 2022, ongoing recipient above $446 trigger. + period: 2022-01 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 5_364 + # Annual $5,364 = $447/month (one above trigger) + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + is_tanf_enrolled: true + households: + household: + members: [person1, person2] + state_code: AR + output: + # Income calculation chain + tanf_gross_earned_income: [447, 0] + ar_tea_countable_earned_income: 143.04 + # 447 * 0.80 * 0.40 = 143.04 + ar_tea_countable_income: 143.04 + + # Eligibility chain + ar_tea_income_eligible: true + # 143.04 <= 223 -> eligible (2022 income limit) + ar_tea_eligible: true + + # Benefit calculation + ar_tea_maximum_benefit: 162 + ar_tea: 81 + # Gross income 447 >= 446, so 50% reduction + # 162 * 0.5 = 81 (no subtraction when above trigger) diff --git a/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea.py b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea.py index 23fa27d8bfe..97c975985c2 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/ar_tea.py @@ -18,9 +18,11 @@ def formula(spm_unit, period, parameters): countable_income = spm_unit("ar_tea_countable_income", period) # Check if gross income triggers 50% payment reduction - gross_earned = spm_unit("tanf_gross_earned_income", period) - unearned = spm_unit("tanf_gross_unearned_income", period) - gross_income = gross_earned + unearned + gross_income = add( + spm_unit, + period, + ["tanf_gross_earned_income", "tanf_gross_unearned_income"], + ) above_trigger = gross_income >= p.payment_standard.trigger.amount reduced_payment = maximum_benefit * ( diff --git a/policyengine_us/variables/gov/states/ar/dhs/tea/eligibility/ar_tea_income_eligible.py b/policyengine_us/variables/gov/states/ar/dhs/tea/eligibility/ar_tea_income_eligible.py index e8f1f3f7b8a..f2c9be33fe4 100644 --- a/policyengine_us/variables/gov/states/ar/dhs/tea/eligibility/ar_tea_income_eligible.py +++ b/policyengine_us/variables/gov/states/ar/dhs/tea/eligibility/ar_tea_income_eligible.py @@ -12,6 +12,6 @@ class ar_tea_income_eligible(Variable): def formula(spm_unit, period, parameters): # Per 208.00.13 Ark. Code R. Section 001, Section 3.3 p = parameters(period).gov.states.ar.dhs.tea.income - # Countable income must be at or below $223 + # Countable income must be at or below the income limit countable_income = spm_unit("ar_tea_countable_income", period) return countable_income <= p.income_limit From f753859d0b25cb2f26765f83d2d074c90ed19cbc Mon Sep 17 00:00:00 2001 From: Ziming Date: Fri, 19 Dec 2025 14:50:23 -0500 Subject: [PATCH 8/8] uv --- uv.lock | 64 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/uv.lock b/uv.lock index f260826736c..7511808d966 100644 --- a/uv.lock +++ b/uv.lock @@ -467,11 +467,27 @@ wheels = [ name = "docutils" version = "0.21.2" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444, upload-time = "2024-04-23T18:57:18.24Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, ] +[[package]] +name = "docutils" +version = "0.22.4" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, +] + [[package]] name = "dpath" version = "2.2.0" @@ -540,19 +556,19 @@ wheels = [ [[package]] name = "furo" -version = "2025.9.25" +version = "2025.12.19" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "accessible-pygments" }, { name = "beautifulsoup4" }, { name = "pygments" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "sphinx-basic-ng" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4e/29/ff3b83a1ffce74676043ab3e7540d398e0b1ce7660917a00d7c4958b93da/furo-2025.9.25.tar.gz", hash = "sha256:3eac05582768fdbbc2bdfa1cdbcdd5d33cfc8b4bd2051729ff4e026a1d7e0a98", size = 1662007, upload-time = "2025-09-25T21:37:19.221Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/20/5f5ad4da6a5a27c80f2ed2ee9aee3f9e36c66e56e21c00fde467b2f8f88f/furo-2025.12.19.tar.gz", hash = "sha256:188d1f942037d8b37cd3985b955839fea62baa1730087dc29d157677c857e2a7", size = 1661473, upload-time = "2025-12-19T17:34:40.889Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/69/964b55f389c289e16ba2a5dfe587c3c462aac09e24123f09ddf703889584/furo-2025.9.25-py3-none-any.whl", hash = "sha256:2937f68e823b8e37b410c972c371bc2b1d88026709534927158e0cb3fac95afe", size = 340409, upload-time = "2025-09-25T21:37:17.244Z" }, + { url = "https://files.pythonhosted.org/packages/f4/b2/50e9b292b5cac13e9e81272c7171301abc753a60460d21505b606e15cf21/furo-2025.12.19-py3-none-any.whl", hash = "sha256:bb0ead5309f9500130665a26bee87693c41ce4dbdff864dbfb6b0dae4673d24f", size = 339262, upload-time = "2025-12-19T17:34:38.905Z" }, ] [[package]] @@ -1085,7 +1101,7 @@ wheels = [ [[package]] name = "nbclient" -version = "0.10.2" +version = "0.10.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jupyter-client" }, @@ -1093,9 +1109,9 @@ dependencies = [ { name = "nbformat" }, { name = "traitlets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/87/66/7ffd18d58eae90d5721f9f39212327695b749e23ad44b3881744eaf4d9e8/nbclient-0.10.2.tar.gz", hash = "sha256:90b7fc6b810630db87a6d0c2250b1f0ab4cf4d3c27a299b0cde78a4ed3fd9193", size = 62424, upload-time = "2024-12-19T10:32:27.164Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8d/f3/1f6cf2ede4b026bc5f0b424cb41adf22f9c804e90a4dbd4fdb42291a35d5/nbclient-0.10.3.tar.gz", hash = "sha256:0baf171ee246e3bb2391da0635e719f27dc77d99aef59e0b04dcb935ee04c575", size = 62564, upload-time = "2025-12-19T15:50:09.331Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/34/6d/e7fa07f03a4a7b221d94b4d586edb754a9b0dc3c9e2c93353e9fa4e0d117/nbclient-0.10.2-py3-none-any.whl", hash = "sha256:4ffee11e788b4a27fabeb7955547e4318a5298f34342a4bfd01f2e1faaeadc3d", size = 25434, upload-time = "2024-12-19T10:32:24.139Z" }, + { url = "https://files.pythonhosted.org/packages/b2/77/0c73678f5260501a271fd7342bee5d639440f2e9e07d590f1100a056d87c/nbclient-0.10.3-py3-none-any.whl", hash = "sha256:39e9bd403504dd2484dd0fd25235bb6a683ce8cd9873356e40d880696adc9e35", size = 25473, upload-time = "2025-12-19T15:50:07.671Z" }, ] [[package]] @@ -1519,7 +1535,7 @@ wheels = [ [[package]] name = "policyengine-us" -version = "1.465.3" +version = "1.467.0" source = { editable = "." } dependencies = [ { name = "microdf-python" }, @@ -1886,18 +1902,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/04/54/6f679c435d28e0a568d8e8a7c0a93a09010818634c3c3907fc98d8983770/roman_numerals-4.1.0-py3-none-any.whl", hash = "sha256:647ba99caddc2cc1e55a51e4360689115551bf4476d90e8162cf8c345fe233c7", size = 7676, upload-time = "2025-12-17T18:25:33.098Z" }, ] -[[package]] -name = "roman-numerals-py" -version = "4.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "roman-numerals", marker = "python_full_version >= '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/cb/b5/de96fca640f4f656eb79bbee0e79aeec52e3e0e359f8a3e6a0d366378b64/roman_numerals_py-4.1.0.tar.gz", hash = "sha256:f5d7b2b4ca52dd855ef7ab8eb3590f428c0b1ea480736ce32b01fef2a5f8daf9", size = 4274, upload-time = "2025-12-17T18:25:41.153Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/27/2c/daca29684cbe9fd4bc711f8246da3c10adca1ccc4d24436b17572eb2590e/roman_numerals_py-4.1.0-py3-none-any.whl", hash = "sha256:553114c1167141c1283a51743759723ecd05604a1b6b507225e91dc1a6df0780", size = 4547, upload-time = "2025-12-17T18:25:40.136Z" }, -] - [[package]] name = "rpds-py" version = "0.30.0" @@ -2065,7 +2069,7 @@ dependencies = [ { name = "alabaster", marker = "python_full_version < '3.11'" }, { name = "babel", marker = "python_full_version < '3.11'" }, { name = "colorama", marker = "python_full_version < '3.11' and sys_platform == 'win32'" }, - { name = "docutils", marker = "python_full_version < '3.11'" }, + { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "imagesize", marker = "python_full_version < '3.11'" }, { name = "jinja2", marker = "python_full_version < '3.11'" }, { name = "packaging", marker = "python_full_version < '3.11'" }, @@ -2087,7 +2091,7 @@ wheels = [ [[package]] name = "sphinx" -version = "8.2.3" +version = "9.0.4" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.12'", @@ -2097,13 +2101,13 @@ dependencies = [ { name = "alabaster", marker = "python_full_version >= '3.11'" }, { name = "babel", marker = "python_full_version >= '3.11'" }, { name = "colorama", marker = "python_full_version >= '3.11' and sys_platform == 'win32'" }, - { name = "docutils", marker = "python_full_version >= '3.11'" }, + { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "imagesize", marker = "python_full_version >= '3.11'" }, { name = "jinja2", marker = "python_full_version >= '3.11'" }, { name = "packaging", marker = "python_full_version >= '3.11'" }, { name = "pygments", marker = "python_full_version >= '3.11'" }, { name = "requests", marker = "python_full_version >= '3.11'" }, - { name = "roman-numerals-py", marker = "python_full_version >= '3.11'" }, + { name = "roman-numerals", marker = "python_full_version >= '3.11'" }, { name = "snowballstemmer", marker = "python_full_version >= '3.11'" }, { name = "sphinxcontrib-applehelp", marker = "python_full_version >= '3.11'" }, { name = "sphinxcontrib-devhelp", marker = "python_full_version >= '3.11'" }, @@ -2112,9 +2116,9 @@ dependencies = [ { name = "sphinxcontrib-qthelp", marker = "python_full_version >= '3.11'" }, { name = "sphinxcontrib-serializinghtml", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/38/ad/4360e50ed56cb483667b8e6dadf2d3fda62359593faabbe749a27c4eaca6/sphinx-8.2.3.tar.gz", hash = "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348", size = 8321876, upload-time = "2025-03-02T22:31:59.658Z" } +sdist = { url = "https://files.pythonhosted.org/packages/42/50/a8c6ccc36d5eacdfd7913ddccd15a9cee03ecafc5ee2bc40e1f168d85022/sphinx-9.0.4.tar.gz", hash = "sha256:594ef59d042972abbc581d8baa577404abe4e6c3b04ef61bd7fc2acbd51f3fa3", size = 8710502, upload-time = "2025-12-04T07:45:27.343Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/53/136e9eca6e0b9dc0e1962e2c908fbea2e5ac000c2a2fbd9a35797958c48b/sphinx-8.2.3-py3-none-any.whl", hash = "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3", size = 3589741, upload-time = "2025-03-02T22:31:56.836Z" }, + { url = "https://files.pythonhosted.org/packages/c6/3f/4bbd76424c393caead2e1eb89777f575dee5c8653e2d4b6afd7a564f5974/sphinx-9.0.4-py3-none-any.whl", hash = "sha256:5bebc595a5e943ea248b99c13814c1c5e10b3ece718976824ffa7959ff95fffb", size = 3917713, upload-time = "2025-12-04T07:45:24.944Z" }, ] [[package]] @@ -2123,7 +2127,7 @@ version = "1.0.0b2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/98/0b/a866924ded68efec7a1759587a4e478aec7559d8165fac8b2ad1c0e774d6/sphinx_basic_ng-1.0.0b2.tar.gz", hash = "sha256:9ec55a47c90c8c002b5960c57492ec3021f5193cb26cebc2dc4ea226848651c9", size = 20736, upload-time = "2023-07-08T18:40:54.166Z" } wheels = [ @@ -2317,15 +2321,15 @@ wheels = [ [[package]] name = "typer-slim" -version = "0.20.0" +version = "0.20.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/45/81b94a52caed434b94da65729c03ad0fb7665fab0f7db9ee54c94e541403/typer_slim-0.20.0.tar.gz", hash = "sha256:9fc6607b3c6c20f5c33ea9590cbeb17848667c51feee27d9e314a579ab07d1a3", size = 106561, upload-time = "2025-10-20T17:03:46.642Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/3d/6a4ec47010e8de34dade20c8e7bce90502b173f62a6b41619523a3fcf562/typer_slim-0.20.1.tar.gz", hash = "sha256:bb9e4f7e6dc31551c8a201383df322b81b0ce37239a5ead302598a2ebb6f7c9c", size = 106113, upload-time = "2025-12-19T16:48:54.206Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5e/dd/5cbf31f402f1cc0ab087c94d4669cfa55bd1e818688b910631e131d74e75/typer_slim-0.20.0-py3-none-any.whl", hash = "sha256:f42a9b7571a12b97dddf364745d29f12221865acef7a2680065f9bb29c7dc89d", size = 47087, upload-time = "2025-10-20T17:03:44.546Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f9/a273c8b57c69ac1b90509ebda204972265fdc978fbbecc25980786f8c038/typer_slim-0.20.1-py3-none-any.whl", hash = "sha256:8e89c5dbaffe87a4f86f4c7a9e2f7059b5b68c66f558f298969d42ce34f10122", size = 47440, upload-time = "2025-12-19T16:48:52.678Z" }, ] [[package]]