From 84ee04a841208cfa76bba2e891e19e5e64a3f24c Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 6 Jan 2026 16:01:34 -0500 Subject: [PATCH 1/5] Add South Carolina TANF program MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements the South Carolina Department of Social Services Family Independence (FI) TANF program including: - Eligibility determination (income and resource tests) - Gross income limit based on FPL - Net income calculation with earned income disregards - Payment standard by family size - Resource limits and countable resources - Integration tests Fixes #4218 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../parameters/gov/states/sc/tanf/README.md | 1 + .../tanf/income/earned/disregard/amount.yaml | 11 +++ .../earned/disregard/percentage/months.yaml | 11 +++ .../earned/disregard/percentage/rate.yaml | 11 +++ .../states/sc/tanf/income/earned/earned.yaml | 13 +++ .../sc/tanf/income/gross_income_limit.yaml | 11 +++ .../sc/tanf/income/need_standard/rate.yaml | 11 +++ .../gov/states/sc/tanf/income/unearned.yaml | 29 ++++++ .../gov/states/sc/tanf/payment/rate.yaml | 11 +++ .../gov/states/sc/tanf/resources/limit.yaml | 11 +++ .../gov/states/sc/tanf/resources/list.yaml | 22 +++++ .../baseline/gov/states/sc/tanf/sc_tanf.yaml | 38 ++++++++ .../gov/states/sc/tanf/sc_tanf_eligible.yaml | 40 ++++++++ .../gov/states/sc/tanf/sc_tanf_fpg.yaml | 45 +++++++++ .../sc/tanf/sc_tanf_income_eligible.yaml | 48 ++++++++++ .../states/sc/tanf/sc_tanf_integration.yaml | 94 +++++++++++++++++++ .../states/sc/tanf/sc_tanf_net_income.yaml | 47 ++++++++++ .../sc/tanf/sc_tanf_resource.eligible.yaml | 50 ++++++++++ .../sc/tanf/eligibility/sc_tanf_eligible.py | 15 +++ .../eligibility/sc_tanf_income_eligible.py | 27 ++++++ .../eligibility/sc_tanf_resource_eligible.py | 28 ++++++ .../sc/tanf/income/sc_tanf_earned_income.py | 11 +++ .../sc/tanf/income/sc_tanf_net_income.py | 35 +++++++ .../sc/tanf/income/sc_tanf_unearned_income.py | 11 +++ .../variables/gov/states/sc/tanf/sc_tanf.py | 22 +++++ .../sc/tanf/sc_tanf_countable_resources.py | 11 +++ .../gov/states/sc/tanf/sc_tanf_fpg.py | 29 ++++++ 27 files changed, 693 insertions(+) create mode 100644 policyengine_us/parameters/gov/states/sc/tanf/README.md create mode 100644 policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml create mode 100644 policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml create mode 100644 policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml create mode 100644 policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml create mode 100644 policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml create mode 100644 policyengine_us/parameters/gov/states/sc/tanf/income/need_standard/rate.yaml create mode 100644 policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml create mode 100644 policyengine_us/parameters/gov/states/sc/tanf/payment/rate.yaml create mode 100644 policyengine_us/parameters/gov/states/sc/tanf/resources/limit.yaml create mode 100644 policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_fpg.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_income_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_integration.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_net_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resource.eligible.yaml create mode 100644 policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py create mode 100644 policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resource_eligible.py create mode 100644 policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_earned_income.py create mode 100644 policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_net_income.py create mode 100644 policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_unearned_income.py create mode 100644 policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py create mode 100644 policyengine_us/variables/gov/states/sc/tanf/sc_tanf_countable_resources.py create mode 100644 policyengine_us/variables/gov/states/sc/tanf/sc_tanf_fpg.py diff --git a/policyengine_us/parameters/gov/states/sc/tanf/README.md b/policyengine_us/parameters/gov/states/sc/tanf/README.md new file mode 100644 index 00000000000..eb8aeb3f951 --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tanf/README.md @@ -0,0 +1 @@ +# Temporary Assistance for Needy Families diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml new file mode 100644 index 00000000000..8913350a63b --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml @@ -0,0 +1,11 @@ +description: South Carolina excludes this amount from earned income, after the initial disregard period, under the TANF program. +values: + 2021-01-01: 100 + +metadata: + unit: currency-USD + period: year + label: South Carolina TANF earned income disregard amount + reference: + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=130 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml new file mode 100644 index 00000000000..a27ca9c5c69 --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml @@ -0,0 +1,11 @@ +description: South Carolina applies a percentage disregard to the earned income for this number of months, under the TANF program. +values: + 2021-01-01: 4 + +metadata: + unit: month + period: year + label: South Carolina TANF earned income percentage disregard applicable months + reference: + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=130 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml new file mode 100644 index 00000000000..59687679543 --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml @@ -0,0 +1,11 @@ +description: South Carolina disregards this share of earnings from the TANF earned income. +values: + 2021-01-01: 0.5 + +metadata: + unit: /1 + period: year + label: South Carolina TANF earned income disregard percentage + reference: + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=130 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml new file mode 100644 index 00000000000..2fd3ec7f9ed --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml @@ -0,0 +1,13 @@ +description: South Carolina counts these income sources as earned income under the TANF program. +values: + 2021-01-01: + - employment_income + - self_employment_income +metadata: + unit: list + period: year + label: South Carolina TANF earned income + reference: + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=100 + diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml new file mode 100644 index 00000000000..c05710a6af8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml @@ -0,0 +1,11 @@ +description: South Carolina limits TANF to filers with gross income below this percentage of the need standard. # need standard is 50% of fpg. +values: + 2021-01-01: 1.85 + +metadata: + unit: /1 + period: year + label: South Carolina TANF gross income limit + reference: + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=131 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/need_standard/rate.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/need_standard/rate.yaml new file mode 100644 index 00000000000..05621bc0432 --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/need_standard/rate.yaml @@ -0,0 +1,11 @@ +description: South Carolina limits TANF to filers with earned income below this percentage of federal poverty guidelines. +values: + 2021-01-01: 0.5 + +metadata: + unit: /1 + period: year + label: South Carolina TANF need standard + reference: + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=131 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml new file mode 100644 index 00000000000..f33aec6cd91 --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml @@ -0,0 +1,29 @@ +description: South Carolina counts these income sources as unearned income under the TANF program. +values: + 2021-01-01: + - partnership_s_corp_income + - farm_income + - farm_rent_income + - capital_gains + - taxable_interest_income + - rental_income + # Royalties included in rental income + - dividend_income + - taxable_pension_income + # Pension income includes annuities and endowment contracts + - debt_relief + # Decedent income + # Estate interest income + - taxable_unemployment_compensation + - taxable_social_security + - illicit_income + - taxable_retirement_distributions + - miscellaneous_income +metadata: + unit: list + period: year + label: South Carolina TANF unearned income + reference: + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=100 + diff --git a/policyengine_us/parameters/gov/states/sc/tanf/payment/rate.yaml b/policyengine_us/parameters/gov/states/sc/tanf/payment/rate.yaml new file mode 100644 index 00000000000..132644be46d --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tanf/payment/rate.yaml @@ -0,0 +1,11 @@ +description: South Carolina multiplies that excess of the need standard over the net income by this rate, under the TANF program. +values: + 2021-01-01: 0.3372 + +metadata: + unit: /1 + period: year + label: South Carolina TANF payment rate + reference: + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=131 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/resources/limit.yaml b/policyengine_us/parameters/gov/states/sc/tanf/resources/limit.yaml new file mode 100644 index 00000000000..8b40390c5a2 --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tanf/resources/limit.yaml @@ -0,0 +1,11 @@ +description: South Carolina limits TANF to households with up to this resource amount. +values: + 2021-10-01: 2_500 + +metadata: + unit: currency-USD + period: year + label: South Carolina TANF household resource limit + reference: + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=90 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml b/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml new file mode 100644 index 00000000000..1ede796b518 --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml @@ -0,0 +1,22 @@ +description: South Carolina accounts for the following resources under the TANF program. +values: + 2021-01-01: + - spm_unit_cash_assets + - retirement_distributions + #- Lump sum payments + #- Prepaid burial contract + #- Refunds of security deposits + #- Revocable trust account + #- Saving certificate + #- Stocks/bonds + #- Building(s) not associated with homestead + #- Non-hoestead property + +metadata: + unit: list + period: year + label: South Carolina TANF household resources + reference: + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=91 + diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf.yaml new file mode 100644 index 00000000000..88830698915 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf.yaml @@ -0,0 +1,38 @@ +- name: Case 1, no earned income is eligible for standard amount. + absolute_error_margin: 1 + period: 2022 + input: + state_code: SC + sc_tanf_net_income: 0 + sc_tanf_eligible: true + spm_unit_size: 2 + state_group_str: CONTIGUOUS_US + output: + sc_tanf: 2974.5 + # tanf = (12880+4540)*9*0.3372*0.5/12 + (13590+4720)*3*0.50.3372/12 = 2974.5255 + +- name: Case 2, did not pass the gross income test. + absolute_error_margin: 1 + period: 2022 + input: + state_code: SC + sc_tanf_net_income: 19_200 + sc_tanf_eligible: false + spm_unit_size: 2 + state_group_str: CONTIGUOUS_US + output: + sc_tanf: 0 + +- name: Case 3, some income. + absolute_error_margin: 1 + period: 2022 + input: + state_code: SC + sc_tanf_net_income: 8_158 + sc_tanf_eligible: true + spm_unit_size: 2 + state_group_str: CONTIGUOUS_US + output: + sc_tanf: 223.6 + + diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_eligible.yaml new file mode 100644 index 00000000000..d06d88f8f23 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_eligible.yaml @@ -0,0 +1,40 @@ +- name: Case 1, eligible for all. + period: 2022 + input: + state_code: SC + is_demographic_tanf_eligible: true + sc_tanf_income_eligible: true + sc_tanf_resource_eligible: true + output: + sc_tanf_eligible: true + +- name: Case 2, not eligible for one. + period: 2022 + input: + state_code: SC + is_demographic_tanf_eligible: false + sc_tanf_income_eligible: true + sc_tanf_resource_eligible: true + output: + sc_tanf_eligible: false + +- name: Case 3, not eligible for one. + period: 2022 + input: + state_code: SC + is_demographic_tanf_eligible: true + sc_tanf_income_eligible: false + sc_tanf_resource_eligible: true + output: + sc_tanf_eligible: false + +- name: Case 4, not eligible for two. + period: 2022 + input: + state_code: SC + is_demographic_tanf_eligible: false + sc_tanf_income_eligible: true + sc_tanf_resource_eligible: false + output: + sc_tanf_eligible: false + diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_fpg.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_fpg.yaml new file mode 100644 index 00000000000..045a5e881f4 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_fpg.yaml @@ -0,0 +1,45 @@ +- name: Household of 3, all child are qualify. + absolute_error_margin: 1 + period: 2022 + input: + people: + parent: + employment_income: 0 + child1: + is_child_dependent: true + age: 10 + child2: + is_child_dependent: true + age: 10 + spm_units: + spm_unit: + members: [parent, child1, child2] + households: + household: + members: [parent, child1, child2] + state_code: SC + output: + sc_tanf_fpg: 22_227.5 + +- name: Household of 2, only one child is qualify. + absolute_error_margin: 1 + period: 2022 + input: + people: + parent: + employment_income: 0 + child1: + is_child_dependent: true + age: 10 + child2: + is_child_dependent: false + age: 10 + spm_units: + spm_unit: + members: [parent, child1, child2] + households: + household: + members: [parent, child1, child2] + state_code: SC + output: + sc_tanf_fpg: 17_642.5 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_income_eligible.yaml new file mode 100644 index 00000000000..e7a32bf257e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_income_eligible.yaml @@ -0,0 +1,48 @@ +- name: Case 1, no earned income is eligible. + period: 2022 + input: + state_code: SC + state_group_str: CONTIGUOUS_US + sc_tanf_net_income: 0 + sc_tanf_earned_income: 0 + spm_unit_size: 2 + output: + sc_tanf_income_eligible: true + +- name: Case 2, did not pass the gross income test. + period: 2022 + input: + state_code: SC + state_group_str: CONTIGUOUS_US + sc_tanf_net_income: 19_200 + sc_tanf_earned_income: 24_000 + spm_unit_size: 2 + output: + sc_tanf_income_eligible: false + # gross income limit for size 2 is 16300 + # need standard: 762*3 + 725*9 = 8811 + +- name: Case 3, pass gross income test but higher than the need standard. + period: 2022 + input: + state_code: SC + state_group_str: CONTIGUOUS_US + sc_tanf_net_income: 9_200 + sc_tanf_earned_income: 12_000 + spm_unit_size: 2 + output: + sc_tanf_income_eligible: false + # need standard for size 2 is 8811. + # gross income limit for size 2 is 16300. + + +- name: Case 4, pass need standard test and gross income test. + period: 2022 + input: + state_code: SC + state_group_str: CONTIGUOUS_US + sc_tanf_net_income: 8_000 + sc_tanf_earned_income: 10_750 + spm_unit_size: 2 + output: + sc_tanf_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_integration.yaml new file mode 100644 index 00000000000..bc6722b8355 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_integration.yaml @@ -0,0 +1,94 @@ +- name: Single parent of 2 children. + absolute_error_margin: 1 + period: 2022 + input: + people: + parent: + age: 40 + employment_income: 0 + retirement_distributions: 0 + child_support_received: 0 + child1: + age: 10 + is_child_dependent: true + child2: + age: 8 + is_child_dependent: true + spm_units: + spm_unit: + members: [parent, child1,child2] + spm_unit_cash_assets: 1_000 + households: + household: + members: [parent, child1,child2] + household_vehicles_value: 0 + household_vehicles_owned: 0 + state_code: SC + output: + sc_tanf: 3_747.6 + # (12880+4540*2)*9*0.3372*0.5/12 + (13590+4720*2)*3*0.50*0.3372/12 + +- name: Single parent of 3 childre, one child is not eligible. + absolute_error_margin: 1 + period: 2022 + input: + people: + parent: + age: 40 + employment_income: 0 + retirement_distributions: 0 + child_support_received: 0 + child1: + age: 10 + is_child_dependent: true + child2: + age: 8 + is_child_dependent: true + child3: + age: 16 + is_child_dependent: false + spm_units: + spm_unit: + members: [parent, child1,child2,child3] + spm_unit_cash_assets: 1_000 + households: + household: + members: [parent, child1,child2,child3] + household_vehicles_value: 0 + household_vehicles_owned: 0 + state_code: SC + output: + sc_tanf: 3_747.6 + +- name: Single parent of 3 children. + absolute_error_margin: 1 + period: 2022 + input: + people: + parent: + age: 40 + employment_income: 0 + retirement_distributions: 0 + child_support_received: 0 + child1: + age: 10 + is_child_dependent: true + child2: + age: 8 + is_child_dependent: true + child3: + age: 12 + is_child_dependent: true + spm_units: + spm_unit: + members: [parent, child1,child2,child3] + spm_unit_cash_assets: 1_000 + households: + household: + members: [parent, child1,child2,child3] + household_vehicles_value: 3_200 + household_vehicles_owned: 2 + state_code: SC + output: + sc_tanf: 0 + diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_net_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_net_income.yaml new file mode 100644 index 00000000000..3acba3b32c9 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_net_income.yaml @@ -0,0 +1,47 @@ +- name: Case 1, no earned income, then total net income is 0. + absolute_error_margin: 1 + period: 2022 + input: + state_code: SC + sc_tanf_earned_income: 0 + sc_tanf_unearned_income: 0 + child_support_received: 0 + output: + sc_tanf_net_income: 0 + +- name: Case 2, have $24000 earned income. + absolute_error_margin: 1 + period: 2022 + input: + state_code: SC + sc_tanf_earned_income: 24_000 + sc_tanf_unearned_income: 0 + child_support_received: 0 + output: + sc_tanf_net_income: 19_200 + # 4*0.5*24000/12 + 8*24000/12 - 800 = 19200 + +- name: Case 3, have $12000 earned income. + absolute_error_margin: 1 + period: 2022 + input: + state_code: SC + sc_tanf_earned_income: 12_000 + sc_tanf_unearned_income: 0 + child_support_received: 0 + output: + sc_tanf_net_income: 9_200 + # 4*0.5*12000/12 + 8*12000/12 - 800 = 9200 + +- name: Case 4, have some earned income, unearned income and child support. + absolute_error_margin: 1 + period: 2022 + input: + state_code: SC + sc_tanf_earned_income: 10_750 + sc_tanf_unearned_income: 2_000 + child_support_received: 1_000 + output: + sc_tanf_net_income: 9_158 + # 4*0.5*10750/12 + 8*10750/12 - 800 = 8158 + # 8158 + 2000 - 1000 = 9158 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resource.eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resource.eligible.yaml new file mode 100644 index 00000000000..dbf5fe8564f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resource.eligible.yaml @@ -0,0 +1,50 @@ +- name: Case 1, household of 2 adults and 2 vehicles, below the limit. + period: 2022 + input: + state_code: SC + spm_unit_cash_assets: 2_000 + retirement_distributions: 0 + household_vehicles_value: 6_000 + household_vehicles_owned: 2 + spm_unit_count_adults: 2 + output: + sc_tanf_resource_eligible: true + +- name: Case 2, household of 2 adults and 3 vehicles, above the limit. + period: 2022 + input: + state_code: SC + spm_unit_cash_assets: 1_000 + retirement_distributions: 0 + household_vehicles_value: 6_000 + household_vehicles_owned: 3 + spm_unit_count_adults: 2 + output: + sc_tanf_resource_eligible: false + # avg vehicles value = 6000/3 = 2000 + # total resources = 2000+ 1000 = 3000 > 2500 + +- name: Case 3, household of 2 adults and 2 vehicles, above the limit. + period: 2022 + input: + state_code: SC + spm_unit_cash_assets: 2_600 + retirement_distributions: 0 + household_vehicles_value: 6_000 + household_vehicles_owned: 2 + spm_unit_count_adults: 2 + output: + sc_tanf_resource_eligible: false + +- name: Case 4, household of 2 adults and no vehicle, below the limit. + period: 2022 + input: + state_code: SC + spm_unit_cash_assets: 2_000 + retirement_distributions: 0 + household_vehicles_value: 0 + household_vehicles_owned: 0 + spm_unit_count_adults: 2 + output: + sc_tanf_resource_eligible: true + \ No newline at end of file diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py new file mode 100644 index 00000000000..5091bd840a9 --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py @@ -0,0 +1,15 @@ +from policyengine_us.model_api import * + + +class sc_tanf_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "Eligible for the South Carolina TANF program" + definition_period = YEAR + defined_for = StateCode.SC + + def formula(spm_unit, period, parameters): + demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) + income_eligible = spm_unit("sc_tanf_income_eligible", period) + resource_eligible = spm_unit("sc_tanf_resource_eligible", period) + return demographic_eligible & income_eligible & resource_eligible diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_income_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_income_eligible.py new file mode 100644 index 00000000000..110a730e493 --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_income_eligible.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class sc_tanf_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "South Carolina TANF income eligible" + definition_period = YEAR + defined_for = StateCode.SC + reference = ( + "https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=131" + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.sc.tanf.income + fpg = spm_unit("sc_tanf_fpg", period) + # get need standard + need_standard = np.floor(fpg * p.need_standard.rate) + # get gross income limit + gross_income_limit = np.floor(need_standard * p.gross_income_limit) + # check eligibility for income disregard + gross_earned_income = add(spm_unit, period, ["sc_tanf_earned_income"]) + eligible_for_disregard = gross_earned_income <= gross_income_limit + # get total net income and compare it with need standard + net_income = spm_unit("sc_tanf_net_income", period) + income_eligible = net_income < need_standard + return income_eligible & eligible_for_disregard diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resource_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resource_eligible.py new file mode 100644 index 00000000000..36a7106208a --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resource_eligible.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class sc_tanf_resource_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "South Carolina TANF resource eligible" + definition_period = YEAR + defined_for = StateCode.SC + + def formula(spm_unit, period, parameters): + resource_limit = parameters(period).gov.states.sc.tanf.resources.limit + countable_resources = add( + spm_unit, period, ["sc_tanf_countable_resources"] + ) + # Each driver's license can exclude one vehicle. + adult_count = spm_unit("spm_unit_count_adults", period) + vehicle_count = spm_unit.household("household_vehicles_owned", period) + vehicle_value = spm_unit.household("household_vehicles_value", period) + avg_vehicle_value = np.zeros_like(vehicle_count) + mask = vehicle_count != 0 + avg_vehicle_value[mask] = vehicle_value[mask] / vehicle_count[mask] + countable_vehicle_value = ( + vehicle_count - adult_count + ) * avg_vehicle_value + return ( + countable_resources + countable_vehicle_value + ) <= resource_limit diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_earned_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_earned_income.py new file mode 100644 index 00000000000..8ab3d19175d --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_earned_income.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class sc_tanf_earned_income(Variable): + value_type = float + entity = SPMUnit + label = "South Carolina TANF earned income" + unit = USD + definition_period = YEAR + defined_for = StateCode.SC + adds = "gov.states.sc.tanf.income.earned.earned" diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_net_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_net_income.py new file mode 100644 index 00000000000..9294beef4c1 --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_net_income.py @@ -0,0 +1,35 @@ +from policyengine_us.model_api import * + + +class sc_tanf_net_income(Variable): + value_type = float + entity = SPMUnit + label = "South Carolina TANF net income" + unit = USD + definition_period = YEAR + defined_for = StateCode.SC + reference = ( + "https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=131" + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.sc.tanf.income.earned.disregard + gross_earned_income = add(spm_unit, period, ["sc_tanf_earned_income"]) + monthly_income = gross_earned_income / MONTHS_IN_YEAR + # Compute earned income after disregard, first four months has 50% disregard, the rest has $100 deduction. + first_four_months_income = ( + monthly_income * p.percentage.rate * p.percentage.months + ) + remaining_months = max_(MONTHS_IN_YEAR - p.percentage.months, 0) + reduced_remaining_monthly_income = max_(monthly_income - p.amount, 0) + remaining_income = reduced_remaining_monthly_income * remaining_months + earned_income_after_disregard = ( + first_four_months_income + remaining_income + ) + # exclude child support + child_support = add(spm_unit, period, ["child_support_received"]) + net_earned_income = max_( + earned_income_after_disregard - child_support, 0 + ) + unearned_income = add(spm_unit, period, ["sc_tanf_unearned_income"]) + return unearned_income + net_earned_income diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_unearned_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_unearned_income.py new file mode 100644 index 00000000000..3c19fc1fdab --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_unearned_income.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class sc_tanf_unearned_income(Variable): + value_type = float + entity = SPMUnit + label = "South Carolina TANF unearned income" + unit = USD + definition_period = YEAR + defined_for = StateCode.SC + adds = "gov.states.sc.tanf.income.unearned" diff --git a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py new file mode 100644 index 00000000000..b602ebcf7ce --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class sc_tanf(Variable): + value_type = float + entity = SPMUnit + label = "South Carolina TANF" + unit = USD + definition_period = YEAR + defined_for = "sc_tanf_eligible" + reference = ( + "https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=131" + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.sc.tanf + # Compute need standard based on ferderal poverty guidlines + fpg = spm_unit("sc_tanf_fpg", period) + need_standard = fpg * p.income.need_standard.rate + net_income = spm_unit("sc_tanf_net_income", period) + excess_income = need_standard - net_income + return excess_income * p.payment.rate diff --git a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_countable_resources.py b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_countable_resources.py new file mode 100644 index 00000000000..6b443b0c827 --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_countable_resources.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class sc_tanf_countable_resources(Variable): + value_type = float + entity = SPMUnit + label = "South Carolina TANF countable resources" + unit = USD + definition_period = YEAR + defined_for = StateCode.SC + adds = "gov.states.sc.tanf.resources.list" diff --git a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_fpg.py b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_fpg.py new file mode 100644 index 00000000000..f2f7a7a2a4e --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_fpg.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class sc_tanf_fpg(Variable): + value_type = float + entity = SPMUnit + label = "South Carolina TANF federal poverty guideline" + unit = USD + defined_for = StateCode.SC + definition_period = MONTH + + def formula(spm_unit, period, parameters): + size = spm_unit("spm_unit_size", period.this_year) + qualifying_child = add( + spm_unit, period.this_year, ["is_child_dependent"] + ) + child_count = add(spm_unit, period.this_year, ["is_child"]) + n = size - child_count + qualifying_child + state_group = spm_unit.household("state_group_str", period.this_year) + year = period.start.year + month = period.start.month + if month >= 10: + instant_str = f"{year}-10-01" + else: + instant_str = f"{year - 1}-10-01" + p_fpg = parameters(instant_str).gov.hhs.fpg + p1 = p_fpg.first_person[state_group] + pn = p_fpg.additional_person[state_group] + return (p1 + pn * (n - 1)) / MONTHS_IN_YEAR From 9b2b740838aa1197d1af4f6fa06975829e46459e Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 6 Jan 2026 18:06:23 -0500 Subject: [PATCH 2/5] draft --- .../tanf/income/earned/disregard/amount.yaml | 6 +-- .../earned/disregard/percentage/months.yaml | 6 +-- .../earned/disregard/percentage/rate.yaml | 6 +-- .../states/sc/tanf/income/earned/earned.yaml | 11 ++--- .../sc/tanf/income/gross_income_limit.yaml | 8 ++-- .../sc/tanf/income/need_standard/rate.yaml | 14 +++--- .../gov/states/sc/tanf/income/unearned.yaml | 7 ++- .../gov/states/sc/tanf/payment/rate.yaml | 12 +++-- .../gov/states/sc/tanf/resources/limit.yaml | 12 +++-- .../gov/states/sc/tanf/resources/list.yaml | 11 +++-- ...tanf_integration.yaml => integration.yaml} | 0 .../baseline/gov/states/sc/tanf/sc_tanf.yaml | 9 ++-- .../tanf/sc_tanf_countable_earned_income.yaml | 31 ++++++++++++ .../sc_tanf_countable_income_eligible.yaml | 31 ++++++++++++ .../gov/states/sc/tanf/sc_tanf_eligible.yaml | 8 ++-- .../gov/states/sc/tanf/sc_tanf_fpg.yaml | 45 ------------------ .../tanf/sc_tanf_gross_income_eligible.yaml | 33 +++++++++++++ .../sc/tanf/sc_tanf_income_eligible.yaml | 12 ++--- .../states/sc/tanf/sc_tanf_net_income.yaml | 47 ------------------- ...e.yaml => sc_tanf_resources_eligible.yaml} | 8 ++-- .../sc_tanf_countable_income_eligible.py | 19 ++++++++ .../sc/tanf/eligibility/sc_tanf_eligible.py | 2 +- .../sc_tanf_gross_income_eligible.py | 20 ++++++++ .../eligibility/sc_tanf_income_eligible.py | 22 ++++----- ...gible.py => sc_tanf_resources_eligible.py} | 4 +- ....py => sc_tanf_countable_earned_income.py} | 17 ++----- .../tanf/income/sc_tanf_countable_income.py | 18 +++++++ .../sc/tanf/income/sc_tanf_gross_income.py | 18 +++++++ .../variables/gov/states/sc/tanf/sc_tanf.py | 8 ++-- .../gov/states/sc/tanf/sc_tanf_fpg.py | 29 ------------ 30 files changed, 253 insertions(+), 221 deletions(-) rename policyengine_us/tests/policy/baseline/gov/states/sc/tanf/{sc_tanf_integration.yaml => integration.yaml} (100%) create mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_income_eligible.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_fpg.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_gross_income_eligible.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_net_income.yaml rename policyengine_us/tests/policy/baseline/gov/states/sc/tanf/{sc_tanf_resource.eligible.yaml => sc_tanf_resources_eligible.yaml} (89%) create mode 100644 policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_countable_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_gross_income_eligible.py rename policyengine_us/variables/gov/states/sc/tanf/eligibility/{sc_tanf_resource_eligible.py => sc_tanf_resources_eligible.py} (91%) rename policyengine_us/variables/gov/states/sc/tanf/income/{sc_tanf_net_income.py => sc_tanf_countable_earned_income.py} (59%) create mode 100644 policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_income.py create mode 100644 policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_income.py delete mode 100644 policyengine_us/variables/gov/states/sc/tanf/sc_tanf_fpg.py diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml index 8913350a63b..f22e5a85a76 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml @@ -1,6 +1,6 @@ -description: South Carolina excludes this amount from earned income, after the initial disregard period, under the TANF program. +description: South Carolina excludes this amount from earned income after the initial disregard period under the Temporary Assistance for Needy Families program. values: - 2021-01-01: 100 + 1996-07-01: 100 metadata: unit: currency-USD @@ -8,4 +8,4 @@ metadata: label: South Carolina TANF earned income disregard amount reference: - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=130 + href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=130 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml index a27ca9c5c69..7fc0fd43486 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml @@ -1,6 +1,6 @@ -description: South Carolina applies a percentage disregard to the earned income for this number of months, under the TANF program. +description: South Carolina applies the earned income percentage disregard for this number of months under the Temporary Assistance for Needy Families program. values: - 2021-01-01: 4 + 1996-07-01: 4 metadata: unit: month @@ -8,4 +8,4 @@ metadata: label: South Carolina TANF earned income percentage disregard applicable months reference: - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=130 + href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=130 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml index 59687679543..09219129231 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml @@ -1,6 +1,6 @@ -description: South Carolina disregards this share of earnings from the TANF earned income. +description: South Carolina excludes this share of earnings from countable income under the Temporary Assistance for Needy Families program. values: - 2021-01-01: 0.5 + 1996-07-01: 0.5 metadata: unit: /1 @@ -8,4 +8,4 @@ metadata: label: South Carolina TANF earned income disregard percentage reference: - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=130 + href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=130 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml index 2fd3ec7f9ed..85e0d853d23 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml @@ -1,13 +1,12 @@ -description: South Carolina counts these income sources as earned income under the TANF program. +description: South Carolina counts these income sources as earned income under the Temporary Assistance for Needy Families program. values: - 2021-01-01: - - employment_income - - self_employment_income + 1996-07-01: + - employment_income_before_lsr + - self_employment_income_before_lsr metadata: unit: list period: year label: South Carolina TANF earned income reference: - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=100 - + href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=100 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml index c05710a6af8..1b0a4250f2e 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml @@ -1,6 +1,6 @@ -description: South Carolina limits TANF to filers with gross income below this percentage of the need standard. # need standard is 50% of fpg. -values: - 2021-01-01: 1.85 +description: South Carolina limits gross income to this multiple of the need standard under the Temporary Assistance for Needy Families program. +values: + 1996-07-01: 1.85 metadata: unit: /1 @@ -8,4 +8,4 @@ metadata: label: South Carolina TANF gross income limit reference: - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=131 + href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/need_standard/rate.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/need_standard/rate.yaml index 05621bc0432..d9c643a8a83 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/need_standard/rate.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/need_standard/rate.yaml @@ -1,11 +1,13 @@ -description: South Carolina limits TANF to filers with earned income below this percentage of federal poverty guidelines. -values: - 2021-01-01: 0.5 +description: South Carolina sets this share of the federal poverty guidelines as the need standard under the Temporary Assistance for Needy Families program. +values: + 1996-07-01: 0.5 metadata: unit: /1 period: year - label: South Carolina TANF need standard + label: South Carolina TANF need standard reference: - - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=131 + - title: S.C. Code Regs. § 114-1140(A)(2) + href: https://www.law.cornell.edu/regulations/south-carolina/S-C-Code-Regs-114-1140 + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml index f33aec6cd91..911bf119a05 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml @@ -1,6 +1,6 @@ -description: South Carolina counts these income sources as unearned income under the TANF program. +description: South Carolina counts these income sources as unearned income under the Temporary Assistance for Needy Families program. values: - 2021-01-01: + 1996-07-01: - partnership_s_corp_income - farm_income - farm_rent_income @@ -25,5 +25,4 @@ metadata: label: South Carolina TANF unearned income reference: - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=100 - + href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=100 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/payment/rate.yaml b/policyengine_us/parameters/gov/states/sc/tanf/payment/rate.yaml index 132644be46d..4759e3f15c8 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/payment/rate.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/payment/rate.yaml @@ -1,11 +1,13 @@ -description: South Carolina multiplies that excess of the need standard over the net income by this rate, under the TANF program. -values: - 2021-01-01: 0.3372 +description: South Carolina uses this rate to calculate benefits under the Temporary Assistance for Needy Families program. +values: + 2016-10-01: 0.3372 metadata: unit: /1 period: year label: South Carolina TANF payment rate reference: - - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=131 + - title: S.C. Code Regs. § 114-1140(A)(3) + href: https://www.law.cornell.edu/regulations/south-carolina/S-C-Code-Regs-114-1140 + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/resources/limit.yaml b/policyengine_us/parameters/gov/states/sc/tanf/resources/limit.yaml index 8b40390c5a2..dc5139bc6b4 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/resources/limit.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/resources/limit.yaml @@ -1,11 +1,13 @@ -description: South Carolina limits TANF to households with up to this resource amount. +description: South Carolina limits resources to this amount under the Temporary Assistance for Needy Families program. values: - 2021-10-01: 2_500 + 1996-07-01: 2_500 metadata: unit: currency-USD period: year - label: South Carolina TANF household resource limit + label: South Carolina TANF household resource limit reference: - - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=90 + - title: S.C. Code Regs. § 114-1140(C) + href: https://www.law.cornell.edu/regulations/south-carolina/S-C-Code-Regs-114-1140 + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=90 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml b/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml index 1ede796b518..5ed4ed66de1 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml @@ -1,6 +1,6 @@ -description: South Carolina accounts for the following resources under the TANF program. +description: South Carolina counts these resources under the Temporary Assistance for Needy Families program. values: - 2021-01-01: + 1996-07-01: - spm_unit_cash_assets - retirement_distributions #- Lump sum payments @@ -17,6 +17,7 @@ metadata: period: year label: South Carolina TANF household resources reference: - - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=91 - + - title: S.C. Code Regs. § 114-1140(C) + href: https://www.law.cornell.edu/regulations/south-carolina/S-C-Code-Regs-114-1140 + - title: The South Carolina Department of Social Services TANF Policy Manual + href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=91 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml similarity index 100% rename from policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_integration.yaml rename to policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf.yaml index 88830698915..73b6dcc5dde 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf.yaml @@ -3,10 +3,9 @@ period: 2022 input: state_code: SC - sc_tanf_net_income: 0 + sc_tanf_countable_income: 0 sc_tanf_eligible: true spm_unit_size: 2 - state_group_str: CONTIGUOUS_US output: sc_tanf: 2974.5 # tanf = (12880+4540)*9*0.3372*0.5/12 + (13590+4720)*3*0.50.3372/12 = 2974.5255 @@ -16,10 +15,9 @@ period: 2022 input: state_code: SC - sc_tanf_net_income: 19_200 + sc_tanf_countable_income: 19_200 sc_tanf_eligible: false spm_unit_size: 2 - state_group_str: CONTIGUOUS_US output: sc_tanf: 0 @@ -28,10 +26,9 @@ period: 2022 input: state_code: SC - sc_tanf_net_income: 8_158 + sc_tanf_countable_income: 8_158 sc_tanf_eligible: true spm_unit_size: 2 - state_group_str: CONTIGUOUS_US output: sc_tanf: 223.6 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income.yaml new file mode 100644 index 00000000000..fe5dbdafbc2 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income.yaml @@ -0,0 +1,31 @@ +- name: Case 1, no earned income. + period: 2024 + input: + state_code: SC + employment_income_before_lsr: 0 + output: + sc_tanf_countable_earned_income: 0 + +- name: Case 2, earned income with disregards. + period: 2024 + input: + state_code: SC + employment_income_before_lsr: 12_000 + output: + sc_tanf_countable_earned_income: 9_200 + # monthly_income = 12,000 / 12 = 1,000 + # first 4 months: 1,000 * 0.5 * 4 = 2,000 + # remaining 8 months: max(1,000 - 100, 0) * 8 = 900 * 8 = 7,200 + # total = 2,000 + 7,200 = 9,200 + +- name: Case 3, low earned income where monthly is less than disregard amount. + period: 2024 + input: + state_code: SC + employment_income_before_lsr: 600 + output: + sc_tanf_countable_earned_income: 100 + # monthly_income = 600 / 12 = 50 + # first 4 months: 50 * 0.5 * 4 = 100 + # remaining 8 months: max(50 - 100, 0) * 8 = 0 * 8 = 0 + # total = 100 + 0 = 100 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_income_eligible.yaml new file mode 100644 index 00000000000..ad78eeb59c3 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_income_eligible.yaml @@ -0,0 +1,31 @@ +- name: Case 1, no income is eligible. + period: 2024 + input: + state_code: SC + spm_unit_size: 2 + output: + sc_tanf_countable_income_eligible: true + +- name: Case 2, countable income below need standard. + period: 2024 + input: + state_code: SC + spm_unit_size: 2 + sc_tanf_countable_income: 10_000 + output: + sc_tanf_countable_income_eligible: true + # FPG for 2 people (2024) = 20,440 + # need_standard = 20,440 * 0.5 = 10,220 + # 10,000 < 10,220 -> eligible + +- name: Case 3, countable income above need standard. + period: 2024 + input: + state_code: SC + spm_unit_size: 2 + sc_tanf_countable_income: 11_000 + output: + sc_tanf_countable_income_eligible: false + # FPG for 2 people (2024) = 20,440 + # need_standard = 20,440 * 0.5 = 10,220 + # 11,000 >= 10,220 -> not eligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_eligible.yaml index d06d88f8f23..5bc3121332d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_eligible.yaml @@ -4,7 +4,7 @@ state_code: SC is_demographic_tanf_eligible: true sc_tanf_income_eligible: true - sc_tanf_resource_eligible: true + sc_tanf_resources_eligible: true output: sc_tanf_eligible: true @@ -14,7 +14,7 @@ state_code: SC is_demographic_tanf_eligible: false sc_tanf_income_eligible: true - sc_tanf_resource_eligible: true + sc_tanf_resources_eligible: true output: sc_tanf_eligible: false @@ -24,7 +24,7 @@ state_code: SC is_demographic_tanf_eligible: true sc_tanf_income_eligible: false - sc_tanf_resource_eligible: true + sc_tanf_resources_eligible: true output: sc_tanf_eligible: false @@ -34,7 +34,7 @@ state_code: SC is_demographic_tanf_eligible: false sc_tanf_income_eligible: true - sc_tanf_resource_eligible: false + sc_tanf_resources_eligible: false output: sc_tanf_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_fpg.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_fpg.yaml deleted file mode 100644 index 045a5e881f4..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_fpg.yaml +++ /dev/null @@ -1,45 +0,0 @@ -- name: Household of 3, all child are qualify. - absolute_error_margin: 1 - period: 2022 - input: - people: - parent: - employment_income: 0 - child1: - is_child_dependent: true - age: 10 - child2: - is_child_dependent: true - age: 10 - spm_units: - spm_unit: - members: [parent, child1, child2] - households: - household: - members: [parent, child1, child2] - state_code: SC - output: - sc_tanf_fpg: 22_227.5 - -- name: Household of 2, only one child is qualify. - absolute_error_margin: 1 - period: 2022 - input: - people: - parent: - employment_income: 0 - child1: - is_child_dependent: true - age: 10 - child2: - is_child_dependent: false - age: 10 - spm_units: - spm_unit: - members: [parent, child1, child2] - households: - household: - members: [parent, child1, child2] - state_code: SC - output: - sc_tanf_fpg: 17_642.5 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_gross_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_gross_income_eligible.yaml new file mode 100644 index 00000000000..7fb1adebb5e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_gross_income_eligible.yaml @@ -0,0 +1,33 @@ +- name: Case 1, no income is eligible. + period: 2024 + input: + state_code: SC + spm_unit_size: 2 + output: + sc_tanf_gross_income_eligible: true + +- name: Case 2, income below gross income limit. + period: 2024 + input: + state_code: SC + spm_unit_size: 2 + employment_income_before_lsr: 18_000 + output: + sc_tanf_gross_income_eligible: true + # FPG for 2 people (2024) = 20,440 + # need_standard = 20,440 * 0.5 = 10,220 + # gross_income_limit = 10,220 * 1.85 = 18,907 + # 18,000 <= 18,907 -> eligible + +- name: Case 3, income above gross income limit. + period: 2024 + input: + state_code: SC + spm_unit_size: 2 + employment_income_before_lsr: 20_000 + output: + sc_tanf_gross_income_eligible: false + # FPG for 2 people (2024) = 20,440 + # need_standard = 20,440 * 0.5 = 10,220 + # gross_income_limit = 10,220 * 1.85 = 18,907 + # 20,000 > 18,907 -> not eligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_income_eligible.yaml index e7a32bf257e..7d0535b9be5 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_income_eligible.yaml @@ -2,8 +2,7 @@ period: 2022 input: state_code: SC - state_group_str: CONTIGUOUS_US - sc_tanf_net_income: 0 + sc_tanf_countable_income: 0 sc_tanf_earned_income: 0 spm_unit_size: 2 output: @@ -13,8 +12,7 @@ period: 2022 input: state_code: SC - state_group_str: CONTIGUOUS_US - sc_tanf_net_income: 19_200 + sc_tanf_countable_income: 19_200 sc_tanf_earned_income: 24_000 spm_unit_size: 2 output: @@ -26,8 +24,7 @@ period: 2022 input: state_code: SC - state_group_str: CONTIGUOUS_US - sc_tanf_net_income: 9_200 + sc_tanf_countable_income: 9_200 sc_tanf_earned_income: 12_000 spm_unit_size: 2 output: @@ -40,8 +37,7 @@ period: 2022 input: state_code: SC - state_group_str: CONTIGUOUS_US - sc_tanf_net_income: 8_000 + sc_tanf_countable_income: 8_000 sc_tanf_earned_income: 10_750 spm_unit_size: 2 output: diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_net_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_net_income.yaml deleted file mode 100644 index 3acba3b32c9..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_net_income.yaml +++ /dev/null @@ -1,47 +0,0 @@ -- name: Case 1, no earned income, then total net income is 0. - absolute_error_margin: 1 - period: 2022 - input: - state_code: SC - sc_tanf_earned_income: 0 - sc_tanf_unearned_income: 0 - child_support_received: 0 - output: - sc_tanf_net_income: 0 - -- name: Case 2, have $24000 earned income. - absolute_error_margin: 1 - period: 2022 - input: - state_code: SC - sc_tanf_earned_income: 24_000 - sc_tanf_unearned_income: 0 - child_support_received: 0 - output: - sc_tanf_net_income: 19_200 - # 4*0.5*24000/12 + 8*24000/12 - 800 = 19200 - -- name: Case 3, have $12000 earned income. - absolute_error_margin: 1 - period: 2022 - input: - state_code: SC - sc_tanf_earned_income: 12_000 - sc_tanf_unearned_income: 0 - child_support_received: 0 - output: - sc_tanf_net_income: 9_200 - # 4*0.5*12000/12 + 8*12000/12 - 800 = 9200 - -- name: Case 4, have some earned income, unearned income and child support. - absolute_error_margin: 1 - period: 2022 - input: - state_code: SC - sc_tanf_earned_income: 10_750 - sc_tanf_unearned_income: 2_000 - child_support_received: 1_000 - output: - sc_tanf_net_income: 9_158 - # 4*0.5*10750/12 + 8*10750/12 - 800 = 8158 - # 8158 + 2000 - 1000 = 9158 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resource.eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resources_eligible.yaml similarity index 89% rename from policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resource.eligible.yaml rename to policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resources_eligible.yaml index dbf5fe8564f..f58e11052d6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resource.eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resources_eligible.yaml @@ -8,7 +8,7 @@ household_vehicles_owned: 2 spm_unit_count_adults: 2 output: - sc_tanf_resource_eligible: true + sc_tanf_resources_eligible: true - name: Case 2, household of 2 adults and 3 vehicles, above the limit. period: 2022 @@ -20,7 +20,7 @@ household_vehicles_owned: 3 spm_unit_count_adults: 2 output: - sc_tanf_resource_eligible: false + sc_tanf_resources_eligible: false # avg vehicles value = 6000/3 = 2000 # total resources = 2000+ 1000 = 3000 > 2500 @@ -34,7 +34,7 @@ household_vehicles_owned: 2 spm_unit_count_adults: 2 output: - sc_tanf_resource_eligible: false + sc_tanf_resources_eligible: false - name: Case 4, household of 2 adults and no vehicle, below the limit. period: 2022 @@ -46,5 +46,5 @@ household_vehicles_owned: 0 spm_unit_count_adults: 2 output: - sc_tanf_resource_eligible: true + sc_tanf_resources_eligible: true \ No newline at end of file diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_countable_income_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_countable_income_eligible.py new file mode 100644 index 00000000000..e9223d32b1e --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_countable_income_eligible.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class sc_tanf_countable_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "South Carolina TANF countable income eligible" + definition_period = YEAR + defined_for = StateCode.SC + reference = ( + "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.sc.tanf.income + fpg = spm_unit("tanf_fpg", period) + need_standard = fpg * p.need_standard.rate + countable_income = spm_unit("sc_tanf_countable_income", period) + return countable_income < need_standard diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py index 5091bd840a9..69f9e03b6eb 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py @@ -11,5 +11,5 @@ class sc_tanf_eligible(Variable): def formula(spm_unit, period, parameters): demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) income_eligible = spm_unit("sc_tanf_income_eligible", period) - resource_eligible = spm_unit("sc_tanf_resource_eligible", period) + resource_eligible = spm_unit("sc_tanf_resources_eligible", period) return demographic_eligible & income_eligible & resource_eligible diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_gross_income_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_gross_income_eligible.py new file mode 100644 index 00000000000..edf8a3197d1 --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_gross_income_eligible.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class sc_tanf_gross_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "South Carolina TANF gross income eligible" + definition_period = YEAR + defined_for = StateCode.SC + reference = ( + "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.sc.tanf.income + fpg = spm_unit("tanf_fpg", period) + need_standard = fpg * p.need_standard.rate + gross_income_limit = need_standard * p.gross_income_limit + gross_income = spm_unit("sc_tanf_gross_income", period) + return gross_income <= gross_income_limit diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_income_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_income_eligible.py index 110a730e493..3fabe2afbdd 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_income_eligible.py +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_income_eligible.py @@ -8,20 +8,14 @@ class sc_tanf_income_eligible(Variable): definition_period = YEAR defined_for = StateCode.SC reference = ( - "https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=131" + "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" ) def formula(spm_unit, period, parameters): - p = parameters(period).gov.states.sc.tanf.income - fpg = spm_unit("sc_tanf_fpg", period) - # get need standard - need_standard = np.floor(fpg * p.need_standard.rate) - # get gross income limit - gross_income_limit = np.floor(need_standard * p.gross_income_limit) - # check eligibility for income disregard - gross_earned_income = add(spm_unit, period, ["sc_tanf_earned_income"]) - eligible_for_disregard = gross_earned_income <= gross_income_limit - # get total net income and compare it with need standard - net_income = spm_unit("sc_tanf_net_income", period) - income_eligible = net_income < need_standard - return income_eligible & eligible_for_disregard + gross_income_eligible = spm_unit( + "sc_tanf_gross_income_eligible", period + ) + countable_income_eligible = spm_unit( + "sc_tanf_countable_income_eligible", period + ) + return gross_income_eligible & countable_income_eligible diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resource_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py similarity index 91% rename from policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resource_eligible.py rename to policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py index 36a7106208a..f2e5e064424 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resource_eligible.py +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py @@ -1,10 +1,10 @@ from policyengine_us.model_api import * -class sc_tanf_resource_eligible(Variable): +class sc_tanf_resources_eligible(Variable): value_type = bool entity = SPMUnit - label = "South Carolina TANF resource eligible" + label = "South Carolina TANF resources eligible" definition_period = YEAR defined_for = StateCode.SC diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_net_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_earned_income.py similarity index 59% rename from policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_net_income.py rename to policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_earned_income.py index 9294beef4c1..20e826464dd 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_net_income.py +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_earned_income.py @@ -1,15 +1,15 @@ from policyengine_us.model_api import * -class sc_tanf_net_income(Variable): +class sc_tanf_countable_earned_income(Variable): value_type = float entity = SPMUnit - label = "South Carolina TANF net income" + label = "South Carolina TANF countable earned income" unit = USD definition_period = YEAR defined_for = StateCode.SC reference = ( - "https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=131" + "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" ) def formula(spm_unit, period, parameters): @@ -23,13 +23,4 @@ def formula(spm_unit, period, parameters): remaining_months = max_(MONTHS_IN_YEAR - p.percentage.months, 0) reduced_remaining_monthly_income = max_(monthly_income - p.amount, 0) remaining_income = reduced_remaining_monthly_income * remaining_months - earned_income_after_disregard = ( - first_four_months_income + remaining_income - ) - # exclude child support - child_support = add(spm_unit, period, ["child_support_received"]) - net_earned_income = max_( - earned_income_after_disregard - child_support, 0 - ) - unearned_income = add(spm_unit, period, ["sc_tanf_unearned_income"]) - return unearned_income + net_earned_income + return first_four_months_income + remaining_income diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_income.py new file mode 100644 index 00000000000..7e80c803708 --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_income.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class sc_tanf_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "South Carolina TANF countable income" + unit = USD + definition_period = YEAR + defined_for = StateCode.SC + reference = ( + "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" + ) + + adds = [ + "sc_tanf_countable_earned_income", + "sc_tanf_unearned_income", + ] diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_income.py new file mode 100644 index 00000000000..9530feebb62 --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_income.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class sc_tanf_gross_income(Variable): + value_type = float + entity = SPMUnit + label = "South Carolina TANF gross income" + unit = USD + definition_period = YEAR + defined_for = StateCode.SC + reference = ( + "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" + ) + + adds = [ + "sc_tanf_earned_income", + "sc_tanf_unearned_income", + ] diff --git a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py index b602ebcf7ce..458312fc6c1 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py +++ b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py @@ -9,14 +9,14 @@ class sc_tanf(Variable): definition_period = YEAR defined_for = "sc_tanf_eligible" reference = ( - "https://dss.sc.gov/media/3926/tanf_policy_manual_vol-60.pdf#page=131" + "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" ) def formula(spm_unit, period, parameters): p = parameters(period).gov.states.sc.tanf # Compute need standard based on ferderal poverty guidlines - fpg = spm_unit("sc_tanf_fpg", period) + fpg = spm_unit("tanf_fpg", period) need_standard = fpg * p.income.need_standard.rate - net_income = spm_unit("sc_tanf_net_income", period) - excess_income = need_standard - net_income + countable_income = spm_unit("sc_tanf_countable_income", period) + excess_income = need_standard - countable_income return excess_income * p.payment.rate diff --git a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_fpg.py b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_fpg.py deleted file mode 100644 index f2f7a7a2a4e..00000000000 --- a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_fpg.py +++ /dev/null @@ -1,29 +0,0 @@ -from policyengine_us.model_api import * - - -class sc_tanf_fpg(Variable): - value_type = float - entity = SPMUnit - label = "South Carolina TANF federal poverty guideline" - unit = USD - defined_for = StateCode.SC - definition_period = MONTH - - def formula(spm_unit, period, parameters): - size = spm_unit("spm_unit_size", period.this_year) - qualifying_child = add( - spm_unit, period.this_year, ["is_child_dependent"] - ) - child_count = add(spm_unit, period.this_year, ["is_child"]) - n = size - child_count + qualifying_child - state_group = spm_unit.household("state_group_str", period.this_year) - year = period.start.year - month = period.start.month - if month >= 10: - instant_str = f"{year}-10-01" - else: - instant_str = f"{year - 1}-10-01" - p_fpg = parameters(instant_str).gov.hhs.fpg - p1 = p_fpg.first_person[state_group] - pn = p_fpg.additional_person[state_group] - return (p1 + pn * (n - 1)) / MONTHS_IN_YEAR From 99a3d9fd7796dc9300beda46e6ed9fc6cbd6a209 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 6 Jan 2026 18:38:03 -0500 Subject: [PATCH 3/5] change from year to month --- changelog_entry.yaml | 4 + .../tanf/income/earned/disregard/amount.yaml | 2 +- .../earned/disregard/percentage/months.yaml | 2 +- .../earned/disregard/percentage/rate.yaml | 2 +- .../states/sc/tanf/income/earned/earned.yaml | 2 +- .../sc/tanf/income/gross_income_limit.yaml | 2 +- .../sc/tanf/income/need_standard/rate.yaml | 4 +- .../gov/states/sc/tanf/income/unearned.yaml | 2 +- .../gov/states/sc/tanf/payment/rate.yaml | 5 +- .../gov/states/sc/tanf/resources/limit.yaml | 4 +- .../gov/states/sc/tanf/resources/list.yaml | 4 +- .../gov/states/sc/tanf/integration.yaml | 90 +++++++++---------- .../baseline/gov/states/sc/tanf/sc_tanf.yaml | 33 +++---- .../tanf/sc_tanf_countable_earned_income.yaml | 34 ++++--- .../sc_tanf_countable_income_eligible.yaml | 21 +++-- .../gov/states/sc/tanf/sc_tanf_eligible.yaml | 17 ++-- .../tanf/sc_tanf_gross_income_eligible.yaml | 24 ++--- .../sc/tanf/sc_tanf_income_eligible.yaml | 47 +++++----- .../sc/tanf/sc_tanf_resources_eligible.yaml | 26 +++--- .../sc_tanf_countable_income_eligible.py | 6 +- .../sc/tanf/eligibility/sc_tanf_eligible.py | 2 +- .../sc_tanf_gross_income_eligible.py | 6 +- .../eligibility/sc_tanf_income_eligible.py | 6 +- .../eligibility/sc_tanf_resources_eligible.py | 16 ++-- .../income/sc_tanf_countable_earned_income.py | 26 +++--- .../tanf/income/sc_tanf_countable_income.py | 6 +- .../sc/tanf/income/sc_tanf_earned_income.py | 2 +- .../sc/tanf/income/sc_tanf_gross_income.py | 6 +- .../sc/tanf/income/sc_tanf_unearned_income.py | 2 +- .../variables/gov/states/sc/tanf/sc_tanf.py | 6 +- .../sc/tanf/sc_tanf_countable_resources.py | 11 ++- 31 files changed, 220 insertions(+), 200 deletions(-) diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..0fdce15941e 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: minor + changes: + added: + - South Carolina TANF (Temporary Assistance for Needy Families) program diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml index f22e5a85a76..78a414fe700 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml @@ -4,7 +4,7 @@ values: metadata: unit: currency-USD - period: year + period: month label: South Carolina TANF earned income disregard amount reference: - title: The South Carolina Department of Social Services TANF Policy Manual diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml index 7fc0fd43486..8e9239a4423 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml @@ -4,7 +4,7 @@ values: metadata: unit: month - period: year + period: month label: South Carolina TANF earned income percentage disregard applicable months reference: - title: The South Carolina Department of Social Services TANF Policy Manual diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml index 09219129231..137ee1ac761 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml @@ -4,7 +4,7 @@ values: metadata: unit: /1 - period: year + period: month label: South Carolina TANF earned income disregard percentage reference: - title: The South Carolina Department of Social Services TANF Policy Manual diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml index 85e0d853d23..bc504809d4c 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml @@ -5,7 +5,7 @@ values: - self_employment_income_before_lsr metadata: unit: list - period: year + period: month label: South Carolina TANF earned income reference: - title: The South Carolina Department of Social Services TANF Policy Manual diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml index 1b0a4250f2e..8238ffa405d 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml @@ -4,7 +4,7 @@ values: metadata: unit: /1 - period: year + period: month label: South Carolina TANF gross income limit reference: - title: The South Carolina Department of Social Services TANF Policy Manual diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/need_standard/rate.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/need_standard/rate.yaml index d9c643a8a83..94e28622b5b 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/need_standard/rate.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/need_standard/rate.yaml @@ -4,10 +4,10 @@ values: metadata: unit: /1 - period: year + period: month label: South Carolina TANF need standard reference: - title: S.C. Code Regs. § 114-1140(A)(2) - href: https://www.law.cornell.edu/regulations/south-carolina/S-C-Code-Regs-114-1140 + href: https://www.law.cornell.edu/regulations/south-carolina/R-114-1140 - title: The South Carolina Department of Social Services TANF Policy Manual href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml index 911bf119a05..8e05400f2c8 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml @@ -21,7 +21,7 @@ values: - miscellaneous_income metadata: unit: list - period: year + period: month label: South Carolina TANF unearned income reference: - title: The South Carolina Department of Social Services TANF Policy Manual diff --git a/policyengine_us/parameters/gov/states/sc/tanf/payment/rate.yaml b/policyengine_us/parameters/gov/states/sc/tanf/payment/rate.yaml index 4759e3f15c8..e6228dad713 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/payment/rate.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/payment/rate.yaml @@ -1,13 +1,14 @@ description: South Carolina uses this rate to calculate benefits under the Temporary Assistance for Needy Families program. values: 2016-10-01: 0.3372 + 2024-10-01: 0.4046 metadata: unit: /1 - period: year + period: month label: South Carolina TANF payment rate reference: - title: S.C. Code Regs. § 114-1140(A)(3) - href: https://www.law.cornell.edu/regulations/south-carolina/S-C-Code-Regs-114-1140 + href: https://www.law.cornell.edu/regulations/south-carolina/R-114-1140 - title: The South Carolina Department of Social Services TANF Policy Manual href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/resources/limit.yaml b/policyengine_us/parameters/gov/states/sc/tanf/resources/limit.yaml index dc5139bc6b4..d14e13b9766 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/resources/limit.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/resources/limit.yaml @@ -4,10 +4,10 @@ values: metadata: unit: currency-USD - period: year + period: month label: South Carolina TANF household resource limit reference: - title: S.C. Code Regs. § 114-1140(C) - href: https://www.law.cornell.edu/regulations/south-carolina/S-C-Code-Regs-114-1140 + href: https://www.law.cornell.edu/regulations/south-carolina/R-114-1140 - title: The South Carolina Department of Social Services TANF Policy Manual href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=90 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml b/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml index 5ed4ed66de1..30919be4cdc 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml @@ -14,10 +14,10 @@ values: metadata: unit: list - period: year + period: month label: South Carolina TANF household resources reference: - title: S.C. Code Regs. § 114-1140(C) - href: https://www.law.cornell.edu/regulations/south-carolina/S-C-Code-Regs-114-1140 + href: https://www.law.cornell.edu/regulations/south-carolina/R-114-1140 - title: The South Carolina Department of Social Services TANF Policy Manual href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=91 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml index bc6722b8355..83483269dab 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml @@ -1,94 +1,94 @@ -- name: Single parent of 2 children. - absolute_error_margin: 1 - period: 2022 +- name: Case 1, single parent of 2 children with no income. + absolute_error_margin: 0.1 + period: 2025-01 input: people: - parent: + person1: age: 40 - employment_income: 0 + employment_income_before_lsr: 0 retirement_distributions: 0 - child_support_received: 0 - child1: + person2: age: 10 is_child_dependent: true - child2: + person3: age: 8 is_child_dependent: true spm_units: spm_unit: - members: [parent, child1,child2] + members: [person1, person2, person3] spm_unit_cash_assets: 1_000 households: household: - members: [parent, child1,child2] - household_vehicles_value: 0 + members: [person1, person2, person3] + household_vehicles_value: 0 household_vehicles_owned: 0 state_code: SC output: - sc_tanf: 3_747.6 - # (12880+4540*2)*9*0.3372*0.5/12 + (13590+4720*2)*3*0.50*0.3372/12 + sc_tanf: 435.28 + # tanf_fpg for size 3 (2025-01, uses 2024-10 FPG) = 2151.67/month + # need_standard = 2151.67 * 0.5 = 1075.83 + # benefit = 1075.83 * 0.4046 = 435.49 -- name: Single parent of 3 childre, one child is not eligible. - absolute_error_margin: 1 - period: 2022 +- name: Case 2, single parent with earned income. + absolute_error_margin: 0.1 + period: 2025-01 input: people: - parent: + person1: age: 40 - employment_income: 0 + employment_income_before_lsr: 6_000 retirement_distributions: 0 - child_support_received: 0 - child1: + person2: age: 10 is_child_dependent: true - child2: + person3: age: 8 is_child_dependent: true - child3: - age: 16 - is_child_dependent: false spm_units: spm_unit: - members: [parent, child1,child2,child3] + members: [person1, person2, person3] spm_unit_cash_assets: 1_000 households: household: - members: [parent, child1,child2,child3] + members: [person1, person2, person3] household_vehicles_value: 0 household_vehicles_owned: 0 state_code: SC output: - sc_tanf: 3_747.6 + sc_tanf: 334.13 + # monthly earned = 6,000/12 = 500 + # January (month 1) uses 50% disregard + # countable_earned = 500 * 0.5 = 250 + # countable_income = 250 + # need_standard = 1075.83 + # excess = 1075.83 - 250 = 825.83 + # benefit = 825.83 * 0.4046 = 334.13 -- name: Single parent of 3 children. - absolute_error_margin: 1 - period: 2022 +- name: Case 3, income above gross limit. + period: 2025-01 input: people: - parent: + person1: age: 40 - employment_income: 0 + employment_income_before_lsr: 24_000 retirement_distributions: 0 - child_support_received: 0 - child1: + person2: age: 10 is_child_dependent: true - child2: - age: 8 - is_child_dependent: true - child3: - age: 12 - is_child_dependent: true spm_units: spm_unit: - members: [parent, child1,child2,child3] + members: [person1, person2] spm_unit_cash_assets: 1_000 households: household: - members: [parent, child1,child2,child3] - household_vehicles_value: 3_200 - household_vehicles_owned: 2 + members: [person1, person2] + household_vehicles_value: 0 + household_vehicles_owned: 0 state_code: SC output: sc_tanf: 0 - + # monthly earned = 24,000/12 = 2,000 + # tanf_fpg for size 2 = 1703.33 + # need_standard = 851.67 + # gross_income_limit = 851.67 * 1.85 = 1575.58 + # 2,000 > 1,575.58 -> not eligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf.yaml index 73b6dcc5dde..01f7c7cfc9a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf.yaml @@ -1,35 +1,38 @@ - name: Case 1, no earned income is eligible for standard amount. - absolute_error_margin: 1 - period: 2022 + absolute_error_margin: 0.1 + period: 2025-01 input: state_code: SC sc_tanf_countable_income: 0 sc_tanf_eligible: true spm_unit_size: 2 output: - sc_tanf: 2974.5 - # tanf = (12880+4540)*9*0.3372*0.5/12 + (13590+4720)*3*0.50.3372/12 = 2974.5255 + sc_tanf: 344.58 + # tanf_fpg for size 2 (2025-01, uses 2024-10 FPG) = 1703.33/month + # need_standard = 1703.33 * 0.5 = 851.67 + # benefit = 851.67 * 0.4046 = 344.59 -- name: Case 2, did not pass the gross income test. - absolute_error_margin: 1 - period: 2022 +- name: Case 2, not eligible. + period: 2025-01 input: state_code: SC - sc_tanf_countable_income: 19_200 + sc_tanf_countable_income: 1_000 sc_tanf_eligible: false spm_unit_size: 2 output: sc_tanf: 0 -- name: Case 3, some income. - absolute_error_margin: 1 - period: 2022 +- name: Case 3, some countable income. + absolute_error_margin: 0.1 + period: 2025-01 input: state_code: SC - sc_tanf_countable_income: 8_158 + sc_tanf_countable_income: 500 sc_tanf_eligible: true spm_unit_size: 2 output: - sc_tanf: 223.6 - - + sc_tanf: 142.28 + # tanf_fpg for size 2 (2025-01) = 1703.33/month + # need_standard = 1703.33 * 0.5 = 851.67 + # excess = 851.67 - 500 = 351.67 + # benefit = 351.67 * 0.4046 = 142.31 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income.yaml index fe5dbdafbc2..9b173663e27 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income.yaml @@ -1,31 +1,41 @@ - name: Case 1, no earned income. - period: 2024 + period: 2025-01 input: state_code: SC employment_income_before_lsr: 0 output: sc_tanf_countable_earned_income: 0 -- name: Case 2, earned income with disregards. - period: 2024 +- name: Case 2, January uses 50% disregard. + period: 2025-01 input: state_code: SC employment_income_before_lsr: 12_000 output: - sc_tanf_countable_earned_income: 9_200 + sc_tanf_countable_earned_income: 500 # monthly_income = 12,000 / 12 = 1,000 - # first 4 months: 1,000 * 0.5 * 4 = 2,000 - # remaining 8 months: max(1,000 - 100, 0) * 8 = 900 * 8 = 7,200 - # total = 2,000 + 7,200 = 9,200 + # January (month 1) <= 4: uses 50% disregard + # countable = 1,000 * 0.5 = 500 + +- name: Case 3, full year verification of two-phase disregard. + period: 2025 + input: + state_code: SC + employment_income_before_lsr: 12_000 + output: + sc_tanf_countable_earned_income: 9_200 + # Jan-Apr (4 months): 1,000 * 0.5 = 500/month → 2,000 + # May-Dec (8 months): max(1,000 - 100, 0) = 900/month → 7,200 + # Annual total: 2,000 + 7,200 = 9,200 -- name: Case 3, low earned income where monthly is less than disregard amount. - period: 2024 +- name: Case 4, low income where $100 disregard zeroes out income. + period: 2025 input: state_code: SC employment_income_before_lsr: 600 output: sc_tanf_countable_earned_income: 100 # monthly_income = 600 / 12 = 50 - # first 4 months: 50 * 0.5 * 4 = 100 - # remaining 8 months: max(50 - 100, 0) * 8 = 0 * 8 = 0 - # total = 100 + 0 = 100 + # Jan-Apr (4 months): 50 * 0.5 = 25/month → 100 + # May-Dec (8 months): max(50 - 100, 0) = 0/month → 0 + # Annual total: 100 + 0 = 100 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_income_eligible.yaml index ad78eeb59c3..50648551889 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_income_eligible.yaml @@ -1,5 +1,5 @@ - name: Case 1, no income is eligible. - period: 2024 + period: 2025-01 input: state_code: SC spm_unit_size: 2 @@ -7,25 +7,24 @@ sc_tanf_countable_income_eligible: true - name: Case 2, countable income below need standard. - period: 2024 + period: 2025-01 input: state_code: SC spm_unit_size: 2 - sc_tanf_countable_income: 10_000 + sc_tanf_countable_income: 800 output: sc_tanf_countable_income_eligible: true - # FPG for 2 people (2024) = 20,440 - # need_standard = 20,440 * 0.5 = 10,220 - # 10,000 < 10,220 -> eligible + # tanf_fpg for size 2 (2025-01) = 1703.33/month + # need_standard = 1703.33 * 0.5 = 851.67 + # 800 < 851.67 -> eligible - name: Case 3, countable income above need standard. - period: 2024 + period: 2025-01 input: state_code: SC spm_unit_size: 2 - sc_tanf_countable_income: 11_000 + sc_tanf_countable_income: 900 output: sc_tanf_countable_income_eligible: false - # FPG for 2 people (2024) = 20,440 - # need_standard = 20,440 * 0.5 = 10,220 - # 11,000 >= 10,220 -> not eligible + # need_standard = 851.67 + # 900 >= 851.67 -> not eligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_eligible.yaml index 5bc3121332d..eae5b4ea2e1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_eligible.yaml @@ -1,5 +1,5 @@ - name: Case 1, eligible for all. - period: 2022 + period: 2025-01 input: state_code: SC is_demographic_tanf_eligible: true @@ -8,8 +8,8 @@ output: sc_tanf_eligible: true -- name: Case 2, not eligible for one. - period: 2022 +- name: Case 2, not demographic eligible. + period: 2025-01 input: state_code: SC is_demographic_tanf_eligible: false @@ -18,8 +18,8 @@ output: sc_tanf_eligible: false -- name: Case 3, not eligible for one. - period: 2022 +- name: Case 3, not income eligible. + period: 2025-01 input: state_code: SC is_demographic_tanf_eligible: true @@ -28,13 +28,12 @@ output: sc_tanf_eligible: false -- name: Case 4, not eligible for two. - period: 2022 +- name: Case 4, not resources eligible. + period: 2025-01 input: state_code: SC - is_demographic_tanf_eligible: false + is_demographic_tanf_eligible: true sc_tanf_income_eligible: true sc_tanf_resources_eligible: false output: sc_tanf_eligible: false - diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_gross_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_gross_income_eligible.yaml index 7fb1adebb5e..2a7d6ed83f0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_gross_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_gross_income_eligible.yaml @@ -1,5 +1,5 @@ - name: Case 1, no income is eligible. - period: 2024 + period: 2025-01 input: state_code: SC spm_unit_size: 2 @@ -7,27 +7,27 @@ sc_tanf_gross_income_eligible: true - name: Case 2, income below gross income limit. - period: 2024 + period: 2025-01 input: state_code: SC spm_unit_size: 2 employment_income_before_lsr: 18_000 output: sc_tanf_gross_income_eligible: true - # FPG for 2 people (2024) = 20,440 - # need_standard = 20,440 * 0.5 = 10,220 - # gross_income_limit = 10,220 * 1.85 = 18,907 - # 18,000 <= 18,907 -> eligible + # monthly earned = 18,000 / 12 = 1,500 + # tanf_fpg for size 2 (2025-01) = 1703.33/month + # need_standard = 1703.33 * 0.5 = 851.67 + # gross_income_limit = 851.67 * 1.85 = 1575.58 + # 1,500 <= 1,575.58 -> eligible - name: Case 3, income above gross income limit. - period: 2024 + period: 2025-01 input: state_code: SC spm_unit_size: 2 - employment_income_before_lsr: 20_000 + employment_income_before_lsr: 24_000 output: sc_tanf_gross_income_eligible: false - # FPG for 2 people (2024) = 20,440 - # need_standard = 20,440 * 0.5 = 10,220 - # gross_income_limit = 10,220 * 1.85 = 18,907 - # 20,000 > 18,907 -> not eligible + # monthly earned = 24,000 / 12 = 2,000 + # gross_income_limit = 1,575.58 + # 2,000 > 1,575.58 -> not eligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_income_eligible.yaml index 7d0535b9be5..da84d0c22da 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_income_eligible.yaml @@ -1,44 +1,49 @@ -- name: Case 1, no earned income is eligible. - period: 2022 +- name: Case 1, no income is eligible. + period: 2025-01 input: state_code: SC - sc_tanf_countable_income: 0 - sc_tanf_earned_income: 0 + sc_tanf_countable_income: 0 + sc_tanf_gross_income: 0 spm_unit_size: 2 output: sc_tanf_income_eligible: true - name: Case 2, did not pass the gross income test. - period: 2022 + period: 2025-01 input: state_code: SC - sc_tanf_countable_income: 19_200 - sc_tanf_earned_income: 24_000 + sc_tanf_countable_income: 500 + sc_tanf_gross_income: 2_000 spm_unit_size: 2 output: sc_tanf_income_eligible: false - # gross income limit for size 2 is 16300 - # need standard: 762*3 + 725*9 = 8811 - -- name: Case 3, pass gross income test but higher than the need standard. - period: 2022 + # tanf_fpg for size 2 (2025-01) = 1703.33/month + # need_standard = 1703.33 * 0.5 = 851.67 + # gross_income_limit = 851.67 * 1.85 = 1575.58 + # gross_income 2,000 > 1,575.58 -> not eligible + +- name: Case 3, pass gross income test but higher than need standard. + period: 2025-01 input: state_code: SC - sc_tanf_countable_income: 9_200 - sc_tanf_earned_income: 12_000 + sc_tanf_countable_income: 900 + sc_tanf_gross_income: 1_200 spm_unit_size: 2 output: sc_tanf_income_eligible: false - # need standard for size 2 is 8811. - # gross income limit for size 2 is 16300. - + # need_standard = 851.67 + # gross_income_limit = 1,575.58 + # gross 1,200 < 1,575.58 -> passes gross test + # countable 900 >= 851.67 -> fails countable test -- name: Case 4, pass need standard test and gross income test. - period: 2022 +- name: Case 4, pass both income tests. + period: 2025-01 input: state_code: SC - sc_tanf_countable_income: 8_000 - sc_tanf_earned_income: 10_750 + sc_tanf_countable_income: 800 + sc_tanf_gross_income: 1_000 spm_unit_size: 2 output: sc_tanf_income_eligible: true + # gross 1,000 < 1,575.58 -> passes gross test + # countable 800 < 851.67 -> passes countable test diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resources_eligible.yaml index f58e11052d6..955888f8ff2 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resources_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resources_eligible.yaml @@ -1,17 +1,19 @@ - name: Case 1, household of 2 adults and 2 vehicles, below the limit. - period: 2022 + period: 2025-01 input: state_code: SC spm_unit_cash_assets: 2_000 retirement_distributions: 0 household_vehicles_value: 6_000 household_vehicles_owned: 2 - spm_unit_count_adults: 2 + spm_unit_count_adults: 2 output: sc_tanf_resources_eligible: true + # 2 adults can exclude 2 vehicles + # countable resources = 2,000 <= 2,500 - name: Case 2, household of 2 adults and 3 vehicles, above the limit. - period: 2022 + period: 2025-01 input: state_code: SC spm_unit_cash_assets: 1_000 @@ -21,11 +23,13 @@ spm_unit_count_adults: 2 output: sc_tanf_resources_eligible: false - # avg vehicles value = 6000/3 = 2000 - # total resources = 2000+ 1000 = 3000 > 2500 + # avg vehicle value = 6,000 / 3 = 2,000 + # countable vehicles = 3 - 2 = 1 + # countable vehicle value = 1 * 2,000 = 2,000 + # total resources = 1,000 + 2,000 = 3,000 > 2,500 -- name: Case 3, household of 2 adults and 2 vehicles, above the limit. - period: 2022 +- name: Case 3, household of 2 adults and 2 vehicles, cash above the limit. + period: 2025-01 input: state_code: SC spm_unit_cash_assets: 2_600 @@ -35,16 +39,16 @@ spm_unit_count_adults: 2 output: sc_tanf_resources_eligible: false - + # 2,600 > 2,500 + - name: Case 4, household of 2 adults and no vehicle, below the limit. - period: 2022 + period: 2025-01 input: state_code: SC spm_unit_cash_assets: 2_000 retirement_distributions: 0 household_vehicles_value: 0 household_vehicles_owned: 0 - spm_unit_count_adults: 2 + spm_unit_count_adults: 2 output: sc_tanf_resources_eligible: true - \ No newline at end of file diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_countable_income_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_countable_income_eligible.py index e9223d32b1e..41c1eaed560 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_countable_income_eligible.py +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_countable_income_eligible.py @@ -5,11 +5,9 @@ class sc_tanf_countable_income_eligible(Variable): value_type = bool entity = SPMUnit label = "South Carolina TANF countable income eligible" - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.SC - reference = ( - "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" - ) + reference = "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" def formula(spm_unit, period, parameters): p = parameters(period).gov.states.sc.tanf.income diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py index 69f9e03b6eb..bf3ae82b85e 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py @@ -5,7 +5,7 @@ class sc_tanf_eligible(Variable): value_type = bool entity = SPMUnit label = "Eligible for the South Carolina TANF program" - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.SC def formula(spm_unit, period, parameters): diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_gross_income_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_gross_income_eligible.py index edf8a3197d1..4b5b3fbbf12 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_gross_income_eligible.py +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_gross_income_eligible.py @@ -5,11 +5,9 @@ class sc_tanf_gross_income_eligible(Variable): value_type = bool entity = SPMUnit label = "South Carolina TANF gross income eligible" - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.SC - reference = ( - "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" - ) + reference = "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" def formula(spm_unit, period, parameters): p = parameters(period).gov.states.sc.tanf.income diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_income_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_income_eligible.py index 3fabe2afbdd..5d876ad5601 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_income_eligible.py +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_income_eligible.py @@ -5,11 +5,9 @@ class sc_tanf_income_eligible(Variable): value_type = bool entity = SPMUnit label = "South Carolina TANF income eligible" - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.SC - reference = ( - "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" - ) + reference = "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" def formula(spm_unit, period, parameters): gross_income_eligible = spm_unit( diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py index f2e5e064424..5759c16f940 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py @@ -5,18 +5,20 @@ class sc_tanf_resources_eligible(Variable): value_type = bool entity = SPMUnit label = "South Carolina TANF resources eligible" - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.SC def formula(spm_unit, period, parameters): resource_limit = parameters(period).gov.states.sc.tanf.resources.limit - countable_resources = add( - spm_unit, period, ["sc_tanf_countable_resources"] - ) + countable_resources = spm_unit("sc_tanf_countable_resources", period) # Each driver's license can exclude one vehicle. - adult_count = spm_unit("spm_unit_count_adults", period) - vehicle_count = spm_unit.household("household_vehicles_owned", period) - vehicle_value = spm_unit.household("household_vehicles_value", period) + adult_count = spm_unit("spm_unit_count_adults", period.this_year) + vehicle_count = spm_unit.household( + "household_vehicles_owned", period.this_year + ) + vehicle_value = spm_unit.household( + "household_vehicles_value", period.this_year + ) avg_vehicle_value = np.zeros_like(vehicle_count) mask = vehicle_count != 0 avg_vehicle_value[mask] = vehicle_value[mask] / vehicle_count[mask] diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_earned_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_earned_income.py index 20e826464dd..1e2d1bd111b 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_earned_income.py @@ -6,21 +6,19 @@ class sc_tanf_countable_earned_income(Variable): entity = SPMUnit label = "South Carolina TANF countable earned income" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.SC - reference = ( - "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" - ) + reference = "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" def formula(spm_unit, period, parameters): p = parameters(period).gov.states.sc.tanf.income.earned.disregard - gross_earned_income = add(spm_unit, period, ["sc_tanf_earned_income"]) - monthly_income = gross_earned_income / MONTHS_IN_YEAR - # Compute earned income after disregard, first four months has 50% disregard, the rest has $100 deduction. - first_four_months_income = ( - monthly_income * p.percentage.rate * p.percentage.months - ) - remaining_months = max_(MONTHS_IN_YEAR - p.percentage.months, 0) - reduced_remaining_monthly_income = max_(monthly_income - p.amount, 0) - remaining_income = reduced_remaining_monthly_income * remaining_months - return first_four_months_income + remaining_income + gross_earned_income = spm_unit("sc_tanf_earned_income", period) + month = period.start.month + + # First 4 months (Jan-Apr): 50% disregard + # Remaining 8 months (May-Dec): $100 flat disregard + initial_period = month <= p.percentage.months + initial_countable = gross_earned_income * p.percentage.rate + ongoing_countable = max_(gross_earned_income - p.amount, 0) + + return where(initial_period, initial_countable, ongoing_countable) diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_income.py index 7e80c803708..73c82b4a12a 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_income.py +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_income.py @@ -6,11 +6,9 @@ class sc_tanf_countable_income(Variable): entity = SPMUnit label = "South Carolina TANF countable income" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.SC - reference = ( - "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" - ) + reference = "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" adds = [ "sc_tanf_countable_earned_income", diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_earned_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_earned_income.py index 8ab3d19175d..4b127fc1668 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_earned_income.py +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_earned_income.py @@ -6,6 +6,6 @@ class sc_tanf_earned_income(Variable): entity = SPMUnit label = "South Carolina TANF earned income" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.SC adds = "gov.states.sc.tanf.income.earned.earned" diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_income.py index 9530feebb62..3966a8d9cd9 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_income.py +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_income.py @@ -6,11 +6,9 @@ class sc_tanf_gross_income(Variable): entity = SPMUnit label = "South Carolina TANF gross income" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.SC - reference = ( - "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" - ) + reference = "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" adds = [ "sc_tanf_earned_income", diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_unearned_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_unearned_income.py index 3c19fc1fdab..566d4d98654 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_unearned_income.py +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_unearned_income.py @@ -6,6 +6,6 @@ class sc_tanf_unearned_income(Variable): entity = SPMUnit label = "South Carolina TANF unearned income" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.SC adds = "gov.states.sc.tanf.income.unearned" diff --git a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py index 458312fc6c1..d9d0b66d03c 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py +++ b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py @@ -6,11 +6,9 @@ class sc_tanf(Variable): entity = SPMUnit label = "South Carolina TANF" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = "sc_tanf_eligible" - reference = ( - "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" - ) + reference = "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" def formula(spm_unit, period, parameters): p = parameters(period).gov.states.sc.tanf diff --git a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_countable_resources.py b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_countable_resources.py index 6b443b0c827..a7d151a4fcc 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_countable_resources.py +++ b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_countable_resources.py @@ -6,6 +6,13 @@ class sc_tanf_countable_resources(Variable): entity = SPMUnit label = "South Carolina TANF countable resources" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.SC - adds = "gov.states.sc.tanf.resources.list" + + def formula(spm_unit, period, parameters): + # Resources are stocks, use period.this_year to avoid /12 conversion + cash_assets = spm_unit("spm_unit_cash_assets", period.this_year) + retirement = add( + spm_unit, period.this_year, ["retirement_distributions"] + ) + return cash_assets + retirement From 444d0915f60496ba7cd4bcb49a350d33acddf02f Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 6 Jan 2026 18:54:13 -0500 Subject: [PATCH 4/5] add tests --- .../gov/states/sc/tanf/resources/list.yaml | 23 ----- .../gov/states/sc/tanf/integration.yaml | 88 ++++++++++++++++++- .../sc_tanf_countable_income_eligible.yaml | 14 +++ .../tanf/sc_tanf_gross_income_eligible.yaml | 14 +++ .../sc/tanf/sc_tanf_resources_eligible.yaml | 46 +++------- .../eligibility/sc_tanf_resources_eligible.py | 22 +---- .../sc/tanf/sc_tanf_countable_resources.py | 18 ---- 7 files changed, 130 insertions(+), 95 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml delete mode 100644 policyengine_us/variables/gov/states/sc/tanf/sc_tanf_countable_resources.py diff --git a/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml b/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml deleted file mode 100644 index 30919be4cdc..00000000000 --- a/policyengine_us/parameters/gov/states/sc/tanf/resources/list.yaml +++ /dev/null @@ -1,23 +0,0 @@ -description: South Carolina counts these resources under the Temporary Assistance for Needy Families program. -values: - 1996-07-01: - - spm_unit_cash_assets - - retirement_distributions - #- Lump sum payments - #- Prepaid burial contract - #- Refunds of security deposits - #- Revocable trust account - #- Saving certificate - #- Stocks/bonds - #- Building(s) not associated with homestead - #- Non-hoestead property - -metadata: - unit: list - period: month - label: South Carolina TANF household resources - reference: - - title: S.C. Code Regs. § 114-1140(C) - href: https://www.law.cornell.edu/regulations/south-carolina/R-114-1140 - - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=91 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml index 83483269dab..08b744828bf 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml @@ -16,7 +16,7 @@ spm_units: spm_unit: members: [person1, person2, person3] - spm_unit_cash_assets: 1_000 + spm_unit_assets: 1_000 households: household: members: [person1, person2, person3] @@ -47,7 +47,7 @@ spm_units: spm_unit: members: [person1, person2, person3] - spm_unit_cash_assets: 1_000 + spm_unit_assets: 1_000 households: household: members: [person1, person2, person3] @@ -78,7 +78,7 @@ spm_units: spm_unit: members: [person1, person2] - spm_unit_cash_assets: 1_000 + spm_unit_assets: 1_000 households: household: members: [person1, person2] @@ -92,3 +92,85 @@ # need_standard = 851.67 # gross_income_limit = 851.67 * 1.85 = 1575.58 # 2,000 > 1,575.58 -> not eligible + +- name: Case 4, single pregnant person with no income. + period: 2025-01 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 25 + is_pregnant: true + employment_income_before_lsr: 0 + retirement_distributions: 0 + spm_units: + spm_unit: + members: [person1] + spm_unit_assets: 500 + households: + household: + members: [person1] + household_vehicles_value: 0 + household_vehicles_owned: 0 + state_code: SC + output: + sc_tanf: 253.89 + # tanf_fpg for size 1 (2025-01) = 1255/month + # need_standard = 1255 * 0.5 = 627.50 + # benefit = 627.50 * 0.4046 = 253.89 + +- name: Case 5, unearned income only. + period: 2025-01 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 0 + taxable_social_security: 3_600 + retirement_distributions: 0 + person2: + age: 8 + is_child_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 500 + households: + household: + members: [person1, person2] + state_code: SC + output: + sc_tanf: 223.20 + # monthly unearned = 3,600/12 = 300 + # tanf_fpg for size 2 = 1703.33 + # need_standard = 1703.33 * 0.5 = 851.67 + # countable_income = 0 (earned) + 300 (unearned) = 300 + # excess = 851.67 - 300 = 551.67 + # benefit = 551.67 * 0.4046 = 223.20 + +- name: Case 6, historical payment rate (pre-Oct 2024). + period: 2024-01 + absolute_error_margin: 0.1 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 0 + retirement_distributions: 0 + person2: + age: 8 + is_child_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 500 + households: + household: + members: [person1, person2] + state_code: SC + output: + sc_tanf: 277.07 + # tanf_fpg for size 2 (2024-01, uses 2023-10 FPG) = 1643.33/month + # need_standard = 1643.33 * 0.5 = 821.67 + # benefit = 821.67 * 0.3372 = 277.07 (old rate) diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_income_eligible.yaml index 50648551889..ed35d4779a1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_income_eligible.yaml @@ -28,3 +28,17 @@ sc_tanf_countable_income_eligible: false # need_standard = 851.67 # 900 >= 851.67 -> not eligible + +- name: Case 4, countable income exactly at need standard. + period: 2025-01 + absolute_error_margin: 0.1 + input: + state_code: SC + spm_unit_size: 2 + sc_tanf_countable_income: 851.67 + output: + sc_tanf_countable_income_eligible: false + # tanf_fpg for size 2 = 1703.33 + # need_standard = 1703.33 * 0.5 = 851.67 + # 851.67 < 851.67 is FALSE (strict less than) + # -> not eligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_gross_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_gross_income_eligible.yaml index 2a7d6ed83f0..dd0656ebf42 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_gross_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_gross_income_eligible.yaml @@ -31,3 +31,17 @@ # monthly earned = 24,000 / 12 = 2,000 # gross_income_limit = 1,575.58 # 2,000 > 1,575.58 -> not eligible + +- name: Case 4, gross income exactly at limit. + period: 2025-01 + absolute_error_margin: 0.1 + input: + state_code: SC + spm_unit_size: 2 + sc_tanf_gross_income: 1_575.58 + output: + sc_tanf_gross_income_eligible: true + # tanf_fpg for size 2 = 1703.33 + # need_standard = 1703.33 * 0.5 = 851.665 + # gross_income_limit = 851.665 * 1.85 = 1575.58 + # 1575.58 <= 1575.58 -> eligible (uses <=) diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resources_eligible.yaml index 955888f8ff2..c25f3d2b122 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resources_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_resources_eligible.yaml @@ -1,54 +1,36 @@ -- name: Case 1, household of 2 adults and 2 vehicles, below the limit. +- name: Case 1, assets below the limit. period: 2025-01 input: state_code: SC - spm_unit_cash_assets: 2_000 - retirement_distributions: 0 - household_vehicles_value: 6_000 - household_vehicles_owned: 2 - spm_unit_count_adults: 2 + spm_unit_assets: 2_000 output: sc_tanf_resources_eligible: true - # 2 adults can exclude 2 vehicles - # countable resources = 2,000 <= 2,500 + # 2,000 <= 2,500 -> eligible -- name: Case 2, household of 2 adults and 3 vehicles, above the limit. +- name: Case 2, assets above the limit. period: 2025-01 input: state_code: SC - spm_unit_cash_assets: 1_000 - retirement_distributions: 0 - household_vehicles_value: 6_000 - household_vehicles_owned: 3 - spm_unit_count_adults: 2 + spm_unit_assets: 3_000 output: sc_tanf_resources_eligible: false - # avg vehicle value = 6,000 / 3 = 2,000 - # countable vehicles = 3 - 2 = 1 - # countable vehicle value = 1 * 2,000 = 2,000 - # total resources = 1,000 + 2,000 = 3,000 > 2,500 + # 3,000 > 2,500 -> not eligible -- name: Case 3, household of 2 adults and 2 vehicles, cash above the limit. +- name: Case 3, assets exactly at the limit. period: 2025-01 + absolute_error_margin: 0.1 input: state_code: SC - spm_unit_cash_assets: 2_600 - retirement_distributions: 0 - household_vehicles_value: 6_000 - household_vehicles_owned: 2 - spm_unit_count_adults: 2 + spm_unit_assets: 2_500 output: - sc_tanf_resources_eligible: false - # 2,600 > 2,500 + sc_tanf_resources_eligible: true + # 2,500 <= 2,500 -> eligible (uses <=) -- name: Case 4, household of 2 adults and no vehicle, below the limit. +- name: Case 4, no assets. period: 2025-01 input: state_code: SC - spm_unit_cash_assets: 2_000 - retirement_distributions: 0 - household_vehicles_value: 0 - household_vehicles_owned: 0 - spm_unit_count_adults: 2 + spm_unit_assets: 0 output: sc_tanf_resources_eligible: true + # 0 <= 2,500 -> eligible diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py index 5759c16f940..354cbd9160e 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py @@ -9,22 +9,6 @@ class sc_tanf_resources_eligible(Variable): defined_for = StateCode.SC def formula(spm_unit, period, parameters): - resource_limit = parameters(period).gov.states.sc.tanf.resources.limit - countable_resources = spm_unit("sc_tanf_countable_resources", period) - # Each driver's license can exclude one vehicle. - adult_count = spm_unit("spm_unit_count_adults", period.this_year) - vehicle_count = spm_unit.household( - "household_vehicles_owned", period.this_year - ) - vehicle_value = spm_unit.household( - "household_vehicles_value", period.this_year - ) - avg_vehicle_value = np.zeros_like(vehicle_count) - mask = vehicle_count != 0 - avg_vehicle_value[mask] = vehicle_value[mask] / vehicle_count[mask] - countable_vehicle_value = ( - vehicle_count - adult_count - ) * avg_vehicle_value - return ( - countable_resources + countable_vehicle_value - ) <= resource_limit + p = parameters(period).gov.states.sc.tanf.resources + assets = spm_unit("spm_unit_assets", period.this_year) + return assets <= p.limit diff --git a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_countable_resources.py b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_countable_resources.py deleted file mode 100644 index a7d151a4fcc..00000000000 --- a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf_countable_resources.py +++ /dev/null @@ -1,18 +0,0 @@ -from policyengine_us.model_api import * - - -class sc_tanf_countable_resources(Variable): - value_type = float - entity = SPMUnit - label = "South Carolina TANF countable resources" - unit = USD - definition_period = MONTH - defined_for = StateCode.SC - - def formula(spm_unit, period, parameters): - # Resources are stocks, use period.this_year to avoid /12 conversion - cash_assets = spm_unit("spm_unit_cash_assets", period.this_year) - retirement = add( - spm_unit, period.this_year, ["retirement_distributions"] - ) - return cash_assets + retirement From f691e123c03381cadd3c4dc6009d17aeb054190e Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 6 Jan 2026 19:30:55 -0500 Subject: [PATCH 5/5] adjustments --- .../tanf/income/earned/disregard/amount.yaml | 2 +- .../earned/disregard/percentage/months.yaml | 2 +- .../earned/disregard/percentage/rate.yaml | 2 +- .../states/sc/tanf/income/earned/earned.yaml | 4 +- .../sc/tanf/income/gross_income_limit.yaml | 4 +- .../gov/states/sc/tanf/income/unearned.yaml | 4 +- .../gov/states/sc/tanf/integration.yaml | 76 +++++++++++++++---- ..._tanf_countable_earned_income_person.yaml} | 8 +- .../sc/tanf/eligibility/sc_tanf_eligible.py | 11 ++- .../eligibility/sc_tanf_resources_eligible.py | 1 + ...sc_tanf_countable_earned_income_person.py} | 14 ++-- .../tanf/income/sc_tanf_countable_income.py | 4 +- .../sc/tanf/income/sc_tanf_earned_income.py | 11 --- .../income/sc_tanf_gross_earned_income.py | 12 +++ .../sc/tanf/income/sc_tanf_gross_income.py | 4 +- .../income/sc_tanf_gross_unearned_income.py | 12 +++ .../sc/tanf/income/sc_tanf_unearned_income.py | 11 --- .../variables/gov/states/sc/tanf/sc_tanf.py | 2 +- 18 files changed, 123 insertions(+), 61 deletions(-) rename policyengine_us/tests/policy/baseline/gov/states/sc/tanf/{sc_tanf_countable_earned_income.yaml => sc_tanf_countable_earned_income_person.yaml} (84%) rename policyengine_us/variables/gov/states/sc/tanf/income/{sc_tanf_countable_earned_income.py => sc_tanf_countable_earned_income_person.py} (60%) delete mode 100644 policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_earned_income.py create mode 100644 policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_earned_income.py create mode 100644 policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_unearned_income.py delete mode 100644 policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_unearned_income.py diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml index 78a414fe700..ae71efe23d7 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/amount.yaml @@ -7,5 +7,5 @@ metadata: period: month label: South Carolina TANF earned income disregard amount reference: - - title: The South Carolina Department of Social Services TANF Policy Manual + - title: SC DSS TANF Policy Manual Section 8.12 href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=130 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml index 8e9239a4423..d80916562a5 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/months.yaml @@ -7,5 +7,5 @@ metadata: period: month label: South Carolina TANF earned income percentage disregard applicable months reference: - - title: The South Carolina Department of Social Services TANF Policy Manual + - title: SC DSS TANF Policy Manual Section 8.12 href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=130 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml index 137ee1ac761..97cf9e46956 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/disregard/percentage/rate.yaml @@ -7,5 +7,5 @@ metadata: period: month label: South Carolina TANF earned income disregard percentage reference: - - title: The South Carolina Department of Social Services TANF Policy Manual + - title: SC DSS TANF Policy Manual Section 8.12 href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=130 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml index bc504809d4c..a4b18e1b009 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/earned/earned.yaml @@ -8,5 +8,5 @@ metadata: period: month label: South Carolina TANF earned income reference: - - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=100 + - title: SC DSS TANF Policy Manual Section 7.1 + href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=101 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml index 8238ffa405d..7ffed0cd6ba 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/gross_income_limit.yaml @@ -7,5 +7,5 @@ metadata: period: month label: South Carolina TANF gross income limit reference: - - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131 + - title: SC DSS TANF Policy Manual Section 8.15 + href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=132 diff --git a/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml b/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml index 8e05400f2c8..04d46ca9f07 100644 --- a/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml +++ b/policyengine_us/parameters/gov/states/sc/tanf/income/unearned.yaml @@ -24,5 +24,5 @@ metadata: period: month label: South Carolina TANF unearned income reference: - - title: The South Carolina Department of Social Services TANF Policy Manual - href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=100 + - title: SC DSS TANF Policy Manual Section 7.1 + href: https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=101 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml index 08b744828bf..c31683622b7 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/integration.yaml @@ -6,7 +6,6 @@ person1: age: 40 employment_income_before_lsr: 0 - retirement_distributions: 0 person2: age: 10 is_child_dependent: true @@ -20,8 +19,6 @@ households: household: members: [person1, person2, person3] - household_vehicles_value: 0 - household_vehicles_owned: 0 state_code: SC output: sc_tanf: 435.28 @@ -37,7 +34,6 @@ person1: age: 40 employment_income_before_lsr: 6_000 - retirement_distributions: 0 person2: age: 10 is_child_dependent: true @@ -51,8 +47,6 @@ households: household: members: [person1, person2, person3] - household_vehicles_value: 0 - household_vehicles_owned: 0 state_code: SC output: sc_tanf: 334.13 @@ -71,7 +65,6 @@ person1: age: 40 employment_income_before_lsr: 24_000 - retirement_distributions: 0 person2: age: 10 is_child_dependent: true @@ -82,8 +75,6 @@ households: household: members: [person1, person2] - household_vehicles_value: 0 - household_vehicles_owned: 0 state_code: SC output: sc_tanf: 0 @@ -102,7 +93,6 @@ age: 25 is_pregnant: true employment_income_before_lsr: 0 - retirement_distributions: 0 spm_units: spm_unit: members: [person1] @@ -110,8 +100,6 @@ households: household: members: [person1] - household_vehicles_value: 0 - household_vehicles_owned: 0 state_code: SC output: sc_tanf: 253.89 @@ -128,7 +116,6 @@ age: 35 employment_income_before_lsr: 0 taxable_social_security: 3_600 - retirement_distributions: 0 person2: age: 8 is_child_dependent: true @@ -157,7 +144,6 @@ person1: age: 35 employment_income_before_lsr: 0 - retirement_distributions: 0 person2: age: 8 is_child_dependent: true @@ -174,3 +160,65 @@ # tanf_fpg for size 2 (2024-01, uses 2023-10 FPG) = 1643.33/month # need_standard = 1643.33 * 0.5 = 821.67 # benefit = 821.67 * 0.3372 = 277.07 (old rate) + +- name: Case 7, two-parent household with 4 children (family of 6). + period: 2025-01 + absolute_error_margin: 1 + input: + people: + parent1: + age: 35 + employment_income_before_lsr: 0 + parent2: + age: 33 + employment_income_before_lsr: 0 + child1: + age: 14 + is_child_dependent: true + child2: + age: 12 + is_child_dependent: true + child3: + age: 8 + is_child_dependent: true + child4: + age: 5 + is_child_dependent: true + spm_units: + spm_unit: + members: [parent1, parent2, child1, child2, child3, child4] + spm_unit_assets: 1_000 + households: + household: + members: [parent1, parent2, child1, child2, child3, child4] + state_code: SC + output: + sc_tanf: 707 + # tanf_fpg for size 6 (2025-01) = 3496/month (from Section 8.15 table) + # need_standard = 3496 * 0.5 = 1748 + # benefit = 1748 * 0.4046 = 707.24 + +- name: Case 8, ineligible due to immigration status. + period: 2025-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 0 + immigration_status: UNDOCUMENTED + person2: + age: 8 + is_child_dependent: true + immigration_status: UNDOCUMENTED + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_assets: 500 + households: + household: + members: [person1, person2] + state_code: SC + output: + sc_tanf: 0 + # Both members are undocumented, so no one qualifies as + # citizen or legal immigrant -> ineligible diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income_person.yaml similarity index 84% rename from policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income.yaml rename to policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income_person.yaml index 9b173663e27..4157a4b30f2 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tanf/sc_tanf_countable_earned_income_person.yaml @@ -4,7 +4,7 @@ state_code: SC employment_income_before_lsr: 0 output: - sc_tanf_countable_earned_income: 0 + sc_tanf_countable_earned_income_person: 0 - name: Case 2, January uses 50% disregard. period: 2025-01 @@ -12,7 +12,7 @@ state_code: SC employment_income_before_lsr: 12_000 output: - sc_tanf_countable_earned_income: 500 + sc_tanf_countable_earned_income_person: 500 # monthly_income = 12,000 / 12 = 1,000 # January (month 1) <= 4: uses 50% disregard # countable = 1,000 * 0.5 = 500 @@ -23,7 +23,7 @@ state_code: SC employment_income_before_lsr: 12_000 output: - sc_tanf_countable_earned_income: 9_200 + sc_tanf_countable_earned_income_person: 9_200 # Jan-Apr (4 months): 1,000 * 0.5 = 500/month → 2,000 # May-Dec (8 months): max(1,000 - 100, 0) = 900/month → 7,200 # Annual total: 2,000 + 7,200 = 9,200 @@ -34,7 +34,7 @@ state_code: SC employment_income_before_lsr: 600 output: - sc_tanf_countable_earned_income: 100 + sc_tanf_countable_earned_income_person: 100 # monthly_income = 600 / 12 = 50 # Jan-Apr (4 months): 50 * 0.5 = 25/month → 100 # May-Dec (8 months): max(50 - 100, 0) = 0/month → 0 diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py index bf3ae82b85e..55bbfbc7d8d 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_eligible.py @@ -7,9 +7,18 @@ class sc_tanf_eligible(Variable): label = "Eligible for the South Carolina TANF program" definition_period = MONTH defined_for = StateCode.SC + reference = "https://www.law.cornell.edu/regulations/south-carolina/S.C.-Code-Regs.-114-1140" def formula(spm_unit, period, parameters): demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) + immigration_eligible = ( + add(spm_unit, period, ["is_citizen_or_legal_immigrant"]) > 0 + ) income_eligible = spm_unit("sc_tanf_income_eligible", period) resource_eligible = spm_unit("sc_tanf_resources_eligible", period) - return demographic_eligible & income_eligible & resource_eligible + return ( + demographic_eligible + & immigration_eligible + & income_eligible + & resource_eligible + ) diff --git a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py index 354cbd9160e..218468a0447 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py +++ b/policyengine_us/variables/gov/states/sc/tanf/eligibility/sc_tanf_resources_eligible.py @@ -7,6 +7,7 @@ class sc_tanf_resources_eligible(Variable): label = "South Carolina TANF resources eligible" definition_period = MONTH defined_for = StateCode.SC + reference = "https://www.law.cornell.edu/regulations/south-carolina/S.C.-Code-Regs.-114-1140" # Section (C) def formula(spm_unit, period, parameters): p = parameters(period).gov.states.sc.tanf.resources diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_earned_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_earned_income_person.py similarity index 60% rename from policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_earned_income.py rename to policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_earned_income_person.py index 1e2d1bd111b..4ac9a3f8583 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_earned_income_person.py @@ -1,24 +1,26 @@ from policyengine_us.model_api import * -class sc_tanf_countable_earned_income(Variable): +class sc_tanf_countable_earned_income_person(Variable): value_type = float - entity = SPMUnit + entity = Person label = "South Carolina TANF countable earned income" unit = USD definition_period = MONTH defined_for = StateCode.SC - reference = "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" + reference = "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=130" # Section 8.12 - def formula(spm_unit, period, parameters): + def formula(person, period, parameters): p = parameters(period).gov.states.sc.tanf.income.earned.disregard - gross_earned_income = spm_unit("sc_tanf_earned_income", period) + gross_earned_income = person("sc_tanf_gross_earned_income", period) month = period.start.month # First 4 months (Jan-Apr): 50% disregard # Remaining 8 months (May-Dec): $100 flat disregard + # Use calendar months as a proxy. The actual policy refers to + # "first 4 months of employment" which cannot be tracked. initial_period = month <= p.percentage.months - initial_countable = gross_earned_income * p.percentage.rate + initial_countable = gross_earned_income * (1 - p.percentage.rate) ongoing_countable = max_(gross_earned_income - p.amount, 0) return where(initial_period, initial_countable, ongoing_countable) diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_income.py index 73c82b4a12a..a949b41ed3f 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_income.py +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_countable_income.py @@ -11,6 +11,6 @@ class sc_tanf_countable_income(Variable): reference = "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" adds = [ - "sc_tanf_countable_earned_income", - "sc_tanf_unearned_income", + "sc_tanf_countable_earned_income_person", + "sc_tanf_gross_unearned_income", ] diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_earned_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_earned_income.py deleted file mode 100644 index 4b127fc1668..00000000000 --- a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_earned_income.py +++ /dev/null @@ -1,11 +0,0 @@ -from policyengine_us.model_api import * - - -class sc_tanf_earned_income(Variable): - value_type = float - entity = SPMUnit - label = "South Carolina TANF earned income" - unit = USD - definition_period = MONTH - defined_for = StateCode.SC - adds = "gov.states.sc.tanf.income.earned.earned" diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_earned_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_earned_income.py new file mode 100644 index 00000000000..7c599d576d3 --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_earned_income.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class sc_tanf_gross_earned_income(Variable): + value_type = float + entity = Person + label = "South Carolina TANF gross earned income" + unit = USD + definition_period = MONTH + defined_for = StateCode.SC + reference = "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=100" # Section 7.1 + adds = "gov.states.sc.tanf.income.earned.earned" diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_income.py index 3966a8d9cd9..7f22abc303f 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_income.py +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_income.py @@ -11,6 +11,6 @@ class sc_tanf_gross_income(Variable): reference = "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=131" adds = [ - "sc_tanf_earned_income", - "sc_tanf_unearned_income", + "sc_tanf_gross_earned_income", + "sc_tanf_gross_unearned_income", ] diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_unearned_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_unearned_income.py new file mode 100644 index 00000000000..36273d0a264 --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_gross_unearned_income.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class sc_tanf_gross_unearned_income(Variable): + value_type = float + entity = Person + label = "South Carolina TANF gross unearned income" + unit = USD + definition_period = MONTH + defined_for = StateCode.SC + reference = "https://dss.sc.gov/media/ojqddxsk/tanf-policy-manual-volume-65.pdf#page=100" # Section 7.1 + adds = "gov.states.sc.tanf.income.unearned" diff --git a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_unearned_income.py b/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_unearned_income.py deleted file mode 100644 index 566d4d98654..00000000000 --- a/policyengine_us/variables/gov/states/sc/tanf/income/sc_tanf_unearned_income.py +++ /dev/null @@ -1,11 +0,0 @@ -from policyengine_us.model_api import * - - -class sc_tanf_unearned_income(Variable): - value_type = float - entity = SPMUnit - label = "South Carolina TANF unearned income" - unit = USD - definition_period = MONTH - defined_for = StateCode.SC - adds = "gov.states.sc.tanf.income.unearned" diff --git a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py index d9d0b66d03c..8e7afa77df6 100644 --- a/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py +++ b/policyengine_us/variables/gov/states/sc/tanf/sc_tanf.py @@ -12,7 +12,7 @@ class sc_tanf(Variable): def formula(spm_unit, period, parameters): p = parameters(period).gov.states.sc.tanf - # Compute need standard based on ferderal poverty guidlines + # Compute need standard based on federal poverty guidelines fpg = spm_unit("tanf_fpg", period) need_standard = fpg * p.income.need_standard.rate countable_income = spm_unit("sc_tanf_countable_income", period)