From f72b11b73bec49c42a7c35abd814933fc6ebc0e3 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Wed, 14 Jan 2026 17:25:38 +0000 Subject: [PATCH 01/29] Initial commit for Iowa TANF implementation Starting implementation of Iowa TANF (Family Investment Program). Documentation and parallel development will follow. Co-Authored-By: Claude Opus 4.5 From 615a62c6d700165ef830443b043683bee516f3bd Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:26:07 +0000 Subject: [PATCH 02/29] Add Iowa TANF standard of need parameters Add Schedule of Living Costs for Iowa FIP (Family Investment Program): - Main parameter with family sizes 1-10 - Additional amount for families larger than 10 Per 441 IAC 41.28(239B), effective 7/1/2025. Co-Authored-By: Claude Opus 4.5 --- .../ia/dhs/tanf/need_standard/additional.yaml | 12 +++++++ .../ia/dhs/tanf/need_standard/main.yaml | 32 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/additional.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/main.yaml diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/additional.yaml new file mode 100644 index 00000000000..e0c8b2b079c --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/additional.yaml @@ -0,0 +1,12 @@ +description: Iowa Family Investment Program (FIP) additional standard of need amount per person for families larger than 10. + +metadata: + unit: currency-USD + period: month + label: Iowa FIP additional standard of need per person + reference: + - title: Iowa Administrative Code 441-41.28(239B) - Need Standards + href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 + +values: + 2025-07-01: 173 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/main.yaml new file mode 100644 index 00000000000..bdef2801925 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/main.yaml @@ -0,0 +1,32 @@ +description: Iowa Family Investment Program (FIP) standard of need (Schedule of Living Costs) by family size. + +metadata: + unit: currency-USD + period: month + breakdown: + - range(1, 11) + label: Iowa FIP standard of need + reference: + - title: Iowa Administrative Code 441-41.28(239B) - Need Standards + href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 + +1: + 2025-07-01: 365 +2: + 2025-07-01: 719 +3: + 2025-07-01: 849 +4: + 2025-07-01: 986 +5: + 2025-07-01: 1092 +6: + 2025-07-01: 1216 +7: + 2025-07-01: 1335 +8: + 2025-07-01: 1457 +9: + 2025-07-01: 1576 +10: + 2025-07-01: 1724 From 4eb44bff431dbc6ade2fee1da291230a446b8d23 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:26:27 +0000 Subject: [PATCH 03/29] Add Iowa TANF payment standard parameters Add Schedule of Basic Needs for Iowa FIP: - Main parameter with family sizes 1-10 - Additional amount for families larger than 10 Per 441 IAC 41.28(239B), effective 7/1/2025. Co-Authored-By: Claude Opus 4.5 --- .../dhs/tanf/payment_standard/additional.yaml | 12 +++++++ .../ia/dhs/tanf/payment_standard/main.yaml | 32 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/additional.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/main.yaml diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/additional.yaml new file mode 100644 index 00000000000..14efac7ae54 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/additional.yaml @@ -0,0 +1,12 @@ +description: Iowa Family Investment Program (FIP) additional payment standard amount per person for families larger than 10. + +metadata: + unit: currency-USD + period: month + label: Iowa FIP additional payment standard per person + reference: + - title: Iowa Administrative Code 441-41.28(239B) - Need Standards + href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 + +values: + 2025-07-01: 87 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/main.yaml new file mode 100644 index 00000000000..ee3b79267fa --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/main.yaml @@ -0,0 +1,32 @@ +description: Iowa Family Investment Program (FIP) payment standard (Schedule of Basic Needs) by family size. + +metadata: + unit: currency-USD + period: month + breakdown: + - range(1, 11) + label: Iowa FIP payment standard + reference: + - title: Iowa Administrative Code 441-41.28(239B) - Need Standards + href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 + +1: + 2025-07-01: 183 +2: + 2025-07-01: 361 +3: + 2025-07-01: 426 +4: + 2025-07-01: 495 +5: + 2025-07-01: 548 +6: + 2025-07-01: 610 +7: + 2025-07-01: 670 +8: + 2025-07-01: 731 +9: + 2025-07-01: 791 +10: + 2025-07-01: 865 From 186be62743048909b8ae259da722a181d2d9facb Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:26:53 +0000 Subject: [PATCH 04/29] Add Iowa TANF income deduction parameters Add FIP income parameters: - 20% earned income deduction rate - 58% work incentive disregard rate - 185% gross income limit (percent of standard of need) Per 441 IAC 41.27(239B), effective 7/1/2025. Co-Authored-By: Claude Opus 4.5 --- .../ia/dhs/tanf/income/earned_income_deduction.yaml | 12 ++++++++++++ .../dhs/tanf/income/gross_income_limit_percent.yaml | 12 ++++++++++++ .../ia/dhs/tanf/income/work_incentive_disregard.yaml | 12 ++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/income/earned_income_deduction.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/income/gross_income_limit_percent.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/income/work_incentive_disregard.yaml diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/earned_income_deduction.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/earned_income_deduction.yaml new file mode 100644 index 00000000000..0c9dcd17e48 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/earned_income_deduction.yaml @@ -0,0 +1,12 @@ +description: Iowa Family Investment Program (FIP) 20% earned income deduction rate applied to gross nonexempt earned income. + +metadata: + unit: /1 + period: month + label: Iowa FIP earned income deduction rate + reference: + - title: Iowa Administrative Code 441-41.27(239B) - Income + href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 + +values: + 2025-07-01: 0.20 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/gross_income_limit_percent.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/gross_income_limit_percent.yaml new file mode 100644 index 00000000000..32f77d332c2 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/gross_income_limit_percent.yaml @@ -0,0 +1,12 @@ +description: Iowa Family Investment Program (FIP) gross income limit as a percentage of the standard of need for Test 1 eligibility. + +metadata: + unit: /1 + period: month + label: Iowa FIP gross income limit percent of standard of need + reference: + - title: Iowa Administrative Code 441-41.27(239B) - Income + href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 + +values: + 2025-07-01: 1.85 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/work_incentive_disregard.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/work_incentive_disregard.yaml new file mode 100644 index 00000000000..bae2e503c02 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/work_incentive_disregard.yaml @@ -0,0 +1,12 @@ +description: Iowa Family Investment Program (FIP) 58% work incentive disregard rate applied after the 20% earned income deduction. + +metadata: + unit: /1 + period: month + label: Iowa FIP work incentive disregard rate + reference: + - title: Iowa Administrative Code 441-41.27(239B) - Income + href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 + +values: + 2025-07-01: 0.58 From 9dfd6e44c402a3fc8d78dc90628c18e6d46b7b27 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:27:12 +0000 Subject: [PATCH 05/29] Add Iowa TANF resource limit parameters Add FIP resource limits: - Applicant families: $2,000 - Recipient families: $5,000 Per 441 IAC 41.26(239B). Co-Authored-By: Claude Opus 4.5 --- .../tanf/eligibility/resource_limit_applicant.yaml | 12 ++++++++++++ .../tanf/eligibility/resource_limit_recipient.yaml | 12 ++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_applicant.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_recipient.yaml diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_applicant.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_applicant.yaml new file mode 100644 index 00000000000..f1bf22190c8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_applicant.yaml @@ -0,0 +1,12 @@ +description: Iowa Family Investment Program (FIP) resource limit for applicant families. + +metadata: + unit: currency-USD + period: month + label: Iowa FIP applicant resource limit + reference: + - title: Iowa Administrative Code 441-41.26(239B) - Resources + href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf + +values: + 2025-07-01: 2000 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_recipient.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_recipient.yaml new file mode 100644 index 00000000000..3069391f8e8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_recipient.yaml @@ -0,0 +1,12 @@ +description: Iowa Family Investment Program (FIP) resource limit for recipient families (received FIP in prior month). + +metadata: + unit: currency-USD + period: month + label: Iowa FIP recipient resource limit + reference: + - title: Iowa Administrative Code 441-41.26(239B) - Resources + href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf + +values: + 2025-07-01: 5000 From e46c878af30b189eb21be798f4f64fa44bd69696 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:28:15 +0000 Subject: [PATCH 06/29] Add Iowa TANF basic variables Add FIP variables: - ia_tanf_standard_of_need: Schedule of Living Costs by family size - ia_tanf_payment_standard: Schedule of Basic Needs by family size - ia_tanf_eligible: Overall eligibility combining demographic and income tests Per 441 IAC 41.27(239B) and 41.28(239B). Co-Authored-By: Claude Opus 4.5 --- .../states/ia/dhs/tanf/ia_tanf_eligible.py | 15 +++++++++++++ .../ia/dhs/tanf/ia_tanf_payment_standard.py | 21 +++++++++++++++++++ .../ia/dhs/tanf/ia_tanf_standard_of_need.py | 21 +++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_eligible.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_standard_of_need.py diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_eligible.py new file mode 100644 index 00000000000..9b5335df9a5 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_eligible.py @@ -0,0 +1,15 @@ +from policyengine_us.model_api import * + + +class ia_tanf_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Iowa TANF eligible" + definition_period = YEAR + defined_for = StateCode.IA + reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" + + def formula(spm_unit, period, parameters): + demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) + income_eligible = spm_unit("ia_tanf_income_eligible", period) + return demographic_eligible & income_eligible diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard.py new file mode 100644 index 00000000000..f67a0517630 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class ia_tanf_payment_standard(Variable): + value_type = float + entity = SPMUnit + label = "Iowa TANF payment standard" + unit = USD + definition_period = YEAR + defined_for = StateCode.IA + reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28" + + def formula(spm_unit, period, parameters): + people = spm_unit("spm_unit_size", period) + capped_people = min_(people, 10).astype(int) + additional_people = people - capped_people + p = parameters(period).gov.states.ia.dhs.tanf.payment_standard + base = p.main[capped_people] + additional_amount = p.additional * additional_people + monthly = base + additional_amount + return monthly * MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_standard_of_need.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_standard_of_need.py new file mode 100644 index 00000000000..f93afe1dab6 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_standard_of_need.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class ia_tanf_standard_of_need(Variable): + value_type = float + entity = SPMUnit + label = "Iowa TANF standard of need" + unit = USD + definition_period = YEAR + defined_for = StateCode.IA + reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28" + + def formula(spm_unit, period, parameters): + people = spm_unit("spm_unit_size", period) + capped_people = min_(people, 10).astype(int) + additional_people = people - capped_people + p = parameters(period).gov.states.ia.dhs.tanf.need_standard + base = p.main[capped_people] + additional_amount = p.additional * additional_people + monthly = base + additional_amount + return monthly * MONTHS_IN_YEAR From f3fdb560db59212030d772c3d2a1c38c66901ed0 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:29:16 +0000 Subject: [PATCH 07/29] Add Iowa TANF income eligibility variables Add FIP income test variables: - ia_tanf_income_eligible: Combined income eligibility - ia_tanf_gross_income_eligible: Test 1 (185% of standard of need) - ia_tanf_net_income_eligible: Test 2 (after 20% deduction) - ia_tanf_payment_standard_eligible: Test 3 (after work incentive) Per 441 IAC 41.27(239B). Co-Authored-By: Claude Opus 4.5 --- .../dhs/tanf/ia_tanf_gross_income_eligible.py | 17 +++++++++++++ .../ia/dhs/tanf/ia_tanf_income_eligible.py | 24 +++++++++++++++++++ .../dhs/tanf/ia_tanf_net_income_eligible.py | 19 +++++++++++++++ .../tanf/ia_tanf_payment_standard_eligible.py | 15 ++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_gross_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_net_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard_eligible.py diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_gross_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_gross_income_eligible.py new file mode 100644 index 00000000000..5ee0e3b5ea9 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_gross_income_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ia_tanf_gross_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Iowa TANF gross income eligible (Test 1)" + definition_period = YEAR + defined_for = StateCode.IA + reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" + + def formula(spm_unit, period, parameters): + gross_income = spm_unit("ia_tanf_gross_income", period) + standard_of_need = spm_unit("ia_tanf_standard_of_need", period) + p = parameters(period).gov.states.ia.dhs.tanf.income + gross_income_limit = standard_of_need * p.gross_income_limit_percent + return gross_income <= gross_income_limit diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_income_eligible.py new file mode 100644 index 00000000000..e8220e67b28 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_income_eligible.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class ia_tanf_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Iowa TANF income eligible" + definition_period = YEAR + defined_for = StateCode.IA + reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" + + def formula(spm_unit, period, parameters): + gross_income_eligible = spm_unit( + "ia_tanf_gross_income_eligible", period + ) + net_income_eligible = spm_unit("ia_tanf_net_income_eligible", period) + payment_standard_eligible = spm_unit( + "ia_tanf_payment_standard_eligible", period + ) + return ( + gross_income_eligible + & net_income_eligible + & payment_standard_eligible + ) diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_net_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_net_income_eligible.py new file mode 100644 index 00000000000..2f2b2bf6b9e --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_net_income_eligible.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class ia_tanf_net_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Iowa TANF net income eligible (Test 2)" + definition_period = YEAR + defined_for = StateCode.IA + reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" + + def formula(spm_unit, period, parameters): + gross_income = spm_unit("ia_tanf_gross_income", period) + gross_earned_income = spm_unit("ia_tanf_gross_earned_income", period) + standard_of_need = spm_unit("ia_tanf_standard_of_need", period) + p = parameters(period).gov.states.ia.dhs.tanf.income + earned_income_deduction = gross_earned_income * p.earned_income_deduction + net_income = gross_income - earned_income_deduction + return net_income < standard_of_need diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard_eligible.py new file mode 100644 index 00000000000..97d33c2eb13 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard_eligible.py @@ -0,0 +1,15 @@ +from policyengine_us.model_api import * + + +class ia_tanf_payment_standard_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Iowa TANF payment standard eligible (Test 3)" + definition_period = YEAR + defined_for = StateCode.IA + reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" + + def formula(spm_unit, period, parameters): + countable_income = spm_unit("ia_tanf_countable_income", period) + payment_standard = spm_unit("ia_tanf_payment_standard", period) + return countable_income < payment_standard From e26e39a3440b81dabd995a534e5db41c21b5122e Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:30:14 +0000 Subject: [PATCH 08/29] Add Iowa TANF income variables and source parameters Add FIP income source parameters: - Earned income sources (employment, self-employment) - Unearned income sources (social security, SSI, unemployment, etc.) Add FIP income variables: - ia_tanf_gross_earned_income: Total earned income - ia_tanf_gross_unearned_income: Total unearned income - ia_tanf_gross_income: Combined gross income - ia_tanf_countable_income: Net income after 20% deduction and 58% work incentive Per 441 IAC 41.27(239B). Co-Authored-By: Claude Opus 4.5 --- .../ia/dhs/tanf/income/sources/earned.yaml | 12 +++++++++++ .../ia/dhs/tanf/income/sources/unearned.yaml | 15 +++++++++++++ .../tanf/income/ia_tanf_countable_income.py | 21 +++++++++++++++++++ .../income/ia_tanf_gross_earned_income.py | 13 ++++++++++++ .../dhs/tanf/income/ia_tanf_gross_income.py | 16 ++++++++++++++ .../income/ia_tanf_gross_unearned_income.py | 13 ++++++++++++ 6 files changed, 90 insertions(+) create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/earned.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/unearned.yaml create mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_countable_income.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_earned_income.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_income.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_unearned_income.py diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/earned.yaml new file mode 100644 index 00000000000..fcc389d2df9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/earned.yaml @@ -0,0 +1,12 @@ +description: Iowa Family Investment Program (FIP) counts these income sources as earned income. + +values: + 2025-07-01: + - employment_income + - self_employment_income + +metadata: + unit: list + reference: + - title: Iowa Administrative Code 441-41.27(239B) - Income + href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/unearned.yaml new file mode 100644 index 00000000000..830d1b387ae --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/unearned.yaml @@ -0,0 +1,15 @@ +description: Iowa Family Investment Program (FIP) counts these income sources as unearned income. + +values: + 2025-07-01: + - social_security + - ssi + - unemployment_compensation + - alimony_income + - child_support_received + +metadata: + unit: list + reference: + - title: Iowa Administrative Code 441-41.27(239B) - Income + href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_countable_income.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_countable_income.py new file mode 100644 index 00000000000..cee452e4c3f --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_countable_income.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class ia_tanf_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "Iowa TANF countable income" + unit = USD + definition_period = YEAR + defined_for = StateCode.IA + reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" + + def formula(spm_unit, period, parameters): + gross_earned = spm_unit("ia_tanf_gross_earned_income", period) + gross_unearned = spm_unit("ia_tanf_gross_unearned_income", period) + p = parameters(period).gov.states.ia.dhs.tanf.income + earned_income_deduction = gross_earned * p.earned_income_deduction + remaining_earned = gross_earned - earned_income_deduction + work_incentive = remaining_earned * p.work_incentive_disregard + countable_earned = remaining_earned - work_incentive + return countable_earned + gross_unearned diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_earned_income.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_earned_income.py new file mode 100644 index 00000000000..45999759fa0 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_earned_income.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class ia_tanf_gross_earned_income(Variable): + value_type = float + entity = SPMUnit + label = "Iowa TANF gross earned income" + unit = USD + definition_period = YEAR + defined_for = StateCode.IA + reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" + + adds = "gov.states.ia.dhs.tanf.income.sources.earned" diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_income.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_income.py new file mode 100644 index 00000000000..24dfa391139 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_income.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class ia_tanf_gross_income(Variable): + value_type = float + entity = SPMUnit + label = "Iowa TANF gross income" + unit = USD + definition_period = YEAR + defined_for = StateCode.IA + reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" + + def formula(spm_unit, period, parameters): + earned = spm_unit("ia_tanf_gross_earned_income", period) + unearned = spm_unit("ia_tanf_gross_unearned_income", period) + return earned + unearned diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_unearned_income.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_unearned_income.py new file mode 100644 index 00000000000..d42dc1bbad3 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_unearned_income.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class ia_tanf_gross_unearned_income(Variable): + value_type = float + entity = SPMUnit + label = "Iowa TANF gross unearned income" + unit = USD + definition_period = YEAR + defined_for = StateCode.IA + reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" + + adds = "gov.states.ia.dhs.tanf.income.sources.unearned" From 583dbfc521d1c9ff0bf5ac6d7e545af3ebcf8920 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:30:33 +0000 Subject: [PATCH 09/29] Add Iowa TANF benefit variable Add main ia_tanf variable that calculates the FIP benefit amount: - Benefit = Payment Standard - Countable Income - Eligible households get max(payment_standard - countable_income, 0) Per 441 IAC 41.28(239B). Co-Authored-By: Claude Opus 4.5 --- .../variables/gov/states/ia/dhs/tanf/ia_tanf.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf.py diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf.py new file mode 100644 index 00000000000..3b277a16801 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf.py @@ -0,0 +1,16 @@ +from policyengine_us.model_api import * + + +class ia_tanf(Variable): + value_type = float + entity = SPMUnit + label = "Iowa Temporary Assistance for Needy Families (TANF)" + unit = USD + definition_period = YEAR + defined_for = "ia_tanf_eligible" + reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28" + + def formula(spm_unit, period, parameters): + payment_standard = spm_unit("ia_tanf_payment_standard", period) + countable_income = spm_unit("ia_tanf_countable_income", period) + return max_(payment_standard - countable_income, 0) From d72b6a3df3201401dd4e0d866236919ed4e916d3 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:31:29 +0000 Subject: [PATCH 10/29] Add Iowa TANF unit and integration tests Add test cases for ia_tanf: - Unit tests for benefit calculation - Integration test based on documentation example (family of 3, $800/month) - Integration test for gross income limit failure Per 441 IAC 41.27(239B) and 41.28(239B). Co-Authored-By: Claude Opus 4.5 --- .../gov/states/ia/dhs/tanf/ia_tanf.yaml | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/tanf/ia_tanf.yaml diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/tanf/ia_tanf.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/tanf/ia_tanf.yaml new file mode 100644 index 00000000000..b031574452d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/tanf/ia_tanf.yaml @@ -0,0 +1,116 @@ +# Iowa TANF (Family Investment Program) benefit tests +# Per 441 IAC 41.27(239B) and 41.28(239B) + +- name: Unit test - eligible household receives benefit + period: 2025 + input: + ia_tanf_payment_standard: 5_112 + ia_tanf_countable_income: 3_225.60 + ia_tanf_eligible: true + state_code: IA + output: + ia_tanf: 1_886.40 + +- name: Unit test - countable income exceeds payment standard + period: 2025 + input: + ia_tanf_payment_standard: 5_112 + ia_tanf_countable_income: 6_000 + ia_tanf_eligible: true + state_code: IA + output: + ia_tanf: 0 + +- name: Unit test - ineligible household receives no benefit + period: 2025 + input: + ia_tanf_payment_standard: 5_112 + ia_tanf_countable_income: 3_000 + ia_tanf_eligible: false + state_code: IA + output: + ia_tanf: 0 + +- name: Integration test - family of 3 with $800/month earnings + # Example from 441 IAC 41.27(239B) documentation + # Family of 3 with one employed parent earning $800/month gross + # Calculations (annual): + # - Gross Income: $9,600 + # - 20% earned income deduction: $9,600 * 0.20 = $1,920 + # - Net after 20%: $9,600 - $1,920 = $7,680 + # - 58% work incentive: $7,680 * 0.58 = $4,454.40 + # - Countable income: $7,680 - $4,454.40 = $3,225.60 + # - Payment standard for 3: $426/month * 12 = $5,112/year + # - Benefit: $5,112 - $3,225.60 = $1,886.40/year + period: 2025 + absolute_error_margin: 1 + input: + people: + parent: + age: 30 + employment_income: 9_600 + is_tax_unit_head_or_spouse: true + child1: + age: 5 + employment_income: 0 + is_tax_unit_dependent: true + child2: + age: 3 + employment_income: 0 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [parent, child1, child2] + tax_units: + tax_unit: + members: [parent, child1, child2] + households: + household: + members: [parent, child1, child2] + state_code: IA + output: + ia_tanf_standard_of_need: 10_188 + ia_tanf_payment_standard: 5_112 + ia_tanf_gross_earned_income: 9_600 + ia_tanf_gross_income: 9_600 + ia_tanf_countable_income: 3_225.60 + ia_tanf_gross_income_eligible: true + ia_tanf_net_income_eligible: true + ia_tanf_payment_standard_eligible: true + ia_tanf_income_eligible: true + ia_tanf_eligible: true + ia_tanf: 1_886.40 + +- name: Integration test - family exceeds gross income limit + # Family of 2 with $2,000/month earnings + # Gross income limit: $719 * 1.85 * 12 = $15,961.80/year + # Gross income: $24,000/year > $15,961.80 - FAIL Test 1 + period: 2025 + absolute_error_margin: 1 + input: + people: + parent: + age: 30 + employment_income: 24_000 + is_tax_unit_head_or_spouse: true + child: + age: 5 + employment_income: 0 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [parent, child] + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: IA + output: + ia_tanf_standard_of_need: 8_628 + ia_tanf_gross_income: 24_000 + ia_tanf_gross_income_eligible: false + ia_tanf_income_eligible: false + ia_tanf_eligible: false + ia_tanf: 0 From a837a7a639884887b8114101260a98d1dc952809 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:34:42 +0000 Subject: [PATCH 11/29] Format Iowa TANF code Apply black formatting to ia_tanf_net_income_eligible.py Co-Authored-By: Claude Opus 4.5 --- .../gov/states/ia/dhs/tanf/ia_tanf_net_income_eligible.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_net_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_net_income_eligible.py index 2f2b2bf6b9e..9d760ad087f 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_net_income_eligible.py +++ b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_net_income_eligible.py @@ -14,6 +14,8 @@ def formula(spm_unit, period, parameters): gross_earned_income = spm_unit("ia_tanf_gross_earned_income", period) standard_of_need = spm_unit("ia_tanf_standard_of_need", period) p = parameters(period).gov.states.ia.dhs.tanf.income - earned_income_deduction = gross_earned_income * p.earned_income_deduction + earned_income_deduction = ( + gross_earned_income * p.earned_income_deduction + ) net_income = gross_income - earned_income_deduction return net_income < standard_of_need From 377aee6e3ea9c5c35ad31ba88ebced2ab7ca9298 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:37:37 +0000 Subject: [PATCH 12/29] Add changelog entry for Iowa TANF Co-Authored-By: Claude Opus 4.5 --- changelog_entry.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..7575b5bfec6 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: minor + changes: + added: + - Iowa TANF (Family Investment Program) benefit calculation, including standard of need, payment standard, income eligibility tests, and benefit amount. From caa8df5e93f6a39a4f602c553c5712c96c3b65a2 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 19 Jan 2026 04:42:09 +0000 Subject: [PATCH 13/29] Changelog --- changelog_entry.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog_entry.yaml b/changelog_entry.yaml index 7575b5bfec6..a1907b97290 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -1,4 +1,4 @@ - bump: minor changes: added: - - Iowa TANF (Family Investment Program) benefit calculation, including standard of need, payment standard, income eligibility tests, and benefit amount. + - Iowa TANF (Family Investment Program) program. From 9512e3af28c8518ec26616ddc092b1afd4ad8686 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Tue, 20 Jan 2026 00:14:18 +0000 Subject: [PATCH 14/29] Merge upstream/main and format code Co-Authored-By: Claude Opus 4.5 --- docs/agents/sources/ia_tanf/README.md | 56 +++ .../sources/ia_tanf/benefit_calculation.md | 263 ++++++++++++ docs/agents/sources/ia_tanf/eligibility.md | 126 ++++++ docs/agents/sources/ia_tanf/sources.md | 199 +++++++++ policyengine_us/tools/variables.py | 6 +- sources/working_references.md | 389 ++++++++++++++++++ 6 files changed, 1037 insertions(+), 2 deletions(-) create mode 100644 docs/agents/sources/ia_tanf/README.md create mode 100644 docs/agents/sources/ia_tanf/benefit_calculation.md create mode 100644 docs/agents/sources/ia_tanf/eligibility.md create mode 100644 docs/agents/sources/ia_tanf/sources.md create mode 100644 sources/working_references.md diff --git a/docs/agents/sources/ia_tanf/README.md b/docs/agents/sources/ia_tanf/README.md new file mode 100644 index 00000000000..ab9a7a264a0 --- /dev/null +++ b/docs/agents/sources/ia_tanf/README.md @@ -0,0 +1,56 @@ +# Iowa TANF (FIP - Family Investment Program) Documentation + +This folder contains authoritative documentation for implementing Iowa's Family Investment Program (FIP), which is Iowa's implementation of the federal Temporary Assistance for Needy Families (TANF) program. + +## Contents + +- `eligibility.md` - Eligibility requirements including citizenship, residency, household composition, resource limits, time limits, and work requirements +- `benefit_calculation.md` - Income tests, deductions, payment standards, and benefit calculation formulas +- `sources.md` - Complete list of authoritative sources with URLs and citations + +## Quick Reference + +### Program Name +- **Official Name**: Family Investment Program (FIP) +- **Federal Program**: Temporary Assistance for Needy Families (TANF) + +### Legal Authority +- Iowa Code Chapter 239B +- Iowa Administrative Code 441, Chapters 41 and 93 + +### Key Parameters (Effective 7/1/2025) + +| Parameter | Value | +|-----------|-------| +| Gross Income Limit | 185% of Standard of Need | +| Earned Income Deduction | 20% | +| Work Incentive Disregard | 58% | +| Resource Limit (Applicant) | $2,000 | +| Resource Limit (Recipient) | $5,000 | +| Time Limit | 60 months lifetime | + +### Payment Standards (Family of 3) + +| Standard | Amount | +|----------|--------| +| Standard of Need | $849/month | +| 185% Gross Limit | $1,570.65/month | +| Payment Standard | $426/month | + +## Implementation Checklist + +- [ ] Create parameter files for income standards +- [ ] Create parameter files for payment standards +- [ ] Implement gross income eligibility test +- [ ] Implement net income eligibility test (applicants) +- [ ] Implement payment standard test +- [ ] Implement 20% earned income deduction +- [ ] Implement 58% work incentive disregard +- [ ] Implement benefit calculation +- [ ] Create unit tests for each component +- [ ] Create integration tests + +## Related Documentation + +- See `working_references.md` in the repository root for a consolidated implementation summary +- See existing state TANF implementations (CO, CA, NY, NC) for code patterns diff --git a/docs/agents/sources/ia_tanf/benefit_calculation.md b/docs/agents/sources/ia_tanf/benefit_calculation.md new file mode 100644 index 00000000000..8d4ecb71e4d --- /dev/null +++ b/docs/agents/sources/ia_tanf/benefit_calculation.md @@ -0,0 +1,263 @@ +# Iowa FIP (Family Investment Program) Benefit Calculation + +## Legal Authority + +- **Iowa Administrative Code 441-41.27(239B)**: Income +- **Iowa Administrative Code 441-41.28(239B)**: Need Standards + +## Income Eligibility Tests + +Iowa FIP uses a three-test system for initial eligibility and a two-test system for continuing eligibility. + +### Initial Eligibility (Three-Step Process) + +1. **Test 1: 185% Gross Income Test** + - Countable gross nonexempt unearned and earned income must be at or below 185% of the Standard of Need for the eligible group size + +2. **Test 2: Standard of Need Test (Net Income)** + - Applied only to applicant families and reapplicants + - Calculation: Gross nonexempt income minus 20% earned income deduction and diversions + - If income >= Standard of Need: application denied + - If income < Standard of Need: eligible for 50% work incentive deduction (58% per current rules) + - Standards found in Schedule of Living Costs (Desk Aid RC-0033) + +3. **Test 3: Payment Standard Test** + - Applied if Tests 1 and 2 are passed + - Calculation: Net income from Test 2 plus work incentive deduction + - If income >= Payment Standard: no eligibility + - If income < Payment Standard: FIP grant = Payment Standard - countable net income + +Reference: Iowa Administrative Code 441-41.27(239B) + +### Continuing Eligibility (Two-Step Process) + +1. Gross nonexempt income cannot exceed 185% of Standard of Need +2. Countable net income must be below Payment Standard + +## Income Deductions and Disregards + +### 20% Earned Income Deduction + +Each person in the assistance unit whose gross nonexempt earned income is considered is entitled to a **20% earned income deduction** of nonexempt monthly gross earnings. + +This deduction covers work-related expenses including: +- Taxes +- Transportation +- Meals +- Uniforms +- Other work-related expenses + +Reference: Iowa Administrative Code 441-41.27(239B) + +### Work Incentive Disregard (58%) + +After deducting the 20% earned income deduction and income diversions, the department disregards **58%** of the total remaining monthly nonexempt earned income. + +This applies to: +- Earnings as an employee +- Net profit from self-employment + +**Note:** The work incentive disregard is NOT time-limited, but does not apply during initial eligibility determination (Test 2). + +Reference: Iowa Administrative Code 441-41.27(239B); Cornell Law Iowa Admin Code r. 441-41.27 + +## Income Standards Tables (Effective 7/1/2025) + +### Schedule of Living Costs (100% Standard of Need) + +| Family Size | Monthly Amount | +|-------------|----------------| +| 1 | $365 | +| 2 | $719 | +| 3 | $849 | +| 4 | $986 | +| 5 | $1,092 | +| 6 | $1,216 | +| 7 | $1,335 | +| 8 | $1,457 | +| 9 | $1,576 | +| 10 | $1,724 | +| Each additional | +$173 | + +Reference: Iowa Administrative Code 441-41.28(239B) + +### 185% of Standard of Need (Gross Income Limit) + +| Family Size | Monthly Amount | +|-------------|----------------| +| 1 | $675.25 | +| 2 | $1,330.15 | +| 3 | $1,570.65 | +| 4 | $1,824.10 | +| 5 | $2,020.20 | +| 6 | $2,249.60 | +| 7 | $2,469.75 | +| 8 | $2,695.45 | +| 9 | $2,915.60 | +| 10 | $3,189.40 | +| Each additional | +$320.05 | + +Reference: Iowa Administrative Code 441-41.28(239B) + +### Schedule of Basic Needs (Payment Standard) + +The Payment Standard equals approximately **50.18%** of the Schedule of Living Costs. + +| Family Size | Monthly Amount | +|-------------|----------------| +| 1 | $183 | +| 2 | $361 | +| 3 | $426 | +| 4 | $495 | +| 5 | $548 | +| 6 | $610 | +| 7 | $670 | +| 8 | $731 | +| 9 | $791 | +| 10 | $865 | +| Each additional | +$87 | + +Reference: Iowa Administrative Code 441-41.28(239B) + +## Benefit Calculation Formula + +### For Eligible Families + +``` +FIP Benefit = Payment Standard - Countable Net Income +``` + +Where Countable Net Income is calculated as: + +**For Initial Applicants (Test 3):** +``` +Countable Net Income = Gross Income - 20% Earned Income Deduction - Diversions - 58% Work Incentive +``` + +**For Recipients:** +``` +Countable Net Income = Gross Income - 20% Earned Income Deduction - Diversions - 58% Work Incentive +``` + +## Special Needs Allowances + +- **Guardian/conservator fee**: An amount not to exceed $10 per case per month may be allowed + +Reference: Iowa Administrative Code 441-41.28(239B) + +## Exempt Income (Complete List) + +The following income is exempt from FIP income calculations: + +### Government Benefits +- SNAP (Food Stamp) benefits +- SSI recipient income (when SSI recipient is not in eligible group) +- Earned Income Tax Credit (EITC) - federal and state +- Low-Income Home Energy Assistance (LIHEAP) +- WIC program benefits +- Foster care/kinship caregiver payments +- Rent supplements from governmental agencies +- Disaster and emergency assistance +- Indian tribal judgment funds +- Retroactive SSI benefits and payments +- General assistance from county funds (non-basic need or emergency) + +### Employment and Training +- PROMISE JOBS payments +- Training allowances (Department of the Blind, JTPA, Vocational Rehabilitation) +- Food Stamp Employment and Training allowances +- Car pool payments +- Job-related reimbursements +- VISTA volunteer payments +- Incentive allowances from Work Force Investment Project +- AmeriCorps educational awards + +### Education +- Educational/training assistance and financial aid +- Earnings of students age 19 or younger in full-time school (high school or equivalent) + +### Child Support +- Up to $50 of current monthly support paid by legally responsible person + +### Other Exempt Income +- Food from home production +- Food coupons value and USDA commodities value +- Income in-kind +- Gifts of $30 or less per person per calendar quarter +- Loans and bona fide loans +- Income tax refunds +- Vendor payments +- Interest or dividend payments +- Third-party reimbursements +- Medical expense settlements +- Individual Development Account (IDA) deposits +- Refunds from rent or utility deposits +- Terminated income of retrospectively budgeted households (when requirements met) +- Veterans benefits under Aid and Attendance program +- Census worker earnings +- Family Support Subsidy payments + +Reference: Iowa Administrative Code 441-41.27(239B) + +## Self-Employment Income Rules + +- **Net Profit Calculation**: Either 40% of gross income deducted OR actual documented expenses +- **Irregular Self-Employment**: Averaged over 12-month period +- **Work Hours Calculation for Self-Employed**: Actual gross income less business expenses divided by federal minimum wage + +Reference: Iowa Administrative Code 441-41.27(239B) + +## Lump Sum Income Treatment + +- Nonrecurring lump sum amounts create ineligibility period +- Ineligibility period calculated by dividing lump sum by standard of need +- Period can be reduced if: + - Living costs increase + - Funds spent on medical services + - Funds spent on home repairs + - Funds spent on funeral expenses + +Reference: Iowa Administrative Code 441-41.27(239B) + +## Income Attribution and Budgeting + +### Prospective Budgeting +Iowa FIP uses prospective budgeting - "a projection of income based on the best estimate of future income." + +### Variable Income +For variable income: "all income received in the period being used and dividing the result by the number of instances" establishes the monthly projection. + +### Income Conversion Rules +- **Weekly Income**: Multiply by 4 regardless of actual payment frequency +- **Biweekly Income**: Multiply by 2 regardless of actual payment frequency + +### Self-Employment Income +Self-employment income not received regularly is "averaged over a 12-month period of time." + +Reference: Iowa Administrative Code 441-41.27(239B) + +## Example Calculation + +**Family of 3 with one employed parent earning $800/month gross:** + +1. **Test 1 (185% Gross Income Test):** + - Gross Income: $800 + - 185% Standard of Need for 3: $1,570.65 + - $800 < $1,570.65 - PASS + +2. **Test 2 (Standard of Need Test - Applicant Only):** + - Gross Income: $800 + - 20% Earned Income Deduction: $800 x 0.20 = $160 + - Net Income: $800 - $160 = $640 + - Standard of Need for 3: $849 + - $640 < $849 - PASS (eligible for work incentive) + +3. **Test 3 (Payment Standard Test):** + - Net Income from Test 2: $640 + - 58% Work Incentive: $640 x 0.58 = $371.20 + - Countable Net Income: $640 - $371.20 = $268.80 + - Payment Standard for 3: $426 + - $268.80 < $426 - PASS + +4. **Benefit Calculation:** + - FIP Benefit = $426 - $268.80 = $157.20/month diff --git a/docs/agents/sources/ia_tanf/eligibility.md b/docs/agents/sources/ia_tanf/eligibility.md new file mode 100644 index 00000000000..46a8a532841 --- /dev/null +++ b/docs/agents/sources/ia_tanf/eligibility.md @@ -0,0 +1,126 @@ +# Iowa FIP (Family Investment Program) Eligibility Requirements + +## Legal Authority + +- **Iowa Code Chapter 239B**: Family Investment Program statute +- **Iowa Administrative Code 441, Chapter 41**: Granting Assistance (FIP eligibility rules) +- **Iowa Administrative Code 441, Chapter 93**: PROMISE JOBS Program + +## Basic Eligibility Requirements + +### Citizenship and Residency +- Must be a U.S. citizen or qualified alien under Chapter 8 USC Section 1641 +- Must be a resident of the state of Iowa + +Reference: Iowa Administrative Code 441-41.22, 441-41.23 + +### Child Requirements +- Must be responsible for a child under age 18 +- OR a child age 18 who is a full-time student in secondary school or vocational/technical training and expected to complete before age 19 +- A child is eligible for the entire month in which the 18th birthday occurs (unless birthday is on the first day of the month) + +Reference: Iowa Administrative Code 441-41.22 + +### Eligible Group Composition + +The eligible group consists of all eligible persons living together who meet non-financial eligibility criteria: + +**Must Be Included (when living together and meeting criteria):** +- The child +- Eligible siblings of the child (whole-blood, half-blood, or adoptive) +- Natural or adoptive parents of the child + +**Optional Members:** +- Nonparental relatives (at the relative's request, if income/resources within limits) +- Incapacitated stepparents + +**Exception:** +- The eligible group may consist of just the parent (or non-parental caretaker) when the only child in the home receives SSI + +Reference: Iowa Administrative Code 441-41.22; WorkWorld FIP Eligible Group + +### Temporary Absences + +Members temporarily absent from home may remain in the eligible group if: +- Away for education/training with expected return upon completion +- In medical institutions with expected return within 12 months +- Out for other reasons with expected return within 3 months + +## Resource/Asset Eligibility + +### Resource Limits + +| Status | Limit | +|--------|-------| +| Applicant families | $2,000 | +| Recipient families (member received FIP in prior month) | $5,000 | + +Reference: Iowa Administrative Code 441-41.26(239B) + +### Excluded Resources + +- Homestead property +- Non-homestead property actively marketed at fair market value or generating income +- Household goods and personal effects +- Life insurance with zero cash value +- Burial plots and funeral trusts (up to $1,500 per person) +- Tools and capital assets for self-employment (up to $10,000 equity) +- Individual Development Account (IDA) balances +- Educational/training assistance funds +- Inventory and supplies for self-employment +- SSI recipient resources +- Current monthly income +- Loans and inaccessible resources +- Child support payments (up to $50 monthly) +- Vehicle equity (see below) + +### Vehicle Exclusion + +Up to **$3,959** in equity value per vehicle for each adult and working teenage child in the family. This amount is adjusted annually for inflation as of July 1st. + +Reference: Iowa DHS Employees' Policy Manual, Title 4, Chapter D; Iowa Administrative Code 441-41.26(239B) + +## Time Limits + +### 60-Month Lifetime Limit +- A person can receive FIP benefits for up to 60 months (5 years) in their lifetime +- The 60-month limit applies to the individual, not the family +- Hardship exemptions available for 6-month extensions + +Reference: Iowa Code 239B.9; Iowa Legal Aid + +## Work Requirements (PROMISE JOBS) + +### Mandatory Referral +All persons in a FIP household shall be referred to the PROMISE JOBS program and shall enter into a Family Investment Agreement (FIA) as a condition of receiving FIP, unless exempt from referral. + +Reference: Iowa Administrative Code 441-41.24(239B) + +### Exemptions from PROMISE JOBS + +The following are exempt from PROMISE JOBS referral: +- Persons receiving SSI or SSDI due to their own disability +- Aliens whose immigration status is not listed under Chapter 8 USC Section 1641 +- Persons determined disabled and unable to participate +- Persons under age 16 who are not parents +- Persons age 16-19 who are not parents and attend school full-time +- Parent/relative of child under 6 months who personally provides care (one exemption per case) +- Person working 30+ hours/week in unsubsidized employment at initial determination + +**Note:** Parents age 19 and younger are NOT exempt unless disabled. They must attend parenting classes and participate in high school completion activities. + +Reference: Iowa Administrative Code 441-41.24; WorkWorld PROMISE JOBS + +### Participation Requirements +- Level of participation equivalent to full-time employment commitment +- Part-time employment is less than 30 hours per week +- FIA with part-time employment must include other PROMISE JOBS activities unless barriers exist +- Work experience subject to FLSA: maximum hours = monthly FIP grant / minimum wage + +### Limited Benefit Plan (LBP) +- If participants fail FIA terms, they enter a Limited Benefit Plan +- Benefits are reduced then terminated for a fixed period +- Future LBPs result in benefits stopping for at least 6 months +- After 6 months, must contact worker, sign new FIA, complete 20 hours of employment/similar activity + +Reference: Iowa Code 239B.9; Iowa Administrative Code 441-93 diff --git a/docs/agents/sources/ia_tanf/sources.md b/docs/agents/sources/ia_tanf/sources.md new file mode 100644 index 00000000000..99cf1b0d26b --- /dev/null +++ b/docs/agents/sources/ia_tanf/sources.md @@ -0,0 +1,199 @@ +# Iowa FIP Documentation Sources + +## Primary Legal Sources + +### Iowa Statutes +- **Iowa Code Chapter 239B - Family Investment Program** + - URL: https://www.legis.iowa.gov/docs/ico/chapter/239B.pdf + - Description: Primary statute authorizing Iowa's TANF program + - Effective: Current + - Key sections: 239B.2 (Conditions of eligibility), 239B.7 (Income/resource exemptions), 239B.8 (Family investment agreements), 239B.9 (Limited benefit plan) + +### Iowa Administrative Code + +- **441 IAC Chapter 41 - Granting Assistance** + - URL: https://www.legis.iowa.gov/docs/iac/chapter/03-25-2009.441.41.pdf + - Description: Complete FIP eligibility rules + - Key sections: + - 441-41.22(239B): Eligible group + - 441-41.23(239B): Home, residence requirements + - 441-41.24(239B): PROMISE JOBS program + - 441-41.25(239B): Uncategorized factors of eligibility + - 441-41.26(239B): Resources + - 441-41.27(239B): Income + - 441-41.28(239B): Need standards + +- **441-41.26(239B) - Resources** + - URL: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf + - Description: Resource/asset eligibility rules and exclusions + +- **441-41.27(239B) - Income** + - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 + - URL (PDF): https://www.legis.iowa.gov/docs/iac/rule/441.41.27.pdf + - Description: Income eligibility rules, exemptions, deductions + - Effective: 7/1/2025 + +- **441-41.28(239B) - Need Standards** + - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 + - URL (PDF): https://www.legis.iowa.gov/docs/iac/rule/441.41.28.pdf + - Description: Schedule of living costs, payment standards + - Effective: 7/1/2025 + +- **441 IAC Chapter 93 - PROMISE JOBS Program** + - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-93-1 + - Description: Work requirements and participation rules + +## Federal TANF Regulations + +- **45 CFR Part 260 - General TANF Provisions** + - URL: https://www.ecfr.gov/current/title-45/subtitle-B/chapter-II/part-260 + - Description: Federal TANF requirements that Iowa must comply with + +- **45 CFR Part 261 - Ensuring That Recipients Work** + - URL: https://www.ecfr.gov/current/title-45/subtitle-B/chapter-II/part-261 + - Description: Federal work participation requirements + - Key sections: + - 261.10: Individual work requirements + - 261.31: Hourly participation requirements (30 hours/week, 20 hours from core activities) + +## Official State Agency Sources + +### Iowa Department of Health and Human Services (HHS) + +- **FIP Program Overview** + - URL: https://hhs.iowa.gov/assistance-programs/cash-assistance/fip-tanf + - Description: Official program page + +- **Comm. 108 - The Family Investment Program** + - URL: https://hhs.iowa.gov/media/6454/download + - Description: Official program brochure/rules summary + - Revision: 06/25 + +- **4-E, FIP Income** + - URL: https://hhs.iowa.gov/media/3970 + - URL (Download): https://hhs.iowa.gov/media/3970/download?inline + - Description: Income policy manual section + - Revision: January 3, 2020 + +- **Iowa TANF State Plan** + - URL: https://hhs.iowa.gov/media/17445/download?inline= + - Description: State TANF plan submitted to federal government + +### Iowa General Information + +- **Get Family Investment Program Benefits** + - URL: https://www.iowa.gov/how-do-i-get-family-investment-program-fip-benefits + - Description: Public-facing application information + +## Secondary/Reference Sources + +### WorkWorld Help System + +- **FIP Eligibility - Net Income Standards and Payment Rates** + - URL: https://help.workworldapp.com/wwwebhelp/fip_eligibility_net_income_standards_and_payment_rates_iowa.htm + - Description: Comprehensive explanation of income tests + +- **FIP Eligibility - Resources** + - URL: http://help.workworldapp.com/wwwebhelp/fip_eligibility_resources_iowa.htm + - Description: Asset/resource eligibility rules + +- **FIP Eligibility - Financial** + - URL: https://help.workworldapp.com/wwwebhelp/fip_eligibility_financial_iowa.htm + - Description: Financial eligibility overview including all three income tests + +- **FIP Eligibility - Gross Income Limits** + - URL: http://help.workworldapp.com/wwwebhelp/fip_eligibility_grorss_income_limits_iowa.htm + - Description: 185% Standard of Need gross income test details + +- **FIP Eligibility - Income Exclusions** + - URL: http://help.workworldapp.com/wwwebhelp/fip_eligibility_income_exclusions_iowa.htm + - Description: Complete list of exempt income types + +- **FIP Eligibility - Eligible Group** + - URL: https://help.workworldapp.com/wwwebhelp/fip_eligibility_eligible_group_iowa.htm + - Description: Household composition rules + +- **FIP Eligibility - PROMISE JOBS** + - URL: https://help.workworldapp.com/wwwebhelp/fip_eligibility_promise_jobs_iowa.htm + - Description: Work requirement details + +### Federal Sources + +- **45 CFR Parts 260-265 - TANF Regulations** + - URL: https://www.ecfr.gov/current/title-45/subtitle-B/chapter-II/part-260 + - Description: Federal TANF requirements that Iowa must comply with + +- **Benefits.gov - Iowa Family Investment Program** + - URL: https://www.benefits.gov/benefit/1387 + - Description: Federal benefits directory entry + +### NCCP (National Center for Children in Poverty) + +- **Iowa State Profile Summary - TANF Flexibilities** + - URL: https://www.nccp.org/wp-content/uploads/2024/11/TANF-profile-Iowa.pdf + - Description: Summary of Iowa TANF policies and flexibilities + +- **50-State Comparison of TANF Amounts** + - URL: https://www.nccp.org/wp-content/uploads/2024/11/TANF-Benefit-Amounts-2024-FINAL.pdf + - Description: Comparison of TANF benefit amounts across all states (2024) + +### Legal Aid / Advocacy Sources + +- **Iowa Legal Aid - 60 Month Lifetime Limit on FIP Benefits** + - URL: https://iowalegalaid.org/resource/60-month-lifetime-limit-on-fip-benefits/ + - Description: Information on time limits and hardship exemptions + +- **Iowa Legal Aid - Limited Benefit Plan Q&A** + - URL: https://www.iowalegalaid.org/resource/questions-and-answers-about-limited-benefit-p + - Description: Information on LBP sanctions + +- **Iowa Legal Aid - Public Benefits and Car Ownership** + - URL: https://iowalegalaid.org/resource/one-car-any-value/ + - Description: Vehicle asset rules for FIP eligibility + +### Federal ACF (Administration for Children and Families) + +- **Iowa's Limited Benefit Plan** + - URL: https://aspe.hhs.gov/reports/iowas-limited-benefit-plan + - Description: Federal analysis of Iowa's Limited Benefit Plan policy + +- **Iowa Family Investment Program (Pathways to Work)** + - URL: https://pathwaystowork.acf.gov/intervention-detail/716 + - Description: Federal overview of Iowa FIP program + +## Cornell Law Institute References + +- **Iowa Admin. Code r. 441-41.24 (PROMISE JOBS)** + - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-24 + +- **Iowa Admin. Code r. 441-41.27 (Income)** + - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 + +- **Iowa Admin. Code r. 441-41.28 (Need Standards)** + - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 + +- **Iowa Admin. Code r. 441-41.29 (Composite FIP/SSI cases)** + - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-29 + +- **Iowa Admin. Code r. 441-93.1 (PROMISE JOBS Definitions)** + - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-93-1 + +## Iowa Legislature Publications + +- **Family Investment Program/PROMISE JOBS - Budget Unit Brief** + - URL: https://www.legis.iowa.gov/docs/publications/FT/1519815.pdf + - Description: Legislative budget analysis of FIP program + +- **TANF Fiscal Topics** + - URL: https://www.legis.iowa.gov/docs/publications/FTNO/1462655.pdf + - Description: Legislative fiscal analysis of TANF/FIP (October 2024) + +- **Monthly FIP Payments and Recipients Data** + - URL: https://www.legis.iowa.gov/docs/publications/FCTA/1216562.pdf + - Description: Historical FIP payment and recipient data + +## Contact Information + +- **Iowa HHS Division of Community Access**: 1-800-972-2017 +- **Iowa HHS General**: (877) 347-5678 +- **Iowa HHS Benefits Portal**: https://dhsservices.iowa.gov/ diff --git a/policyengine_us/tools/variables.py b/policyengine_us/tools/variables.py index 2ae0e45eb64..fe9805cec7d 100644 --- a/policyengine_us/tools/variables.py +++ b/policyengine_us/tools/variables.py @@ -13,7 +13,9 @@ def add_n(word): def print_variable_summary(variable_name: str): variable = variables.get(variable_name) - return Markdown(f""" + return Markdown( + f""" ## {variable.name} This variable models a{add_n(variable.entity.label)}**{variable.entity.label}**'s **{variable.label}**. - """) + """ + ) diff --git a/sources/working_references.md b/sources/working_references.md new file mode 100644 index 00000000000..88b620c52c6 --- /dev/null +++ b/sources/working_references.md @@ -0,0 +1,389 @@ +# Collected Documentation + +## Official Program Name + +**Federal Program**: Temporary Assistance for Needy Families (TANF) +**State's Official Name**: Family Investment Program (FIP) +**State**: Iowa (IA) +**Abbreviation**: FIP +**Source**: Iowa Code Section 239B + +**Variable Prefix**: `ia_tanf` +**Parameter Path**: `gov.states.ia.dhs.tanf` + +--- + +## Iowa TANF (FIP - Family Investment Program) Implementation +**Collected**: 2026-01-15 (Updated) +**Implementation Task**: Implement Iowa FIP cash assistance program with eligibility tests and benefit calculations + +### Source Information + +#### Primary Legal Sources +- **Title**: Iowa Code Chapter 239B - Family Investment Program +- **Citation**: Iowa Code Section 239B +- **URL**: https://www.legis.iowa.gov/docs/ico/chapter/239B.pdf +- **Effective Date**: Current + +- **Title**: Iowa Administrative Code 441-41.27(239B) - Income +- **Citation**: 441 IAC 41.27(239B) +- **URL**: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 +- **Effective Date**: 7/1/2025 + +- **Title**: Iowa Administrative Code 441-41.28(239B) - Need Standards +- **Citation**: 441 IAC 41.28(239B) +- **URL**: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 +- **Effective Date**: 7/1/2025 + +- **Title**: Iowa Administrative Code 441-41.26(239B) - Resources +- **Citation**: 441 IAC 41.26(239B) +- **URL**: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf +- **Effective Date**: Current + +#### Federal TANF Regulations +- **Title**: 45 CFR Part 260 - General TANF Provisions +- **URL**: https://www.ecfr.gov/current/title-45/subtitle-B/chapter-II/part-260 +- **Title**: 45 CFR Part 261 - Ensuring That Recipients Work +- **URL**: https://www.ecfr.gov/current/title-45/subtitle-B/chapter-II/part-261 + +### Key Rules and Thresholds + +#### Resource Limits +- Applicant families: $2,000 +- Recipient families (member received FIP in prior month): $5,000 +- Vehicle equity exclusion: $3,959 per vehicle per adult/working teen (adjusted annually as of July 1) + +#### Excluded Resources (Not Counted) +- Homestead property +- Non-homestead property listed for sale at fair market value or producing income +- Household goods and personal effects +- Life insurance with zero cash value +- Burial plots (one per household member) and funeral trusts (up to $1,500 per person) +- Tools and capital assets for self-employment (up to $10,000 equity) +- Inventory and supplies for self-employment +- Individual Development Account (IDA) balances (full balance excluded) +- Educational/training assistance funds +- SSI recipient resources +- Current monthly income +- Loans and inaccessible resources +- Child support payments (up to $50 monthly) +- Medical expense reserves from lump-sum payments + +#### Income Eligibility Tests +1. **Test 1**: Gross income <= 185% of Standard of Need +2. **Test 2**: Net income (after 20% earned income deduction) < Standard of Need (applicants only) +3. **Test 3**: Net income (after work incentive) < Payment Standard + +#### Income Deductions +- **20% Earned Income Deduction**: Applied to gross nonexempt earned income (covers taxes, transportation, meals, uniforms, other work expenses) +- **58% Work Incentive Disregard**: Applied after 20% deduction to remaining earned income (not time-limited) + +#### Time Limits +- 60-month lifetime limit on benefits +- Hardship exemptions available for 6-month extensions +- Hardship criteria: domestic violence, lack of employability, lack of suitable child care, medical/mental health issues, housing situations, substance abuse issues, child requiring parent at home +- Extension request can be filed starting in month 59 +- SSI exemption: 60-month limit does not apply if child lives with one parent on SSI or both parents on SSI + +### Payment Standards (Effective 7/1/2025) + +#### Schedule of Living Costs (100% Standard of Need) + +| Family Size | Monthly Amount | +|-------------|----------------| +| 1 | $365 | +| 2 | $719 | +| 3 | $849 | +| 4 | $986 | +| 5 | $1,092 | +| 6 | $1,216 | +| 7 | $1,335 | +| 8 | $1,457 | +| 9 | $1,576 | +| 10 | $1,724 | +| Each additional | +$173 | + +#### 185% of Standard of Need (Gross Income Limit - Test 1) + +| Family Size | Monthly Amount | +|-------------|----------------| +| 1 | $675.25 | +| 2 | $1,330.15 | +| 3 | $1,570.65 | +| 4 | $1,824.10 | +| 5 | $2,020.20 | +| 6 | $2,249.60 | +| 7 | $2,469.75 | +| 8 | $2,695.45 | +| 9 | $2,915.60 | +| 10 | $3,189.40 | +| Each additional | +$320.05 | + +#### Schedule of Basic Needs (Payment Standard) + +| Family Size | Monthly Amount | +|-------------|----------------| +| 1 | $183 | +| 2 | $361 | +| 3 | $426 | +| 4 | $495 | +| 5 | $548 | +| 6 | $610 | +| 7 | $670 | +| 8 | $731 | +| 9 | $791 | +| 10 | $865 | +| Each additional | +$87 | + +### Exempt Income (Complete List) + +The following income is NOT counted for FIP eligibility: + +**Government Benefits** +- SNAP (Food Stamp) benefits +- SSI recipient income (when not in eligible group) +- Earned Income Tax Credit (EITC) - federal and state +- Low-Income Home Energy Assistance (LIHEAP) +- WIC program benefits +- Foster care/kinship caregiver payments +- Rent supplements from governmental agencies +- Disaster and emergency assistance +- Indian tribal judgment funds +- Retroactive SSI benefits and payments +- General assistance from county funds (non-basic need or emergency) + +**Employment and Training** +- PROMISE JOBS payments +- Training allowances (Department of the Blind, JTPA, Vocational Rehabilitation) +- Food Stamp Employment and Training allowances +- Car pool payments +- Job-related reimbursements +- VISTA volunteer payments +- Incentive allowances from Work Force Investment Project +- AmeriCorps educational awards + +**Education** +- Educational/training assistance and financial aid +- Earnings of students age 19 or younger in full-time school (high school or equivalent) + +**Child Support** +- Up to $50 of current monthly support paid by legally responsible person + +**Other** +- Food from home production +- Food coupons value and USDA commodities value +- Income in-kind +- Gifts of $30 or less per person per calendar quarter +- Loans and bona fide loans +- Income tax refunds +- Vendor payments +- Interest or dividend payments +- Third-party reimbursements +- Medical expense settlements +- Individual Development Account (IDA) deposits +- Refunds from rent or utility deposits +- Terminated income of retrospectively budgeted households (when requirements met) +- Veterans benefits under Aid and Attendance program +- Census worker earnings +- Family Support Subsidy payments + +### Self-Employment Income Rules + +- **Net Profit Calculation**: Either 40% of gross income deducted OR actual documented expenses +- **Irregular Self-Employment**: Averaged over 12-month period +- **Work Hours Calculation for Self-Employed**: Actual gross income less business expenses divided by federal minimum wage + +### Lump Sum Income Treatment + +- Nonrecurring lump sum amounts create ineligibility period +- Ineligibility period calculated by dividing lump sum by standard of need +- Period can be reduced if: + - Living costs increase + - Funds spent on medical services + - Funds spent on home repairs + - Funds spent on funeral expenses + +### Income Budgeting Rules + +- **Weekly Income**: Multiply by 4 regardless of actual payment frequency +- **Biweekly Income**: Multiply by 2 regardless of actual payment frequency +- **Prospective Budgeting**: Projection based on best estimate of future income using income from 30 days before interview +- **Variable Income**: Average all instances received in the period + +### Calculation Formulas + +#### Income Eligibility + +```python +# Test 1: Gross Income Test (185% Standard of Need) +gross_income_limit = standard_of_need * 1.85 +passes_test_1 = gross_income <= gross_income_limit + +# Test 2: Net Income Test (Standard of Need) - Applicants Only +earned_income_deduction = gross_earned_income * 0.20 +net_income_test_2 = gross_income - earned_income_deduction +passes_test_2 = net_income_test_2 < standard_of_need + +# Test 3: Payment Standard Test +work_incentive_disregard = (gross_earned_income - earned_income_deduction) * 0.58 +countable_net_income = gross_income - earned_income_deduction - work_incentive_disregard +passes_test_3 = countable_net_income < payment_standard +``` + +#### Benefit Calculation + +```python +# FIP Benefit = Payment Standard - Countable Net Income +fip_benefit = max(payment_standard - countable_net_income, 0) +``` + +#### Complete Benefit Formula + +```python +def calculate_fip_benefit(gross_earned_income, gross_unearned_income, family_size): + # Get parameters + standard_of_need = get_standard_of_need(family_size) + payment_standard = get_payment_standard(family_size) + gross_income_limit = standard_of_need * 1.85 + + gross_income = gross_earned_income + gross_unearned_income + + # Test 1: 185% Gross Income Test + if gross_income > gross_income_limit: + return 0 + + # 20% Earned Income Deduction + earned_income_deduction = gross_earned_income * 0.20 + + # Test 2: Standard of Need Test (for applicants) + net_income_after_20 = gross_income - earned_income_deduction + if net_income_after_20 >= standard_of_need: + return 0 # Applicant ineligible + + # 58% Work Incentive Disregard + remaining_earned = gross_earned_income - earned_income_deduction + work_incentive = remaining_earned * 0.58 + + # Test 3: Payment Standard Test + countable_net_income = gross_income - earned_income_deduction - work_incentive + if countable_net_income >= payment_standard: + return 0 + + # Calculate benefit + return payment_standard - countable_net_income +``` + +### Example Calculation + +**Family of 3 with one employed parent earning $800/month gross:** + +1. **Test 1 (185% Gross Income Test):** + - Gross Income: $800 + - 185% Standard of Need for 3: $1,570.65 + - $800 < $1,570.65 - PASS + +2. **Test 2 (Standard of Need Test - Applicant Only):** + - Gross Income: $800 + - 20% Earned Income Deduction: $800 x 0.20 = $160 + - Net Income: $800 - $160 = $640 + - Standard of Need for 3: $849 + - $640 < $849 - PASS (eligible for work incentive) + +3. **Test 3 (Payment Standard Test):** + - Net Income from Test 2: $640 + - 58% Work Incentive: $640 x 0.58 = $371.20 + - Countable Net Income: $640 - $371.20 = $268.80 + - Payment Standard for 3: $426 + - $268.80 < $426 - PASS + +4. **Benefit Calculation:** + - FIP Benefit = $426 - $268.80 = $157.20/month + +### Special Cases and Exceptions + +#### Eligible Group +- Must include child, eligible siblings, and natural/adoptive parents when living together +- Nonparental relatives optional (at relative's request) +- Incapacitated stepparents may be included +- Exception: Parent-only case when only child receives SSI + +#### Two-Parent Families +- No 100-hour rule (eliminated under FIP) +- Both parents must participate in PROMISE JOBS unless one meets exemption criteria + +#### Caretaker Relative Rules +- Unmarried specified relative under 19 living with parents: needs included with parent(s) +- Nonparental relative as caretaker: children considered separate eligible group + +#### Temporary Absences +- Education/training: remain in group if expected to return upon completion +- Medical institutions: remain in group if expected return within 12 months +- Other reasons: remain in group if expected return within 3 months + +#### Work Requirements (PROMISE JOBS) +- Required unless exempt +- Exemptions: + - SSI/SSDI recipients (due to own disability) + - Aliens not listed under 8 USC Section 1641 + - Persons determined disabled and unable to participate + - Children under age 16 who are not parents + - Students 16-19 (non-parents) attending school full-time + - Parent/relative of child under 6 months who personally provides care (one exemption per case) + - Person working 30+ hours/week in unsubsidized employment at initial determination +- Limited Benefit Plan for non-compliance: + - First LBP: benefits reduced then terminated + - Subsequent LBPs: 6-month minimum termination + - Must complete 20 hours of employment/similar activity to restart + +#### Federal TANF Work Requirements (45 CFR 261) +- 30 hours/week minimum for overall rate (20 hours from core activities) +- Single parent with child under 6: 20 hours/week minimum +- Community service required if received assistance for 2 months (unless exempt or engaged in work) + +### References for Metadata + +```yaml +# For parameters: +reference: + - title: "Iowa Administrative Code 441-41.28(239B) - Need Standards" + href: "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28" +``` + +```python +# For variables: +reference = "441 IAC 41.27(239B)" +documentation = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" +``` + +### Implementation Notes + +1. **Parameter Files Needed**: + - `gov/states/ia/hhs/tanf/income/standard_of_need.yaml` - Schedule of Living Costs by family size + - `gov/states/ia/hhs/tanf/income/gross_income_limit_percent.yaml` - 185% multiplier + - `gov/states/ia/hhs/tanf/income/earned_income_deduction.yaml` - 20% deduction rate + - `gov/states/ia/hhs/tanf/income/work_incentive_disregard.yaml` - 58% disregard rate + - `gov/states/ia/hhs/tanf/benefit/payment_standard.yaml` - Schedule of Basic Needs by family size + - `gov/states/ia/hhs/tanf/eligibility/resource_limit_applicant.yaml` - $2,000 + - `gov/states/ia/hhs/tanf/eligibility/resource_limit_recipient.yaml` - $5,000 + +2. **Variable Files Needed**: + - `ia_tanf.py` - Main benefit calculation + - `ia_tanf_eligible.py` - Overall eligibility + - `ia_tanf_gross_income_eligible.py` - Test 1 + - `ia_tanf_net_income_eligible.py` - Test 2 (applicants) + - `ia_tanf_payment_standard_eligible.py` - Test 3 + - `ia_tanf_countable_earned_income.py` - Earned income after deductions + - `ia_tanf_countable_unearned_income.py` - Unearned income + - `ia_tanf_payment_standard.py` - Payment standard by family size + - `ia_tanf_standard_of_need.py` - Standard of need by family size + +3. **Entity**: SPMUnit (consistent with other state TANF implementations) + +4. **Definition Period**: YEAR (consistent with other state TANF implementations) + +5. **Key Differences from Federal TANF**: + - Iowa uses 58% work incentive (vs. typical 50%) + - Iowa has separate applicant ($2,000) and recipient ($5,000) resource limits + - Iowa eliminated 100-hour rule for two-parent families + +--- From 92900dba1c6f8cf086aa979337700c77b842c877 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Tue, 20 Jan 2026 06:10:42 +0000 Subject: [PATCH 15/29] Rename Iowa TANF to FIP and add comprehensive tests Refactored Iowa TANF implementation to use FIP (Family Investment Program) naming convention which is the official state program name. Added 11 tests covering unit tests, integration tests with various income scenarios, and edge cases including large families and non-Iowa states. Co-Authored-By: Claude Opus 4.5 --- changelog_entry.yaml | 2 +- .../eligibility/resource_limit_applicant.yaml | 14 + .../eligibility/resource_limit_recipient.yaml | 14 + .../fip/income/earned_income_deduction.yaml | 12 + .../income/gross_income_limit_percent.yaml | 12 + .../ia/dhs/fip/income/sources/earned.yaml | 14 + .../ia/dhs/fip/income/sources/unearned.yaml | 17 + .../fip/income/work_incentive_disregard.yaml | 12 + .../gov/states/ia/dhs/fip/max_unit_size.yaml | 14 + .../ia/dhs/fip/need_standard/additional.yaml | 12 + .../states/ia/dhs/fip/need_standard/main.yaml | 32 ++ .../dhs/fip/payment_standard/additional.yaml | 12 + .../{tanf => fip}/payment_standard/main.yaml | 22 +- .../eligibility/resource_limit_applicant.yaml | 12 - .../eligibility/resource_limit_recipient.yaml | 12 - .../tanf/income/earned_income_deduction.yaml | 12 - .../income/gross_income_limit_percent.yaml | 12 - .../ia/dhs/tanf/income/sources/earned.yaml | 12 - .../ia/dhs/tanf/income/sources/unearned.yaml | 15 - .../tanf/income/work_incentive_disregard.yaml | 12 - .../ia/dhs/tanf/need_standard/additional.yaml | 12 - .../ia/dhs/tanf/need_standard/main.yaml | 32 -- .../dhs/tanf/payment_standard/additional.yaml | 12 - .../gov/states/ia/dhs/fip/ia_fip.yaml | 387 ++++++++++++++++++ .../gov/states/ia/dhs/tanf/ia_tanf.yaml | 116 ------ .../gov/states/ia/dhs/fip/ia_fip_eligible.py | 25 ++ .../ia/dhs/fip/ia_fip_income_eligible.py | 40 ++ .../ia/dhs/fip/ia_fip_payment_standard.py | 22 + .../ia_fip_standard_of_need.py} | 13 +- .../states/ia/dhs/{tanf => fip}/ia_tanf.py | 10 +- .../income/ia_fip_countable_income.py} | 14 +- .../fip/income/ia_fip_gross_earned_income.py | 15 + .../ia/dhs/fip/income/ia_fip_gross_income.py | 18 + .../income/ia_fip_gross_unearned_income.py | 15 + .../states/ia/dhs/tanf/ia_tanf_eligible.py | 15 - .../dhs/tanf/ia_tanf_gross_income_eligible.py | 17 - .../ia/dhs/tanf/ia_tanf_income_eligible.py | 24 -- .../dhs/tanf/ia_tanf_net_income_eligible.py | 21 - .../tanf/ia_tanf_payment_standard_eligible.py | 15 - .../ia/dhs/tanf/ia_tanf_standard_of_need.py | 21 - .../income/ia_tanf_gross_earned_income.py | 13 - .../dhs/tanf/income/ia_tanf_gross_income.py | 16 - .../income/ia_tanf_gross_unearned_income.py | 13 - 43 files changed, 719 insertions(+), 443 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_applicant.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_recipient.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/earned.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml create mode 100644 policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml rename policyengine_us/parameters/gov/states/ia/dhs/{tanf => fip}/payment_standard/main.yaml (62%) delete mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_applicant.yaml delete mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_recipient.yaml delete mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/income/earned_income_deduction.yaml delete mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/income/gross_income_limit_percent.yaml delete mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/earned.yaml delete mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/unearned.yaml delete mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/income/work_incentive_disregard.yaml delete mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/additional.yaml delete mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/main.yaml delete mode 100644 policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/additional.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/tanf/ia_tanf.yaml create mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_payment_standard.py rename policyengine_us/variables/gov/states/ia/dhs/{tanf/ia_tanf_payment_standard.py => fip/ia_fip_standard_of_need.py} (59%) rename policyengine_us/variables/gov/states/ia/dhs/{tanf => fip}/ia_tanf.py (54%) rename policyengine_us/variables/gov/states/ia/dhs/{tanf/income/ia_tanf_countable_income.py => fip/income/ia_fip_countable_income.py} (57%) create mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_earned_income.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_income.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_unearned_income.py delete mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_eligible.py delete mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_gross_income_eligible.py delete mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_income_eligible.py delete mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_net_income_eligible.py delete mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard_eligible.py delete mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_standard_of_need.py delete mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_earned_income.py delete mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_income.py delete mode 100644 policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_unearned_income.py diff --git a/changelog_entry.yaml b/changelog_entry.yaml index a1907b97290..461b0ea7095 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -1,4 +1,4 @@ - bump: minor changes: added: - - Iowa TANF (Family Investment Program) program. + - Iowa TANF (Temporary Assistance for Needy Families) program, or FIP (Family Investment Program). diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_applicant.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_applicant.yaml new file mode 100644 index 00000000000..2d9f103c357 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_applicant.yaml @@ -0,0 +1,14 @@ +description: Iowa limits resources to this amount under the Family Investment Program (FIP) for applicant families. + +values: + 2025-07-01: 2_000 + +metadata: + unit: currency-USD + period: month + label: Iowa FIP applicant resource limit + reference: + - title: Iowa Administrative Code 441-41.26(239B) - Resources, 41.26(1)(e) + href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf + - title: Iowa TANF State Plan 2025 + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) \ No newline at end of file diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_recipient.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_recipient.yaml new file mode 100644 index 00000000000..ba24ad02a16 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_recipient.yaml @@ -0,0 +1,14 @@ +description: Iowa limits resources to this amount under the Family Investment Program for recipient families (received FIP in prior month). + +values: + 2025-07-01: 5_000 + +metadata: + unit: currency-USD + period: month + label: Iowa FIP recipient resource limit + reference: + - title: Iowa Administrative Code 441-41.26(239B) - Resources, 41.26(1)(e) + href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf + - title: Iowa TANF State Plan 2025 + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) \ No newline at end of file diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml new file mode 100644 index 00000000000..5a658b22677 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml @@ -0,0 +1,12 @@ +description: Iowa deducts this percentage of the gross nonexempt earned income under the Family Investment Program. + +values: + 2025-07-01: 0.2 + +metadata: + unit: /1 + period: month + label: Iowa FIP earned income deduction rate + reference: + - title: Iowa Administrative Code 441-41.27(239B) - Income, 41.27(2)(a) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=21 \ No newline at end of file diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml new file mode 100644 index 00000000000..0254cce1cc5 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml @@ -0,0 +1,12 @@ +description: Iowa sets the gross income limit for the first income eligibility test as this percentage of the standard of need under the Family Investment Program. + +values: + 2025-07-01: 1.85 + +metadata: + unit: /1 + period: month + label: Iowa FIP gross income limit percent of standard of need + reference: + - title: Iowa Administrative Code 441-41.27(239B) - Income, (2) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=20 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/earned.yaml new file mode 100644 index 00000000000..8f31d7dd67a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/earned.yaml @@ -0,0 +1,14 @@ +description: Iowa counts these income sources as earned income under the Family Investment Program. + +values: + 2025-07-01: + - employment_income + - self_employment_income + +metadata: + unit: list + period: month + label: Iowa FIP earned income sources + reference: + - title: Iowa Administrative Code 441-41.27(239B) - Income, 41.27(2) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=21 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml new file mode 100644 index 00000000000..832614647ba --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml @@ -0,0 +1,17 @@ +description: Iowa counts these income sources as unearned income under the Family Investment Program. + +values: + 2025-07-01: + - social_security + - ssi + - unemployment_compensation + - alimony_income + - child_support_received + +metadata: + unit: list + period: month + label: Iowa FIP unearned income sources + reference: + - title: Iowa Administrative Code 441-41.27(239B) - Income, 41.27(1) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=20 \ No newline at end of file diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml new file mode 100644 index 00000000000..94ad1afd453 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml @@ -0,0 +1,12 @@ +description: Iowa deducts this percentage of work incentive disregard after the earned income deduction under the Family Investment Program. + +values: + 2025-07-01: 0.58 + +metadata: + unit: /1 + period: month + label: Iowa FIP work incentive disregard rate + reference: + - title: Iowa Administrative Code 441-41.27(239B) - Income, 41.27(2)(c) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=21 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml new file mode 100644 index 00000000000..9ea10c46a69 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml @@ -0,0 +1,14 @@ +description: Iowa sets this maximum unit size for determining standard of need and payment standards under the Family Investment Program. + +values: + 2025-07-01: 10 + +metadata: + unit: person + period: year + label: Iowa FIP maximum unit size for standards lookup + reference: + - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 + - title: Iowa TANF State Plan 2025 + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) \ No newline at end of file diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml new file mode 100644 index 00000000000..ad43683a127 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml @@ -0,0 +1,12 @@ +description: Iowa sets this value as the additional standard of need amount per person for families larger than 10 under the Family Investment Program. + +metadata: + unit: currency-USD + period: month + label: Iowa FIP additional standard of need per person + reference: + - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 + +values: + 2025-07-01: 173 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml new file mode 100644 index 00000000000..cd71ed17537 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml @@ -0,0 +1,32 @@ +description: Iowa sets these values as the standard of need amount, or the schedule of living costs, by family size under the Family Investment Program. + +1: + 2025-07-01: 365 +2: + 2025-07-01: 719 +3: + 2025-07-01: 849 +4: + 2025-07-01: 986 +5: + 2025-07-01: 1_092 +6: + 2025-07-01: 1_216 +7: + 2025-07-01: 1_335 +8: + 2025-07-01: 1_457 +9: + 2025-07-01: 1_576 +10: + 2025-07-01: 1_724 + +metadata: + unit: currency-USD + period: month + breakdown: + - range(1, 11) + label: Iowa FIP standard of need + reference: + - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 \ No newline at end of file diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml new file mode 100644 index 00000000000..472c7ea8af6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml @@ -0,0 +1,12 @@ +description: Iowa sets this value as the additional payment standard amount per person for families larger than 10 under the Family Investment Program. + +values: + 2025-07-01: 87 + +metadata: + unit: currency-USD + period: month + label: Iowa FIP additional payment standard per person + reference: + - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 \ No newline at end of file diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml similarity index 62% rename from policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/main.yaml rename to policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml index ee3b79267fa..11aef980792 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/main.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml @@ -1,14 +1,4 @@ -description: Iowa Family Investment Program (FIP) payment standard (Schedule of Basic Needs) by family size. - -metadata: - unit: currency-USD - period: month - breakdown: - - range(1, 11) - label: Iowa FIP payment standard - reference: - - title: Iowa Administrative Code 441-41.28(239B) - Need Standards - href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 +description: Iowa sets these values as the payment standard, or the schedule of basic needs, by family size under the Family Investment Program. 1: 2025-07-01: 183 @@ -30,3 +20,13 @@ metadata: 2025-07-01: 791 10: 2025-07-01: 865 + +metadata: + unit: currency-USD + period: month + breakdown: + - range(1, 11) + label: Iowa FIP payment standard + reference: + - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 \ No newline at end of file diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_applicant.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_applicant.yaml deleted file mode 100644 index f1bf22190c8..00000000000 --- a/policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_applicant.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: Iowa Family Investment Program (FIP) resource limit for applicant families. - -metadata: - unit: currency-USD - period: month - label: Iowa FIP applicant resource limit - reference: - - title: Iowa Administrative Code 441-41.26(239B) - Resources - href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf - -values: - 2025-07-01: 2000 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_recipient.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_recipient.yaml deleted file mode 100644 index 3069391f8e8..00000000000 --- a/policyengine_us/parameters/gov/states/ia/dhs/tanf/eligibility/resource_limit_recipient.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: Iowa Family Investment Program (FIP) resource limit for recipient families (received FIP in prior month). - -metadata: - unit: currency-USD - period: month - label: Iowa FIP recipient resource limit - reference: - - title: Iowa Administrative Code 441-41.26(239B) - Resources - href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf - -values: - 2025-07-01: 5000 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/earned_income_deduction.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/earned_income_deduction.yaml deleted file mode 100644 index 0c9dcd17e48..00000000000 --- a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/earned_income_deduction.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: Iowa Family Investment Program (FIP) 20% earned income deduction rate applied to gross nonexempt earned income. - -metadata: - unit: /1 - period: month - label: Iowa FIP earned income deduction rate - reference: - - title: Iowa Administrative Code 441-41.27(239B) - Income - href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 - -values: - 2025-07-01: 0.20 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/gross_income_limit_percent.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/gross_income_limit_percent.yaml deleted file mode 100644 index 32f77d332c2..00000000000 --- a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/gross_income_limit_percent.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: Iowa Family Investment Program (FIP) gross income limit as a percentage of the standard of need for Test 1 eligibility. - -metadata: - unit: /1 - period: month - label: Iowa FIP gross income limit percent of standard of need - reference: - - title: Iowa Administrative Code 441-41.27(239B) - Income - href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 - -values: - 2025-07-01: 1.85 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/earned.yaml deleted file mode 100644 index fcc389d2df9..00000000000 --- a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/earned.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: Iowa Family Investment Program (FIP) counts these income sources as earned income. - -values: - 2025-07-01: - - employment_income - - self_employment_income - -metadata: - unit: list - reference: - - title: Iowa Administrative Code 441-41.27(239B) - Income - href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/unearned.yaml deleted file mode 100644 index 830d1b387ae..00000000000 --- a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/sources/unearned.yaml +++ /dev/null @@ -1,15 +0,0 @@ -description: Iowa Family Investment Program (FIP) counts these income sources as unearned income. - -values: - 2025-07-01: - - social_security - - ssi - - unemployment_compensation - - alimony_income - - child_support_received - -metadata: - unit: list - reference: - - title: Iowa Administrative Code 441-41.27(239B) - Income - href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/work_incentive_disregard.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/work_incentive_disregard.yaml deleted file mode 100644 index bae2e503c02..00000000000 --- a/policyengine_us/parameters/gov/states/ia/dhs/tanf/income/work_incentive_disregard.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: Iowa Family Investment Program (FIP) 58% work incentive disregard rate applied after the 20% earned income deduction. - -metadata: - unit: /1 - period: month - label: Iowa FIP work incentive disregard rate - reference: - - title: Iowa Administrative Code 441-41.27(239B) - Income - href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 - -values: - 2025-07-01: 0.58 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/additional.yaml deleted file mode 100644 index e0c8b2b079c..00000000000 --- a/policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/additional.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: Iowa Family Investment Program (FIP) additional standard of need amount per person for families larger than 10. - -metadata: - unit: currency-USD - period: month - label: Iowa FIP additional standard of need per person - reference: - - title: Iowa Administrative Code 441-41.28(239B) - Need Standards - href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 - -values: - 2025-07-01: 173 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/main.yaml deleted file mode 100644 index bdef2801925..00000000000 --- a/policyengine_us/parameters/gov/states/ia/dhs/tanf/need_standard/main.yaml +++ /dev/null @@ -1,32 +0,0 @@ -description: Iowa Family Investment Program (FIP) standard of need (Schedule of Living Costs) by family size. - -metadata: - unit: currency-USD - period: month - breakdown: - - range(1, 11) - label: Iowa FIP standard of need - reference: - - title: Iowa Administrative Code 441-41.28(239B) - Need Standards - href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 - -1: - 2025-07-01: 365 -2: - 2025-07-01: 719 -3: - 2025-07-01: 849 -4: - 2025-07-01: 986 -5: - 2025-07-01: 1092 -6: - 2025-07-01: 1216 -7: - 2025-07-01: 1335 -8: - 2025-07-01: 1457 -9: - 2025-07-01: 1576 -10: - 2025-07-01: 1724 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/additional.yaml deleted file mode 100644 index 14efac7ae54..00000000000 --- a/policyengine_us/parameters/gov/states/ia/dhs/tanf/payment_standard/additional.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: Iowa Family Investment Program (FIP) additional payment standard amount per person for families larger than 10. - -metadata: - unit: currency-USD - period: month - label: Iowa FIP additional payment standard per person - reference: - - title: Iowa Administrative Code 441-41.28(239B) - Need Standards - href: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 - -values: - 2025-07-01: 87 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip.yaml new file mode 100644 index 00000000000..cb52d1a3319 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip.yaml @@ -0,0 +1,387 @@ +# Iowa TANF (Family Investment Program) benefit tests +# Per 441 IAC 41.27(239B) and 41.28(239B) + +# Unit tests - isolate core benefit calculation logic + +- name: Unit test - eligible household receives benefit + period: 2025 + input: + ia_fip_payment_standard: 5_112 + ia_fip_countable_income: 3_225.60 + ia_fip_eligible: true + state_code: IA + output: + ia_fip: 1_886.40 + +- name: Unit test - countable income exceeds payment standard + period: 2025 + input: + ia_fip_payment_standard: 5_112 + ia_fip_countable_income: 6_000 + ia_fip_eligible: true + state_code: IA + output: + ia_fip: 0 + +- name: Unit test - ineligible household receives no benefit + period: 2025 + input: + ia_fip_payment_standard: 5_112 + ia_fip_countable_income: 3_000 + ia_fip_eligible: false + state_code: IA + output: + ia_fip: 0 + +# Integration tests - full calculation with realistic household structures + +- name: Integration test - family of 3 with $800/month earnings + # Example from 441 IAC 41.27(239B) documentation + # Family of 3 with one employed parent earning $800/month gross + # Calculations (annual): + # - Gross Income: $9,600 + # - 20% earned income deduction: $9,600 * 0.20 = $1,920 + # - Net after 20%: $9,600 - $1,920 = $7,680 + # - 58% work incentive: $7,680 * 0.58 = $4,454.40 + # - Countable income: $7,680 - $4,454.40 = $3,225.60 + # - Payment standard for 3: $426/month * 12 = $5,112/year + # - Benefit: $5,112 - $3,225.60 = $1,886.40/year + period: 2025 + absolute_error_margin: 1 + input: + people: + parent: + age: 30 + employment_income: 9_600 + is_tax_unit_head_or_spouse: true + child1: + age: 5 + employment_income: 0 + is_tax_unit_dependent: true + child2: + age: 3 + employment_income: 0 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [parent, child1, child2] + tax_units: + tax_unit: + members: [parent, child1, child2] + households: + household: + members: [parent, child1, child2] + state_code: IA + output: + ia_fip_standard_of_need: 10_188 + ia_fip_payment_standard: 5_112 + ia_fip_gross_earned_income: 9_600 + ia_fip_gross_income: 9_600 + ia_fip_countable_income: 3_225.60 + ia_fip_income_eligible: true + ia_fip_eligible: true + ia_fip: 1_886.40 + +- name: Integration test - family exceeds gross income limit + # Family of 2 with $2,000/month earnings + # Standard of need for 2: $719/month * 12 = $8,628/year + # Gross income limit: $8,628 * 1.85 = $15,961.80/year + # Gross income: $24,000/year > $15,961.80 - FAIL Test 1 + period: 2025 + absolute_error_margin: 1 + input: + people: + parent: + age: 30 + employment_income: 24_000 + is_tax_unit_head_or_spouse: true + child: + age: 5 + employment_income: 0 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [parent, child] + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: IA + output: + ia_fip_standard_of_need: 8_628 + ia_fip_gross_income: 24_000 + ia_fip_income_eligible: false + ia_fip_eligible: false + ia_fip: 0 + +- name: Integration test - zero income household receives max benefit + # Family of 2 with zero income + # Payment standard for 2: $361/month * 12 = $4,332/year + # Countable income: $0 + # Benefit: $4,332 - $0 = $4,332/year + period: 2025 + absolute_error_margin: 1 + input: + people: + parent: + age: 30 + employment_income: 0 + is_tax_unit_head_or_spouse: true + child: + age: 5 + employment_income: 0 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [parent, child] + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: IA + output: + ia_fip_standard_of_need: 8_628 + ia_fip_payment_standard: 4_332 + ia_fip_gross_earned_income: 0 + ia_fip_gross_unearned_income: 0 + ia_fip_gross_income: 0 + ia_fip_countable_income: 0 + ia_fip_income_eligible: true + ia_fip_eligible: true + ia_fip: 4_332 + +- name: Integration test - unearned income only (no deductions) + # Family of 2 with $400/month unearned income + # Unearned income does not get the 20% deduction or 58% work incentive + # Standard of need for 2: $719/month * 12 = $8,628/year + # Payment standard for 2: $361/month * 12 = $4,332/year + # Gross income: $4,800/year + # Gross income limit: $8,628 * 1.85 = $15,961.80 > $4,800 - PASS Test 1 + # Net income: $4,800 < $8,628 - PASS Test 2 + # Countable income: $4,800 (no earned income deductions apply) + # Countable income $4,800 > payment standard $4,332 - FAIL Test 3 + period: 2025 + absolute_error_margin: 1 + input: + people: + parent: + age: 30 + employment_income: 0 + social_security: 4_800 + is_tax_unit_head_or_spouse: true + child: + age: 5 + employment_income: 0 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [parent, child] + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: IA + output: + ia_fip_standard_of_need: 8_628 + ia_fip_payment_standard: 4_332 + ia_fip_gross_earned_income: 0 + ia_fip_gross_unearned_income: 4_800 + ia_fip_gross_income: 4_800 + ia_fip_countable_income: 4_800 + ia_fip_income_eligible: false + ia_fip_eligible: false + ia_fip: 0 + +- name: Integration test - mixed earned and unearned income + # Family of 3 with $500/month earned and $200/month unearned + # Standard of need for 3: $849/month * 12 = $10,188/year + # Payment standard for 3: $426/month * 12 = $5,112/year + # Gross earned: $6,000/year + # Gross unearned: $2,400/year + # Gross income: $8,400/year + # Gross income limit: $10,188 * 1.85 = $18,847.80 > $8,400 - PASS Test 1 + # 20% deduction: $6,000 * 0.20 = $1,200 + # Net income: $8,400 - $1,200 = $7,200 < $10,188 - PASS Test 2 + # Remaining earned: $6,000 - $1,200 = $4,800 + # 58% work incentive: $4,800 * 0.58 = $2,784 + # Countable earned: $4,800 - $2,784 = $2,016 + # Countable income: $2,016 + $2,400 = $4,416 < $5,112 - PASS Test 3 + # Benefit: $5,112 - $4,416 = $696/year + period: 2025 + absolute_error_margin: 1 + input: + people: + parent: + age: 30 + employment_income: 6_000 + social_security: 2_400 + is_tax_unit_head_or_spouse: true + child1: + age: 5 + employment_income: 0 + is_tax_unit_dependent: true + child2: + age: 3 + employment_income: 0 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [parent, child1, child2] + tax_units: + tax_unit: + members: [parent, child1, child2] + households: + household: + members: [parent, child1, child2] + state_code: IA + output: + ia_fip_standard_of_need: 10_188 + ia_fip_payment_standard: 5_112 + ia_fip_gross_earned_income: 6_000 + ia_fip_gross_unearned_income: 2_400 + ia_fip_gross_income: 8_400 + ia_fip_countable_income: 4_416 + ia_fip_income_eligible: true + ia_fip_eligible: true + ia_fip: 696 + +- name: Integration test - single parent household + # Single parent with 1 child earning $600/month + # Standard of need for 2: $719/month * 12 = $8,628/year + # Payment standard for 2: $361/month * 12 = $4,332/year + # Gross earned: $7,200/year + # Gross income limit: $8,628 * 1.85 = $15,961.80 > $7,200 - PASS Test 1 + # 20% deduction: $7,200 * 0.20 = $1,440 + # Net income: $7,200 - $1,440 = $5,760 < $8,628 - PASS Test 2 + # Remaining earned: $7,200 - $1,440 = $5,760 + # 58% work incentive: $5,760 * 0.58 = $3,340.80 + # Countable income: $5,760 - $3,340.80 = $2,419.20 < $4,332 - PASS Test 3 + # Benefit: $4,332 - $2,419.20 = $1,912.80/year + period: 2025 + absolute_error_margin: 1 + input: + people: + parent: + age: 25 + employment_income: 7_200 + is_tax_unit_head_or_spouse: true + child: + age: 2 + employment_income: 0 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [parent, child] + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: IA + output: + ia_fip_standard_of_need: 8_628 + ia_fip_payment_standard: 4_332 + ia_fip_gross_earned_income: 7_200 + ia_fip_countable_income: 2_419.20 + ia_fip_income_eligible: true + ia_fip_eligible: true + ia_fip: 1_912.80 + +- name: Integration test - large family (over 10 members) + # Family of 11 members (at max cap 10 + 1 additional) + # Standard of need for 10: $1,724/month + # Additional per person: varies, let's check the additional parameter + # Payment standard for 10: $865/month + period: 2025 + absolute_error_margin: 1 + input: + people: + parent1: + age: 35 + employment_income: 0 + is_tax_unit_head_or_spouse: true + parent2: + age: 33 + employment_income: 0 + is_tax_unit_head_or_spouse: true + child1: + age: 16 + employment_income: 0 + is_tax_unit_dependent: true + child2: + age: 14 + employment_income: 0 + is_tax_unit_dependent: true + child3: + age: 12 + employment_income: 0 + is_tax_unit_dependent: true + child4: + age: 10 + employment_income: 0 + is_tax_unit_dependent: true + child5: + age: 8 + employment_income: 0 + is_tax_unit_dependent: true + child6: + age: 6 + employment_income: 0 + is_tax_unit_dependent: true + child7: + age: 4 + employment_income: 0 + is_tax_unit_dependent: true + child8: + age: 2 + employment_income: 0 + is_tax_unit_dependent: true + child9: + age: 1 + employment_income: 0 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [parent1, parent2, child1, child2, child3, child4, child5, child6, child7, child8, child9] + tax_units: + tax_unit: + members: [parent1, parent2, child1, child2, child3, child4, child5, child6, child7, child8, child9] + households: + household: + members: [parent1, parent2, child1, child2, child3, child4, child5, child6, child7, child8, child9] + state_code: IA + output: + ia_fip_income_eligible: true + ia_fip_eligible: true + +- name: Integration test - non-Iowa state gets zero benefit + period: 2025 + input: + people: + parent: + age: 30 + employment_income: 0 + is_tax_unit_head_or_spouse: true + child: + age: 5 + employment_income: 0 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [parent, child] + tax_units: + tax_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: IL + output: + ia_fip: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/tanf/ia_tanf.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/tanf/ia_tanf.yaml deleted file mode 100644 index b031574452d..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/tanf/ia_tanf.yaml +++ /dev/null @@ -1,116 +0,0 @@ -# Iowa TANF (Family Investment Program) benefit tests -# Per 441 IAC 41.27(239B) and 41.28(239B) - -- name: Unit test - eligible household receives benefit - period: 2025 - input: - ia_tanf_payment_standard: 5_112 - ia_tanf_countable_income: 3_225.60 - ia_tanf_eligible: true - state_code: IA - output: - ia_tanf: 1_886.40 - -- name: Unit test - countable income exceeds payment standard - period: 2025 - input: - ia_tanf_payment_standard: 5_112 - ia_tanf_countable_income: 6_000 - ia_tanf_eligible: true - state_code: IA - output: - ia_tanf: 0 - -- name: Unit test - ineligible household receives no benefit - period: 2025 - input: - ia_tanf_payment_standard: 5_112 - ia_tanf_countable_income: 3_000 - ia_tanf_eligible: false - state_code: IA - output: - ia_tanf: 0 - -- name: Integration test - family of 3 with $800/month earnings - # Example from 441 IAC 41.27(239B) documentation - # Family of 3 with one employed parent earning $800/month gross - # Calculations (annual): - # - Gross Income: $9,600 - # - 20% earned income deduction: $9,600 * 0.20 = $1,920 - # - Net after 20%: $9,600 - $1,920 = $7,680 - # - 58% work incentive: $7,680 * 0.58 = $4,454.40 - # - Countable income: $7,680 - $4,454.40 = $3,225.60 - # - Payment standard for 3: $426/month * 12 = $5,112/year - # - Benefit: $5,112 - $3,225.60 = $1,886.40/year - period: 2025 - absolute_error_margin: 1 - input: - people: - parent: - age: 30 - employment_income: 9_600 - is_tax_unit_head_or_spouse: true - child1: - age: 5 - employment_income: 0 - is_tax_unit_dependent: true - child2: - age: 3 - employment_income: 0 - is_tax_unit_dependent: true - spm_units: - spm_unit: - members: [parent, child1, child2] - tax_units: - tax_unit: - members: [parent, child1, child2] - households: - household: - members: [parent, child1, child2] - state_code: IA - output: - ia_tanf_standard_of_need: 10_188 - ia_tanf_payment_standard: 5_112 - ia_tanf_gross_earned_income: 9_600 - ia_tanf_gross_income: 9_600 - ia_tanf_countable_income: 3_225.60 - ia_tanf_gross_income_eligible: true - ia_tanf_net_income_eligible: true - ia_tanf_payment_standard_eligible: true - ia_tanf_income_eligible: true - ia_tanf_eligible: true - ia_tanf: 1_886.40 - -- name: Integration test - family exceeds gross income limit - # Family of 2 with $2,000/month earnings - # Gross income limit: $719 * 1.85 * 12 = $15,961.80/year - # Gross income: $24,000/year > $15,961.80 - FAIL Test 1 - period: 2025 - absolute_error_margin: 1 - input: - people: - parent: - age: 30 - employment_income: 24_000 - is_tax_unit_head_or_spouse: true - child: - age: 5 - employment_income: 0 - is_tax_unit_dependent: true - spm_units: - spm_unit: - members: [parent, child] - tax_units: - tax_unit: - members: [parent, child] - households: - household: - members: [parent, child] - state_code: IA - output: - ia_tanf_standard_of_need: 8_628 - ia_tanf_gross_income: 24_000 - ia_tanf_gross_income_eligible: false - ia_tanf_income_eligible: false - ia_tanf_eligible: false - ia_tanf: 0 diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py new file mode 100644 index 00000000000..e76648fbd4d --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class ia_fip_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Iowa FIP eligible" + definition_period = YEAR + defined_for = StateCode.IA + reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" + + def formula(spm_unit, period, parameters): + # Must have at least one eligible child (uses federal demographic rules) + has_children = spm_unit("is_demographic_tanf_eligible", period) + # Must meet immigration status eligibility (citizen or qualified alien) + # Per Iowa legal code 441—41.23(239B), 41.23(5) + immigration_eligible = ( + add(spm_unit, period, ["is_citizen_or_legal_immigrant"]) > 0 + ) + # Resource eligibility assumed for this simple implementation + # Actual resource checking would compare spm_unit resources against + # p.resource_limit_applicant ($2,000) or p.resource_limit_recipient ($5,000) + income_eligible = spm_unit("ia_fip_income_eligible", period) + + return has_children & immigration_eligible & income_eligible diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py new file mode 100644 index 00000000000..fd8a5361a0a --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py @@ -0,0 +1,40 @@ +from policyengine_us.model_api import * + + +class ia_fip_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Iowa FIP income eligible" + definition_period = YEAR + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf" + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ia.dhs.fip.income + # three step income test + # test 1: countable gross income below some percentage of standard of need + gross_income = spm_unit("ia_fip_gross_income", period) + standard_of_need = spm_unit("ia_fip_standard_of_need", period) + gross_income_limit = standard_of_need * p.gross_income_limit_percent + gross_income_eligible = gross_income <= gross_income_limit + + # test 2: countable net income below standard of need + gross_earned_income = spm_unit("ia_fip_gross_earned_income", period) + earned_income_deduction = ( + gross_earned_income * p.earned_income_deduction + ) + net_income = gross_income - earned_income_deduction + net_income_eligible = net_income < standard_of_need + + # test 3: countable net income below payment standard + countable_income = spm_unit("ia_fip_countable_income", period) + payment_standard = spm_unit("ia_fip_payment_standard", period) + payment_standard_eligible = countable_income < payment_standard + + return ( + gross_income_eligible + & net_income_eligible + & payment_standard_eligible + ) diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_payment_standard.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_payment_standard.py new file mode 100644 index 00000000000..2b653b86e61 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_payment_standard.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class ia_fip_payment_standard(Variable): + value_type = float + entity = SPMUnit + label = "Iowa FIP payment standard" + unit = USD + definition_period = YEAR + defined_for = StateCode.IA + reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ia.dhs.fip + people = spm_unit("spm_unit_size", period) + capped_people = min_(people, p.max_unit_size).astype(int) + additional_people = people - capped_people + + base = p.payment_standard.main[capped_people] + additional_amount = p.payment_standard.additional * additional_people + monthly = base + additional_amount + return monthly * MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py similarity index 59% rename from policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard.py rename to policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py index f67a0517630..aa033839b18 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py @@ -1,21 +1,22 @@ from policyengine_us.model_api import * -class ia_tanf_payment_standard(Variable): +class ia_fip_standard_of_need(Variable): value_type = float entity = SPMUnit - label = "Iowa TANF payment standard" + label = "Iowa FIP standard of need" unit = USD definition_period = YEAR defined_for = StateCode.IA reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28" def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ia.dhs.fip people = spm_unit("spm_unit_size", period) - capped_people = min_(people, 10).astype(int) + capped_people = min_(people, p.max_unit_size).astype(int) additional_people = people - capped_people - p = parameters(period).gov.states.ia.dhs.tanf.payment_standard - base = p.main[capped_people] - additional_amount = p.additional * additional_people + + base = p.need_standard.main[capped_people] + additional_amount = p.need_standard.additional * additional_people monthly = base + additional_amount return monthly * MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_tanf.py similarity index 54% rename from policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf.py rename to policyengine_us/variables/gov/states/ia/dhs/fip/ia_tanf.py index 3b277a16801..5d6c26aa9c2 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_tanf.py @@ -1,16 +1,16 @@ from policyengine_us.model_api import * -class ia_tanf(Variable): +class ia_fip(Variable): value_type = float entity = SPMUnit - label = "Iowa Temporary Assistance for Needy Families (TANF)" + label = "Iowa Family Investment Program (FIP)" unit = USD definition_period = YEAR - defined_for = "ia_tanf_eligible" + defined_for = "ia_fip_eligible" reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28" def formula(spm_unit, period, parameters): - payment_standard = spm_unit("ia_tanf_payment_standard", period) - countable_income = spm_unit("ia_tanf_countable_income", period) + payment_standard = spm_unit("ia_fip_payment_standard", period) + countable_income = spm_unit("ia_fip_countable_income", period) return max_(payment_standard - countable_income, 0) diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_countable_income.py b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_countable_income.py similarity index 57% rename from policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_countable_income.py rename to policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_countable_income.py index cee452e4c3f..d8237e5eb24 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_countable_income.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_countable_income.py @@ -1,19 +1,21 @@ from policyengine_us.model_api import * -class ia_tanf_countable_income(Variable): +class ia_fip_countable_income(Variable): value_type = float entity = SPMUnit - label = "Iowa TANF countable income" + label = "Iowa FIP countable income" unit = USD definition_period = YEAR defined_for = StateCode.IA - reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf" + ) def formula(spm_unit, period, parameters): - gross_earned = spm_unit("ia_tanf_gross_earned_income", period) - gross_unearned = spm_unit("ia_tanf_gross_unearned_income", period) - p = parameters(period).gov.states.ia.dhs.tanf.income + gross_earned = spm_unit("ia_fip_gross_earned_income", period) + gross_unearned = spm_unit("ia_fip_gross_unearned_income", period) + p = parameters(period).gov.states.ia.dhs.fip.income earned_income_deduction = gross_earned * p.earned_income_deduction remaining_earned = gross_earned - earned_income_deduction work_incentive = remaining_earned * p.work_incentive_disregard diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_earned_income.py b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_earned_income.py new file mode 100644 index 00000000000..163eb0601d0 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_earned_income.py @@ -0,0 +1,15 @@ +from policyengine_us.model_api import * + + +class ia_fip_gross_earned_income(Variable): + value_type = float + entity = SPMUnit + label = "Iowa FIP gross earned income" + unit = USD + definition_period = YEAR + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf" + ) + + adds = "gov.states.ia.dhs.fip.income.sources.earned" diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_income.py b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_income.py new file mode 100644 index 00000000000..7433f71980b --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_income.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class ia_fip_gross_income(Variable): + value_type = float + entity = SPMUnit + label = "Iowa FIP gross income" + unit = USD + definition_period = YEAR + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf" + ) + + adds = [ + "ia_fip_gross_earned_income", + "ia_fip_gross_unearned_income", + ] diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_unearned_income.py b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_unearned_income.py new file mode 100644 index 00000000000..ebde8c8d156 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_unearned_income.py @@ -0,0 +1,15 @@ +from policyengine_us.model_api import * + + +class ia_fip_gross_unearned_income(Variable): + value_type = float + entity = SPMUnit + label = "Iowa FIP gross unearned income" + unit = USD + definition_period = YEAR + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf" + ) + + adds = "gov.states.ia.dhs.fip.income.sources.unearned" diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_eligible.py deleted file mode 100644 index 9b5335df9a5..00000000000 --- a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_eligible.py +++ /dev/null @@ -1,15 +0,0 @@ -from policyengine_us.model_api import * - - -class ia_tanf_eligible(Variable): - value_type = bool - entity = SPMUnit - label = "Iowa TANF eligible" - definition_period = YEAR - defined_for = StateCode.IA - reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" - - def formula(spm_unit, period, parameters): - demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) - income_eligible = spm_unit("ia_tanf_income_eligible", period) - return demographic_eligible & income_eligible diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_gross_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_gross_income_eligible.py deleted file mode 100644 index 5ee0e3b5ea9..00000000000 --- a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_gross_income_eligible.py +++ /dev/null @@ -1,17 +0,0 @@ -from policyengine_us.model_api import * - - -class ia_tanf_gross_income_eligible(Variable): - value_type = bool - entity = SPMUnit - label = "Iowa TANF gross income eligible (Test 1)" - definition_period = YEAR - defined_for = StateCode.IA - reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" - - def formula(spm_unit, period, parameters): - gross_income = spm_unit("ia_tanf_gross_income", period) - standard_of_need = spm_unit("ia_tanf_standard_of_need", period) - p = parameters(period).gov.states.ia.dhs.tanf.income - gross_income_limit = standard_of_need * p.gross_income_limit_percent - return gross_income <= gross_income_limit diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_income_eligible.py deleted file mode 100644 index e8220e67b28..00000000000 --- a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_income_eligible.py +++ /dev/null @@ -1,24 +0,0 @@ -from policyengine_us.model_api import * - - -class ia_tanf_income_eligible(Variable): - value_type = bool - entity = SPMUnit - label = "Iowa TANF income eligible" - definition_period = YEAR - defined_for = StateCode.IA - reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" - - def formula(spm_unit, period, parameters): - gross_income_eligible = spm_unit( - "ia_tanf_gross_income_eligible", period - ) - net_income_eligible = spm_unit("ia_tanf_net_income_eligible", period) - payment_standard_eligible = spm_unit( - "ia_tanf_payment_standard_eligible", period - ) - return ( - gross_income_eligible - & net_income_eligible - & payment_standard_eligible - ) diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_net_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_net_income_eligible.py deleted file mode 100644 index 9d760ad087f..00000000000 --- a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_net_income_eligible.py +++ /dev/null @@ -1,21 +0,0 @@ -from policyengine_us.model_api import * - - -class ia_tanf_net_income_eligible(Variable): - value_type = bool - entity = SPMUnit - label = "Iowa TANF net income eligible (Test 2)" - definition_period = YEAR - defined_for = StateCode.IA - reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" - - def formula(spm_unit, period, parameters): - gross_income = spm_unit("ia_tanf_gross_income", period) - gross_earned_income = spm_unit("ia_tanf_gross_earned_income", period) - standard_of_need = spm_unit("ia_tanf_standard_of_need", period) - p = parameters(period).gov.states.ia.dhs.tanf.income - earned_income_deduction = ( - gross_earned_income * p.earned_income_deduction - ) - net_income = gross_income - earned_income_deduction - return net_income < standard_of_need diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard_eligible.py deleted file mode 100644 index 97d33c2eb13..00000000000 --- a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_payment_standard_eligible.py +++ /dev/null @@ -1,15 +0,0 @@ -from policyengine_us.model_api import * - - -class ia_tanf_payment_standard_eligible(Variable): - value_type = bool - entity = SPMUnit - label = "Iowa TANF payment standard eligible (Test 3)" - definition_period = YEAR - defined_for = StateCode.IA - reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" - - def formula(spm_unit, period, parameters): - countable_income = spm_unit("ia_tanf_countable_income", period) - payment_standard = spm_unit("ia_tanf_payment_standard", period) - return countable_income < payment_standard diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_standard_of_need.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_standard_of_need.py deleted file mode 100644 index f93afe1dab6..00000000000 --- a/policyengine_us/variables/gov/states/ia/dhs/tanf/ia_tanf_standard_of_need.py +++ /dev/null @@ -1,21 +0,0 @@ -from policyengine_us.model_api import * - - -class ia_tanf_standard_of_need(Variable): - value_type = float - entity = SPMUnit - label = "Iowa TANF standard of need" - unit = USD - definition_period = YEAR - defined_for = StateCode.IA - reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28" - - def formula(spm_unit, period, parameters): - people = spm_unit("spm_unit_size", period) - capped_people = min_(people, 10).astype(int) - additional_people = people - capped_people - p = parameters(period).gov.states.ia.dhs.tanf.need_standard - base = p.main[capped_people] - additional_amount = p.additional * additional_people - monthly = base + additional_amount - return monthly * MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_earned_income.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_earned_income.py deleted file mode 100644 index 45999759fa0..00000000000 --- a/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_earned_income.py +++ /dev/null @@ -1,13 +0,0 @@ -from policyengine_us.model_api import * - - -class ia_tanf_gross_earned_income(Variable): - value_type = float - entity = SPMUnit - label = "Iowa TANF gross earned income" - unit = USD - definition_period = YEAR - defined_for = StateCode.IA - reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" - - adds = "gov.states.ia.dhs.tanf.income.sources.earned" diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_income.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_income.py deleted file mode 100644 index 24dfa391139..00000000000 --- a/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_income.py +++ /dev/null @@ -1,16 +0,0 @@ -from policyengine_us.model_api import * - - -class ia_tanf_gross_income(Variable): - value_type = float - entity = SPMUnit - label = "Iowa TANF gross income" - unit = USD - definition_period = YEAR - defined_for = StateCode.IA - reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" - - def formula(spm_unit, period, parameters): - earned = spm_unit("ia_tanf_gross_earned_income", period) - unearned = spm_unit("ia_tanf_gross_unearned_income", period) - return earned + unearned diff --git a/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_unearned_income.py b/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_unearned_income.py deleted file mode 100644 index d42dc1bbad3..00000000000 --- a/policyengine_us/variables/gov/states/ia/dhs/tanf/income/ia_tanf_gross_unearned_income.py +++ /dev/null @@ -1,13 +0,0 @@ -from policyengine_us.model_api import * - - -class ia_tanf_gross_unearned_income(Variable): - value_type = float - entity = SPMUnit - label = "Iowa TANF gross unearned income" - unit = USD - definition_period = YEAR - defined_for = StateCode.IA - reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" - - adds = "gov.states.ia.dhs.tanf.income.sources.unearned" From dc74f380ba974d677d972344e6dc1ce7c24aa461 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Tue, 20 Jan 2026 06:22:04 +0000 Subject: [PATCH 16/29] Formatting --- .../eligibility/resource_limit_applicant.yaml | 2 +- .../eligibility/resource_limit_recipient.yaml | 2 +- .../fip/income/earned_income_deduction.yaml | 2 +- .../ia/dhs/fip/income/sources/unearned.yaml | 2 +- .../gov/states/ia/dhs/fip/max_unit_size.yaml | 2 +- .../states/ia/dhs/fip/need_standard/main.yaml | 2 +- .../dhs/fip/payment_standard/additional.yaml | 2 +- .../ia/dhs/fip/payment_standard/main.yaml | 2 +- .../gov/states/ia/dhs/fip/ia_fip_eligible.py | 23 +++++++++++++++---- 9 files changed, 26 insertions(+), 13 deletions(-) diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_applicant.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_applicant.yaml index 2d9f103c357..5aaa8ea3dd5 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_applicant.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_applicant.yaml @@ -11,4 +11,4 @@ metadata: - title: Iowa Administrative Code 441-41.26(239B) - Resources, 41.26(1)(e) href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf - title: Iowa TANF State Plan 2025 - href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) \ No newline at end of file + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_recipient.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_recipient.yaml index ba24ad02a16..e182f48b2d1 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_recipient.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_recipient.yaml @@ -11,4 +11,4 @@ metadata: - title: Iowa Administrative Code 441-41.26(239B) - Resources, 41.26(1)(e) href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf - title: Iowa TANF State Plan 2025 - href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) \ No newline at end of file + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml index 5a658b22677..28182c46bd5 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml @@ -9,4 +9,4 @@ metadata: label: Iowa FIP earned income deduction rate reference: - title: Iowa Administrative Code 441-41.27(239B) - Income, 41.27(2)(a) - href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=21 \ No newline at end of file + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=21 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml index 832614647ba..2d757e1acfd 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml @@ -14,4 +14,4 @@ metadata: label: Iowa FIP unearned income sources reference: - title: Iowa Administrative Code 441-41.27(239B) - Income, 41.27(1) - href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=20 \ No newline at end of file + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=20 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml index 9ea10c46a69..1d100c135ed 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml @@ -11,4 +11,4 @@ metadata: - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 - title: Iowa TANF State Plan 2025 - href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) \ No newline at end of file + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml index cd71ed17537..8551d6d0faa 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml @@ -29,4 +29,4 @@ metadata: label: Iowa FIP standard of need reference: - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) - href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 \ No newline at end of file + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml index 472c7ea8af6..ac00f3fa7f5 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml @@ -9,4 +9,4 @@ metadata: label: Iowa FIP additional payment standard per person reference: - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) - href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 \ No newline at end of file + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml index 11aef980792..5c4e1240590 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml @@ -29,4 +29,4 @@ metadata: label: Iowa FIP payment standard reference: - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) - href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 \ No newline at end of file + href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py index e76648fbd4d..f71c1fceb44 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py @@ -7,9 +7,12 @@ class ia_fip_eligible(Variable): label = "Iowa FIP eligible" definition_period = YEAR defined_for = StateCode.IA - reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf" + ) def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ia.dhs.fip.eligibility # Must have at least one eligible child (uses federal demographic rules) has_children = spm_unit("is_demographic_tanf_eligible", period) # Must meet immigration status eligibility (citizen or qualified alien) @@ -17,9 +20,19 @@ def formula(spm_unit, period, parameters): immigration_eligible = ( add(spm_unit, period, ["is_citizen_or_legal_immigrant"]) > 0 ) - # Resource eligibility assumed for this simple implementation - # Actual resource checking would compare spm_unit resources against - # p.resource_limit_applicant ($2,000) or p.resource_limit_recipient ($5,000) + current_recipient = spm_unit("is_tanf_enrolled", period) + limit = where( + current_recipient, + p.resource_limit_recipient, + p.resource_limit_applicant, + ) + resources = spm_unit("spm_unit_assets", period.this_year) + resource_eligible = resources <= limit income_eligible = spm_unit("ia_fip_income_eligible", period) - return has_children & immigration_eligible & income_eligible + return ( + has_children + & immigration_eligible + & resource_eligible + & income_eligible + ) From f510c2013d2f87ad6dd7ee8eb7d7ed250bdcd376 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Tue, 20 Jan 2026 06:35:13 +0000 Subject: [PATCH 17/29] Add comprehensive unit tests for Iowa FIP variables Add individual test files for each Iowa FIP variable following the Arizona TANF pattern from PR #7150: - ia_fip_eligible.yaml (8 tests) - ia_fip_income_eligible.yaml (8 tests) - ia_fip_payment_standard.yaml (8 tests) - ia_fip_standard_of_need.yaml (8 tests) - ia_fip_countable_income.yaml (8 tests) - ia_fip_gross_income.yaml (6 tests) - ia_fip_gross_earned_income.yaml (7 tests) - ia_fip_gross_unearned_income.yaml (10 tests) Co-Authored-By: Claude Opus 4.5 --- .../ia/dhs/fip/ia_fip_countable_income.yaml | 181 +++++++++++++ .../states/ia/dhs/fip/ia_fip_eligible.yaml | 214 +++++++++++++++ .../dhs/fip/ia_fip_gross_earned_income.yaml | 135 ++++++++++ .../ia/dhs/fip/ia_fip_gross_income.yaml | 116 ++++++++ .../dhs/fip/ia_fip_gross_unearned_income.yaml | 192 ++++++++++++++ .../ia/dhs/fip/ia_fip_income_eligible.yaml | 249 ++++++++++++++++++ .../ia/dhs/fip/ia_fip_payment_standard.yaml | 196 ++++++++++++++ .../ia/dhs/fip/ia_fip_standard_of_need.yaml | 197 ++++++++++++++ 8 files changed, 1480 insertions(+) create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_earned_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_unearned_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_income_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_payment_standard.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_standard_of_need.yaml diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income.yaml new file mode 100644 index 00000000000..6189cf7825d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income.yaml @@ -0,0 +1,181 @@ +# Unit tests for Iowa FIP countable income +# Countable income calculation: +# 1. Apply 20% earned income deduction +# 2. Apply 58% work incentive disregard to remaining earned income +# 3. Add unearned income (no deductions) +# Reference: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf + +- name: Case 1, zero income. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_countable_income: 0 + +- name: Case 2, earned income only ($800/month). + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Gross earned: $9,600 + # 20% deduction: $9,600 * 0.20 = $1,920 + # Remaining: $9,600 - $1,920 = $7,680 + # 58% work incentive: $7,680 * 0.58 = $4,454.40 + # Countable earned: $7,680 - $4,454.40 = $3,225.60 + ia_fip_countable_income: 3_225.60 + +- name: Case 3, unearned income only. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + social_security: 4_800 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Unearned income has no deductions + # Countable = $4,800 + ia_fip_countable_income: 4_800 + +- name: Case 4, mixed earned and unearned income. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 6_000 + social_security: 2_400 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Gross earned: $6,000 + # 20% deduction: $6,000 * 0.20 = $1,200 + # Remaining: $6,000 - $1,200 = $4,800 + # 58% work incentive: $4,800 * 0.58 = $2,784 + # Countable earned: $4,800 - $2,784 = $2,016 + # Total countable: $2,016 + $2,400 = $4,416 + ia_fip_countable_income: 4_416 + +- name: Case 5, low earned income ($600/month). + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 25 + employment_income: 7_200 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Gross earned: $7,200 + # 20% deduction: $7,200 * 0.20 = $1,440 + # Remaining: $7,200 - $1,440 = $5,760 + # 58% work incentive: $5,760 * 0.58 = $3,340.80 + # Countable earned: $5,760 - $3,340.80 = $2,419.20 + ia_fip_countable_income: 2_419.20 + +- name: Case 6, high earned income ($2,000/month). + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 30 + employment_income: 24_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Gross earned: $24,000 + # 20% deduction: $24,000 * 0.20 = $4,800 + # Remaining: $24,000 - $4,800 = $19,200 + # 58% work incentive: $19,200 * 0.58 = $11,136 + # Countable earned: $19,200 - $11,136 = $8,064 + ia_fip_countable_income: 8_064 + +- name: Case 7, multiple earners in household. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + employment_income: 10_000 + person2: + age: 33 + employment_income: 2_000 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Gross earned: $10,000 + $2,000 = $12,000 + # 20% deduction: $12,000 * 0.20 = $2,400 + # Remaining: $12,000 - $2,400 = $9,600 + # 58% work incentive: $9,600 * 0.58 = $5,568 + # Countable earned: $9,600 - $5,568 = $4,032 + ia_fip_countable_income: 4_032 + +- name: Case 8, non-Iowa state gets zero. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IL + output: + # defined_for StateCode.IA, other states return 0 + ia_fip_countable_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_eligible.yaml new file mode 100644 index 00000000000..04847397179 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_eligible.yaml @@ -0,0 +1,214 @@ +# Unit tests for Iowa FIP eligibility +# Requires: demographic eligibility (minor child), immigration eligibility, +# resource eligibility, and income eligibility +# Reference: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf + +- name: Case 1, eligible family with minor child. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + is_tax_unit_head: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + ia_fip_eligible: true + +- name: Case 2, ineligible due to no minor child. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + is_tax_unit_head: true + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 1_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Single adult without minor child fails demographic eligibility + ia_fip_eligible: false + +- name: Case 3, ineligible due to high income. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income: 24_000 + is_tax_unit_head: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 1_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Gross income $24,000 > 185% of standard of need ($8,628 * 1.85 = $15,961.80) + # Fails Test 1 (gross income test) + ia_fip_eligible: false + +- name: Case 4, ineligible due to high assets (applicant). + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + is_tax_unit_head: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 3_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # $3,000 > $2,000 applicant resource limit + ia_fip_eligible: false + +- name: Case 5, recipient eligible with higher assets. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + is_tax_unit_head: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 4_000 + is_tanf_enrolled: true + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Recipients have $5,000 limit, $4,000 < $5,000 + ia_fip_eligible: true + +- name: Case 6, recipient ineligible with assets over limit. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + is_tax_unit_head: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 6_000 + is_tanf_enrolled: true + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Recipients have $5,000 limit, $6,000 > $5,000 + ia_fip_eligible: false + +- name: Case 7, eligible pregnant woman. + period: 2025 + input: + people: + person1: + age: 25 + employment_income: 0 + is_tax_unit_head: true + is_pregnant: true + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 500 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Pregnant woman is demographically eligible + ia_fip_eligible: true + +- name: Case 8, eligible family with moderate income. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income: 6_000 + is_tax_unit_head: true + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_assets: 1_500 + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # Family of 3 with $6,000/year earned income + # Standard of need: $849 * 12 = $10,188 + # Gross income limit: $10,188 * 1.85 = $18,847.80 > $6,000 - PASS Test 1 + # 20% deduction: $6,000 * 0.20 = $1,200 + # Net income: $6,000 - $1,200 = $4,800 < $10,188 - PASS Test 2 + # Remaining earned: $4,800 + # 58% work incentive: $4,800 * 0.58 = $2,784 + # Countable income: $4,800 - $2,784 = $2,016 < $5,112 - PASS Test 3 + ia_fip_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_earned_income.yaml new file mode 100644 index 00000000000..d7b060e4f3d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_earned_income.yaml @@ -0,0 +1,135 @@ +# Unit tests for Iowa FIP gross earned income +# Earned income includes: employment_income, self_employment_income +# Reference: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf + +- name: Case 1, zero earned income. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_gross_earned_income: 0 + +- name: Case 2, employment income only. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_gross_earned_income: 9_600 + +- name: Case 3, self employment income only. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + self_employment_income: 12_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_gross_earned_income: 12_000 + +- name: Case 4, mixed employment and self employment. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 6_000 + self_employment_income: 4_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # $6,000 + $4,000 = $10,000 + ia_fip_gross_earned_income: 10_000 + +- name: Case 5, multiple earners in household. + period: 2025 + input: + people: + person1: + age: 35 + employment_income: 10_000 + self_employment_income: 2_000 + person2: + age: 33 + employment_income: 3_000 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Person1: $10,000 + $2,000 = $12,000 + # Person2: $3,000 + # Total: $12,000 + $3,000 = $15,000 + ia_fip_gross_earned_income: 15_000 + +- name: Case 6, unearned income does not count. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 5_000 + social_security: 3_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Social security is unearned, only employment counts + ia_fip_gross_earned_income: 5_000 + +- name: Case 7, non-Iowa state gets zero. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IL + output: + # defined_for StateCode.IA, other states return 0 + ia_fip_gross_earned_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income.yaml new file mode 100644 index 00000000000..5e2949a097a --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income.yaml @@ -0,0 +1,116 @@ +# Unit tests for Iowa FIP gross income +# Gross income = gross earned income + gross unearned income +# Reference: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf + +- name: Case 1, zero income. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_gross_income: 0 + +- name: Case 2, earned income only. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_gross_income: 9_600 + +- name: Case 3, unearned income only. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + social_security: 4_800 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_gross_income: 4_800 + +- name: Case 4, mixed earned and unearned income. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 6_000 + social_security: 2_400 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Gross = $6,000 + $2,400 = $8,400 + ia_fip_gross_income: 8_400 + +- name: Case 5, multiple earners with unearned income. + period: 2025 + input: + people: + person1: + age: 35 + employment_income: 10_000 + social_security: 1_200 + person2: + age: 33 + employment_income: 2_000 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Earned: $10,000 + $2,000 = $12,000 + # Unearned: $1,200 + # Gross = $12,000 + $1,200 = $13,200 + ia_fip_gross_income: 13_200 + +- name: Case 6, non-Iowa state gets zero. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 9_600 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IL + output: + # defined_for StateCode.IA, other states return 0 + ia_fip_gross_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_unearned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_unearned_income.yaml new file mode 100644 index 00000000000..b36f743e2c5 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_unearned_income.yaml @@ -0,0 +1,192 @@ +# Unit tests for Iowa FIP gross unearned income +# Unearned income includes: social_security, ssi, unemployment_compensation, +# alimony_income, child_support_received +# Reference: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf + +- name: Case 1, zero unearned income. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_gross_unearned_income: 0 + +- name: Case 2, social security income only. + period: 2025 + input: + people: + person1: + age: 65 + employment_income: 0 + social_security: 12_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_gross_unearned_income: 12_000 + +- name: Case 3, SSI income only. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + ssi: 9_600 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_gross_unearned_income: 9_600 + +- name: Case 4, unemployment compensation. + period: 2025 + input: + people: + person1: + age: 40 + employment_income: 0 + unemployment_compensation: 6_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_gross_unearned_income: 6_000 + +- name: Case 5, child support received. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + child_support_received: 4_800 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_gross_unearned_income: 4_800 + +- name: Case 6, alimony income. + period: 2025 + input: + people: + person1: + age: 35 + employment_income: 0 + alimony_income: 6_000 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_gross_unearned_income: 6_000 + +- name: Case 7, multiple unearned income sources. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + social_security: 3_600 + child_support_received: 2_400 + alimony_income: 1_200 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # $3,600 + $2,400 + $1,200 = $7,200 + ia_fip_gross_unearned_income: 7_200 + +- name: Case 8, earned income does not count. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 10_000 + social_security: 2_400 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Employment income is earned, only unearned counts + ia_fip_gross_unearned_income: 2_400 + +- name: Case 9, multiple people with unearned income. + period: 2025 + input: + people: + person1: + age: 40 + employment_income: 0 + social_security: 8_000 + person2: + age: 16 + child_support_received: 2_400 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # $8,000 + $2,400 = $10,400 + ia_fip_gross_unearned_income: 10_400 + +- name: Case 10, non-Iowa state gets zero. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + social_security: 4_800 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IL + output: + # defined_for StateCode.IA, other states return 0 + ia_fip_gross_unearned_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_income_eligible.yaml new file mode 100644 index 00000000000..b17823df8b9 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_income_eligible.yaml @@ -0,0 +1,249 @@ +# Unit tests for Iowa FIP income eligibility +# Three-step income test: +# 1. Gross income <= 185% of standard of need +# 2. Net income (after 20% earned deduction) < standard of need +# 3. Countable income (after 58% work incentive) < payment standard +# Reference: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf + +- name: Case 1, zero income eligible. + period: 2025 + input: + people: + person1: + age: 30 + employment_income: 0 + is_tax_unit_head: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Zero income passes all three tests + ia_fip_income_eligible: true + +- name: Case 2, low earned income eligible. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income: 7_200 + is_tax_unit_head: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Family of 2, $7,200/year earned income ($600/month) + # Standard of need: $8,628/year + # Payment standard: $4,332/year + # Test 1: $7,200 <= $8,628 * 1.85 = $15,961.80 - PASS + # Test 2: $7,200 - ($7,200 * 0.20) = $5,760 < $8,628 - PASS + # Test 3: $5,760 - ($5,760 * 0.58) = $2,419.20 < $4,332 - PASS + ia_fip_income_eligible: true + +- name: Case 3, income exceeds gross income limit (Test 1 fails). + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income: 24_000 + is_tax_unit_head: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Family of 2, $24,000/year gross income ($2,000/month) + # Standard of need: $8,628/year + # Gross income limit: $8,628 * 1.85 = $15,961.80 + # Test 1: $24,000 > $15,961.80 - FAIL + ia_fip_income_eligible: false + +- name: Case 4, unearned income exceeds payment standard (Test 3 fails). + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income: 0 + social_security: 4_800 + is_tax_unit_head: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Family of 2, $4,800/year unearned income ($400/month) + # Standard of need: $8,628/year + # Payment standard: $4,332/year + # Test 1: $4,800 <= $15,961.80 - PASS + # Test 2: $4,800 < $8,628 - PASS + # Test 3: $4,800 >= $4,332 - FAIL (no deductions for unearned income) + ia_fip_income_eligible: false + +- name: Case 5, larger family with mixed income eligible. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income: 6_000 + social_security: 2_400 + is_tax_unit_head: true + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # Family of 3, $6,000 earned + $2,400 unearned = $8,400 gross + # Standard of need: $10,188/year + # Payment standard: $5,112/year + # Test 1: $8,400 <= $10,188 * 1.85 = $18,847.80 - PASS + # Test 2: $8,400 - ($6,000 * 0.20) = $7,200 < $10,188 - PASS + # Remaining earned: $6,000 - $1,200 = $4,800 + # Work incentive: $4,800 * 0.58 = $2,784 + # Countable earned: $4,800 - $2,784 = $2,016 + # Test 3: $2,016 + $2,400 = $4,416 < $5,112 - PASS + ia_fip_income_eligible: true + +- name: Case 6, high mixed income fails Test 3. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + employment_income: 9_600 + social_security: 3_600 + is_tax_unit_head: true + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # Family of 3, $9,600 earned + $3,600 unearned = $13,200 gross + # Standard of need: $10,188/year + # Payment standard: $5,112/year + # Test 1: $13,200 <= $18,847.80 - PASS + # Test 2: $13,200 - ($9,600 * 0.20) = $11,280 >= $10,188 - FAIL + ia_fip_income_eligible: false + +- name: Case 7, single person household eligible. + period: 2025 + input: + people: + person1: + age: 25 + employment_income: 0 + is_tax_unit_head: true + is_pregnant: true + spm_units: + spm_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Single pregnant person with zero income + # Standard of need: $365 * 12 = $4,380/year + # Payment standard: $183 * 12 = $2,196/year + # All tests pass with zero income + ia_fip_income_eligible: true + +- name: Case 8, family of 4 at income threshold. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 35 + employment_income: 10_000 + is_tax_unit_head: true + person2: + age: 33 + employment_income: 2_000 + is_tax_unit_spouse: true + person3: + age: 10 + person4: + age: 7 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: IA + output: + # Family of 4, $12,000/year gross earned income + # Standard of need: $986 * 12 = $11,832/year + # Payment standard: $495 * 12 = $5,940/year + # Test 1: $12,000 <= $11,832 * 1.85 = $21,889.20 - PASS + # Test 2: $12,000 - ($12,000 * 0.20) = $9,600 < $11,832 - PASS + # Test 3: $9,600 - ($9,600 * 0.58) = $4,032 < $5,940 - PASS + ia_fip_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_payment_standard.yaml new file mode 100644 index 00000000000..2ce249c8ad5 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_payment_standard.yaml @@ -0,0 +1,196 @@ +# Unit tests for Iowa FIP payment standard +# The payment standard is the schedule of basic needs by family size +# Reference: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 + +- name: Case 1, family of 1. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 25 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Payment standard for 1: $183/month * 12 = $2,196/year + ia_fip_payment_standard: 2_196 + +- name: Case 2, family of 2. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Payment standard for 2: $361/month * 12 = $4,332/year + ia_fip_payment_standard: 4_332 + +- name: Case 3, family of 3. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # Payment standard for 3: $426/month * 12 = $5,112/year + ia_fip_payment_standard: 5_112 + +- name: Case 4, family of 4. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 10 + person4: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: IA + output: + # Payment standard for 4: $495/month * 12 = $5,940/year + ia_fip_payment_standard: 5_940 + +- name: Case 5, family of 5. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 12 + person4: + age: 10 + person5: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: IA + output: + # Payment standard for 5: $548/month * 12 = $6,576/year + ia_fip_payment_standard: 6_576 + +- name: Case 6, family of 6. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 14 + person4: + age: 12 + person5: + age: 10 + person6: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6] + households: + household: + members: [person1, person2, person3, person4, person5, person6] + state_code: IA + output: + # Payment standard for 6: $610/month * 12 = $7,320/year + ia_fip_payment_standard: 7_320 + +- name: Case 7, family of 10 (max size in table). + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 40 + person2: + age: 38 + person3: + age: 17 + person4: + age: 15 + person5: + age: 13 + person6: + age: 11 + person7: + age: 9 + person8: + age: 7 + person9: + age: 5 + person10: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] + state_code: IA + output: + # Payment standard for 10: $865/month * 12 = $10,380/year + ia_fip_payment_standard: 10_380 + +- name: Case 8, non-Iowa state gets zero. + period: 2025 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IL + output: + # defined_for StateCode.IA, other states return 0 + ia_fip_payment_standard: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_standard_of_need.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_standard_of_need.yaml new file mode 100644 index 00000000000..ab6042659f7 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_standard_of_need.yaml @@ -0,0 +1,197 @@ +# Unit tests for Iowa FIP standard of need +# The standard of need is the schedule of living costs by family size +# Used for gross income and net income eligibility tests +# Reference: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 + +- name: Case 1, family of 1. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 25 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Standard of need for 1: $365/month * 12 = $4,380/year + ia_fip_standard_of_need: 4_380 + +- name: Case 2, family of 2. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Standard of need for 2: $719/month * 12 = $8,628/year + ia_fip_standard_of_need: 8_628 + +- name: Case 3, family of 3. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 30 + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # Standard of need for 3: $849/month * 12 = $10,188/year + ia_fip_standard_of_need: 10_188 + +- name: Case 4, family of 4. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 10 + person4: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: IA + output: + # Standard of need for 4: $986/month * 12 = $11,832/year + ia_fip_standard_of_need: 11_832 + +- name: Case 5, family of 5. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 12 + person4: + age: 10 + person5: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: IA + output: + # Standard of need for 5: $1,092/month * 12 = $13,104/year + ia_fip_standard_of_need: 13_104 + +- name: Case 6, family of 6. + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 35 + person2: + age: 33 + person3: + age: 14 + person4: + age: 12 + person5: + age: 10 + person6: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6] + households: + household: + members: [person1, person2, person3, person4, person5, person6] + state_code: IA + output: + # Standard of need for 6: $1,216/month * 12 = $14,592/year + ia_fip_standard_of_need: 14_592 + +- name: Case 7, family of 10 (max size in table). + period: 2025 + absolute_error_margin: 1 + input: + people: + person1: + age: 40 + person2: + age: 38 + person3: + age: 17 + person4: + age: 15 + person5: + age: 13 + person6: + age: 11 + person7: + age: 9 + person8: + age: 7 + person9: + age: 5 + person10: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8, person9, person10] + state_code: IA + output: + # Standard of need for 10: $1,724/month * 12 = $20,688/year + ia_fip_standard_of_need: 20_688 + +- name: Case 8, non-Iowa state gets zero. + period: 2025 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IL + output: + # defined_for StateCode.IA, other states return 0 + ia_fip_standard_of_need: 0 From b3d72c8dff89b7105dc12ac12c7c50cbf44645ea Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Wed, 21 Jan 2026 16:49:51 +0000 Subject: [PATCH 18/29] Small changes --- .../fip/income/work_incentive_disregard.yaml | 4 +++- .../ia/dhs/fip/need_standard/additional.yaml | 2 +- .../dhs/fip/payment_standard/additional.yaml | 4 +++- .../ia/dhs/fip/payment_standard/main.yaml | 2 ++ .../ia/dhs/fip/{ia_tanf.py => ia_fip.py} | 2 +- .../ia/dhs/fip/ia_fip_income_eligible.py | 4 +--- .../ia/dhs/fip/ia_fip_standard_of_need.py | 2 +- sources/working_references.md | 20 +++++++++---------- 8 files changed, 22 insertions(+), 18 deletions(-) rename policyengine_us/variables/gov/states/ia/dhs/fip/{ia_tanf.py => ia_fip.py} (84%) diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml index 94ad1afd453..463553de3ea 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml @@ -1,4 +1,4 @@ -description: Iowa deducts this percentage of work incentive disregard after the earned income deduction under the Family Investment Program. +description: Iowa deducts this rate of work incentive disregard after the earned income deduction under the Family Investment Program. values: 2025-07-01: 0.58 @@ -10,3 +10,5 @@ metadata: reference: - title: Iowa Administrative Code 441-41.27(239B) - Income, 41.27(2)(c) href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=21 + - title: Iowa TANF State Plan 2025 + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) \ No newline at end of file diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml index ad43683a127..296ee46f792 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml @@ -1,4 +1,4 @@ -description: Iowa sets this value as the additional standard of need amount per person for families larger than 10 under the Family Investment Program. +description: Iowa sets this value as the additional standard of need amount per person for families larger than than the max unit size under the Family Investment Program. metadata: unit: currency-USD diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml index ac00f3fa7f5..bbca440b00b 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml @@ -1,4 +1,4 @@ -description: Iowa sets this value as the additional payment standard amount per person for families larger than 10 under the Family Investment Program. +description: Iowa sets this value as the additional payment standard amount per person for families larger than the max unit size under the Family Investment Program. values: 2025-07-01: 87 @@ -10,3 +10,5 @@ metadata: reference: - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 + - title: Iowa TANF State Plan 2025 + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) - Net Monthly Income Limits \ No newline at end of file diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml index 5c4e1240590..f18815ace3a 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml @@ -30,3 +30,5 @@ metadata: reference: - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 + - title: Iowa TANF State Plan 2025 + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) - Net Monthly Income Limits diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_tanf.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip.py similarity index 84% rename from policyengine_us/variables/gov/states/ia/dhs/fip/ia_tanf.py rename to policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip.py index 5d6c26aa9c2..4ede36a66b5 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_tanf.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip.py @@ -8,7 +8,7 @@ class ia_fip(Variable): unit = USD definition_period = YEAR defined_for = "ia_fip_eligible" - reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28" + reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=20" def formula(spm_unit, period, parameters): payment_standard = spm_unit("ia_fip_payment_standard", period) diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py index fd8a5361a0a..a166d071d63 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py @@ -7,9 +7,7 @@ class ia_fip_income_eligible(Variable): label = "Iowa FIP income eligible" definition_period = YEAR defined_for = StateCode.IA - reference = ( - "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf" - ) + reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=19" def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ia.dhs.fip.income diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py index aa033839b18..c6f527df66c 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py @@ -8,7 +8,7 @@ class ia_fip_standard_of_need(Variable): unit = USD definition_period = YEAR defined_for = StateCode.IA - reference = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28" + reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31" def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ia.dhs.fip diff --git a/sources/working_references.md b/sources/working_references.md index 88b620c52c6..ea7a39cd820 100644 --- a/sources/working_references.md +++ b/sources/working_references.md @@ -8,7 +8,7 @@ **Abbreviation**: FIP **Source**: Iowa Code Section 239B -**Variable Prefix**: `ia_tanf` +**Variable Prefix**: `ia_fip` **Parameter Path**: `gov.states.ia.dhs.tanf` --- @@ -367,15 +367,15 @@ documentation = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r- - `gov/states/ia/hhs/tanf/eligibility/resource_limit_recipient.yaml` - $5,000 2. **Variable Files Needed**: - - `ia_tanf.py` - Main benefit calculation - - `ia_tanf_eligible.py` - Overall eligibility - - `ia_tanf_gross_income_eligible.py` - Test 1 - - `ia_tanf_net_income_eligible.py` - Test 2 (applicants) - - `ia_tanf_payment_standard_eligible.py` - Test 3 - - `ia_tanf_countable_earned_income.py` - Earned income after deductions - - `ia_tanf_countable_unearned_income.py` - Unearned income - - `ia_tanf_payment_standard.py` - Payment standard by family size - - `ia_tanf_standard_of_need.py` - Standard of need by family size + - `ia_fip.py` - Main benefit calculation + - `ia_fip_eligible.py` - Overall eligibility + - `ia_fip_gross_income_eligible.py` - Test 1 + - `ia_fip_net_income_eligible.py` - Test 2 (applicants) + - `ia_fip_payment_standard_eligible.py` - Test 3 + - `ia_fip_countable_earned_income.py` - Earned income after deductions + - `ia_fip_countable_unearned_income.py` - Unearned income + - `ia_fip_payment_standard.py` - Payment standard by family size + - `ia_fip_standard_of_need.py` - Standard of need by family size 3. **Entity**: SPMUnit (consistent with other state TANF implementations) From 6374c4bf1d02cc33b4d6fa63a741d2fc06cda0c5 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 26 Jan 2026 05:49:33 +0000 Subject: [PATCH 19/29] Changes --- .../hhs/tanf/cash/income/sources/earned.yaml | 4 +- .../fip/income/earned_income_deduction.yaml | 2 +- .../income/gross_income_limit_percent.yaml | 2 +- .../ia/dhs/fip/income/sources/earned.yaml | 2 +- .../ia/dhs/fip/income/sources/unearned.yaml | 2 +- .../fip/income/work_incentive_disregard.yaml | 2 +- .../gov/states/ia/dhs/fip/max_unit_size.yaml | 2 +- .../ia/dhs/fip/need_standard/additional.yaml | 2 +- .../states/ia/dhs/fip/need_standard/main.yaml | 22 +- .../dhs/fip/payment_standard/additional.yaml | 2 +- .../ia/dhs/fip/payment_standard/main.yaml | 22 +- .../applicant_limit.yaml} | 2 +- .../recipient_limit.yaml} | 2 +- .../gov/states/ia/dhs/fip/ia_fip.yaml | 22 +- .../states/ia/dhs/fip/ia_fip_eligible.yaml | 4 +- .../dhs/fip/ia_fip_gross_earned_income.yaml | 135 ------------ .../dhs/fip/ia_fip_gross_unearned_income.yaml | 192 ------------------ .../ia/dhs/fip/ia_fip_income_eligible.yaml | 114 ++++++++++- .../ia/dhs/fip/ia_fip_payment_standard.yaml | 14 +- .../ia/dhs/fip/ia_fip_standard_of_need.yaml | 14 +- .../variables/gov/states/ia/dhs/fip/ia_fip.py | 2 +- .../gov/states/ia/dhs/fip/ia_fip_eligible.py | 12 +- .../ia/dhs/fip/ia_fip_income_eligible.py | 47 ++++- .../ia/dhs/fip/ia_fip_payment_standard.py | 5 +- .../ia/dhs/fip/ia_fip_resource_eligible.py | 21 ++ .../ia/dhs/fip/ia_fip_standard_of_need.py | 5 +- .../income/ia_fip_countable_earned_income.py | 19 ++ .../dhs/fip/income/ia_fip_countable_income.py | 16 +- .../fip/income/ia_fip_gross_earned_income.py | 15 -- .../ia/dhs/fip/income/ia_fip_gross_income.py | 6 +- .../income/ia_fip_gross_unearned_income.py | 15 -- 31 files changed, 258 insertions(+), 468 deletions(-) rename policyengine_us/parameters/gov/states/ia/dhs/fip/{eligibility/resource_limit_applicant.yaml => resources/applicant_limit.yaml} (96%) rename policyengine_us/parameters/gov/states/ia/dhs/fip/{eligibility/resource_limit_recipient.yaml => resources/recipient_limit.yaml} (96%) delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_earned_income.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_unearned_income.yaml create mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_countable_earned_income.py delete mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_earned_income.py delete mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_unearned_income.py diff --git a/policyengine_us/parameters/gov/hhs/tanf/cash/income/sources/earned.yaml b/policyengine_us/parameters/gov/hhs/tanf/cash/income/sources/earned.yaml index bf90b78cae1..3d744c9fcdf 100644 --- a/policyengine_us/parameters/gov/hhs/tanf/cash/income/sources/earned.yaml +++ b/policyengine_us/parameters/gov/hhs/tanf/cash/income/sources/earned.yaml @@ -1,8 +1,8 @@ description: The Department of Health and Human Services counts these income sources as earned income under the Temporary Assistance for Needy Families program. values: 2020-01-01: - - employment_income_before_lsr - - self_employment_income_before_lsr + - employment_income + - self_employment_income metadata: unit: list period: year diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml index 28182c46bd5..012fa847e2b 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml @@ -1,7 +1,7 @@ description: Iowa deducts this percentage of the gross nonexempt earned income under the Family Investment Program. values: - 2025-07-01: 0.2 + 2017-10-27: 0.2 metadata: unit: /1 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml index 0254cce1cc5..3a089162803 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml @@ -1,7 +1,7 @@ description: Iowa sets the gross income limit for the first income eligibility test as this percentage of the standard of need under the Family Investment Program. values: - 2025-07-01: 1.85 + 2017-10-27: 1.85 metadata: unit: /1 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/earned.yaml index 8f31d7dd67a..a969bb42aa6 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/earned.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/earned.yaml @@ -1,7 +1,7 @@ description: Iowa counts these income sources as earned income under the Family Investment Program. values: - 2025-07-01: + 2017-10-27: - employment_income - self_employment_income diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml index 2d757e1acfd..74011f9b10c 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml @@ -1,7 +1,7 @@ description: Iowa counts these income sources as unearned income under the Family Investment Program. values: - 2025-07-01: + 2017-10-27: - social_security - ssi - unemployment_compensation diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml index 463553de3ea..6b13ec67949 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml @@ -1,7 +1,7 @@ description: Iowa deducts this rate of work incentive disregard after the earned income deduction under the Family Investment Program. values: - 2025-07-01: 0.58 + 2017-10-27: 0.58 metadata: unit: /1 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml index 1d100c135ed..8c9efecf2e3 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml @@ -1,7 +1,7 @@ description: Iowa sets this maximum unit size for determining standard of need and payment standards under the Family Investment Program. values: - 2025-07-01: 10 + 2017-10-27: 10 metadata: unit: person diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml index 296ee46f792..26f0ad62a7e 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml @@ -9,4 +9,4 @@ metadata: href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 values: - 2025-07-01: 173 + 2017-10-27: 173 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml index 8551d6d0faa..5d8d91e6749 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml @@ -1,31 +1,33 @@ description: Iowa sets these values as the standard of need amount, or the schedule of living costs, by family size under the Family Investment Program. 1: - 2025-07-01: 365 + 2017-10-27: 365 2: - 2025-07-01: 719 + 2017-10-27: 719 3: - 2025-07-01: 849 + 2017-10-27: 849 4: - 2025-07-01: 986 + 2017-10-27: 986 5: - 2025-07-01: 1_092 + 2017-10-27: 1_092 6: - 2025-07-01: 1_216 + 2017-10-27: 1_216 7: - 2025-07-01: 1_335 + 2017-10-27: 1_335 8: - 2025-07-01: 1_457 + 2017-10-27: 1_457 9: - 2025-07-01: 1_576 + 2017-10-27: 1_576 10: - 2025-07-01: 1_724 + 2017-10-27: 1_724 metadata: unit: currency-USD period: month breakdown: - range(1, 11) + breakdown_labels: + - Assistance unit size label: Iowa FIP standard of need reference: - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml index bbca440b00b..d6aac55876d 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml @@ -1,7 +1,7 @@ description: Iowa sets this value as the additional payment standard amount per person for families larger than the max unit size under the Family Investment Program. values: - 2025-07-01: 87 + 2017-10-27: 87 metadata: unit: currency-USD diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml index f18815ace3a..bdd76111348 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml @@ -1,31 +1,33 @@ description: Iowa sets these values as the payment standard, or the schedule of basic needs, by family size under the Family Investment Program. 1: - 2025-07-01: 183 + 2017-10-27: 183 2: - 2025-07-01: 361 + 2017-10-27: 361 3: - 2025-07-01: 426 + 2017-10-27: 426 4: - 2025-07-01: 495 + 2017-10-27: 495 5: - 2025-07-01: 548 + 2017-10-27: 548 6: - 2025-07-01: 610 + 2017-10-27: 610 7: - 2025-07-01: 670 + 2017-10-27: 670 8: - 2025-07-01: 731 + 2017-10-27: 731 9: - 2025-07-01: 791 + 2017-10-27: 791 10: - 2025-07-01: 865 + 2017-10-27: 865 metadata: unit: currency-USD period: month breakdown: - range(1, 11) + breakdown_labels: + - Assistance unit size label: Iowa FIP payment standard reference: - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_applicant.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml similarity index 96% rename from policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_applicant.yaml rename to policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml index 5aaa8ea3dd5..4645aecbb95 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_applicant.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml @@ -1,7 +1,7 @@ description: Iowa limits resources to this amount under the Family Investment Program (FIP) for applicant families. values: - 2025-07-01: 2_000 + 2017-10-27: 2_000 metadata: unit: currency-USD diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_recipient.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml similarity index 96% rename from policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_recipient.yaml rename to policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml index e182f48b2d1..918200102ca 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/eligibility/resource_limit_recipient.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml @@ -1,7 +1,7 @@ description: Iowa limits resources to this amount under the Family Investment Program for recipient families (received FIP in prior month). values: - 2025-07-01: 5_000 + 2017-10-27: 5_000 metadata: unit: currency-USD diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip.yaml index cb52d1a3319..610a87c01bb 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip.yaml @@ -47,7 +47,7 @@ # - Payment standard for 3: $426/month * 12 = $5,112/year # - Benefit: $5,112 - $3,225.60 = $1,886.40/year period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: parent: @@ -75,7 +75,6 @@ output: ia_fip_standard_of_need: 10_188 ia_fip_payment_standard: 5_112 - ia_fip_gross_earned_income: 9_600 ia_fip_gross_income: 9_600 ia_fip_countable_income: 3_225.60 ia_fip_income_eligible: true @@ -88,7 +87,7 @@ # Gross income limit: $8,628 * 1.85 = $15,961.80/year # Gross income: $24,000/year > $15,961.80 - FAIL Test 1 period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: parent: @@ -122,7 +121,7 @@ # Countable income: $0 # Benefit: $4,332 - $0 = $4,332/year period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: parent: @@ -146,8 +145,6 @@ output: ia_fip_standard_of_need: 8_628 ia_fip_payment_standard: 4_332 - ia_fip_gross_earned_income: 0 - ia_fip_gross_unearned_income: 0 ia_fip_gross_income: 0 ia_fip_countable_income: 0 ia_fip_income_eligible: true @@ -165,7 +162,7 @@ # Countable income: $4,800 (no earned income deductions apply) # Countable income $4,800 > payment standard $4,332 - FAIL Test 3 period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: parent: @@ -190,8 +187,6 @@ output: ia_fip_standard_of_need: 8_628 ia_fip_payment_standard: 4_332 - ia_fip_gross_earned_income: 0 - ia_fip_gross_unearned_income: 4_800 ia_fip_gross_income: 4_800 ia_fip_countable_income: 4_800 ia_fip_income_eligible: false @@ -214,7 +209,7 @@ # Countable income: $2,016 + $2,400 = $4,416 < $5,112 - PASS Test 3 # Benefit: $5,112 - $4,416 = $696/year period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: parent: @@ -243,8 +238,6 @@ output: ia_fip_standard_of_need: 10_188 ia_fip_payment_standard: 5_112 - ia_fip_gross_earned_income: 6_000 - ia_fip_gross_unearned_income: 2_400 ia_fip_gross_income: 8_400 ia_fip_countable_income: 4_416 ia_fip_income_eligible: true @@ -264,7 +257,7 @@ # Countable income: $5,760 - $3,340.80 = $2,419.20 < $4,332 - PASS Test 3 # Benefit: $4,332 - $2,419.20 = $1,912.80/year period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: parent: @@ -288,7 +281,6 @@ output: ia_fip_standard_of_need: 8_628 ia_fip_payment_standard: 4_332 - ia_fip_gross_earned_income: 7_200 ia_fip_countable_income: 2_419.20 ia_fip_income_eligible: true ia_fip_eligible: true @@ -300,7 +292,7 @@ # Additional per person: varies, let's check the additional parameter # Payment standard for 10: $865/month period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: parent1: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_eligible.yaml index 04847397179..c55f58ae8f7 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_eligible.yaml @@ -52,7 +52,7 @@ - name: Case 3, ineligible due to high income. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -180,7 +180,7 @@ - name: Case 8, eligible family with moderate income. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_earned_income.yaml deleted file mode 100644 index d7b060e4f3d..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_earned_income.yaml +++ /dev/null @@ -1,135 +0,0 @@ -# Unit tests for Iowa FIP gross earned income -# Earned income includes: employment_income, self_employment_income -# Reference: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf - -- name: Case 1, zero earned income. - period: 2025 - input: - people: - person1: - age: 30 - employment_income: 0 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - ia_fip_gross_earned_income: 0 - -- name: Case 2, employment income only. - period: 2025 - input: - people: - person1: - age: 30 - employment_income: 9_600 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - ia_fip_gross_earned_income: 9_600 - -- name: Case 3, self employment income only. - period: 2025 - input: - people: - person1: - age: 30 - employment_income: 0 - self_employment_income: 12_000 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - ia_fip_gross_earned_income: 12_000 - -- name: Case 4, mixed employment and self employment. - period: 2025 - input: - people: - person1: - age: 30 - employment_income: 6_000 - self_employment_income: 4_000 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - # $6,000 + $4,000 = $10,000 - ia_fip_gross_earned_income: 10_000 - -- name: Case 5, multiple earners in household. - period: 2025 - input: - people: - person1: - age: 35 - employment_income: 10_000 - self_employment_income: 2_000 - person2: - age: 33 - employment_income: 3_000 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: IA - output: - # Person1: $10,000 + $2,000 = $12,000 - # Person2: $3,000 - # Total: $12,000 + $3,000 = $15,000 - ia_fip_gross_earned_income: 15_000 - -- name: Case 6, unearned income does not count. - period: 2025 - input: - people: - person1: - age: 30 - employment_income: 5_000 - social_security: 3_000 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - # Social security is unearned, only employment counts - ia_fip_gross_earned_income: 5_000 - -- name: Case 7, non-Iowa state gets zero. - period: 2025 - input: - people: - person1: - age: 30 - employment_income: 9_600 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IL - output: - # defined_for StateCode.IA, other states return 0 - ia_fip_gross_earned_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_unearned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_unearned_income.yaml deleted file mode 100644 index b36f743e2c5..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_unearned_income.yaml +++ /dev/null @@ -1,192 +0,0 @@ -# Unit tests for Iowa FIP gross unearned income -# Unearned income includes: social_security, ssi, unemployment_compensation, -# alimony_income, child_support_received -# Reference: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf - -- name: Case 1, zero unearned income. - period: 2025 - input: - people: - person1: - age: 30 - employment_income: 0 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - ia_fip_gross_unearned_income: 0 - -- name: Case 2, social security income only. - period: 2025 - input: - people: - person1: - age: 65 - employment_income: 0 - social_security: 12_000 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - ia_fip_gross_unearned_income: 12_000 - -- name: Case 3, SSI income only. - period: 2025 - input: - people: - person1: - age: 30 - employment_income: 0 - ssi: 9_600 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - ia_fip_gross_unearned_income: 9_600 - -- name: Case 4, unemployment compensation. - period: 2025 - input: - people: - person1: - age: 40 - employment_income: 0 - unemployment_compensation: 6_000 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - ia_fip_gross_unearned_income: 6_000 - -- name: Case 5, child support received. - period: 2025 - input: - people: - person1: - age: 30 - employment_income: 0 - child_support_received: 4_800 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - ia_fip_gross_unearned_income: 4_800 - -- name: Case 6, alimony income. - period: 2025 - input: - people: - person1: - age: 35 - employment_income: 0 - alimony_income: 6_000 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - ia_fip_gross_unearned_income: 6_000 - -- name: Case 7, multiple unearned income sources. - period: 2025 - input: - people: - person1: - age: 30 - employment_income: 0 - social_security: 3_600 - child_support_received: 2_400 - alimony_income: 1_200 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - # $3,600 + $2,400 + $1,200 = $7,200 - ia_fip_gross_unearned_income: 7_200 - -- name: Case 8, earned income does not count. - period: 2025 - input: - people: - person1: - age: 30 - employment_income: 10_000 - social_security: 2_400 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - # Employment income is earned, only unearned counts - ia_fip_gross_unearned_income: 2_400 - -- name: Case 9, multiple people with unearned income. - period: 2025 - input: - people: - person1: - age: 40 - employment_income: 0 - social_security: 8_000 - person2: - age: 16 - child_support_received: 2_400 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: IA - output: - # $8,000 + $2,400 = $10,400 - ia_fip_gross_unearned_income: 10_400 - -- name: Case 10, non-Iowa state gets zero. - period: 2025 - input: - people: - person1: - age: 30 - employment_income: 0 - social_security: 4_800 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IL - output: - # defined_for StateCode.IA, other states return 0 - ia_fip_gross_unearned_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_income_eligible.yaml index b17823df8b9..937989b8fa6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_income_eligible.yaml @@ -31,7 +31,7 @@ - name: Case 2, low earned income eligible. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -61,7 +61,7 @@ - name: Case 3, income exceeds gross income limit (Test 1 fails). period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -89,7 +89,7 @@ - name: Case 4, unearned income exceeds payment standard (Test 3 fails). period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -120,7 +120,7 @@ - name: Case 5, larger family with mixed income eligible. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -156,7 +156,7 @@ - name: Case 6, high mixed income fails Test 3. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -214,7 +214,7 @@ - name: Case 8, family of 4 at income threshold. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -247,3 +247,105 @@ # Test 2: $12,000 - ($12,000 * 0.20) = $9,600 < $11,832 - PASS # Test 3: $9,600 - ($9,600 * 0.58) = $4,032 < $5,940 - PASS ia_fip_income_eligible: true + +# Continuing eligibility tests per IAC 441-41.27(239B) +# Initial eligibility uses 3 tests; continuing eligibility uses only 2 +# (skips the net income < standard of need test) + +- name: Case 9, initial applicant fails net income test (not enrolled). + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income: 15_600 + is_tax_unit_head: true + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + is_tanf_enrolled: false + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # Family of 3, $15,600/year earned income ($1,300/month) + # Standard of need: $10,188/year + # Payment standard: $5,112/year + # Test 1: $15,600 <= $10,188 * 1.85 = $18,847.80 - PASS + # Test 2: $15,600 - ($15,600 * 0.20) = $12,480 >= $10,188 - FAIL + # Test 3: $15,600 * 0.80 * 0.42 = $5,241.60 >= $5,112 - FAIL + # Initial eligibility requires all 3 tests - FAIL + ia_fip_income_eligible: false + +- name: Case 10, continuing recipient passes with same income (enrolled). + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income: 13_200 + is_tax_unit_head: true + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + is_tanf_enrolled: true + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # Family of 3, $13,200/year earned income ($1,100/month) + # Standard of need: $10,188/year + # Payment standard: $5,112/year + # Test 1: $13,200 <= $18,847.80 - PASS + # Test 2: $13,200 * 0.80 = $10,560 >= $10,188 - FAIL (but skipped for continuing) + # Test 3: $13,200 * 0.80 * 0.42 = $4,435.20 < $5,112 - PASS + # Continuing eligibility only requires tests 1 and 3 - PASS + ia_fip_income_eligible: true + +- name: Case 11, same income ineligible as initial applicant. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income: 13_200 + is_tax_unit_head: true + person2: + age: 5 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + is_tanf_enrolled: false + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: IA + output: + # Same income as Case 10, but as initial applicant + # Test 2: $10,560 >= $10,188 - FAIL + # Initial eligibility requires all 3 tests - FAIL + ia_fip_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_payment_standard.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_payment_standard.yaml index 2ce249c8ad5..733b22b3a78 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_payment_standard.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_payment_standard.yaml @@ -4,7 +4,7 @@ - name: Case 1, family of 1. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -22,7 +22,7 @@ - name: Case 2, family of 2. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -42,7 +42,7 @@ - name: Case 3, family of 3. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -64,7 +64,7 @@ - name: Case 4, family of 4. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -88,7 +88,7 @@ - name: Case 5, family of 5. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -114,7 +114,7 @@ - name: Case 6, family of 6. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -142,7 +142,7 @@ - name: Case 7, family of 10 (max size in table). period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_standard_of_need.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_standard_of_need.yaml index ab6042659f7..1f4ae9c277b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_standard_of_need.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_standard_of_need.yaml @@ -5,7 +5,7 @@ - name: Case 1, family of 1. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -23,7 +23,7 @@ - name: Case 2, family of 2. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -43,7 +43,7 @@ - name: Case 3, family of 3. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -65,7 +65,7 @@ - name: Case 4, family of 4. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -89,7 +89,7 @@ - name: Case 5, family of 5. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -115,7 +115,7 @@ - name: Case 6, family of 6. period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: @@ -143,7 +143,7 @@ - name: Case 7, family of 10 (max size in table). period: 2025 - absolute_error_margin: 1 + absolute_error_margin: 0.1 input: people: person1: diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip.py index 4ede36a66b5..79fb334cbf5 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip.py @@ -6,7 +6,7 @@ class ia_fip(Variable): entity = SPMUnit label = "Iowa Family Investment Program (FIP)" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = "ia_fip_eligible" reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=20" diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py index f71c1fceb44..5d7e12bff3b 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py @@ -5,14 +5,13 @@ class ia_fip_eligible(Variable): value_type = bool entity = SPMUnit label = "Iowa FIP eligible" - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.IA reference = ( "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf" ) def formula(spm_unit, period, parameters): - p = parameters(period).gov.states.ia.dhs.fip.eligibility # Must have at least one eligible child (uses federal demographic rules) has_children = spm_unit("is_demographic_tanf_eligible", period) # Must meet immigration status eligibility (citizen or qualified alien) @@ -20,14 +19,7 @@ def formula(spm_unit, period, parameters): immigration_eligible = ( add(spm_unit, period, ["is_citizen_or_legal_immigrant"]) > 0 ) - current_recipient = spm_unit("is_tanf_enrolled", period) - limit = where( - current_recipient, - p.resource_limit_recipient, - p.resource_limit_applicant, - ) - resources = spm_unit("spm_unit_assets", period.this_year) - resource_eligible = resources <= limit + resource_eligible = spm_unit("ia_fip_resource_eligible", period) income_eligible = spm_unit("ia_fip_income_eligible", period) return ( diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py index a166d071d63..3836cce4353 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py @@ -5,34 +5,63 @@ class ia_fip_income_eligible(Variable): value_type = bool entity = SPMUnit label = "Iowa FIP income eligible" - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.IA - reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=19" + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=19", + "https://www.law.cornell.edu/regulations/iowa/Iowa-Code-r-441-41.27", + ) def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ia.dhs.fip.income - # three step income test - # test 1: countable gross income below some percentage of standard of need + + # Iowa FIP has different income tests for initial vs continuing eligibility + # per IAC 441-41.27(239B): + # + # Initial eligibility (3-step process): + # 1. Gross income <= 185% of standard of need + # 2. Net income (after 20% earned income deduction) < standard of need + # 3. Countable income (after 58% work incentive disregard) < payment standard + # + # Continuing eligibility (2-step process): + # 1. Gross income <= 185% of standard of need + # 2. Countable income (after 58% work incentive disregard) < payment standard + # + # The work incentive disregard does NOT apply to the net income test (step 2) + # for initial eligibility. Continuing recipients skip step 2 entirely. + + is_enrolled = spm_unit("is_tanf_enrolled", period) + + # Test 1: Gross income <= 185% of standard of need (applies to both) gross_income = spm_unit("ia_fip_gross_income", period) standard_of_need = spm_unit("ia_fip_standard_of_need", period) gross_income_limit = standard_of_need * p.gross_income_limit_percent gross_income_eligible = gross_income <= gross_income_limit - # test 2: countable net income below standard of need - gross_earned_income = spm_unit("ia_fip_gross_earned_income", period) + # Test 2: Net income < standard of need (initial eligibility only) + # Uses 20% earned income deduction but NOT the 58% work incentive disregard + gross_earned_income = add( + spm_unit, period, ["tanf_gross_earned_income"] + ) earned_income_deduction = ( gross_earned_income * p.earned_income_deduction ) net_income = gross_income - earned_income_deduction net_income_eligible = net_income < standard_of_need - # test 3: countable net income below payment standard + # Test 3: Countable income < payment standard (applies to both) + # Uses both 20% deduction AND 58% work incentive disregard countable_income = spm_unit("ia_fip_countable_income", period) payment_standard = spm_unit("ia_fip_payment_standard", period) payment_standard_eligible = countable_income < payment_standard - return ( + # Apply appropriate tests based on enrollment status + return where( + is_enrolled, + # Continuing eligibility: tests 1 and 3 only + gross_income_eligible & payment_standard_eligible, + # Initial eligibility: all three tests gross_income_eligible & net_income_eligible - & payment_standard_eligible + & payment_standard_eligible, ) diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_payment_standard.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_payment_standard.py index 2b653b86e61..8058dbce972 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_payment_standard.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_payment_standard.py @@ -6,7 +6,7 @@ class ia_fip_payment_standard(Variable): entity = SPMUnit label = "Iowa FIP payment standard" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.IA reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31" @@ -18,5 +18,4 @@ def formula(spm_unit, period, parameters): base = p.payment_standard.main[capped_people] additional_amount = p.payment_standard.additional * additional_people - monthly = base + additional_amount - return monthly * MONTHS_IN_YEAR + return base + additional_amount diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py new file mode 100644 index 00000000000..88d413df7e9 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class ia_fip_resource_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Iowa FIP resource eligible" + definition_period = MONTH + defined_for = StateCode.IA + reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=16" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ia.dhs.fip.resources + current_recipient = spm_unit("is_tanf_enrolled", period) + limit = where( + current_recipient, + p.recipient_limit, + p.applicant_limit, + ) + resources = spm_unit("spm_unit_assets", period.this_year) + return resources <= limit diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py index c6f527df66c..ae1cb09e317 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py @@ -6,7 +6,7 @@ class ia_fip_standard_of_need(Variable): entity = SPMUnit label = "Iowa FIP standard of need" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.IA reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31" @@ -18,5 +18,4 @@ def formula(spm_unit, period, parameters): base = p.need_standard.main[capped_people] additional_amount = p.need_standard.additional * additional_people - monthly = base + additional_amount - return monthly * MONTHS_IN_YEAR + return base + additional_amount diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_countable_earned_income.py b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_countable_earned_income.py new file mode 100644 index 00000000000..a06366d69b1 --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_countable_earned_income.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class ia_fip_countable_earned_income(Variable): + value_type = float + entity = SPMUnit + label = "Iowa FIP countable earned income" + unit = USD + definition_period = MONTH + defined_for = StateCode.IA + reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=19" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ia.dhs.fip.income + gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) + earned_income_after_deduction = gross_earned * ( + 1 - p.earned_income_deduction + ) + return earned_income_after_deduction * (1 - p.work_incentive_disregard) diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_countable_income.py b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_countable_income.py index d8237e5eb24..9568b461cc4 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_countable_income.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_countable_income.py @@ -6,18 +6,8 @@ class ia_fip_countable_income(Variable): entity = SPMUnit label = "Iowa FIP countable income" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.IA - reference = ( - "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf" - ) + reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=19" - def formula(spm_unit, period, parameters): - gross_earned = spm_unit("ia_fip_gross_earned_income", period) - gross_unearned = spm_unit("ia_fip_gross_unearned_income", period) - p = parameters(period).gov.states.ia.dhs.fip.income - earned_income_deduction = gross_earned * p.earned_income_deduction - remaining_earned = gross_earned - earned_income_deduction - work_incentive = remaining_earned * p.work_incentive_disregard - countable_earned = remaining_earned - work_incentive - return countable_earned + gross_unearned + adds = ["ia_fip_countable_earned_income", "tanf_gross_unearned_income"] diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_earned_income.py b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_earned_income.py deleted file mode 100644 index 163eb0601d0..00000000000 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_earned_income.py +++ /dev/null @@ -1,15 +0,0 @@ -from policyengine_us.model_api import * - - -class ia_fip_gross_earned_income(Variable): - value_type = float - entity = SPMUnit - label = "Iowa FIP gross earned income" - unit = USD - definition_period = YEAR - defined_for = StateCode.IA - reference = ( - "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf" - ) - - adds = "gov.states.ia.dhs.fip.income.sources.earned" diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_income.py b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_income.py index 7433f71980b..6f80b5d61fb 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_income.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_income.py @@ -6,13 +6,13 @@ class ia_fip_gross_income(Variable): entity = SPMUnit label = "Iowa FIP gross income" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.IA reference = ( "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf" ) adds = [ - "ia_fip_gross_earned_income", - "ia_fip_gross_unearned_income", + "tanf_gross_earned_income", + "tanf_gross_unearned_income", ] diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_unearned_income.py b/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_unearned_income.py deleted file mode 100644 index ebde8c8d156..00000000000 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/income/ia_fip_gross_unearned_income.py +++ /dev/null @@ -1,15 +0,0 @@ -from policyengine_us.model_api import * - - -class ia_fip_gross_unearned_income(Variable): - value_type = float - entity = SPMUnit - label = "Iowa FIP gross unearned income" - unit = USD - definition_period = YEAR - defined_for = StateCode.IA - reference = ( - "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf" - ) - - adds = "gov.states.ia.dhs.fip.income.sources.unearned" From 50ace1252b4d260bb10d70f88fff7f7d873d83c1 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 26 Jan 2026 06:15:56 +0000 Subject: [PATCH 20/29] Integration test --- .../gov/states/ia/dhs/fip/integration.yaml | 299 ++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/integration.yaml diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/integration.yaml new file mode 100644 index 00000000000..14824558502 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/integration.yaml @@ -0,0 +1,299 @@ +# Integration tests for Iowa FIP (Family Investment Program) - full pipeline testing +# Tests realistic family scenarios with complete eligibility and benefit calculations +# Reference: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf +# +# Key Iowa FIP rules: +# - 20% earned income deduction +# - 58% work incentive disregard (applied after 20% deduction) +# - Gross income limit: 185% of standard of need +# - Net income test (applicants only): net income < standard of need +# - Payment standard test: countable income < payment standard +# - Payment standard ~ 50.18% of standard of need +# - Resource limits: $2,000 applicants, $5,000 recipients + +- name: Scenario 1, single parent with 2 children, no income - full benefit. + period: 2025-01 + absolute_error_margin: 1 + input: + people: + parent: + age: 30 + employment_income: 0 + child1: + age: 5 + child2: + age: 3 + spm_units: + spm_unit: + members: [parent, child1, child2] + tax_units: + tax_unit: + members: [parent, child1, child2] + households: + household: + members: [parent, child1, child2] + state_code: IA + output: + # Family of 3 + # Standard of need: $849, Payment standard: $426 + ia_fip_standard_of_need: 849 + ia_fip_payment_standard: 426 + # No income - all tests pass + ia_fip_gross_income: 0 + ia_fip_countable_income: 0 + ia_fip_income_eligible: true + ia_fip_eligible: true + # Benefit: $426 - $0 = $426 + ia_fip: 426 + +- name: Scenario 2, single parent with 1 child, $800/month earnings. + period: 2025-01 + absolute_error_margin: 1 + input: + people: + parent: + age: 28 + employment_income: 800 + child1: + age: 4 + spm_units: + spm_unit: + members: [parent, child1] + tax_units: + tax_unit: + members: [parent, child1] + households: + household: + members: [parent, child1] + state_code: IA + output: + # Family of 2 + # Standard of need: $719, Payment standard: $361 + ia_fip_standard_of_need: 719 + ia_fip_payment_standard: 361 + # Gross income: $800 + ia_fip_gross_income: 800 + # Test 1: $800 <= $719 * 1.85 = $1,330.15 -> pass + # Test 2: $800 - ($800 * 0.20) = $640 < $719 -> pass + # Test 3: 20% deduction: $800 * 0.20 = $160 + # Remaining: $640, 58% disregard: $640 * 0.58 = $371.20 + # Countable earned: $640 - $371.20 = $268.80 + ia_fip_countable_earned_income: 269 + ia_fip_countable_income: 269 + # $269 < $361 -> pass + ia_fip_income_eligible: true + ia_fip_eligible: true + # Benefit: $361 - $269 = $92 + ia_fip: 92 + +- name: Scenario 3, family of 4 with mixed income. + period: 2025-01 + absolute_error_margin: 1 + input: + people: + parent: + age: 35 + employment_income: 600 + social_security: 200 + child1: + age: 10 + child2: + age: 7 + child3: + age: 3 + spm_units: + spm_unit: + members: [parent, child1, child2, child3] + tax_units: + tax_unit: + members: [parent, child1, child2, child3] + households: + household: + members: [parent, child1, child2, child3] + state_code: IA + output: + # Family of 4 + # Standard of need: $986, Payment standard: $495 + ia_fip_standard_of_need: 986 + ia_fip_payment_standard: 495 + # Gross income: $600 + $200 = $800 + ia_fip_gross_income: 800 + # Test 1: $800 <= $986 * 1.85 = $1,824.10 -> pass + # Test 2: $800 - ($600 * 0.20) = $800 - $120 = $680 < $986 -> pass + # Test 3: 20% deduction on earned: $600 * 0.20 = $120 + # Remaining earned: $480, 58% disregard: $480 * 0.58 = $278.40 + # Countable earned: $480 - $278.40 = $201.60 + # Countable income: $201.60 + $200 = $401.60 + ia_fip_countable_earned_income: 202 + ia_fip_countable_income: 402 + # $402 < $495 -> pass + ia_fip_income_eligible: true + ia_fip_eligible: true + # Benefit: $495 - $402 = $93 + ia_fip: 93 + +- name: Scenario 4, income exceeds payment standard - ineligible. + period: 2025-01 + absolute_error_margin: 1 + input: + people: + parent: + age: 32 + employment_income: 1_500 + child1: + age: 6 + spm_units: + spm_unit: + members: [parent, child1] + tax_units: + tax_unit: + members: [parent, child1] + households: + household: + members: [parent, child1] + state_code: IA + output: + # Family of 2 + # Standard of need: $719, Payment standard: $361 + ia_fip_standard_of_need: 719 + ia_fip_payment_standard: 361 + # Gross income: $1,500 + # Test 1: $1,500 > $719 * 1.85 = $1,330.15 -> FAIL + ia_fip_gross_income: 1_500 + ia_fip_income_eligible: false + ia_fip_eligible: false + ia_fip: 0 + +- name: Scenario 5, passes gross test but fails net income test (applicant). + period: 2025-01 + absolute_error_margin: 1 + input: + people: + parent: + age: 30 + employment_income: 100 + social_security: 600 + child1: + age: 8 + spm_units: + spm_unit: + members: [parent, child1] + tax_units: + tax_unit: + members: [parent, child1] + households: + household: + members: [parent, child1] + state_code: IA + output: + # Family of 2 + # Standard of need: $719, Payment standard: $361 + ia_fip_standard_of_need: 719 + ia_fip_payment_standard: 361 + # Gross income: $100 + $600 = $700 + ia_fip_gross_income: 700 + # Test 1: $700 <= $1,330.15 -> pass + # Test 2 (applicant): net = $700 - ($100 * 0.20) = $680 + # $680 < $719 -> pass + # Test 3: earned after deductions: $100 * 0.80 = $80 + # 58% disregard: $80 * 0.58 = $46.40 + # Countable earned: $80 - $46.40 = $33.60 + # Countable: $33.60 + $600 = $633.60 + ia_fip_countable_income: 634 + # $634 > $361 -> FAIL payment standard test + ia_fip_income_eligible: false + ia_fip_eligible: false + ia_fip: 0 + +- name: Scenario 6, single parent, no children - ineligible (no TANF demographics). + period: 2025-01 + input: + people: + person1: + age: 25 + employment_income: 0 + spm_units: + spm_unit: + members: [person1] + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_eligible: false + ia_fip: 0 + +- name: Scenario 7, non-Iowa state returns zero. + period: 2025-01 + input: + people: + parent: + age: 30 + employment_income: 0 + child1: + age: 5 + spm_units: + spm_unit: + members: [parent, child1] + tax_units: + tax_unit: + members: [parent, child1] + households: + household: + members: [parent, child1] + state_code: IL + output: + ia_fip_eligible: false + ia_fip: 0 + +- name: Scenario 8, large family of 6, low income - eligible. + period: 2025-01 + absolute_error_margin: 1 + input: + people: + parent1: + age: 35 + employment_income: 500 + parent2: + age: 33 + employment_income: 0 + child1: + age: 12 + child2: + age: 9 + child3: + age: 6 + child4: + age: 2 + spm_units: + spm_unit: + members: [parent1, parent2, child1, child2, child3, child4] + tax_units: + tax_unit: + members: [parent1, parent2, child1, child2, child3, child4] + households: + household: + members: [parent1, parent2, child1, child2, child3, child4] + state_code: IA + output: + # Family of 6 + # Standard of need: $1,216, Payment standard: $610 + ia_fip_standard_of_need: 1_216 + ia_fip_payment_standard: 610 + # Gross: $500 + ia_fip_gross_income: 500 + # Test 1: $500 <= $1,216 * 1.85 = $2,249.60 -> pass + # Test 2: $500 - ($500 * 0.20) = $400 < $1,216 -> pass + # Test 3: 20% deduction: $500 * 0.20 = $100 + # Remaining: $400, 58% disregard: $400 * 0.58 = $232 + # Countable earned: $400 - $232 = $168 + ia_fip_countable_earned_income: 168 + ia_fip_countable_income: 168 + # $168 < $610 -> pass + ia_fip_income_eligible: true + ia_fip_eligible: true + # Benefit: $610 - $168 = $442 + ia_fip: 442 From 56b185e7eff39eef9c627ee0ff90dac615799524 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 26 Jan 2026 06:33:47 +0000 Subject: [PATCH 21/29] Fix integration test --- .../gov/states/ia/dhs/fip/integration.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/integration.yaml index 14824558502..ea5150d4054 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/integration.yaml @@ -53,7 +53,7 @@ people: parent: age: 28 - employment_income: 800 + employment_income: 9_600 # $800/month * 12 child1: age: 4 spm_units: @@ -93,8 +93,8 @@ people: parent: age: 35 - employment_income: 600 - social_security: 200 + employment_income: 7_200 # $600/month * 12 + social_security: 2_400 # $200/month * 12 child1: age: 10 child2: @@ -139,7 +139,7 @@ people: parent: age: 32 - employment_income: 1_500 + employment_income: 18_000 # $1,500/month * 12 child1: age: 6 spm_units: @@ -171,8 +171,8 @@ people: parent: age: 30 - employment_income: 100 - social_security: 600 + employment_income: 1_200 # $100/month * 12 + social_security: 7_200 # $600/month * 12 child1: age: 8 spm_units: @@ -256,7 +256,7 @@ people: parent1: age: 35 - employment_income: 500 + employment_income: 6_000 # $500/month * 12 parent2: age: 33 employment_income: 0 From 5c1c3b66b16949e9e893a60e502b97351a8a804a Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 26 Jan 2026 09:49:07 -0800 Subject: [PATCH 22/29] Update earned income sources for TANF program --- .../parameters/gov/hhs/tanf/cash/income/sources/earned.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/policyengine_us/parameters/gov/hhs/tanf/cash/income/sources/earned.yaml b/policyengine_us/parameters/gov/hhs/tanf/cash/income/sources/earned.yaml index 3d744c9fcdf..bf90b78cae1 100644 --- a/policyengine_us/parameters/gov/hhs/tanf/cash/income/sources/earned.yaml +++ b/policyengine_us/parameters/gov/hhs/tanf/cash/income/sources/earned.yaml @@ -1,8 +1,8 @@ description: The Department of Health and Human Services counts these income sources as earned income under the Temporary Assistance for Needy Families program. values: 2020-01-01: - - employment_income - - self_employment_income + - employment_income_before_lsr + - self_employment_income_before_lsr metadata: unit: list period: year From df9495e6cc4307aa103fde97bf84ebb912823162 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 26 Jan 2026 18:29:31 +0000 Subject: [PATCH 23/29] Remove claude docs --- docs/agents/sources/ia_tanf/README.md | 56 --- .../sources/ia_tanf/benefit_calculation.md | 263 ------------ docs/agents/sources/ia_tanf/eligibility.md | 126 ------ docs/agents/sources/ia_tanf/sources.md | 199 --------- .../ia/dhs/fip/income/sources/earned.yaml | 14 - .../ia/dhs/fip/income/sources/unearned.yaml | 17 - .../gov/states/ia/dhs/fip/ia_fip.yaml | 54 +-- .../ia/dhs/fip/ia_fip_countable_income.yaml | 18 +- .../states/ia/dhs/fip/ia_fip_eligible.yaml | 16 +- .../ia/dhs/fip/ia_fip_gross_income.yaml | 14 +- .../ia/dhs/fip/ia_fip_income_eligible.yaml | 24 +- .../gov/states/ia/dhs/fip/integration.yaml | 18 +- policyengine_us/tools/variables.py | 6 +- .../ia/dhs/fip/ia_fip_resource_eligible.py | 2 +- sources/working_references.md | 389 ------------------ 15 files changed, 75 insertions(+), 1141 deletions(-) delete mode 100644 docs/agents/sources/ia_tanf/README.md delete mode 100644 docs/agents/sources/ia_tanf/benefit_calculation.md delete mode 100644 docs/agents/sources/ia_tanf/eligibility.md delete mode 100644 docs/agents/sources/ia_tanf/sources.md delete mode 100644 policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/earned.yaml delete mode 100644 policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml delete mode 100644 sources/working_references.md diff --git a/docs/agents/sources/ia_tanf/README.md b/docs/agents/sources/ia_tanf/README.md deleted file mode 100644 index ab9a7a264a0..00000000000 --- a/docs/agents/sources/ia_tanf/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# Iowa TANF (FIP - Family Investment Program) Documentation - -This folder contains authoritative documentation for implementing Iowa's Family Investment Program (FIP), which is Iowa's implementation of the federal Temporary Assistance for Needy Families (TANF) program. - -## Contents - -- `eligibility.md` - Eligibility requirements including citizenship, residency, household composition, resource limits, time limits, and work requirements -- `benefit_calculation.md` - Income tests, deductions, payment standards, and benefit calculation formulas -- `sources.md` - Complete list of authoritative sources with URLs and citations - -## Quick Reference - -### Program Name -- **Official Name**: Family Investment Program (FIP) -- **Federal Program**: Temporary Assistance for Needy Families (TANF) - -### Legal Authority -- Iowa Code Chapter 239B -- Iowa Administrative Code 441, Chapters 41 and 93 - -### Key Parameters (Effective 7/1/2025) - -| Parameter | Value | -|-----------|-------| -| Gross Income Limit | 185% of Standard of Need | -| Earned Income Deduction | 20% | -| Work Incentive Disregard | 58% | -| Resource Limit (Applicant) | $2,000 | -| Resource Limit (Recipient) | $5,000 | -| Time Limit | 60 months lifetime | - -### Payment Standards (Family of 3) - -| Standard | Amount | -|----------|--------| -| Standard of Need | $849/month | -| 185% Gross Limit | $1,570.65/month | -| Payment Standard | $426/month | - -## Implementation Checklist - -- [ ] Create parameter files for income standards -- [ ] Create parameter files for payment standards -- [ ] Implement gross income eligibility test -- [ ] Implement net income eligibility test (applicants) -- [ ] Implement payment standard test -- [ ] Implement 20% earned income deduction -- [ ] Implement 58% work incentive disregard -- [ ] Implement benefit calculation -- [ ] Create unit tests for each component -- [ ] Create integration tests - -## Related Documentation - -- See `working_references.md` in the repository root for a consolidated implementation summary -- See existing state TANF implementations (CO, CA, NY, NC) for code patterns diff --git a/docs/agents/sources/ia_tanf/benefit_calculation.md b/docs/agents/sources/ia_tanf/benefit_calculation.md deleted file mode 100644 index 8d4ecb71e4d..00000000000 --- a/docs/agents/sources/ia_tanf/benefit_calculation.md +++ /dev/null @@ -1,263 +0,0 @@ -# Iowa FIP (Family Investment Program) Benefit Calculation - -## Legal Authority - -- **Iowa Administrative Code 441-41.27(239B)**: Income -- **Iowa Administrative Code 441-41.28(239B)**: Need Standards - -## Income Eligibility Tests - -Iowa FIP uses a three-test system for initial eligibility and a two-test system for continuing eligibility. - -### Initial Eligibility (Three-Step Process) - -1. **Test 1: 185% Gross Income Test** - - Countable gross nonexempt unearned and earned income must be at or below 185% of the Standard of Need for the eligible group size - -2. **Test 2: Standard of Need Test (Net Income)** - - Applied only to applicant families and reapplicants - - Calculation: Gross nonexempt income minus 20% earned income deduction and diversions - - If income >= Standard of Need: application denied - - If income < Standard of Need: eligible for 50% work incentive deduction (58% per current rules) - - Standards found in Schedule of Living Costs (Desk Aid RC-0033) - -3. **Test 3: Payment Standard Test** - - Applied if Tests 1 and 2 are passed - - Calculation: Net income from Test 2 plus work incentive deduction - - If income >= Payment Standard: no eligibility - - If income < Payment Standard: FIP grant = Payment Standard - countable net income - -Reference: Iowa Administrative Code 441-41.27(239B) - -### Continuing Eligibility (Two-Step Process) - -1. Gross nonexempt income cannot exceed 185% of Standard of Need -2. Countable net income must be below Payment Standard - -## Income Deductions and Disregards - -### 20% Earned Income Deduction - -Each person in the assistance unit whose gross nonexempt earned income is considered is entitled to a **20% earned income deduction** of nonexempt monthly gross earnings. - -This deduction covers work-related expenses including: -- Taxes -- Transportation -- Meals -- Uniforms -- Other work-related expenses - -Reference: Iowa Administrative Code 441-41.27(239B) - -### Work Incentive Disregard (58%) - -After deducting the 20% earned income deduction and income diversions, the department disregards **58%** of the total remaining monthly nonexempt earned income. - -This applies to: -- Earnings as an employee -- Net profit from self-employment - -**Note:** The work incentive disregard is NOT time-limited, but does not apply during initial eligibility determination (Test 2). - -Reference: Iowa Administrative Code 441-41.27(239B); Cornell Law Iowa Admin Code r. 441-41.27 - -## Income Standards Tables (Effective 7/1/2025) - -### Schedule of Living Costs (100% Standard of Need) - -| Family Size | Monthly Amount | -|-------------|----------------| -| 1 | $365 | -| 2 | $719 | -| 3 | $849 | -| 4 | $986 | -| 5 | $1,092 | -| 6 | $1,216 | -| 7 | $1,335 | -| 8 | $1,457 | -| 9 | $1,576 | -| 10 | $1,724 | -| Each additional | +$173 | - -Reference: Iowa Administrative Code 441-41.28(239B) - -### 185% of Standard of Need (Gross Income Limit) - -| Family Size | Monthly Amount | -|-------------|----------------| -| 1 | $675.25 | -| 2 | $1,330.15 | -| 3 | $1,570.65 | -| 4 | $1,824.10 | -| 5 | $2,020.20 | -| 6 | $2,249.60 | -| 7 | $2,469.75 | -| 8 | $2,695.45 | -| 9 | $2,915.60 | -| 10 | $3,189.40 | -| Each additional | +$320.05 | - -Reference: Iowa Administrative Code 441-41.28(239B) - -### Schedule of Basic Needs (Payment Standard) - -The Payment Standard equals approximately **50.18%** of the Schedule of Living Costs. - -| Family Size | Monthly Amount | -|-------------|----------------| -| 1 | $183 | -| 2 | $361 | -| 3 | $426 | -| 4 | $495 | -| 5 | $548 | -| 6 | $610 | -| 7 | $670 | -| 8 | $731 | -| 9 | $791 | -| 10 | $865 | -| Each additional | +$87 | - -Reference: Iowa Administrative Code 441-41.28(239B) - -## Benefit Calculation Formula - -### For Eligible Families - -``` -FIP Benefit = Payment Standard - Countable Net Income -``` - -Where Countable Net Income is calculated as: - -**For Initial Applicants (Test 3):** -``` -Countable Net Income = Gross Income - 20% Earned Income Deduction - Diversions - 58% Work Incentive -``` - -**For Recipients:** -``` -Countable Net Income = Gross Income - 20% Earned Income Deduction - Diversions - 58% Work Incentive -``` - -## Special Needs Allowances - -- **Guardian/conservator fee**: An amount not to exceed $10 per case per month may be allowed - -Reference: Iowa Administrative Code 441-41.28(239B) - -## Exempt Income (Complete List) - -The following income is exempt from FIP income calculations: - -### Government Benefits -- SNAP (Food Stamp) benefits -- SSI recipient income (when SSI recipient is not in eligible group) -- Earned Income Tax Credit (EITC) - federal and state -- Low-Income Home Energy Assistance (LIHEAP) -- WIC program benefits -- Foster care/kinship caregiver payments -- Rent supplements from governmental agencies -- Disaster and emergency assistance -- Indian tribal judgment funds -- Retroactive SSI benefits and payments -- General assistance from county funds (non-basic need or emergency) - -### Employment and Training -- PROMISE JOBS payments -- Training allowances (Department of the Blind, JTPA, Vocational Rehabilitation) -- Food Stamp Employment and Training allowances -- Car pool payments -- Job-related reimbursements -- VISTA volunteer payments -- Incentive allowances from Work Force Investment Project -- AmeriCorps educational awards - -### Education -- Educational/training assistance and financial aid -- Earnings of students age 19 or younger in full-time school (high school or equivalent) - -### Child Support -- Up to $50 of current monthly support paid by legally responsible person - -### Other Exempt Income -- Food from home production -- Food coupons value and USDA commodities value -- Income in-kind -- Gifts of $30 or less per person per calendar quarter -- Loans and bona fide loans -- Income tax refunds -- Vendor payments -- Interest or dividend payments -- Third-party reimbursements -- Medical expense settlements -- Individual Development Account (IDA) deposits -- Refunds from rent or utility deposits -- Terminated income of retrospectively budgeted households (when requirements met) -- Veterans benefits under Aid and Attendance program -- Census worker earnings -- Family Support Subsidy payments - -Reference: Iowa Administrative Code 441-41.27(239B) - -## Self-Employment Income Rules - -- **Net Profit Calculation**: Either 40% of gross income deducted OR actual documented expenses -- **Irregular Self-Employment**: Averaged over 12-month period -- **Work Hours Calculation for Self-Employed**: Actual gross income less business expenses divided by federal minimum wage - -Reference: Iowa Administrative Code 441-41.27(239B) - -## Lump Sum Income Treatment - -- Nonrecurring lump sum amounts create ineligibility period -- Ineligibility period calculated by dividing lump sum by standard of need -- Period can be reduced if: - - Living costs increase - - Funds spent on medical services - - Funds spent on home repairs - - Funds spent on funeral expenses - -Reference: Iowa Administrative Code 441-41.27(239B) - -## Income Attribution and Budgeting - -### Prospective Budgeting -Iowa FIP uses prospective budgeting - "a projection of income based on the best estimate of future income." - -### Variable Income -For variable income: "all income received in the period being used and dividing the result by the number of instances" establishes the monthly projection. - -### Income Conversion Rules -- **Weekly Income**: Multiply by 4 regardless of actual payment frequency -- **Biweekly Income**: Multiply by 2 regardless of actual payment frequency - -### Self-Employment Income -Self-employment income not received regularly is "averaged over a 12-month period of time." - -Reference: Iowa Administrative Code 441-41.27(239B) - -## Example Calculation - -**Family of 3 with one employed parent earning $800/month gross:** - -1. **Test 1 (185% Gross Income Test):** - - Gross Income: $800 - - 185% Standard of Need for 3: $1,570.65 - - $800 < $1,570.65 - PASS - -2. **Test 2 (Standard of Need Test - Applicant Only):** - - Gross Income: $800 - - 20% Earned Income Deduction: $800 x 0.20 = $160 - - Net Income: $800 - $160 = $640 - - Standard of Need for 3: $849 - - $640 < $849 - PASS (eligible for work incentive) - -3. **Test 3 (Payment Standard Test):** - - Net Income from Test 2: $640 - - 58% Work Incentive: $640 x 0.58 = $371.20 - - Countable Net Income: $640 - $371.20 = $268.80 - - Payment Standard for 3: $426 - - $268.80 < $426 - PASS - -4. **Benefit Calculation:** - - FIP Benefit = $426 - $268.80 = $157.20/month diff --git a/docs/agents/sources/ia_tanf/eligibility.md b/docs/agents/sources/ia_tanf/eligibility.md deleted file mode 100644 index 46a8a532841..00000000000 --- a/docs/agents/sources/ia_tanf/eligibility.md +++ /dev/null @@ -1,126 +0,0 @@ -# Iowa FIP (Family Investment Program) Eligibility Requirements - -## Legal Authority - -- **Iowa Code Chapter 239B**: Family Investment Program statute -- **Iowa Administrative Code 441, Chapter 41**: Granting Assistance (FIP eligibility rules) -- **Iowa Administrative Code 441, Chapter 93**: PROMISE JOBS Program - -## Basic Eligibility Requirements - -### Citizenship and Residency -- Must be a U.S. citizen or qualified alien under Chapter 8 USC Section 1641 -- Must be a resident of the state of Iowa - -Reference: Iowa Administrative Code 441-41.22, 441-41.23 - -### Child Requirements -- Must be responsible for a child under age 18 -- OR a child age 18 who is a full-time student in secondary school or vocational/technical training and expected to complete before age 19 -- A child is eligible for the entire month in which the 18th birthday occurs (unless birthday is on the first day of the month) - -Reference: Iowa Administrative Code 441-41.22 - -### Eligible Group Composition - -The eligible group consists of all eligible persons living together who meet non-financial eligibility criteria: - -**Must Be Included (when living together and meeting criteria):** -- The child -- Eligible siblings of the child (whole-blood, half-blood, or adoptive) -- Natural or adoptive parents of the child - -**Optional Members:** -- Nonparental relatives (at the relative's request, if income/resources within limits) -- Incapacitated stepparents - -**Exception:** -- The eligible group may consist of just the parent (or non-parental caretaker) when the only child in the home receives SSI - -Reference: Iowa Administrative Code 441-41.22; WorkWorld FIP Eligible Group - -### Temporary Absences - -Members temporarily absent from home may remain in the eligible group if: -- Away for education/training with expected return upon completion -- In medical institutions with expected return within 12 months -- Out for other reasons with expected return within 3 months - -## Resource/Asset Eligibility - -### Resource Limits - -| Status | Limit | -|--------|-------| -| Applicant families | $2,000 | -| Recipient families (member received FIP in prior month) | $5,000 | - -Reference: Iowa Administrative Code 441-41.26(239B) - -### Excluded Resources - -- Homestead property -- Non-homestead property actively marketed at fair market value or generating income -- Household goods and personal effects -- Life insurance with zero cash value -- Burial plots and funeral trusts (up to $1,500 per person) -- Tools and capital assets for self-employment (up to $10,000 equity) -- Individual Development Account (IDA) balances -- Educational/training assistance funds -- Inventory and supplies for self-employment -- SSI recipient resources -- Current monthly income -- Loans and inaccessible resources -- Child support payments (up to $50 monthly) -- Vehicle equity (see below) - -### Vehicle Exclusion - -Up to **$3,959** in equity value per vehicle for each adult and working teenage child in the family. This amount is adjusted annually for inflation as of July 1st. - -Reference: Iowa DHS Employees' Policy Manual, Title 4, Chapter D; Iowa Administrative Code 441-41.26(239B) - -## Time Limits - -### 60-Month Lifetime Limit -- A person can receive FIP benefits for up to 60 months (5 years) in their lifetime -- The 60-month limit applies to the individual, not the family -- Hardship exemptions available for 6-month extensions - -Reference: Iowa Code 239B.9; Iowa Legal Aid - -## Work Requirements (PROMISE JOBS) - -### Mandatory Referral -All persons in a FIP household shall be referred to the PROMISE JOBS program and shall enter into a Family Investment Agreement (FIA) as a condition of receiving FIP, unless exempt from referral. - -Reference: Iowa Administrative Code 441-41.24(239B) - -### Exemptions from PROMISE JOBS - -The following are exempt from PROMISE JOBS referral: -- Persons receiving SSI or SSDI due to their own disability -- Aliens whose immigration status is not listed under Chapter 8 USC Section 1641 -- Persons determined disabled and unable to participate -- Persons under age 16 who are not parents -- Persons age 16-19 who are not parents and attend school full-time -- Parent/relative of child under 6 months who personally provides care (one exemption per case) -- Person working 30+ hours/week in unsubsidized employment at initial determination - -**Note:** Parents age 19 and younger are NOT exempt unless disabled. They must attend parenting classes and participate in high school completion activities. - -Reference: Iowa Administrative Code 441-41.24; WorkWorld PROMISE JOBS - -### Participation Requirements -- Level of participation equivalent to full-time employment commitment -- Part-time employment is less than 30 hours per week -- FIA with part-time employment must include other PROMISE JOBS activities unless barriers exist -- Work experience subject to FLSA: maximum hours = monthly FIP grant / minimum wage - -### Limited Benefit Plan (LBP) -- If participants fail FIA terms, they enter a Limited Benefit Plan -- Benefits are reduced then terminated for a fixed period -- Future LBPs result in benefits stopping for at least 6 months -- After 6 months, must contact worker, sign new FIA, complete 20 hours of employment/similar activity - -Reference: Iowa Code 239B.9; Iowa Administrative Code 441-93 diff --git a/docs/agents/sources/ia_tanf/sources.md b/docs/agents/sources/ia_tanf/sources.md deleted file mode 100644 index 99cf1b0d26b..00000000000 --- a/docs/agents/sources/ia_tanf/sources.md +++ /dev/null @@ -1,199 +0,0 @@ -# Iowa FIP Documentation Sources - -## Primary Legal Sources - -### Iowa Statutes -- **Iowa Code Chapter 239B - Family Investment Program** - - URL: https://www.legis.iowa.gov/docs/ico/chapter/239B.pdf - - Description: Primary statute authorizing Iowa's TANF program - - Effective: Current - - Key sections: 239B.2 (Conditions of eligibility), 239B.7 (Income/resource exemptions), 239B.8 (Family investment agreements), 239B.9 (Limited benefit plan) - -### Iowa Administrative Code - -- **441 IAC Chapter 41 - Granting Assistance** - - URL: https://www.legis.iowa.gov/docs/iac/chapter/03-25-2009.441.41.pdf - - Description: Complete FIP eligibility rules - - Key sections: - - 441-41.22(239B): Eligible group - - 441-41.23(239B): Home, residence requirements - - 441-41.24(239B): PROMISE JOBS program - - 441-41.25(239B): Uncategorized factors of eligibility - - 441-41.26(239B): Resources - - 441-41.27(239B): Income - - 441-41.28(239B): Need standards - -- **441-41.26(239B) - Resources** - - URL: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf - - Description: Resource/asset eligibility rules and exclusions - -- **441-41.27(239B) - Income** - - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 - - URL (PDF): https://www.legis.iowa.gov/docs/iac/rule/441.41.27.pdf - - Description: Income eligibility rules, exemptions, deductions - - Effective: 7/1/2025 - -- **441-41.28(239B) - Need Standards** - - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 - - URL (PDF): https://www.legis.iowa.gov/docs/iac/rule/441.41.28.pdf - - Description: Schedule of living costs, payment standards - - Effective: 7/1/2025 - -- **441 IAC Chapter 93 - PROMISE JOBS Program** - - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-93-1 - - Description: Work requirements and participation rules - -## Federal TANF Regulations - -- **45 CFR Part 260 - General TANF Provisions** - - URL: https://www.ecfr.gov/current/title-45/subtitle-B/chapter-II/part-260 - - Description: Federal TANF requirements that Iowa must comply with - -- **45 CFR Part 261 - Ensuring That Recipients Work** - - URL: https://www.ecfr.gov/current/title-45/subtitle-B/chapter-II/part-261 - - Description: Federal work participation requirements - - Key sections: - - 261.10: Individual work requirements - - 261.31: Hourly participation requirements (30 hours/week, 20 hours from core activities) - -## Official State Agency Sources - -### Iowa Department of Health and Human Services (HHS) - -- **FIP Program Overview** - - URL: https://hhs.iowa.gov/assistance-programs/cash-assistance/fip-tanf - - Description: Official program page - -- **Comm. 108 - The Family Investment Program** - - URL: https://hhs.iowa.gov/media/6454/download - - Description: Official program brochure/rules summary - - Revision: 06/25 - -- **4-E, FIP Income** - - URL: https://hhs.iowa.gov/media/3970 - - URL (Download): https://hhs.iowa.gov/media/3970/download?inline - - Description: Income policy manual section - - Revision: January 3, 2020 - -- **Iowa TANF State Plan** - - URL: https://hhs.iowa.gov/media/17445/download?inline= - - Description: State TANF plan submitted to federal government - -### Iowa General Information - -- **Get Family Investment Program Benefits** - - URL: https://www.iowa.gov/how-do-i-get-family-investment-program-fip-benefits - - Description: Public-facing application information - -## Secondary/Reference Sources - -### WorkWorld Help System - -- **FIP Eligibility - Net Income Standards and Payment Rates** - - URL: https://help.workworldapp.com/wwwebhelp/fip_eligibility_net_income_standards_and_payment_rates_iowa.htm - - Description: Comprehensive explanation of income tests - -- **FIP Eligibility - Resources** - - URL: http://help.workworldapp.com/wwwebhelp/fip_eligibility_resources_iowa.htm - - Description: Asset/resource eligibility rules - -- **FIP Eligibility - Financial** - - URL: https://help.workworldapp.com/wwwebhelp/fip_eligibility_financial_iowa.htm - - Description: Financial eligibility overview including all three income tests - -- **FIP Eligibility - Gross Income Limits** - - URL: http://help.workworldapp.com/wwwebhelp/fip_eligibility_grorss_income_limits_iowa.htm - - Description: 185% Standard of Need gross income test details - -- **FIP Eligibility - Income Exclusions** - - URL: http://help.workworldapp.com/wwwebhelp/fip_eligibility_income_exclusions_iowa.htm - - Description: Complete list of exempt income types - -- **FIP Eligibility - Eligible Group** - - URL: https://help.workworldapp.com/wwwebhelp/fip_eligibility_eligible_group_iowa.htm - - Description: Household composition rules - -- **FIP Eligibility - PROMISE JOBS** - - URL: https://help.workworldapp.com/wwwebhelp/fip_eligibility_promise_jobs_iowa.htm - - Description: Work requirement details - -### Federal Sources - -- **45 CFR Parts 260-265 - TANF Regulations** - - URL: https://www.ecfr.gov/current/title-45/subtitle-B/chapter-II/part-260 - - Description: Federal TANF requirements that Iowa must comply with - -- **Benefits.gov - Iowa Family Investment Program** - - URL: https://www.benefits.gov/benefit/1387 - - Description: Federal benefits directory entry - -### NCCP (National Center for Children in Poverty) - -- **Iowa State Profile Summary - TANF Flexibilities** - - URL: https://www.nccp.org/wp-content/uploads/2024/11/TANF-profile-Iowa.pdf - - Description: Summary of Iowa TANF policies and flexibilities - -- **50-State Comparison of TANF Amounts** - - URL: https://www.nccp.org/wp-content/uploads/2024/11/TANF-Benefit-Amounts-2024-FINAL.pdf - - Description: Comparison of TANF benefit amounts across all states (2024) - -### Legal Aid / Advocacy Sources - -- **Iowa Legal Aid - 60 Month Lifetime Limit on FIP Benefits** - - URL: https://iowalegalaid.org/resource/60-month-lifetime-limit-on-fip-benefits/ - - Description: Information on time limits and hardship exemptions - -- **Iowa Legal Aid - Limited Benefit Plan Q&A** - - URL: https://www.iowalegalaid.org/resource/questions-and-answers-about-limited-benefit-p - - Description: Information on LBP sanctions - -- **Iowa Legal Aid - Public Benefits and Car Ownership** - - URL: https://iowalegalaid.org/resource/one-car-any-value/ - - Description: Vehicle asset rules for FIP eligibility - -### Federal ACF (Administration for Children and Families) - -- **Iowa's Limited Benefit Plan** - - URL: https://aspe.hhs.gov/reports/iowas-limited-benefit-plan - - Description: Federal analysis of Iowa's Limited Benefit Plan policy - -- **Iowa Family Investment Program (Pathways to Work)** - - URL: https://pathwaystowork.acf.gov/intervention-detail/716 - - Description: Federal overview of Iowa FIP program - -## Cornell Law Institute References - -- **Iowa Admin. Code r. 441-41.24 (PROMISE JOBS)** - - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-24 - -- **Iowa Admin. Code r. 441-41.27 (Income)** - - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 - -- **Iowa Admin. Code r. 441-41.28 (Need Standards)** - - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 - -- **Iowa Admin. Code r. 441-41.29 (Composite FIP/SSI cases)** - - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-29 - -- **Iowa Admin. Code r. 441-93.1 (PROMISE JOBS Definitions)** - - URL: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-93-1 - -## Iowa Legislature Publications - -- **Family Investment Program/PROMISE JOBS - Budget Unit Brief** - - URL: https://www.legis.iowa.gov/docs/publications/FT/1519815.pdf - - Description: Legislative budget analysis of FIP program - -- **TANF Fiscal Topics** - - URL: https://www.legis.iowa.gov/docs/publications/FTNO/1462655.pdf - - Description: Legislative fiscal analysis of TANF/FIP (October 2024) - -- **Monthly FIP Payments and Recipients Data** - - URL: https://www.legis.iowa.gov/docs/publications/FCTA/1216562.pdf - - Description: Historical FIP payment and recipient data - -## Contact Information - -- **Iowa HHS Division of Community Access**: 1-800-972-2017 -- **Iowa HHS General**: (877) 347-5678 -- **Iowa HHS Benefits Portal**: https://dhsservices.iowa.gov/ diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/earned.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/earned.yaml deleted file mode 100644 index a969bb42aa6..00000000000 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/earned.yaml +++ /dev/null @@ -1,14 +0,0 @@ -description: Iowa counts these income sources as earned income under the Family Investment Program. - -values: - 2017-10-27: - - employment_income - - self_employment_income - -metadata: - unit: list - period: month - label: Iowa FIP earned income sources - reference: - - title: Iowa Administrative Code 441-41.27(239B) - Income, 41.27(2) - href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=21 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml deleted file mode 100644 index 74011f9b10c..00000000000 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/sources/unearned.yaml +++ /dev/null @@ -1,17 +0,0 @@ -description: Iowa counts these income sources as unearned income under the Family Investment Program. - -values: - 2017-10-27: - - social_security - - ssi - - unemployment_compensation - - alimony_income - - child_support_received - -metadata: - unit: list - period: month - label: Iowa FIP unearned income sources - reference: - - title: Iowa Administrative Code 441-41.27(239B) - Income, 41.27(1) - href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=20 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip.yaml index 610a87c01bb..39ac1dbe34f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip.yaml @@ -52,15 +52,15 @@ people: parent: age: 30 - employment_income: 9_600 + employment_income_before_lsr: 9_600 is_tax_unit_head_or_spouse: true child1: age: 5 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true child2: age: 3 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true spm_units: spm_unit: @@ -92,11 +92,11 @@ people: parent: age: 30 - employment_income: 24_000 + employment_income_before_lsr: 24_000 is_tax_unit_head_or_spouse: true child: age: 5 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true spm_units: spm_unit: @@ -126,11 +126,11 @@ people: parent: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_head_or_spouse: true child: age: 5 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true spm_units: spm_unit: @@ -167,12 +167,12 @@ people: parent: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 social_security: 4_800 is_tax_unit_head_or_spouse: true child: age: 5 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true spm_units: spm_unit: @@ -214,16 +214,16 @@ people: parent: age: 30 - employment_income: 6_000 + employment_income_before_lsr: 6_000 social_security: 2_400 is_tax_unit_head_or_spouse: true child1: age: 5 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true child2: age: 3 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true spm_units: spm_unit: @@ -262,11 +262,11 @@ people: parent: age: 25 - employment_income: 7_200 + employment_income_before_lsr: 7_200 is_tax_unit_head_or_spouse: true child: age: 2 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true spm_units: spm_unit: @@ -297,47 +297,47 @@ people: parent1: age: 35 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_head_or_spouse: true parent2: age: 33 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_head_or_spouse: true child1: age: 16 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true child2: age: 14 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true child3: age: 12 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true child4: age: 10 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true child5: age: 8 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true child6: age: 6 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true child7: age: 4 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true child8: age: 2 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true child9: age: 1 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true spm_units: spm_unit: @@ -359,11 +359,11 @@ people: parent: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_head_or_spouse: true child: age: 5 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_dependent: true spm_units: spm_unit: diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income.yaml index 6189cf7825d..eaefc81ab6f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income.yaml @@ -11,7 +11,7 @@ people: person1: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 spm_units: spm_unit: members: [person1] @@ -29,7 +29,7 @@ people: person1: age: 30 - employment_income: 9_600 + employment_income_before_lsr: 9_600 spm_units: spm_unit: members: [person1] @@ -51,7 +51,7 @@ people: person1: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 social_security: 4_800 spm_units: spm_unit: @@ -72,7 +72,7 @@ people: person1: age: 30 - employment_income: 6_000 + employment_income_before_lsr: 6_000 social_security: 2_400 spm_units: spm_unit: @@ -97,7 +97,7 @@ people: person1: age: 25 - employment_income: 7_200 + employment_income_before_lsr: 7_200 spm_units: spm_unit: members: [person1] @@ -120,7 +120,7 @@ people: person1: age: 30 - employment_income: 24_000 + employment_income_before_lsr: 24_000 spm_units: spm_unit: members: [person1] @@ -143,10 +143,10 @@ people: person1: age: 35 - employment_income: 10_000 + employment_income_before_lsr: 10_000 person2: age: 33 - employment_income: 2_000 + employment_income_before_lsr: 2_000 spm_units: spm_unit: members: [person1, person2] @@ -168,7 +168,7 @@ people: person1: age: 30 - employment_income: 9_600 + employment_income_before_lsr: 9_600 spm_units: spm_unit: members: [person1] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_eligible.yaml index c55f58ae8f7..69b65288868 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_eligible.yaml @@ -9,7 +9,7 @@ people: person1: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_head: true person2: age: 5 @@ -33,7 +33,7 @@ people: person1: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_head: true spm_units: spm_unit: @@ -57,7 +57,7 @@ people: person1: age: 30 - employment_income: 24_000 + employment_income_before_lsr: 24_000 is_tax_unit_head: true person2: age: 5 @@ -83,7 +83,7 @@ people: person1: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_head: true person2: age: 5 @@ -108,7 +108,7 @@ people: person1: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_head: true person2: age: 5 @@ -134,7 +134,7 @@ people: person1: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_head: true person2: age: 5 @@ -160,7 +160,7 @@ people: person1: age: 25 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_head: true is_pregnant: true spm_units: @@ -185,7 +185,7 @@ people: person1: age: 30 - employment_income: 6_000 + employment_income_before_lsr: 6_000 is_tax_unit_head: true person2: age: 5 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income.yaml index 5e2949a097a..a8ee0b410c1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income.yaml @@ -8,7 +8,7 @@ people: person1: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 spm_units: spm_unit: members: [person1] @@ -25,7 +25,7 @@ people: person1: age: 30 - employment_income: 9_600 + employment_income_before_lsr: 9_600 spm_units: spm_unit: members: [person1] @@ -42,7 +42,7 @@ people: person1: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 social_security: 4_800 spm_units: spm_unit: @@ -60,7 +60,7 @@ people: person1: age: 30 - employment_income: 6_000 + employment_income_before_lsr: 6_000 social_security: 2_400 spm_units: spm_unit: @@ -79,11 +79,11 @@ people: person1: age: 35 - employment_income: 10_000 + employment_income_before_lsr: 10_000 social_security: 1_200 person2: age: 33 - employment_income: 2_000 + employment_income_before_lsr: 2_000 spm_units: spm_unit: members: [person1, person2] @@ -103,7 +103,7 @@ people: person1: age: 30 - employment_income: 9_600 + employment_income_before_lsr: 9_600 spm_units: spm_unit: members: [person1] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_income_eligible.yaml index 937989b8fa6..2f3854915f4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_income_eligible.yaml @@ -11,7 +11,7 @@ people: person1: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_head: true person2: age: 5 @@ -36,7 +36,7 @@ people: person1: age: 30 - employment_income: 7_200 + employment_income_before_lsr: 7_200 is_tax_unit_head: true person2: age: 5 @@ -66,7 +66,7 @@ people: person1: age: 30 - employment_income: 24_000 + employment_income_before_lsr: 24_000 is_tax_unit_head: true person2: age: 5 @@ -94,7 +94,7 @@ people: person1: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 social_security: 4_800 is_tax_unit_head: true person2: @@ -125,7 +125,7 @@ people: person1: age: 30 - employment_income: 6_000 + employment_income_before_lsr: 6_000 social_security: 2_400 is_tax_unit_head: true person2: @@ -161,7 +161,7 @@ people: person1: age: 30 - employment_income: 9_600 + employment_income_before_lsr: 9_600 social_security: 3_600 is_tax_unit_head: true person2: @@ -192,7 +192,7 @@ people: person1: age: 25 - employment_income: 0 + employment_income_before_lsr: 0 is_tax_unit_head: true is_pregnant: true spm_units: @@ -219,11 +219,11 @@ people: person1: age: 35 - employment_income: 10_000 + employment_income_before_lsr: 10_000 is_tax_unit_head: true person2: age: 33 - employment_income: 2_000 + employment_income_before_lsr: 2_000 is_tax_unit_spouse: true person3: age: 10 @@ -259,7 +259,7 @@ people: person1: age: 30 - employment_income: 15_600 + employment_income_before_lsr: 15_600 is_tax_unit_head: true person2: age: 5 @@ -293,7 +293,7 @@ people: person1: age: 30 - employment_income: 13_200 + employment_income_before_lsr: 13_200 is_tax_unit_head: true person2: age: 5 @@ -327,7 +327,7 @@ people: person1: age: 30 - employment_income: 13_200 + employment_income_before_lsr: 13_200 is_tax_unit_head: true person2: age: 5 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/integration.yaml index ea5150d4054..af7de78f1ec 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/integration.yaml @@ -18,7 +18,7 @@ people: parent: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 child1: age: 5 child2: @@ -53,7 +53,7 @@ people: parent: age: 28 - employment_income: 9_600 # $800/month * 12 + employment_income_before_lsr: 9_600 # $800/month * 12 child1: age: 4 spm_units: @@ -93,7 +93,7 @@ people: parent: age: 35 - employment_income: 7_200 # $600/month * 12 + employment_income_before_lsr: 7_200 # $600/month * 12 social_security: 2_400 # $200/month * 12 child1: age: 10 @@ -139,7 +139,7 @@ people: parent: age: 32 - employment_income: 18_000 # $1,500/month * 12 + employment_income_before_lsr: 18_000 # $1,500/month * 12 child1: age: 6 spm_units: @@ -171,7 +171,7 @@ people: parent: age: 30 - employment_income: 1_200 # $100/month * 12 + employment_income_before_lsr: 1_200 # $100/month * 12 social_security: 7_200 # $600/month * 12 child1: age: 8 @@ -211,7 +211,7 @@ people: person1: age: 25 - employment_income: 0 + employment_income_before_lsr: 0 spm_units: spm_unit: members: [person1] @@ -232,7 +232,7 @@ people: parent: age: 30 - employment_income: 0 + employment_income_before_lsr: 0 child1: age: 5 spm_units: @@ -256,10 +256,10 @@ people: parent1: age: 35 - employment_income: 6_000 # $500/month * 12 + employment_income_before_lsr: 6_000 # $500/month * 12 parent2: age: 33 - employment_income: 0 + employment_income_before_lsr: 0 child1: age: 12 child2: diff --git a/policyengine_us/tools/variables.py b/policyengine_us/tools/variables.py index fe9805cec7d..2ae0e45eb64 100644 --- a/policyengine_us/tools/variables.py +++ b/policyengine_us/tools/variables.py @@ -13,9 +13,7 @@ def add_n(word): def print_variable_summary(variable_name: str): variable = variables.get(variable_name) - return Markdown( - f""" + return Markdown(f""" ## {variable.name} This variable models a{add_n(variable.entity.label)}**{variable.entity.label}**'s **{variable.label}**. - """ - ) + """) diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py index 88d413df7e9..a7f90412dca 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py @@ -17,5 +17,5 @@ def formula(spm_unit, period, parameters): p.recipient_limit, p.applicant_limit, ) - resources = spm_unit("spm_unit_assets", period.this_year) + resources = spm_unit("spm_unit_assets", period) return resources <= limit diff --git a/sources/working_references.md b/sources/working_references.md deleted file mode 100644 index ea7a39cd820..00000000000 --- a/sources/working_references.md +++ /dev/null @@ -1,389 +0,0 @@ -# Collected Documentation - -## Official Program Name - -**Federal Program**: Temporary Assistance for Needy Families (TANF) -**State's Official Name**: Family Investment Program (FIP) -**State**: Iowa (IA) -**Abbreviation**: FIP -**Source**: Iowa Code Section 239B - -**Variable Prefix**: `ia_fip` -**Parameter Path**: `gov.states.ia.dhs.tanf` - ---- - -## Iowa TANF (FIP - Family Investment Program) Implementation -**Collected**: 2026-01-15 (Updated) -**Implementation Task**: Implement Iowa FIP cash assistance program with eligibility tests and benefit calculations - -### Source Information - -#### Primary Legal Sources -- **Title**: Iowa Code Chapter 239B - Family Investment Program -- **Citation**: Iowa Code Section 239B -- **URL**: https://www.legis.iowa.gov/docs/ico/chapter/239B.pdf -- **Effective Date**: Current - -- **Title**: Iowa Administrative Code 441-41.27(239B) - Income -- **Citation**: 441 IAC 41.27(239B) -- **URL**: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27 -- **Effective Date**: 7/1/2025 - -- **Title**: Iowa Administrative Code 441-41.28(239B) - Need Standards -- **Citation**: 441 IAC 41.28(239B) -- **URL**: https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28 -- **Effective Date**: 7/1/2025 - -- **Title**: Iowa Administrative Code 441-41.26(239B) - Resources -- **Citation**: 441 IAC 41.26(239B) -- **URL**: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf -- **Effective Date**: Current - -#### Federal TANF Regulations -- **Title**: 45 CFR Part 260 - General TANF Provisions -- **URL**: https://www.ecfr.gov/current/title-45/subtitle-B/chapter-II/part-260 -- **Title**: 45 CFR Part 261 - Ensuring That Recipients Work -- **URL**: https://www.ecfr.gov/current/title-45/subtitle-B/chapter-II/part-261 - -### Key Rules and Thresholds - -#### Resource Limits -- Applicant families: $2,000 -- Recipient families (member received FIP in prior month): $5,000 -- Vehicle equity exclusion: $3,959 per vehicle per adult/working teen (adjusted annually as of July 1) - -#### Excluded Resources (Not Counted) -- Homestead property -- Non-homestead property listed for sale at fair market value or producing income -- Household goods and personal effects -- Life insurance with zero cash value -- Burial plots (one per household member) and funeral trusts (up to $1,500 per person) -- Tools and capital assets for self-employment (up to $10,000 equity) -- Inventory and supplies for self-employment -- Individual Development Account (IDA) balances (full balance excluded) -- Educational/training assistance funds -- SSI recipient resources -- Current monthly income -- Loans and inaccessible resources -- Child support payments (up to $50 monthly) -- Medical expense reserves from lump-sum payments - -#### Income Eligibility Tests -1. **Test 1**: Gross income <= 185% of Standard of Need -2. **Test 2**: Net income (after 20% earned income deduction) < Standard of Need (applicants only) -3. **Test 3**: Net income (after work incentive) < Payment Standard - -#### Income Deductions -- **20% Earned Income Deduction**: Applied to gross nonexempt earned income (covers taxes, transportation, meals, uniforms, other work expenses) -- **58% Work Incentive Disregard**: Applied after 20% deduction to remaining earned income (not time-limited) - -#### Time Limits -- 60-month lifetime limit on benefits -- Hardship exemptions available for 6-month extensions -- Hardship criteria: domestic violence, lack of employability, lack of suitable child care, medical/mental health issues, housing situations, substance abuse issues, child requiring parent at home -- Extension request can be filed starting in month 59 -- SSI exemption: 60-month limit does not apply if child lives with one parent on SSI or both parents on SSI - -### Payment Standards (Effective 7/1/2025) - -#### Schedule of Living Costs (100% Standard of Need) - -| Family Size | Monthly Amount | -|-------------|----------------| -| 1 | $365 | -| 2 | $719 | -| 3 | $849 | -| 4 | $986 | -| 5 | $1,092 | -| 6 | $1,216 | -| 7 | $1,335 | -| 8 | $1,457 | -| 9 | $1,576 | -| 10 | $1,724 | -| Each additional | +$173 | - -#### 185% of Standard of Need (Gross Income Limit - Test 1) - -| Family Size | Monthly Amount | -|-------------|----------------| -| 1 | $675.25 | -| 2 | $1,330.15 | -| 3 | $1,570.65 | -| 4 | $1,824.10 | -| 5 | $2,020.20 | -| 6 | $2,249.60 | -| 7 | $2,469.75 | -| 8 | $2,695.45 | -| 9 | $2,915.60 | -| 10 | $3,189.40 | -| Each additional | +$320.05 | - -#### Schedule of Basic Needs (Payment Standard) - -| Family Size | Monthly Amount | -|-------------|----------------| -| 1 | $183 | -| 2 | $361 | -| 3 | $426 | -| 4 | $495 | -| 5 | $548 | -| 6 | $610 | -| 7 | $670 | -| 8 | $731 | -| 9 | $791 | -| 10 | $865 | -| Each additional | +$87 | - -### Exempt Income (Complete List) - -The following income is NOT counted for FIP eligibility: - -**Government Benefits** -- SNAP (Food Stamp) benefits -- SSI recipient income (when not in eligible group) -- Earned Income Tax Credit (EITC) - federal and state -- Low-Income Home Energy Assistance (LIHEAP) -- WIC program benefits -- Foster care/kinship caregiver payments -- Rent supplements from governmental agencies -- Disaster and emergency assistance -- Indian tribal judgment funds -- Retroactive SSI benefits and payments -- General assistance from county funds (non-basic need or emergency) - -**Employment and Training** -- PROMISE JOBS payments -- Training allowances (Department of the Blind, JTPA, Vocational Rehabilitation) -- Food Stamp Employment and Training allowances -- Car pool payments -- Job-related reimbursements -- VISTA volunteer payments -- Incentive allowances from Work Force Investment Project -- AmeriCorps educational awards - -**Education** -- Educational/training assistance and financial aid -- Earnings of students age 19 or younger in full-time school (high school or equivalent) - -**Child Support** -- Up to $50 of current monthly support paid by legally responsible person - -**Other** -- Food from home production -- Food coupons value and USDA commodities value -- Income in-kind -- Gifts of $30 or less per person per calendar quarter -- Loans and bona fide loans -- Income tax refunds -- Vendor payments -- Interest or dividend payments -- Third-party reimbursements -- Medical expense settlements -- Individual Development Account (IDA) deposits -- Refunds from rent or utility deposits -- Terminated income of retrospectively budgeted households (when requirements met) -- Veterans benefits under Aid and Attendance program -- Census worker earnings -- Family Support Subsidy payments - -### Self-Employment Income Rules - -- **Net Profit Calculation**: Either 40% of gross income deducted OR actual documented expenses -- **Irregular Self-Employment**: Averaged over 12-month period -- **Work Hours Calculation for Self-Employed**: Actual gross income less business expenses divided by federal minimum wage - -### Lump Sum Income Treatment - -- Nonrecurring lump sum amounts create ineligibility period -- Ineligibility period calculated by dividing lump sum by standard of need -- Period can be reduced if: - - Living costs increase - - Funds spent on medical services - - Funds spent on home repairs - - Funds spent on funeral expenses - -### Income Budgeting Rules - -- **Weekly Income**: Multiply by 4 regardless of actual payment frequency -- **Biweekly Income**: Multiply by 2 regardless of actual payment frequency -- **Prospective Budgeting**: Projection based on best estimate of future income using income from 30 days before interview -- **Variable Income**: Average all instances received in the period - -### Calculation Formulas - -#### Income Eligibility - -```python -# Test 1: Gross Income Test (185% Standard of Need) -gross_income_limit = standard_of_need * 1.85 -passes_test_1 = gross_income <= gross_income_limit - -# Test 2: Net Income Test (Standard of Need) - Applicants Only -earned_income_deduction = gross_earned_income * 0.20 -net_income_test_2 = gross_income - earned_income_deduction -passes_test_2 = net_income_test_2 < standard_of_need - -# Test 3: Payment Standard Test -work_incentive_disregard = (gross_earned_income - earned_income_deduction) * 0.58 -countable_net_income = gross_income - earned_income_deduction - work_incentive_disregard -passes_test_3 = countable_net_income < payment_standard -``` - -#### Benefit Calculation - -```python -# FIP Benefit = Payment Standard - Countable Net Income -fip_benefit = max(payment_standard - countable_net_income, 0) -``` - -#### Complete Benefit Formula - -```python -def calculate_fip_benefit(gross_earned_income, gross_unearned_income, family_size): - # Get parameters - standard_of_need = get_standard_of_need(family_size) - payment_standard = get_payment_standard(family_size) - gross_income_limit = standard_of_need * 1.85 - - gross_income = gross_earned_income + gross_unearned_income - - # Test 1: 185% Gross Income Test - if gross_income > gross_income_limit: - return 0 - - # 20% Earned Income Deduction - earned_income_deduction = gross_earned_income * 0.20 - - # Test 2: Standard of Need Test (for applicants) - net_income_after_20 = gross_income - earned_income_deduction - if net_income_after_20 >= standard_of_need: - return 0 # Applicant ineligible - - # 58% Work Incentive Disregard - remaining_earned = gross_earned_income - earned_income_deduction - work_incentive = remaining_earned * 0.58 - - # Test 3: Payment Standard Test - countable_net_income = gross_income - earned_income_deduction - work_incentive - if countable_net_income >= payment_standard: - return 0 - - # Calculate benefit - return payment_standard - countable_net_income -``` - -### Example Calculation - -**Family of 3 with one employed parent earning $800/month gross:** - -1. **Test 1 (185% Gross Income Test):** - - Gross Income: $800 - - 185% Standard of Need for 3: $1,570.65 - - $800 < $1,570.65 - PASS - -2. **Test 2 (Standard of Need Test - Applicant Only):** - - Gross Income: $800 - - 20% Earned Income Deduction: $800 x 0.20 = $160 - - Net Income: $800 - $160 = $640 - - Standard of Need for 3: $849 - - $640 < $849 - PASS (eligible for work incentive) - -3. **Test 3 (Payment Standard Test):** - - Net Income from Test 2: $640 - - 58% Work Incentive: $640 x 0.58 = $371.20 - - Countable Net Income: $640 - $371.20 = $268.80 - - Payment Standard for 3: $426 - - $268.80 < $426 - PASS - -4. **Benefit Calculation:** - - FIP Benefit = $426 - $268.80 = $157.20/month - -### Special Cases and Exceptions - -#### Eligible Group -- Must include child, eligible siblings, and natural/adoptive parents when living together -- Nonparental relatives optional (at relative's request) -- Incapacitated stepparents may be included -- Exception: Parent-only case when only child receives SSI - -#### Two-Parent Families -- No 100-hour rule (eliminated under FIP) -- Both parents must participate in PROMISE JOBS unless one meets exemption criteria - -#### Caretaker Relative Rules -- Unmarried specified relative under 19 living with parents: needs included with parent(s) -- Nonparental relative as caretaker: children considered separate eligible group - -#### Temporary Absences -- Education/training: remain in group if expected to return upon completion -- Medical institutions: remain in group if expected return within 12 months -- Other reasons: remain in group if expected return within 3 months - -#### Work Requirements (PROMISE JOBS) -- Required unless exempt -- Exemptions: - - SSI/SSDI recipients (due to own disability) - - Aliens not listed under 8 USC Section 1641 - - Persons determined disabled and unable to participate - - Children under age 16 who are not parents - - Students 16-19 (non-parents) attending school full-time - - Parent/relative of child under 6 months who personally provides care (one exemption per case) - - Person working 30+ hours/week in unsubsidized employment at initial determination -- Limited Benefit Plan for non-compliance: - - First LBP: benefits reduced then terminated - - Subsequent LBPs: 6-month minimum termination - - Must complete 20 hours of employment/similar activity to restart - -#### Federal TANF Work Requirements (45 CFR 261) -- 30 hours/week minimum for overall rate (20 hours from core activities) -- Single parent with child under 6: 20 hours/week minimum -- Community service required if received assistance for 2 months (unless exempt or engaged in work) - -### References for Metadata - -```yaml -# For parameters: -reference: - - title: "Iowa Administrative Code 441-41.28(239B) - Need Standards" - href: "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-28" -``` - -```python -# For variables: -reference = "441 IAC 41.27(239B)" -documentation = "https://www.law.cornell.edu/regulations/iowa/Iowa-Admin-Code-r-441-41-27" -``` - -### Implementation Notes - -1. **Parameter Files Needed**: - - `gov/states/ia/hhs/tanf/income/standard_of_need.yaml` - Schedule of Living Costs by family size - - `gov/states/ia/hhs/tanf/income/gross_income_limit_percent.yaml` - 185% multiplier - - `gov/states/ia/hhs/tanf/income/earned_income_deduction.yaml` - 20% deduction rate - - `gov/states/ia/hhs/tanf/income/work_incentive_disregard.yaml` - 58% disregard rate - - `gov/states/ia/hhs/tanf/benefit/payment_standard.yaml` - Schedule of Basic Needs by family size - - `gov/states/ia/hhs/tanf/eligibility/resource_limit_applicant.yaml` - $2,000 - - `gov/states/ia/hhs/tanf/eligibility/resource_limit_recipient.yaml` - $5,000 - -2. **Variable Files Needed**: - - `ia_fip.py` - Main benefit calculation - - `ia_fip_eligible.py` - Overall eligibility - - `ia_fip_gross_income_eligible.py` - Test 1 - - `ia_fip_net_income_eligible.py` - Test 2 (applicants) - - `ia_fip_payment_standard_eligible.py` - Test 3 - - `ia_fip_countable_earned_income.py` - Earned income after deductions - - `ia_fip_countable_unearned_income.py` - Unearned income - - `ia_fip_payment_standard.py` - Payment standard by family size - - `ia_fip_standard_of_need.py` - Standard of need by family size - -3. **Entity**: SPMUnit (consistent with other state TANF implementations) - -4. **Definition Period**: YEAR (consistent with other state TANF implementations) - -5. **Key Differences from Federal TANF**: - - Iowa uses 58% work incentive (vs. typical 50%) - - Iowa has separate applicant ($2,000) and recipient ($5,000) resource limits - - Iowa eliminated 100-hour rule for two-parent families - ---- From 43a9d60b09a137ac7500b1b52187ee37c6ab69f3 Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 26 Jan 2026 18:42:24 +0000 Subject: [PATCH 24/29] Fix tests --- policyengine_us/tools/variables.py | 6 ++++-- .../gov/states/ia/dhs/fip/ia_fip_resource_eligible.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/policyengine_us/tools/variables.py b/policyengine_us/tools/variables.py index 2ae0e45eb64..fe9805cec7d 100644 --- a/policyengine_us/tools/variables.py +++ b/policyengine_us/tools/variables.py @@ -13,7 +13,9 @@ def add_n(word): def print_variable_summary(variable_name: str): variable = variables.get(variable_name) - return Markdown(f""" + return Markdown( + f""" ## {variable.name} This variable models a{add_n(variable.entity.label)}**{variable.entity.label}**'s **{variable.label}**. - """) + """ + ) diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py index a7f90412dca..88d413df7e9 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py @@ -17,5 +17,5 @@ def formula(spm_unit, period, parameters): p.recipient_limit, p.applicant_limit, ) - resources = spm_unit("spm_unit_assets", period) + resources = spm_unit("spm_unit_assets", period.this_year) return resources <= limit From 71eb6bacd8df3cb3739c2a45ce58791dffcc08ac Mon Sep 17 00:00:00 2001 From: Lucy Lennemann <78785519+llennemann@users.noreply.github.com> Date: Mon, 26 Jan 2026 18:46:05 +0000 Subject: [PATCH 25/29] Changes --- policyengine_us/tools/variables.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/policyengine_us/tools/variables.py b/policyengine_us/tools/variables.py index fe9805cec7d..2ae0e45eb64 100644 --- a/policyengine_us/tools/variables.py +++ b/policyengine_us/tools/variables.py @@ -13,9 +13,7 @@ def add_n(word): def print_variable_summary(variable_name: str): variable = variables.get(variable_name) - return Markdown( - f""" + return Markdown(f""" ## {variable.name} This variable models a{add_n(variable.entity.label)}**{variable.entity.label}**'s **{variable.label}**. - """ - ) + """) From b069c7d09c3f51a449375dc3125e2d108c78cddf Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 2 Feb 2026 15:15:47 -0500 Subject: [PATCH 26/29] Refactor Iowa FIP: update dates, reorganize variables, add tests - Update all parameter effective dates from 2017-10-27 to 2017-01-01 - Rename ia_fip_resource_eligible to ia_fip_resources_eligible - Add #page=1 anchor to resource limit PDF references - Fix typo in need_standard/additional.yaml description - Create eligibility/ folder and move eligibility variables - Break down ia_fip_income_eligible into sub-components: - ia_fip_gross_income_eligible (Test 1) - ia_fip_net_income_eligible (Test 2) - ia_fip_countable_income_eligible (Test 3) - Add comprehensive test files for new variables - Remove unnecessary test files for adds-only variables Co-Authored-By: Claude Opus 4.5 --- .../fip/income/earned_income_deduction.yaml | 2 +- .../income/gross_income_limit_percent.yaml | 2 +- .../fip/income/work_incentive_disregard.yaml | 4 +- .../gov/states/ia/dhs/fip/max_unit_size.yaml | 2 +- .../ia/dhs/fip/need_standard/additional.yaml | 4 +- .../states/ia/dhs/fip/need_standard/main.yaml | 20 +- .../dhs/fip/payment_standard/additional.yaml | 4 +- .../ia/dhs/fip/payment_standard/main.yaml | 20 +- .../ia/dhs/fip/resources/applicant_limit.yaml | 4 +- .../ia/dhs/fip/resources/recipient_limit.yaml | 4 +- .../fip/ia_fip_countable_earned_income.yaml | 60 ++++++ .../ia/dhs/fip/ia_fip_countable_income.yaml | 181 ------------------ .../fip/ia_fip_countable_income_eligible.yaml | 149 ++++++++++++++ .../ia/dhs/fip/ia_fip_gross_income.yaml | 116 ----------- .../dhs/fip/ia_fip_gross_income_eligible.yaml | 112 +++++++++++ .../dhs/fip/ia_fip_net_income_eligible.yaml | 144 ++++++++++++++ .../ia/dhs/fip/ia_fip_resources_eligible.yaml | 99 ++++++++++ .../ia_fip_countable_income_eligible.py | 17 ++ .../fip/{ => eligibility}/ia_fip_eligible.py | 4 +- .../ia_fip_gross_income_eligible.py | 17 ++ .../fip/eligibility/ia_fip_income_eligible.py | 46 +++++ .../eligibility/ia_fip_net_income_eligible.py | 23 +++ .../ia_fip_resources_eligible.py} | 4 +- .../ia/dhs/fip/ia_fip_income_eligible.py | 67 ------- 24 files changed, 704 insertions(+), 401 deletions(-) create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_earned_income.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income_eligible.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_net_income_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_resources_eligible.yaml create mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_countable_income_eligible.py rename policyengine_us/variables/gov/states/ia/dhs/fip/{ => eligibility}/ia_fip_eligible.py (89%) create mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_gross_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_net_income_eligible.py rename policyengine_us/variables/gov/states/ia/dhs/fip/{ia_fip_resource_eligible.py => eligibility/ia_fip_resources_eligible.py} (88%) delete mode 100644 policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml index 012fa847e2b..9baff3f865f 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml @@ -1,7 +1,7 @@ description: Iowa deducts this percentage of the gross nonexempt earned income under the Family Investment Program. values: - 2017-10-27: 0.2 + 2017-01-01: 0.2 metadata: unit: /1 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml index 3a089162803..f776f586815 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml @@ -1,7 +1,7 @@ description: Iowa sets the gross income limit for the first income eligibility test as this percentage of the standard of need under the Family Investment Program. values: - 2017-10-27: 1.85 + 2017-01-01: 1.85 metadata: unit: /1 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml index 6b13ec67949..7252c2e44d9 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml @@ -1,7 +1,7 @@ description: Iowa deducts this rate of work incentive disregard after the earned income deduction under the Family Investment Program. values: - 2017-10-27: 0.58 + 2017-01-01: 0.58 metadata: unit: /1 @@ -11,4 +11,4 @@ metadata: - title: Iowa Administrative Code 441-41.27(239B) - Income, 41.27(2)(c) href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=21 - title: Iowa TANF State Plan 2025 - href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) \ No newline at end of file + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml index 8c9efecf2e3..5c5bd3eb9dc 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml @@ -1,7 +1,7 @@ description: Iowa sets this maximum unit size for determining standard of need and payment standards under the Family Investment Program. values: - 2017-10-27: 10 + 2017-01-01: 10 metadata: unit: person diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml index 26f0ad62a7e..4216df9d645 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml @@ -1,4 +1,4 @@ -description: Iowa sets this value as the additional standard of need amount per person for families larger than than the max unit size under the Family Investment Program. +description: Iowa sets this value as the additional standard of need amount per person for families larger than the max unit size under the Family Investment Program. metadata: unit: currency-USD @@ -9,4 +9,4 @@ metadata: href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 values: - 2017-10-27: 173 + 2017-01-01: 173 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml index 5d8d91e6749..b353747b5c1 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml @@ -1,25 +1,25 @@ description: Iowa sets these values as the standard of need amount, or the schedule of living costs, by family size under the Family Investment Program. 1: - 2017-10-27: 365 + 2017-01-01: 365 2: - 2017-10-27: 719 + 2017-01-01: 719 3: - 2017-10-27: 849 + 2017-01-01: 849 4: - 2017-10-27: 986 + 2017-01-01: 986 5: - 2017-10-27: 1_092 + 2017-01-01: 1_092 6: - 2017-10-27: 1_216 + 2017-01-01: 1_216 7: - 2017-10-27: 1_335 + 2017-01-01: 1_335 8: - 2017-10-27: 1_457 + 2017-01-01: 1_457 9: - 2017-10-27: 1_576 + 2017-01-01: 1_576 10: - 2017-10-27: 1_724 + 2017-01-01: 1_724 metadata: unit: currency-USD diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml index d6aac55876d..f58e6624b89 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml @@ -1,7 +1,7 @@ description: Iowa sets this value as the additional payment standard amount per person for families larger than the max unit size under the Family Investment Program. values: - 2017-10-27: 87 + 2017-01-01: 87 metadata: unit: currency-USD @@ -11,4 +11,4 @@ metadata: - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 - title: Iowa TANF State Plan 2025 - href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) - Net Monthly Income Limits \ No newline at end of file + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) - Net Monthly Income Limits diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml index bdd76111348..00a41c1d980 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml @@ -1,25 +1,25 @@ description: Iowa sets these values as the payment standard, or the schedule of basic needs, by family size under the Family Investment Program. 1: - 2017-10-27: 183 + 2017-01-01: 183 2: - 2017-10-27: 361 + 2017-01-01: 361 3: - 2017-10-27: 426 + 2017-01-01: 426 4: - 2017-10-27: 495 + 2017-01-01: 495 5: - 2017-10-27: 548 + 2017-01-01: 548 6: - 2017-10-27: 610 + 2017-01-01: 610 7: - 2017-10-27: 670 + 2017-01-01: 670 8: - 2017-10-27: 731 + 2017-01-01: 731 9: - 2017-10-27: 791 + 2017-01-01: 791 10: - 2017-10-27: 865 + 2017-01-01: 865 metadata: unit: currency-USD diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml index 4645aecbb95..cdffb8f65c1 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml @@ -1,7 +1,7 @@ description: Iowa limits resources to this amount under the Family Investment Program (FIP) for applicant families. values: - 2017-10-27: 2_000 + 2017-01-01: 2_000 metadata: unit: currency-USD @@ -9,6 +9,6 @@ metadata: label: Iowa FIP applicant resource limit reference: - title: Iowa Administrative Code 441-41.26(239B) - Resources, 41.26(1)(e) - href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf + href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf#page=1 - title: Iowa TANF State Plan 2025 href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml index 918200102ca..aa33293739a 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml @@ -1,7 +1,7 @@ description: Iowa limits resources to this amount under the Family Investment Program for recipient families (received FIP in prior month). values: - 2017-10-27: 5_000 + 2017-01-01: 5_000 metadata: unit: currency-USD @@ -9,6 +9,6 @@ metadata: label: Iowa FIP recipient resource limit reference: - title: Iowa Administrative Code 441-41.26(239B) - Resources, 41.26(1)(e) - href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf + href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf#page=1 - title: Iowa TANF State Plan 2025 href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_earned_income.yaml new file mode 100644 index 00000000000..6858d14e142 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_earned_income.yaml @@ -0,0 +1,60 @@ +- name: Case 1, no earned income. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + ia_fip_countable_earned_income: 0 + +- name: Case 2, earned income with deductions. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Gross earned: $12,000/year = $1,000/month + # After 20% deduction: $1,000 * 0.8 = $800 + # After 58% work incentive disregard: $800 * 0.42 = $336 + # Annual: $336 * 12 = $4,032 + ia_fip_countable_earned_income: 4_032 + +- name: Case 3, higher earned income. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 24_000 # $2,000/month + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_code: IA + output: + # Gross earned: $24,000/year = $2,000/month + # After 20% deduction: $2,000 * 0.8 = $1,600 + # After 58% work incentive disregard: $1,600 * 0.42 = $672 + # Annual: $672 * 12 = $8,064 + ia_fip_countable_earned_income: 8_064 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income.yaml deleted file mode 100644 index eaefc81ab6f..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income.yaml +++ /dev/null @@ -1,181 +0,0 @@ -# Unit tests for Iowa FIP countable income -# Countable income calculation: -# 1. Apply 20% earned income deduction -# 2. Apply 58% work incentive disregard to remaining earned income -# 3. Add unearned income (no deductions) -# Reference: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf - -- name: Case 1, zero income. - period: 2025 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - ia_fip_countable_income: 0 - -- name: Case 2, earned income only ($800/month). - period: 2025 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 9_600 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - # Gross earned: $9,600 - # 20% deduction: $9,600 * 0.20 = $1,920 - # Remaining: $9,600 - $1,920 = $7,680 - # 58% work incentive: $7,680 * 0.58 = $4,454.40 - # Countable earned: $7,680 - $4,454.40 = $3,225.60 - ia_fip_countable_income: 3_225.60 - -- name: Case 3, unearned income only. - period: 2025 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - social_security: 4_800 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - # Unearned income has no deductions - # Countable = $4,800 - ia_fip_countable_income: 4_800 - -- name: Case 4, mixed earned and unearned income. - period: 2025 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 6_000 - social_security: 2_400 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - # Gross earned: $6,000 - # 20% deduction: $6,000 * 0.20 = $1,200 - # Remaining: $6,000 - $1,200 = $4,800 - # 58% work incentive: $4,800 * 0.58 = $2,784 - # Countable earned: $4,800 - $2,784 = $2,016 - # Total countable: $2,016 + $2,400 = $4,416 - ia_fip_countable_income: 4_416 - -- name: Case 5, low earned income ($600/month). - period: 2025 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 25 - employment_income_before_lsr: 7_200 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - # Gross earned: $7,200 - # 20% deduction: $7,200 * 0.20 = $1,440 - # Remaining: $7,200 - $1,440 = $5,760 - # 58% work incentive: $5,760 * 0.58 = $3,340.80 - # Countable earned: $5,760 - $3,340.80 = $2,419.20 - ia_fip_countable_income: 2_419.20 - -- name: Case 6, high earned income ($2,000/month). - period: 2025 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 24_000 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - # Gross earned: $24,000 - # 20% deduction: $24,000 * 0.20 = $4,800 - # Remaining: $24,000 - $4,800 = $19,200 - # 58% work incentive: $19,200 * 0.58 = $11,136 - # Countable earned: $19,200 - $11,136 = $8,064 - ia_fip_countable_income: 8_064 - -- name: Case 7, multiple earners in household. - period: 2025 - absolute_error_margin: 0.01 - input: - people: - person1: - age: 35 - employment_income_before_lsr: 10_000 - person2: - age: 33 - employment_income_before_lsr: 2_000 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: IA - output: - # Gross earned: $10,000 + $2,000 = $12,000 - # 20% deduction: $12,000 * 0.20 = $2,400 - # Remaining: $12,000 - $2,400 = $9,600 - # 58% work incentive: $9,600 * 0.58 = $5,568 - # Countable earned: $9,600 - $5,568 = $4,032 - ia_fip_countable_income: 4_032 - -- name: Case 8, non-Iowa state gets zero. - period: 2025 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 9_600 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IL - output: - # defined_for StateCode.IA, other states return 0 - ia_fip_countable_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income_eligible.yaml new file mode 100644 index 00000000000..782a3da680e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_countable_income_eligible.yaml @@ -0,0 +1,149 @@ +# Test 3: Countable income < payment standard +# Countable income applies both 20% deduction AND 58% work incentive disregard + +- name: Case 1, no income. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Countable: $0 < $361 payment standard + ia_fip_countable_income_eligible: true + +- name: Case 2, moderate earned income passes. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 9_600 # $800/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Earned: $800/month + # After 20% deduction: $800 * 0.8 = $640 + # After 58% disregard: $640 * 0.42 = $268.80 + # Countable: $268.80 < $361 payment standard + ia_fip_countable_income_eligible: true + +- name: Case 3, higher earned income fails. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Earned: $1,000/month + # After 20% deduction: $1,000 * 0.8 = $800 + # After 58% disregard: $800 * 0.42 = $336 + # Plus unearned: $0 + # Countable: $336 < $361 payment standard + ia_fip_countable_income_eligible: true + +- name: Case 4, unearned income no disregard. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + social_security: 4_800 # $400/month unearned (SSI not counted in TANF) + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Unearned has no deductions + # Countable: $400 >= $361 payment standard + ia_fip_countable_income_eligible: false + +- name: Case 5, mixed income with disregard on earned only. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 # $500/month earned + social_security: 1_200 # $100/month unearned + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Earned: $500/month + # After 20% deduction: $500 * 0.8 = $400 + # After 58% disregard: $400 * 0.42 = $168 + # Plus unearned: $100 + # Countable: $168 + $100 = $268 < $361 + ia_fip_countable_income_eligible: true + +- name: Case 6, two-parent family with higher payment standard. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 12_000 # $1,000/month + person2: + age: 32 + employment_income_before_lsr: 6_000 # $500/month + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: IA + output: + # Family of 4: payment standard = $495 + # Total earned: $1,500/month + # After 20% deduction: $1,500 * 0.8 = $1,200 + # After 58% disregard: $1,200 * 0.42 = $504 + # Countable: $504 >= $495 payment standard + ia_fip_countable_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income.yaml deleted file mode 100644 index a8ee0b410c1..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income.yaml +++ /dev/null @@ -1,116 +0,0 @@ -# Unit tests for Iowa FIP gross income -# Gross income = gross earned income + gross unearned income -# Reference: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf - -- name: Case 1, zero income. - period: 2025 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - ia_fip_gross_income: 0 - -- name: Case 2, earned income only. - period: 2025 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 9_600 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - ia_fip_gross_income: 9_600 - -- name: Case 3, unearned income only. - period: 2025 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 0 - social_security: 4_800 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - ia_fip_gross_income: 4_800 - -- name: Case 4, mixed earned and unearned income. - period: 2025 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 6_000 - social_security: 2_400 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IA - output: - # Gross = $6,000 + $2,400 = $8,400 - ia_fip_gross_income: 8_400 - -- name: Case 5, multiple earners with unearned income. - period: 2025 - input: - people: - person1: - age: 35 - employment_income_before_lsr: 10_000 - social_security: 1_200 - person2: - age: 33 - employment_income_before_lsr: 2_000 - spm_units: - spm_unit: - members: [person1, person2] - households: - household: - members: [person1, person2] - state_code: IA - output: - # Earned: $10,000 + $2,000 = $12,000 - # Unearned: $1,200 - # Gross = $12,000 + $1,200 = $13,200 - ia_fip_gross_income: 13_200 - -- name: Case 6, non-Iowa state gets zero. - period: 2025 - input: - people: - person1: - age: 30 - employment_income_before_lsr: 9_600 - spm_units: - spm_unit: - members: [person1] - households: - household: - members: [person1] - state_code: IL - output: - # defined_for StateCode.IA, other states return 0 - ia_fip_gross_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income_eligible.yaml new file mode 100644 index 00000000000..04d31a25056 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_gross_income_eligible.yaml @@ -0,0 +1,112 @@ +# Test 1: Gross income <= 185% of standard of need +# Family of 2: Standard of need = $719/month, 185% = $1,330.15/month + +- name: Case 1, no income single parent with child. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + ia_fip_gross_income_eligible: true + +- name: Case 2, earned income below 185% limit. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month < $1,330.15 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Family of 2: 185% of $719 = $1,330.15/month + # Gross income: $1,000/month < $1,330.15 + ia_fip_gross_income_eligible: true + +- name: Case 3, earned income above 185% limit. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 24_000 # $2,000/month > $1,330.15 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Gross income: $2,000/month > $1,330.15 + ia_fip_gross_income_eligible: false + +- name: Case 4, mixed earned and unearned income at threshold. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 # $500/month earned + social_security: 9_600 # $800/month unearned + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Gross income: $500 + $800 = $1,300/month < $1,330.15 + ia_fip_gross_income_eligible: true + +- name: Case 5, two-parent family with two children. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 18_000 # $1,500/month + person2: + age: 32 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: IA + output: + # Family of 4: 185% of $986 = $1,824.10/month + # Gross income: $1,500/month < $1,824.10 + ia_fip_gross_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_net_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_net_income_eligible.yaml new file mode 100644 index 00000000000..3d1202d2f85 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_net_income_eligible.yaml @@ -0,0 +1,144 @@ +# Test 2: Net income < standard of need (applicants only) +# Net income = gross income - 20% earned income deduction +# Does NOT include 58% work incentive disregard + +- name: Case 1, no income. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Net income: $0 < $719 + ia_fip_net_income_eligible: true + +- name: Case 2, earned income with 20% deduction passes. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 9_600 # $800/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Gross: $800/month + # 20% deduction: $800 * 0.20 = $160 + # Net: $800 - $160 = $640 < $719 standard of need + ia_fip_net_income_eligible: true + +- name: Case 3, earned income with 20% deduction fails. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Gross: $1,000/month + # 20% deduction: $1,000 * 0.20 = $200 + # Net: $1,000 - $200 = $800 >= $719 standard of need + ia_fip_net_income_eligible: false + +- name: Case 4, unearned income only no deduction. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + social_security: 8_400 # $700/month unearned + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Gross: $700/month (unearned) + # 20% deduction only applies to earned: $0 + # Net: $700 - $0 = $700 < $719 + ia_fip_net_income_eligible: true + +- name: Case 5, mixed income deduction only on earned. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 6_000 # $500/month earned + social_security: 3_600 # $300/month unearned + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: IA + output: + # Gross: $500 + $300 = $800/month + # 20% deduction on earned only: $500 * 0.20 = $100 + # Net: $800 - $100 = $700 < $719 + ia_fip_net_income_eligible: true + +- name: Case 6, larger family higher threshold. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 12_000 # $1,000/month + person2: + age: 32 + person3: + age: 10 + person4: + age: 7 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: IA + output: + # Family of 4: standard of need = $986 + # Gross: $1,000/month + # 20% deduction: $1,000 * 0.20 = $200 + # Net: $1,000 - $200 = $800 < $986 + ia_fip_net_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_resources_eligible.yaml new file mode 100644 index 00000000000..409080b416d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/dhs/fip/ia_fip_resources_eligible.yaml @@ -0,0 +1,99 @@ +- name: Case 1, applicant with resources below limit. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 1_500 + is_tanf_enrolled: false + households: + household: + members: [person1] + state_code: IA + output: + # Applicant limit is $2,000 + ia_fip_resources_eligible: true + +- name: Case 2, applicant with resources above limit. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 2_500 + is_tanf_enrolled: false + households: + household: + members: [person1] + state_code: IA + output: + # Applicant limit is $2,000 + ia_fip_resources_eligible: false + +- name: Case 3, recipient with resources below higher limit. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 4_000 + is_tanf_enrolled: true + households: + household: + members: [person1] + state_code: IA + output: + # Recipient limit is $5,000 + ia_fip_resources_eligible: true + +- name: Case 4, recipient with resources above higher limit. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 6_000 + is_tanf_enrolled: true + households: + household: + members: [person1] + state_code: IA + output: + # Recipient limit is $5,000 + ia_fip_resources_eligible: false + +- name: Case 5, applicant at exact limit. + period: 2025 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 30 + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 2_000 + is_tanf_enrolled: false + households: + household: + members: [person1] + state_code: IA + output: + # At limit should be eligible (<=) + ia_fip_resources_eligible: true diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_countable_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_countable_income_eligible.py new file mode 100644 index 00000000000..de2a29ffbaa --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_countable_income_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ia_fip_countable_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Iowa FIP countable income eligible" + definition_period = MONTH + defined_for = StateCode.IA + reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=20" + + def formula(spm_unit, period, parameters): + # Test 3: Countable income < payment standard + # Countable income applies both 20% deduction AND 58% work incentive disregard + countable_income = spm_unit("ia_fip_countable_income", period) + payment_standard = spm_unit("ia_fip_payment_standard", period) + return countable_income < payment_standard diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_eligible.py similarity index 89% rename from policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py rename to policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_eligible.py index 5d7e12bff3b..c66b0c4a647 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_eligible.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_eligible.py @@ -19,12 +19,12 @@ def formula(spm_unit, period, parameters): immigration_eligible = ( add(spm_unit, period, ["is_citizen_or_legal_immigrant"]) > 0 ) - resource_eligible = spm_unit("ia_fip_resource_eligible", period) + resources_eligible = spm_unit("ia_fip_resources_eligible", period) income_eligible = spm_unit("ia_fip_income_eligible", period) return ( has_children & immigration_eligible - & resource_eligible + & resources_eligible & income_eligible ) diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_gross_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_gross_income_eligible.py new file mode 100644 index 00000000000..7de595a60eb --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_gross_income_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ia_fip_gross_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Iowa FIP gross income eligible" + definition_period = MONTH + defined_for = StateCode.IA + reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=20" + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.ia.dhs.fip.income + gross_income = spm_unit("ia_fip_gross_income", period) + standard_of_need = spm_unit("ia_fip_standard_of_need", period) + gross_income_limit = standard_of_need * p.gross_income_limit_percent + return gross_income <= gross_income_limit diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_income_eligible.py new file mode 100644 index 00000000000..0e2cf7f48eb --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_income_eligible.py @@ -0,0 +1,46 @@ +from policyengine_us.model_api import * + + +class ia_fip_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Iowa FIP income eligible" + definition_period = MONTH + defined_for = StateCode.IA + reference = ( + "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=19", + "https://www.law.cornell.edu/regulations/iowa/Iowa-Code-r-441-41.27", + ) + + def formula(spm_unit, period, parameters): + # Iowa FIP has different income tests for initial vs continuing eligibility + # per IAC 441-41.27(239B): + # + # Initial eligibility (3-step process): + # 1. Gross income <= 185% of standard of need + # 2. Net income (after 20% earned income deduction) < standard of need + # 3. Countable income (after 58% work incentive disregard) < payment standard + # + # Continuing eligibility (2-step process): + # 1. Gross income <= 185% of standard of need + # 2. Countable income (after 58% work incentive disregard) < payment standard + # + # The work incentive disregard does NOT apply to the net income test (step 2) + # for initial eligibility. Continuing recipients skip step 2 entirely. + + is_enrolled = spm_unit("is_tanf_enrolled", period) + gross_income_eligible = spm_unit( + "ia_fip_gross_income_eligible", period + ) + net_income_eligible = spm_unit("ia_fip_net_income_eligible", period) + countable_income_eligible = spm_unit( + "ia_fip_countable_income_eligible", period + ) + + return where( + is_enrolled, + gross_income_eligible & countable_income_eligible, + gross_income_eligible + & net_income_eligible + & countable_income_eligible, + ) diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_net_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_net_income_eligible.py new file mode 100644 index 00000000000..d9cd54ffcce --- /dev/null +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_net_income_eligible.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class ia_fip_net_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Iowa FIP net income eligible" + definition_period = MONTH + defined_for = StateCode.IA + reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=20" + + def formula(spm_unit, period, parameters): + # Test 2 for initial eligibility only + # Net income = gross income - 20% earned income deduction + # Must be < standard of need + # Note: Does NOT include the 58% work incentive disregard + p = parameters(period).gov.states.ia.dhs.fip.income + gross_income = spm_unit("ia_fip_gross_income", period) + gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) + earned_income_deduction = gross_earned * p.earned_income_deduction + net_income = gross_income - earned_income_deduction + standard_of_need = spm_unit("ia_fip_standard_of_need", period) + return net_income < standard_of_need diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_resources_eligible.py similarity index 88% rename from policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py rename to policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_resources_eligible.py index 88d413df7e9..0c71bdd2128 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_resource_eligible.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/eligibility/ia_fip_resources_eligible.py @@ -1,10 +1,10 @@ from policyengine_us.model_api import * -class ia_fip_resource_eligible(Variable): +class ia_fip_resources_eligible(Variable): value_type = bool entity = SPMUnit - label = "Iowa FIP resource eligible" + label = "Iowa FIP resources eligible" definition_period = MONTH defined_for = StateCode.IA reference = "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=16" diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py deleted file mode 100644 index 3836cce4353..00000000000 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_income_eligible.py +++ /dev/null @@ -1,67 +0,0 @@ -from policyengine_us.model_api import * - - -class ia_fip_income_eligible(Variable): - value_type = bool - entity = SPMUnit - label = "Iowa FIP income eligible" - definition_period = MONTH - defined_for = StateCode.IA - reference = ( - "https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=19", - "https://www.law.cornell.edu/regulations/iowa/Iowa-Code-r-441-41.27", - ) - - def formula(spm_unit, period, parameters): - p = parameters(period).gov.states.ia.dhs.fip.income - - # Iowa FIP has different income tests for initial vs continuing eligibility - # per IAC 441-41.27(239B): - # - # Initial eligibility (3-step process): - # 1. Gross income <= 185% of standard of need - # 2. Net income (after 20% earned income deduction) < standard of need - # 3. Countable income (after 58% work incentive disregard) < payment standard - # - # Continuing eligibility (2-step process): - # 1. Gross income <= 185% of standard of need - # 2. Countable income (after 58% work incentive disregard) < payment standard - # - # The work incentive disregard does NOT apply to the net income test (step 2) - # for initial eligibility. Continuing recipients skip step 2 entirely. - - is_enrolled = spm_unit("is_tanf_enrolled", period) - - # Test 1: Gross income <= 185% of standard of need (applies to both) - gross_income = spm_unit("ia_fip_gross_income", period) - standard_of_need = spm_unit("ia_fip_standard_of_need", period) - gross_income_limit = standard_of_need * p.gross_income_limit_percent - gross_income_eligible = gross_income <= gross_income_limit - - # Test 2: Net income < standard of need (initial eligibility only) - # Uses 20% earned income deduction but NOT the 58% work incentive disregard - gross_earned_income = add( - spm_unit, period, ["tanf_gross_earned_income"] - ) - earned_income_deduction = ( - gross_earned_income * p.earned_income_deduction - ) - net_income = gross_income - earned_income_deduction - net_income_eligible = net_income < standard_of_need - - # Test 3: Countable income < payment standard (applies to both) - # Uses both 20% deduction AND 58% work incentive disregard - countable_income = spm_unit("ia_fip_countable_income", period) - payment_standard = spm_unit("ia_fip_payment_standard", period) - payment_standard_eligible = countable_income < payment_standard - - # Apply appropriate tests based on enrollment status - return where( - is_enrolled, - # Continuing eligibility: tests 1 and 3 only - gross_income_eligible & payment_standard_eligible, - # Initial eligibility: all three tests - gross_income_eligible - & net_income_eligible - & payment_standard_eligible, - ) From 8be5e86e9db30b1c4edfabe767bc9857d307695b Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 2 Feb 2026 15:17:46 -0500 Subject: [PATCH 27/29] Fix reference format: move inline comments to title field Co-Authored-By: Claude Opus 4.5 --- .../states/ia/dhs/fip/income/work_incentive_disregard.yaml | 4 ++-- .../parameters/gov/states/ia/dhs/fip/max_unit_size.yaml | 4 ++-- .../gov/states/ia/dhs/fip/payment_standard/additional.yaml | 4 ++-- .../gov/states/ia/dhs/fip/payment_standard/main.yaml | 4 ++-- .../gov/states/ia/dhs/fip/resources/applicant_limit.yaml | 4 ++-- .../gov/states/ia/dhs/fip/resources/recipient_limit.yaml | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml index 7252c2e44d9..d501faae8e0 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml @@ -10,5 +10,5 @@ metadata: reference: - title: Iowa Administrative Code 441-41.27(239B) - Income, 41.27(2)(c) href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=21 - - title: Iowa TANF State Plan 2025 - href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) + - title: Iowa TANF State Plan 2025, Section (3) + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml index 5c5bd3eb9dc..70639524403 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml @@ -10,5 +10,5 @@ metadata: reference: - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 - - title: Iowa TANF State Plan 2025 - href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) + - title: Iowa TANF State Plan 2025, Section (3) + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml index f58e6624b89..c1758e399a7 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml @@ -10,5 +10,5 @@ metadata: reference: - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 - - title: Iowa TANF State Plan 2025 - href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) - Net Monthly Income Limits + - title: Iowa TANF State Plan 2025, Section (3) + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml index 00a41c1d980..2006301e66b 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml @@ -32,5 +32,5 @@ metadata: reference: - title: Iowa Administrative Code 441-41.28(239B) - Need Standards, 41.28(2) href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 - - title: Iowa TANF State Plan 2025 - href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) - Net Monthly Income Limits + - title: Iowa TANF State Plan 2025, Section (3) + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml index cdffb8f65c1..cd13b716678 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml @@ -10,5 +10,5 @@ metadata: reference: - title: Iowa Administrative Code 441-41.26(239B) - Resources, 41.26(1)(e) href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf#page=1 - - title: Iowa TANF State Plan 2025 - href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) + - title: Iowa TANF State Plan 2025, Section (3) + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml index aa33293739a..eb37cdf0fff 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml @@ -10,5 +10,5 @@ metadata: reference: - title: Iowa Administrative Code 441-41.26(239B) - Resources, 41.26(1)(e) href: https://www.legis.iowa.gov/docs/iac/rule/441.41.26.pdf#page=1 - - title: Iowa TANF State Plan 2025 - href: https://hhs.iowa.gov/media/17445/download?inline#page=7 # (3) + - title: Iowa TANF State Plan 2025, Section (3) + href: https://hhs.iowa.gov/media/17445/download?inline#page=7 From 400037cf4da76eb1c4f3a97ba21ea90c194c70ef Mon Sep 17 00:00:00 2001 From: Ziming Date: Mon, 2 Feb 2026 15:18:53 -0500 Subject: [PATCH 28/29] Update changelog wording Co-Authored-By: Claude Opus 4.5 --- changelog_entry.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog_entry.yaml b/changelog_entry.yaml index 461b0ea7095..65926855c36 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -1,4 +1,4 @@ - bump: minor changes: added: - - Iowa TANF (Temporary Assistance for Needy Families) program, or FIP (Family Investment Program). + - Iowa Family Investment Program (FIP), the state's TANF cash assistance program. From b3361c24f9b7f3099964affc00570527ec1860aa Mon Sep 17 00:00:00 2001 From: Ziming Date: Fri, 13 Feb 2026 12:01:45 -0500 Subject: [PATCH 29/29] change date --- .../fip/income/earned_income_deduction.yaml | 2 +- .../income/gross_income_limit_percent.yaml | 2 +- .../fip/income/work_incentive_disregard.yaml | 3 ++- .../gov/states/ia/dhs/fip/max_unit_size.yaml | 2 +- .../ia/dhs/fip/need_standard/additional.yaml | 2 +- .../states/ia/dhs/fip/need_standard/main.yaml | 20 +++++++++---------- .../dhs/fip/payment_standard/additional.yaml | 2 +- .../ia/dhs/fip/payment_standard/main.yaml | 20 +++++++++---------- .../ia/dhs/fip/resources/applicant_limit.yaml | 2 +- .../ia/dhs/fip/resources/recipient_limit.yaml | 2 +- .../ia/dhs/fip/ia_fip_payment_standard.py | 2 +- .../ia/dhs/fip/ia_fip_standard_of_need.py | 2 +- uv.lock | 2 +- 13 files changed, 32 insertions(+), 31 deletions(-) diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml index 9baff3f865f..172343734d7 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/earned_income_deduction.yaml @@ -1,7 +1,7 @@ description: Iowa deducts this percentage of the gross nonexempt earned income under the Family Investment Program. values: - 2017-01-01: 0.2 + 1997-01-01: 0.2 metadata: unit: /1 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml index f776f586815..781963b08dd 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/gross_income_limit_percent.yaml @@ -1,7 +1,7 @@ description: Iowa sets the gross income limit for the first income eligibility test as this percentage of the standard of need under the Family Investment Program. values: - 2017-01-01: 1.85 + 1997-01-01: 1.85 metadata: unit: /1 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml index d501faae8e0..d47abbb3595 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/income/work_incentive_disregard.yaml @@ -1,7 +1,8 @@ description: Iowa deducts this rate of work incentive disregard after the earned income deduction under the Family Investment Program. values: - 2017-01-01: 0.58 + 1997-01-01: 0.5 + 2007-08-01: 0.58 metadata: unit: /1 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml index 70639524403..dfaf8d43f48 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/max_unit_size.yaml @@ -1,7 +1,7 @@ description: Iowa sets this maximum unit size for determining standard of need and payment standards under the Family Investment Program. values: - 2017-01-01: 10 + 1997-01-01: 10 metadata: unit: person diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml index 4216df9d645..ac6231c785e 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/additional.yaml @@ -9,4 +9,4 @@ metadata: href: https://www.legis.iowa.gov/docs/iac/chapter/01-07-2026.441.41.pdf#page=31 values: - 2017-01-01: 173 + 1997-01-01: 173 diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml index b353747b5c1..422eb6c8f89 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/need_standard/main.yaml @@ -1,25 +1,25 @@ description: Iowa sets these values as the standard of need amount, or the schedule of living costs, by family size under the Family Investment Program. 1: - 2017-01-01: 365 + 1997-01-01: 365 2: - 2017-01-01: 719 + 1997-01-01: 719 3: - 2017-01-01: 849 + 1997-01-01: 849 4: - 2017-01-01: 986 + 1997-01-01: 986 5: - 2017-01-01: 1_092 + 1997-01-01: 1_092 6: - 2017-01-01: 1_216 + 1997-01-01: 1_216 7: - 2017-01-01: 1_335 + 1997-01-01: 1_335 8: - 2017-01-01: 1_457 + 1997-01-01: 1_457 9: - 2017-01-01: 1_576 + 1997-01-01: 1_576 10: - 2017-01-01: 1_724 + 1997-01-01: 1_724 metadata: unit: currency-USD diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml index c1758e399a7..5d606aafc02 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/additional.yaml @@ -1,7 +1,7 @@ description: Iowa sets this value as the additional payment standard amount per person for families larger than the max unit size under the Family Investment Program. values: - 2017-01-01: 87 + 1997-01-01: 87 metadata: unit: currency-USD diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml index 2006301e66b..9064794ebab 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/payment_standard/main.yaml @@ -1,25 +1,25 @@ description: Iowa sets these values as the payment standard, or the schedule of basic needs, by family size under the Family Investment Program. 1: - 2017-01-01: 183 + 1997-01-01: 183 2: - 2017-01-01: 361 + 1997-01-01: 361 3: - 2017-01-01: 426 + 1997-01-01: 426 4: - 2017-01-01: 495 + 1997-01-01: 495 5: - 2017-01-01: 548 + 1997-01-01: 548 6: - 2017-01-01: 610 + 1997-01-01: 610 7: - 2017-01-01: 670 + 1997-01-01: 670 8: - 2017-01-01: 731 + 1997-01-01: 731 9: - 2017-01-01: 791 + 1997-01-01: 791 10: - 2017-01-01: 865 + 1997-01-01: 865 metadata: unit: currency-USD diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml index cd13b716678..e0804c5005c 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/applicant_limit.yaml @@ -1,7 +1,7 @@ description: Iowa limits resources to this amount under the Family Investment Program (FIP) for applicant families. values: - 2017-01-01: 2_000 + 1997-01-01: 2_000 metadata: unit: currency-USD diff --git a/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml index eb37cdf0fff..2f6bd2b4278 100644 --- a/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml +++ b/policyengine_us/parameters/gov/states/ia/dhs/fip/resources/recipient_limit.yaml @@ -1,7 +1,7 @@ description: Iowa limits resources to this amount under the Family Investment Program for recipient families (received FIP in prior month). values: - 2017-01-01: 5_000 + 1997-01-01: 5_000 metadata: unit: currency-USD diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_payment_standard.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_payment_standard.py index 8058dbce972..ecde0f97809 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_payment_standard.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_payment_standard.py @@ -12,7 +12,7 @@ class ia_fip_payment_standard(Variable): def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ia.dhs.fip - people = spm_unit("spm_unit_size", period) + people = spm_unit("spm_unit_size", period.this_year) capped_people = min_(people, p.max_unit_size).astype(int) additional_people = people - capped_people diff --git a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py index ae1cb09e317..0c729672485 100644 --- a/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py +++ b/policyengine_us/variables/gov/states/ia/dhs/fip/ia_fip_standard_of_need.py @@ -12,7 +12,7 @@ class ia_fip_standard_of_need(Variable): def formula(spm_unit, period, parameters): p = parameters(period).gov.states.ia.dhs.fip - people = spm_unit("spm_unit_size", period) + people = spm_unit("spm_unit_size", period.this_year) capped_people = min_(people, p.max_unit_size).astype(int) additional_people = people - capped_people diff --git a/uv.lock b/uv.lock index f11130ff8a4..66293da3350 100644 --- a/uv.lock +++ b/uv.lock @@ -1664,7 +1664,7 @@ wheels = [ [[package]] name = "policyengine-us" -version = "1.534.2" +version = "1.549.0" source = { editable = "." } dependencies = [ { name = "microdf-python" },