diff --git a/changelog.d/fix-10685-nc-work-first-resources.fixed.md b/changelog.d/fix-10685-nc-work-first-resources.fixed.md new file mode 100644 index 00000000000..30bb7a0c94f --- /dev/null +++ b/changelog.d/fix-10685-nc-work-first-resources.fixed.md @@ -0,0 +1 @@ +North Carolina Work First applies its $3,000 resource limit (10A NCAC 71W .0407). diff --git a/policyengine_us/parameters/gov/states/nc/ncdhhs/tanf/resources/limit.yaml b/policyengine_us/parameters/gov/states/nc/ncdhhs/tanf/resources/limit.yaml new file mode 100644 index 00000000000..4a2c7c1dc26 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nc/ncdhhs/tanf/resources/limit.yaml @@ -0,0 +1,18 @@ +description: North Carolina limits the Temporary Assistance for Needy Families program to units with countable resources up to this amount. + +values: + # The earliest source found is the Work First Manual's 2009 resources section; the value is + # backdated to the program's start, as the other North Carolina TANF parameters are. + 1997-01-01: 3_000 + +metadata: + unit: currency-USD + period: year + label: North Carolina TANF resource limit + reference: + - title: 10A NCAC 71W .0407 - Reserve + href: https://regulations.justia.com/states/north-carolina/title-10a/chapter-71/subchapter-w/section-0400/section-71w-0407 + - title: Work First Manual, section 115 - Resources (I.A. Resource Limit) + href: https://policies.ncdhhs.gov/wp-content/uploads/wf115.pdf#page=1 + - title: North Carolina TANF State Plan FFY 2026-2028, Financial Rules 1-2 + href: https://www.ncdhhs.gov/efs-wf-06-2025a2/open#page=18 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/integration.yaml index e69796b5b0d..a1dddd6e38a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/integration.yaml @@ -502,3 +502,98 @@ nc_tanf_countable_gross_unearned_income: 3_600 # Need standard for 1: 362 a month; 0.5 * (362 - 300) = 31 a month nc_tanf: 31 * 12 + +- name: One adult and one child with no income and $3,000 in the bank receive the full payment. + period: 2024 + input: + people: + person1: + age: 30 + bank_account_assets: 3_000 + person2: + age: 17 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NC + output: + # $3,000 is at the limit (10A NCAC 71W .0407), so the unit stays eligible. + nc_tanf: (472 - 0) * 0.5 * 12 + +- name: One adult and one child with no income and $5,000 in stocks receive nothing. + period: 2024 + input: + people: + person1: + age: 30 + stock_assets: 5_000 + person2: + age: 17 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NC + output: + # $5,000 of countable resources exceeds the $3,000 limit. + nc_tanf: 0 + +- name: An SSI-recipient parent with $4,000 in the bank and a child aged 10 receive $181 per month. + period: 2025 + input: + people: + parent: + age: 35 + ssi: 11_000 + bank_account_assets: 4_000 + child: + age: 10 + spm_units: + spm_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NC + output: + # The SSI parent is not in the household size, and their income and + # resources do not count (10A NCAC 71W .0407(b)(1)). + nc_tanf_household_size: 1 + nc_tanf_countable_gross_unearned_income: 0 + nc_tanf_countable_resources: 0 + nc_tanf_resources_eligible: true + # Need standard for 1: 362 a month; 0.5 * (362 - 0) = 181 a month + nc_tanf: 181 * 12 # 2_172 + +- name: A parent, an SSI-recipient child aged 8 with $4,000 in the bank, and a child aged 5 receive $236 per month. + period: 2025 + input: + people: + parent: + age: 35 + child1: + age: 8 + ssi: 11_000 + bank_account_assets: 4_000 + child2: + age: 5 + spm_units: + spm_unit: + members: [parent, child1, child2] + households: + household: + members: [parent, child1, child2] + state_code: NC + output: + # The SSI child is not in the household size, and their resources do not + # count (10A NCAC 71W .0407(b)(2)). + nc_tanf_household_size: 2 + nc_tanf_countable_resources: 0 + nc_tanf_resources_eligible: true + # Need standard for 2: 472 a month; 0.5 * (472 - 0) = 236 a month + nc_tanf: 236 * 12 # 2_832 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/nc_tanf_countable_resources.yaml b/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/nc_tanf_countable_resources.yaml new file mode 100644 index 00000000000..17ea6a968ec --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/nc_tanf_countable_resources.yaml @@ -0,0 +1,96 @@ +- name: Bank, stock and bond assets count; vehicle value does not. + period: 2025 + input: + people: + parent: + age: 30 + bank_account_assets: 1_000 + stock_assets: 1_500 + bond_assets: 700 + child: + age: 5 + spm_units: + spm_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NC + household_vehicles_value: 20_000 + output: + # 1,000 + 1,500 + 700 = 3,200; the vehicle is excluded. + nc_tanf_countable_resources: 3_200 + nc_tanf_resources_eligible: false + +- name: An SSI-recipient parent's $4,000 bank balance does not count. + period: 2025 + input: + people: + parent: + age: 35 + ssi: 11_000 + bank_account_assets: 4_000 + child: + age: 10 + spm_units: + spm_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NC + output: + # 10A NCAC 71W .0407(b)(1): a parent's resources count unless the parent + # receives SSI. 4,000 - 4,000 = 0. + nc_tanf_countable_resources: 0 + nc_tanf_resources_eligible: true + +- name: An SSI-recipient child's $4,000 bank balance does not count. + period: 2025 + input: + people: + parent: + age: 35 + child1: + age: 8 + ssi: 11_000 + bank_account_assets: 4_000 + child2: + age: 5 + spm_units: + spm_unit: + members: [parent, child1, child2] + households: + household: + members: [parent, child1, child2] + state_code: NC + output: + # 10A NCAC 71W .0407(b)(2): a child's resources count only if the child + # is in the payment, and an SSI recipient is not. 4,000 - 4,000 = 0. + nc_tanf_countable_resources: 0 + nc_tanf_resources_eligible: true + +- name: Only the SSI recipient's share is removed when other members also hold assets. + period: 2025 + input: + people: + parent: + age: 35 + receives_ssi: true + bank_account_assets: 4_000 + stock_assets: 2_000 + child: + age: 10 + bank_account_assets: 3_500 + spm_units: + spm_unit: + members: [parent, child] + households: + household: + members: [parent, child] + state_code: NC + output: + # Total 4,000 + 2,000 + 3,500 = 9,500; the SSI parent's 6,000 is removed. + # 9,500 - 6,000 = 3,500, which exceeds the 3,000 limit. + nc_tanf_countable_resources: 3_500 + nc_tanf_resources_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/nc_tanf_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/nc_tanf_eligible.yaml index f3556562872..8bdc990f8fe 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/nc_tanf_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/nc_tanf_eligible.yaml @@ -24,3 +24,13 @@ nc_tanf_income_eligible: true output: nc_tanf_eligible: false + +- name: Demographic and income eligible, but resources above the limit. + period: 2024 + input: + state_code: NC + nc_demographic_tanf_eligible: true + nc_tanf_income_eligible: true + nc_tanf_resources_eligible: false + output: + nc_tanf_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/nc_tanf_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/nc_tanf_resources_eligible.yaml new file mode 100644 index 00000000000..bd219361921 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nc/ncdhhs/tanf/nc_tanf_resources_eligible.yaml @@ -0,0 +1,15 @@ +- name: Countable resources at the $3,000 limit are allowed. + period: 2025 + input: + state_code: NC + nc_tanf_countable_resources: 3_000 + output: + nc_tanf_resources_eligible: true + +- name: Countable resources above the $3,000 limit make the unit ineligible. + period: 2025 + input: + state_code: NC + nc_tanf_countable_resources: 3_001 + output: + nc_tanf_resources_eligible: false diff --git a/policyengine_us/variables/gov/states/nc/ncdhhs/tanf/nc_tanf_countable_resources.py b/policyengine_us/variables/gov/states/nc/ncdhhs/tanf/nc_tanf_countable_resources.py new file mode 100644 index 00000000000..a175ee809bd --- /dev/null +++ b/policyengine_us/variables/gov/states/nc/ncdhhs/tanf/nc_tanf_countable_resources.py @@ -0,0 +1,48 @@ +from policyengine_us.model_api import * + + +class nc_tanf_countable_resources(Variable): + value_type = float + entity = SPMUnit + label = "North Carolina TANF countable resources" + unit = USD + definition_period = YEAR + quantity_type = STOCK + reference = ( + "https://regulations.justia.com/states/north-carolina/title-10a/chapter-71/subchapter-w/section-0400/section-71w-0407", + # PDF pages 6-7 + "http://reports.oah.state.nc.us/ncac/title%2010a%20-%20health%20and%20human%20services/chapter%2071%20-%20adult%20and%20family%20support/subchapter%20w/subchapter%20w%20rules.pdf#page=6", + # PDF pages 2-4 + "https://policies.ncdhhs.gov/wp-content/uploads/wf115.pdf#page=2", + ) + defined_for = StateCode.NC + + def formula(spm_unit, period, parameters): + # 10A NCAC 71W .0407(d)-(e) and Work First Manual section 115, II: + # cash, checking and savings accounts, stocks, bonds and mutual fund + # shares count; motor vehicles, real property and retirement funds do + # not. Simplification: .0407(d)(3) and (e)(5) exclude the part of a + # checking account that is the month's income deposited for the + # family's needs, but bank_account_assets has no such split, so the + # full balance counts. + total = spm_unit("spm_unit_cash_assets", period) + # .0407(b)(1)-(2): a parent's resources count unless the parent + # receives SSI, and a child's count only if the child is in the + # payment, which SSI recipients are not (as in nc_tanf_household_size + # and the NC TANF income variables). The excluded members' share is + # subtracted from the unit aggregate, so households that supply only + # spm_unit_cash_assets keep the aggregate behavior. + # Limitation: .0407(b) does not list non-parent adults (for example a + # grandparent caretaker in a child-only case, an adult sibling or an + # unmarried partner), but their resources count here, as their income + # does in the NC TANF income variables. + person = spm_unit.members + is_ssi_recipient = (person("ssi", period) > 0) | person("receives_ssi", period) + # Read the components from spm_unit_cash_assets.adds, so the + # subtraction removes exactly the excluded members' share. + components = spm_unit.simulation.tax_benefit_system.get_variable( + "spm_unit_cash_assets" + ).adds + person_assets = add(person, period, components) + excluded_assets = spm_unit.sum(person_assets * is_ssi_recipient) + return max_(total - excluded_assets, 0) diff --git a/policyengine_us/variables/gov/states/nc/ncdhhs/tanf/nc_tanf_eligible.py b/policyengine_us/variables/gov/states/nc/ncdhhs/tanf/nc_tanf_eligible.py index 362d75a2852..786a1a04aae 100644 --- a/policyengine_us/variables/gov/states/nc/ncdhhs/tanf/nc_tanf_eligible.py +++ b/policyengine_us/variables/gov/states/nc/ncdhhs/tanf/nc_tanf_eligible.py @@ -11,5 +11,6 @@ class nc_tanf_eligible(Variable): def formula(spm_unit, period, parameters): is_demographically_eligible = spm_unit("nc_demographic_tanf_eligible", period) is_income_eligible = spm_unit("nc_tanf_income_eligible", period) + is_resources_eligible = spm_unit("nc_tanf_resources_eligible", period) - return is_income_eligible & is_demographically_eligible + return is_income_eligible & is_demographically_eligible & is_resources_eligible diff --git a/policyengine_us/variables/gov/states/nc/ncdhhs/tanf/nc_tanf_resources_eligible.py b/policyengine_us/variables/gov/states/nc/ncdhhs/tanf/nc_tanf_resources_eligible.py new file mode 100644 index 00000000000..3d5c0e972a5 --- /dev/null +++ b/policyengine_us/variables/gov/states/nc/ncdhhs/tanf/nc_tanf_resources_eligible.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class nc_tanf_resources_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "North Carolina TANF resources eligible" + definition_period = YEAR + reference = ( + "https://regulations.justia.com/states/north-carolina/title-10a/chapter-71/subchapter-w/section-0400/section-71w-0407", + "https://policies.ncdhhs.gov/wp-content/uploads/wf115.pdf#page=1", + ) + defined_for = StateCode.NC + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nc.ncdhhs.tanf.resources + countable_resources = spm_unit("nc_tanf_countable_resources", period) + return countable_resources <= p.limit