diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..0a97913369a 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: minor + changes: + added: + - Add New Mexico Works (NM Works) program diff --git a/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/child_support/disregard.yaml b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/child_support/disregard.yaml new file mode 100644 index 00000000000..5d472e7fa5f --- /dev/null +++ b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/child_support/disregard.yaml @@ -0,0 +1,12 @@ +description: New Mexico excludes this amount of child support received from countable income under the New Mexico Works program. + +values: + 2015-01-01: 50 + +metadata: + unit: currency-USD + period: month + label: New Mexico Works child support disregard amount + reference: + - title: 8.102.520.9(J) NMAC - Exempt Income + href: https://www.srca.nm.gov/parts/title08/08.102.0520.html diff --git a/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/child_support/passthrough.yaml b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/child_support/passthrough.yaml new file mode 100644 index 00000000000..11b23c2e944 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/child_support/passthrough.yaml @@ -0,0 +1,24 @@ +description: New Mexico passes through this amount of child support to families under the New Mexico Works program. + +metadata: + period: month + label: New Mexico Works child support passthrough amount + type: single_amount + threshold_unit: /1 + amount_unit: currency-USD + reference: + - title: 8.102.520.9(J) NMAC - Exempt Income + href: https://www.srca.nm.gov/parts/title08/08.102.0520.html + - title: HCA - Child Support Passthrough Increase (Jan 2023) + href: https://www.hca.nm.gov/2023/01/10/human-services-department-to-pass-through-more-money-to-low-income-families/ + +brackets: + - threshold: + 2015-01-01: 1 + amount: + 2015-01-01: 100 + - threshold: + 2015-01-01: 2 + amount: + 2015-01-01: 100 + 2023-01-01: 200 diff --git a/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/childcare/amount.yaml b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/childcare/amount.yaml new file mode 100644 index 00000000000..6c66d9c9875 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/childcare/amount.yaml @@ -0,0 +1,23 @@ +description: New Mexico deducts up to this amount of childcare expenses per child from countable income under the New Mexico Works program. + +metadata: + period: month + label: New Mexico Works childcare deduction amount + type: single_amount + threshold_unit: year + amount_unit: currency-USD + reference: + - title: 8.102.520.12(D) NMAC - Earned Income Deductions + href: https://www.srca.nm.gov/parts/title08/08.102.0520.html + - title: TANF Final State Plan 2024-2026, Section 9.8 + href: https://www.hca.nm.gov/wp-content/uploads/TANF-Final-State-Plan-2024-to-2026.pdf#page=21 + +brackets: + - threshold: + 2015-01-01: 0 + amount: + 2015-01-01: 200 + - threshold: + 2015-01-01: 2 + amount: + 2015-01-01: 175 diff --git a/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/work_incentive/rate.yaml b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/work_incentive/rate.yaml new file mode 100644 index 00000000000..54b09ee6bdc --- /dev/null +++ b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/work_incentive/rate.yaml @@ -0,0 +1,14 @@ +description: New Mexico excludes this share of earnings remaining after the flat work incentive deduction under the New Mexico Works program. + +values: + 2015-01-01: 0.5 + +metadata: + unit: /1 + period: month + label: New Mexico Works work incentive percentage disregard rate + reference: + - title: 8.102.520.12(C) NMAC - Earned Income Deductions + href: https://www.srca.nm.gov/parts/title08/08.102.0520.html + - title: TANF Final State Plan 2024-2026, Section 9.8 + href: https://www.hca.nm.gov/wp-content/uploads/TANF-Final-State-Plan-2024-to-2026.pdf#page=21 diff --git a/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/work_incentive/single_parent/amount.yaml b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/work_incentive/single_parent/amount.yaml new file mode 100644 index 00000000000..d647d3963aa --- /dev/null +++ b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/work_incentive/single_parent/amount.yaml @@ -0,0 +1,14 @@ +description: New Mexico deducts this amount from gross earned income for single-parent benefit groups under the New Mexico Works program. + +values: + 2015-01-01: 125 + +metadata: + unit: currency-USD + period: month + label: New Mexico Works single-parent work incentive flat deduction amount + reference: + - title: 8.102.520.12(C) NMAC - Earned Income Deductions + href: https://www.srca.nm.gov/parts/title08/08.102.0520.html + - title: TANF Final State Plan 2024-2026, Section 9.8 + href: https://www.hca.nm.gov/wp-content/uploads/TANF-Final-State-Plan-2024-to-2026.pdf#page=21 diff --git a/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/work_incentive/two_parent/amount.yaml b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/work_incentive/two_parent/amount.yaml new file mode 100644 index 00000000000..4cb072133ac --- /dev/null +++ b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/deductions/work_incentive/two_parent/amount.yaml @@ -0,0 +1,14 @@ +description: New Mexico deducts this amount per parent from gross earned income for two-parent benefit groups under the New Mexico Works program. + +values: + 2015-01-01: 225 + +metadata: + unit: currency-USD + period: month + label: New Mexico Works two-parent work incentive flat deduction amount + reference: + - title: 8.102.520.12(C) NMAC - Earned Income Deductions + href: https://www.srca.nm.gov/parts/title08/08.102.0520.html + - title: TANF Final State Plan 2024-2026, Section 9.8 + href: https://www.hca.nm.gov/wp-content/uploads/TANF-Final-State-Plan-2024-to-2026.pdf#page=21 diff --git a/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/gross_limit/rate.yaml b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/gross_limit/rate.yaml new file mode 100644 index 00000000000..a92824c0e1a --- /dev/null +++ b/policyengine_us/parameters/gov/states/nm/hca/nm_works/income/gross_limit/rate.yaml @@ -0,0 +1,14 @@ +description: New Mexico limits gross income to this share of the federal poverty guidelines under the New Mexico Works program. + +values: + 2015-01-01: 0.85 + +metadata: + unit: /1 + period: month + label: New Mexico Works gross income limit rate + reference: + - title: 8.102.500.8(B) NMAC - Income Eligibility + href: https://www.srca.nm.gov/parts/title08/08.102.0500.html + - title: TANF Final State Plan 2024-2026, Section 9.8 + href: https://www.hca.nm.gov/wp-content/uploads/TANF-Final-State-Plan-2024-to-2026.pdf#page=20 diff --git a/policyengine_us/parameters/gov/states/nm/hca/nm_works/payment_standard/additional_person.yaml b/policyengine_us/parameters/gov/states/nm/hca/nm_works/payment_standard/additional_person.yaml new file mode 100644 index 00000000000..99081bd6884 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nm/hca/nm_works/payment_standard/additional_person.yaml @@ -0,0 +1,22 @@ +description: New Mexico provides this additional amount per person for benefit groups larger than the maximum table size under the New Mexico Works program. + +# 2015-08-01: 7.5% budgetary adjustment applied (+$83) +# 2018-11-01: Budgetary adjustment removed (+$91) +# 2023-08-01: 23% increase (+$111) + +values: + 2015-08-01: 83 + 2018-11-01: 91 + 2023-08-01: 111 + +metadata: + unit: currency-USD + period: month + label: New Mexico Works additional person payment standard amount + reference: + - title: 8.102.500.8(D) NMAC - Eligibility Policy + href: https://www.srca.nm.gov/parts/title08/08.102.0500.html + - title: NM Human Services Register Vol. 41 No. 17 - Removal of Budgetary Allowance + href: https://www.hca.nm.gov/wp-content/uploads/HSR-Vol-41-No-17-with-proposed-rule.pdf#page=1 + - title: HCA - 23% Cash Assistance Increase Announcement (Sept 2023) + href: https://www.hca.nm.gov/2023/09/01/state-announces-a-23-percent-increase-in-cash-assistance-for-low-income-new-mexico-families/ diff --git a/policyengine_us/parameters/gov/states/nm/hca/nm_works/payment_standard/amount.yaml b/policyengine_us/parameters/gov/states/nm/hca/nm_works/payment_standard/amount.yaml new file mode 100644 index 00000000000..fc7a62fa3fd --- /dev/null +++ b/policyengine_us/parameters/gov/states/nm/hca/nm_works/payment_standard/amount.yaml @@ -0,0 +1,62 @@ +description: New Mexico provides this amount as the payment standard under the New Mexico Works program. + +metadata: + unit: currency-USD + period: month + breakdown: + - range(1, 9) + breakdown_label: + - Assistance unit size + label: New Mexico Works payment standard amount + reference: + - title: 8.102.500.8(D)NMAC - Eligibility Policy + href: https://www.srca.nm.gov/parts/title08/08.102.0500.html + - title: NM Human Services Register Vol. 41 No. 17 - Removal of Budgetary Allowance + href: https://www.hca.nm.gov/wp-content/uploads/HSR-Vol-41-No-17-with-proposed-rule.pdf#page=1 + - title: NM Works Fact Sheet (2017) + href: https://www.hsd.state.nm.us/wp-content/uploads/FileLinks/f13cd6ab72d244089c5bf80111f07524/Temporary_Assistance_to_Needy_Families__TANF__Fact_Sheet_2017.pdf#page=3 + - title: NM TANF State Plan (2024-2026) + href: https://www.hca.nm.gov/wp-content/uploads/TANF-Final-State-Plan-2024-to-2026.pdf#page=19 + +# Budgetary Adjustment History: +# Due to state budget constraints, NM implemented a 15% budgetary adjustment on 2011-01-01, +# reducing the maximum monthly benefit below the payment standard. In August 2015, this was +# reduced to 7.5%. The adjustment was fully removed on 2018-11-01. The values below reflect +# the effective payment standard (after any budgetary adjustment) for each period. +# +# 2015-08-01: 7.5% budgetary adjustment applied (e.g., size 3: $447 - $38 = $409) +# 2018-11-01: Budgetary adjustment removed (e.g., size 3: $447) +# 2023-08-01: 23% increase to payment standards (e.g., size 3: $549) + +1: + 2015-08-01: 244 + 2018-11-01: 266 + 2023-08-01: 327 +2: + 2015-08-01: 327 + 2018-11-01: 357 + 2023-08-01: 439 +3: + 2015-08-01: 409 + 2018-11-01: 447 + 2023-08-01: 549 +4: + 2015-08-01: 493 + 2018-11-01: 539 + 2023-08-01: 663 +5: + 2015-08-01: 576 + 2018-11-01: 630 + 2023-08-01: 775 +6: + 2015-08-01: 659 + 2018-11-01: 721 + 2023-08-01: 887 +7: + 2015-08-01: 743 + 2018-11-01: 812 + 2023-08-01: 999 +8: + 2015-08-01: 843 + 2018-11-01: 922 + 2023-08-01: 1_134 diff --git a/policyengine_us/parameters/gov/states/nm/hca/nm_works/payment_standard/max_table_size.yaml b/policyengine_us/parameters/gov/states/nm/hca/nm_works/payment_standard/max_table_size.yaml new file mode 100644 index 00000000000..8d5e68761c9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nm/hca/nm_works/payment_standard/max_table_size.yaml @@ -0,0 +1,14 @@ +description: New Mexico provides the New Mexico Works payment standard table up to this benefit group size. + +values: + 2015-08-01: 8 + +metadata: + unit: person + period: year + label: New Mexico Works payment standard maximum table size + reference: + - title: 8.102.500.8(D) NMAC - Eligibility Policy + href: https://www.srca.nm.gov/parts/title08/08.102.0500.html + - title: NM TANF State Plan (2024-2026) + href: https://www.hca.nm.gov/wp-content/uploads/TANF-Final-State-Plan-2024-to-2026.pdf#page=19 diff --git a/policyengine_us/parameters/gov/states/nm/hca/nm_works/resources/limit/liquid.yaml b/policyengine_us/parameters/gov/states/nm/hca/nm_works/resources/limit/liquid.yaml new file mode 100644 index 00000000000..a2429247504 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nm/hca/nm_works/resources/limit/liquid.yaml @@ -0,0 +1,14 @@ +description: New Mexico limits liquid resources to this amount under the New Mexico Works program. + +values: + 2015-01-01: 1_500 + +metadata: + unit: currency-USD + period: month + label: New Mexico Works liquid resource limit amount + reference: + - title: 8.102.510.8(A) NMAC - Resources/Property + href: https://www.srca.nm.gov/parts/title08/08.102.0510.html + - title: TANF Final State Plan 2024-2026, Section 9.7 + href: https://www.hca.nm.gov/wp-content/uploads/TANF-Final-State-Plan-2024-to-2026.pdf#page=20 diff --git a/policyengine_us/parameters/gov/states/nm/hca/nm_works/resources/limit/non_liquid.yaml b/policyengine_us/parameters/gov/states/nm/hca/nm_works/resources/limit/non_liquid.yaml new file mode 100644 index 00000000000..9582153989c --- /dev/null +++ b/policyengine_us/parameters/gov/states/nm/hca/nm_works/resources/limit/non_liquid.yaml @@ -0,0 +1,14 @@ +description: New Mexico limits non-liquid resources to this amount under the New Mexico Works program. + +values: + 2015-01-01: 2_000 + +metadata: + unit: currency-USD + period: month + label: New Mexico Works non-liquid resource limit amount + reference: + - title: 8.102.510.8(B) NMAC - Resources/Property + href: https://www.srca.nm.gov/parts/title08/08.102.0510.html + - title: TANF Final State Plan 2024-2026, Section 9.7 + href: https://www.hca.nm.gov/wp-content/uploads/TANF-Final-State-Plan-2024-to-2026.pdf#page=20 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/eligibility/nm_works_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/eligibility/nm_works_eligible.yaml new file mode 100644 index 00000000000..84c381c9078 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/eligibility/nm_works_eligible.yaml @@ -0,0 +1,53 @@ +# New Mexico Works (TANF) Eligibility Unit Tests +# Tests the main eligibility determination +# Source: 8.102.400 NMAC - Eligibility Determination + +- name: Case 1, eligible when both gross and net income tests pass. + period: 2024-01 + input: + state_code: NM + nm_works_gross_income_eligible: true + nm_works_net_income_eligible: true + is_demographic_tanf_eligible: true + output: + nm_works_eligible: true + +- name: Case 2, ineligible when gross income test fails. + period: 2024-01 + input: + state_code: NM + nm_works_gross_income_eligible: false + nm_works_net_income_eligible: true + is_demographic_tanf_eligible: true + output: + nm_works_eligible: false + +- name: Case 3, ineligible when net income test fails. + period: 2024-01 + input: + state_code: NM + nm_works_gross_income_eligible: true + nm_works_net_income_eligible: false + is_demographic_tanf_eligible: true + output: + nm_works_eligible: false + +- name: Case 4, ineligible when both income tests fail. + period: 2024-01 + input: + state_code: NM + nm_works_gross_income_eligible: false + nm_works_net_income_eligible: false + is_demographic_tanf_eligible: true + output: + nm_works_eligible: false + +- name: Case 5, ineligible when demographic requirements not met. + period: 2024-01 + input: + state_code: NM + nm_works_gross_income_eligible: true + nm_works_net_income_eligible: true + is_demographic_tanf_eligible: false + output: + nm_works_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/eligibility/nm_works_gross_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/eligibility/nm_works_gross_income_eligible.yaml new file mode 100644 index 00000000000..8b5b1df230c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/eligibility/nm_works_gross_income_eligible.yaml @@ -0,0 +1,123 @@ +- name: Case 1, no income is eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # 85% FPL for size 2: $1,396/month + nm_works_gross_income_eligible: true + +- name: Case 2, income below limit is eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + nm_works_gross_income: 1_000 + households: + household: + members: [person1, person2] + state_code: NM + output: + # $1,000 < $1,396 = eligible + nm_works_gross_income_eligible: true + +- name: Case 3, income at limit is eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + nm_works_gross_income: 1_396.83 + households: + household: + members: [person1, person2] + state_code: NM + output: + # Formula uses <= so at limit is eligible + nm_works_gross_income_eligible: true + +- name: Case 4, income above limit is ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + nm_works_gross_income: 2_000 + households: + household: + members: [person1, person2] + state_code: NM + output: + nm_works_gross_income_eligible: false + +- name: Case 5, larger household below limit. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 10 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + nm_works_gross_income: 2_000 + households: + household: + members: [person1, person2, person3, person4] + state_code: NM + output: + # 85% FPL for size 4: 0.85 * $2,503.33 = $2,127.83 + # $2,000 < $2,128 = eligible + nm_works_gross_income_eligible: true + +- name: Case 6, income one dollar above limit is ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + nm_works_gross_income: 1_397 + households: + household: + members: [person1, person2] + state_code: NM + output: + # 85% FPL for size 2: 0.85 * $1,643.33 = $1,396.83 + # $1,397 > $1,396.83 = ineligible + nm_works_gross_income_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/eligibility/nm_works_net_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/eligibility/nm_works_net_income_eligible.yaml new file mode 100644 index 00000000000..b235638763f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/eligibility/nm_works_net_income_eligible.yaml @@ -0,0 +1,108 @@ +- name: Case 1, no countable income is eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + nm_works_countable_income: 0 + nm_works_maximum_benefit: 439 + households: + household: + members: [person1, person2] + state_code: NM + output: + # $0 <= $439 = eligible + nm_works_net_income_eligible: true + +- name: Case 2, countable income below standard is eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + nm_works_countable_income: 300 + nm_works_maximum_benefit: 439 + households: + household: + members: [person1, person2] + state_code: NM + output: + # $300 <= $439 = eligible + nm_works_net_income_eligible: true + +- name: Case 3, countable income at standard is eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + nm_works_countable_income: 439 + nm_works_maximum_benefit: 439 + households: + household: + members: [person1, person2] + state_code: NM + output: + # $439 <= $439 = eligible (boundary) + nm_works_net_income_eligible: true + +- name: Case 4, countable income above standard is ineligible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + nm_works_countable_income: 500 + nm_works_maximum_benefit: 439 + households: + household: + members: [person1, person2] + state_code: NM + output: + # $500 > $439 = ineligible + nm_works_net_income_eligible: false + +- name: Case 5, larger household below standard. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 10 + person3: + age: 8 + person4: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + nm_works_countable_income: 500 + nm_works_maximum_benefit: 663 + households: + household: + members: [person1, person2, person3, person4] + state_code: NM + output: + # $500 <= $663 = eligible + nm_works_net_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/eligibility/nm_works_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/eligibility/nm_works_resources_eligible.yaml new file mode 100644 index 00000000000..20bf71a27c5 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/eligibility/nm_works_resources_eligible.yaml @@ -0,0 +1,35 @@ +- name: Case 1, zero assets is eligible. + period: 2024-01 + input: + state_code: NM + spm_unit_assets: 0 + output: + nm_works_resources_eligible: true + +- name: Case 2, one dollar below limit is eligible. + period: 2024-01 + input: + state_code: NM + spm_unit_assets: 3_499 + output: + # Combined limit: $1,500 + $2,000 = $3,500 + # $3,499 <= $3,500 = eligible + nm_works_resources_eligible: true + +- name: Case 3, at limit is eligible. + period: 2024-01 + input: + state_code: NM + spm_unit_assets: 3_500 + output: + # $3,500 <= $3,500 = eligible (boundary) + nm_works_resources_eligible: true + +- name: Case 4, one dollar above limit is ineligible. + period: 2024-01 + input: + state_code: NM + spm_unit_assets: 3_501 + output: + # $3,501 > $3,500 = ineligible + nm_works_resources_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_child_support_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_child_support_deduction.yaml new file mode 100644 index 00000000000..e74048b9c6c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_child_support_deduction.yaml @@ -0,0 +1,253 @@ +# New Mexico Works Child Support Deduction Unit Tests +# Tests the child support deduction: $50 disregard + passthrough ($100 for 1 child, $200 for 2+ children) +# Total deduction = min(child_support_received, disregard + passthrough) +# Source: 8.102.520.9(J) NMAC - Exempt Income + +- name: Case 1, zero child support results in zero deduction. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # No child support received, no deduction + nm_works_child_support_deduction: 0 + +- name: Case 2, small child support with one child caps at amount received. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 600 # $50/month (annual input) + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Child support: $50/month + # 1 child: disregard $50 + passthrough $100 = $150 max deduction + # Deduction = min($50, $150) = $50 + nm_works_child_support_deduction: 50 + +- name: Case 3, child support at disregard only with zero children. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 600 # $50/month (annual input) + person2: + age: 25 # Adult, not a child + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Child support: $50/month + # 0 children: disregard $50 + passthrough $0 = $50 max deduction + # Deduction = min($50, $50) = $50 + nm_works_child_support_deduction: 50 + +- name: Case 4, child support exactly at max deduction for one child. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 1_800 # $150/month (annual input) + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Child support: $150/month + # 1 child: disregard $50 + passthrough $100 = $150 max deduction + # Deduction = min($150, $150) = $150 + nm_works_child_support_deduction: 150 + +- name: Case 5, child support exceeds max deduction for one child. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 3_600 # $300/month (annual input) + person2: + age: 8 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Child support: $300/month + # 1 child: disregard $50 + passthrough $100 = $150 max deduction + # Deduction = min($300, $150) = $150 (capped) + nm_works_child_support_deduction: 150 + +- name: Case 6, child support exactly at max deduction for two children. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 3_000 # $250/month (annual input) + person2: + age: 10 + person3: + age: 7 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Child support: $250/month + # 2 children: disregard $50 + passthrough $200 = $250 max deduction + # Deduction = min($250, $250) = $250 + nm_works_child_support_deduction: 250 + +- name: Case 7, child support exceeds max deduction for two plus children. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 4_800 # $400/month (annual input) + person2: + age: 12 + person3: + age: 9 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Child support: $400/month + # 2+ children: disregard $50 + passthrough $200 = $250 max deduction + # Deduction = min($400, $250) = $250 (capped) + nm_works_child_support_deduction: 250 + +- name: Case 8, child at age 17 counts as child. + period: 2024-01 + input: + people: + person1: + age: 40 + child_support_received: 3_600 # $300/month (annual input) + person2: + age: 17 # Under 18, counts as child + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Child support: $300/month + # 1 child (age 17 < 18): disregard $50 + passthrough $100 = $150 max deduction + # Deduction = min($300, $150) = $150 + nm_works_child_support_deduction: 150 + +- name: Case 9, person at age 18 does not count as child. + period: 2024-01 + input: + people: + person1: + age: 40 + child_support_received: 3_600 # $300/month (annual input) + person2: + age: 18 # Not under 18, not a child + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Child support: $300/month + # 0 children (age 18 >= 18): disregard $50 + passthrough $0 = $50 max deduction + # Deduction = min($300, $50) = $50 + nm_works_child_support_deduction: 50 + +- name: Case 10, three children still get 200 dollar passthrough. + period: 2024-01 + input: + people: + person1: + age: 35 + child_support_received: 4_800 # $400/month (annual input) + person2: + age: 14 + person3: + age: 11 + person4: + age: 6 + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: NM + output: + # Child support: $400/month + # 3 children (2+ rule): disregard $50 + passthrough $200 = $250 max deduction + # Deduction = min($400, $250) = $250 + nm_works_child_support_deduction: 250 + +- name: Case 11, pre-2023 two children get 100 dollar passthrough. + period: 2022-01 + input: + people: + person1: + age: 30 + child_support_received: 3_600 # $300/month (annual input) + person2: + age: 10 + person3: + age: 7 + spm_units: + spm_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Child support: $300/month + # Before Jan 2023: 2+ children: disregard $50 + passthrough $100 = $150 max deduction + # Deduction = min($300, $150) = $150 (capped) + nm_works_child_support_deduction: 150 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_childcare_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_childcare_deduction.yaml new file mode 100644 index 00000000000..aaf7fa28703 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_childcare_deduction.yaml @@ -0,0 +1,325 @@ +# New Mexico Works (TANF) Child Care Deduction Unit Tests +# Tests the child care deduction calculation +# Source: 8.102.520.12 NMAC +# Limits: Under 2: $200/month, Age 2+: $175/month + +- name: Case 1, no child care expenses results in zero deduction. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 3 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 0 + households: + household: + members: [person1, person2] + state_code: NM + output: + nm_works_childcare_deduction: 0 + +- name: Case 2, child care for child under 2 at max limit. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 1 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 3_000 # $250/month + households: + household: + members: [person1, person2] + state_code: NM + output: + # Under 2 limit: $200/month + # Expense: $250/month, capped at $200 + nm_works_childcare_deduction: 200 + +- name: Case 3, child care for child age 2 or older at max limit. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 4 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 2_400 # $200/month + households: + household: + members: [person1, person2] + state_code: NM + output: + # Age 2+ limit: $175/month + # Expense: $200/month, capped at $175 + nm_works_childcare_deduction: 175 + +- name: Case 4, child care below limit is fully deductible. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 1_200 # $100/month + households: + household: + members: [person1, person2] + state_code: NM + output: + # Age 2+ limit: $175/month + # Expense: $100/month < $175, so full $100 + nm_works_childcare_deduction: 100 + +- name: Case 5, multiple children with mixed ages. + period: 2024-01 + input: + people: + person1: + age: 32 + person2: + age: 1 # Under 2 + person3: + age: 4 # Age 2+ + spm_units: + spm_unit: + members: [person1, person2, person3] + childcare_expenses: 6_000 # $500/month total + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Under 2 limit: $200 + # Age 2+ limit: $175 + # Total max: $200 + $175 = $375 + # Expense: $500/month, capped at $375 + nm_works_childcare_deduction: 375 + +- name: Case 6, child care expenses allocated below limits. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 1 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + childcare_expenses: 3_000 # $250/month total + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Under 2 limit: $200 + # Age 2+ limit: $175 + # Total expense: $250 < combined limit $375 + # Full expense deductible: $250 + nm_works_childcare_deduction: 250 + +# Edge Cases: Age boundary and special scenarios + +- name: Case 7, child exactly at age 2 gets lower deduction limit. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 2 # Exactly age 2 (boundary) + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 3_000 # $250/month + households: + household: + members: [person1, person2] + state_code: NM + output: + # Age 2+ limit: $175/month (age 2 uses the $175 bracket) + # Expense: $250/month, capped at $175 + nm_works_childcare_deduction: 175 + +- name: Case 8, infant at age 0 gets higher deduction limit. + period: 2024-01 + input: + people: + person1: + age: 25 + person2: + age: 0 # Newborn + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 3_000 # $250/month + households: + household: + members: [person1, person2] + state_code: NM + output: + # Under 2 limit: $200/month (age 0 is under 2) + # Expense: $250/month, capped at $200 + nm_works_childcare_deduction: 200 + +- name: Case 9, non-dependent adult does not qualify for child care deduction. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 20 # Adult, not a dependent + is_tax_unit_dependent: false + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 2_400 # $200/month + households: + household: + members: [person1, person2] + state_code: NM + output: + # Non-dependent (age 20) gets $0 toward childcare limit + # Total max: $0 + # Expense capped at $0 + nm_works_childcare_deduction: 0 + +- name: Case 10, two children both under age 2. + period: 2024-01 + input: + people: + person1: + age: 28 + person2: + age: 1 + person3: + age: 0 # Newborn + spm_units: + spm_unit: + members: [person1, person2, person3] + childcare_expenses: 6_000 # $500/month + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Both children under 2: $200 each + # Total max: $200 + $200 = $400 + # Expense: $500/month, capped at $400 + nm_works_childcare_deduction: 400 + +- name: Case 11, two children both age 2 or older. + period: 2024-01 + input: + people: + person1: + age: 32 + person2: + age: 3 + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + childcare_expenses: 4_800 # $400/month + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Both children age 2+: $175 each + # Total max: $175 + $175 = $350 + # Expense: $400/month, capped at $350 + nm_works_childcare_deduction: 350 + +- name: Case 12, child care expenses exactly at combined limit. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 1 # Under 2: $200 + person3: + age: 4 # Age 2+: $175 + spm_units: + spm_unit: + members: [person1, person2, person3] + childcare_expenses: 4_500 # $375/month = exact limit + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Total max: $200 + $175 = $375 + # Expense: $375/month = exact limit + nm_works_childcare_deduction: 375 + +- name: Case 13, large family with many children of mixed ages. + period: 2024-01 + input: + people: + person1: + age: 35 + person2: + age: 0 # Under 2: $200 + person3: + age: 1 # Under 2: $200 + person4: + age: 3 # Age 2+: $175 + person5: + age: 6 # Age 2+: $175 + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5] + childcare_expenses: 12_000 # $1,000/month + households: + household: + members: [person1, person2, person3, person4, person5] + state_code: NM + output: + # 2 under 2: $200 * 2 = $400 + # 2 age 2+: $175 * 2 = $350 + # Total max: $750 + # Expense: $1,000/month, capped at $750 + nm_works_childcare_deduction: 750 + +- name: Case 14, child care expenses at zero with dependents. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 1 + person3: + age: 3 + spm_units: + spm_unit: + members: [person1, person2, person3] + childcare_expenses: 0 + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # No expenses = no deduction regardless of eligible children + nm_works_childcare_deduction: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_countable_earned_income.yaml new file mode 100644 index 00000000000..40a982609d1 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_countable_earned_income.yaml @@ -0,0 +1,202 @@ +# New Mexico Works Countable Earned Income Unit Tests +# Tests the countable earned income after work incentive and childcare deductions +# Formula: max(gross_earned - earned_deduction - childcare_deduction, 0) +# Source: 8.102.520.12 NMAC + +- name: Case 1, no earnings results in zero countable. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + is_parent: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + nm_works_countable_earned_income: 0 + +- name: Case 2, single parent with moderate earnings. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month + is_parent: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Single parent deduction: $125 + 50% of remainder + # Gross: $1,000 + # After flat: $1,000 - $125 = $875 + # After percentage: $875 * 0.50 = $437.50 + # Childcare deduction: $0 (no childcare expenses) + # Countable earned: $437.50 + nm_works_countable_earned_income: 437.5 + +- name: Case 3, single parent with earnings below flat deduction. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 1_200 # $100/month + is_parent: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Gross: $100 + # Flat deduction $125 > gross, so after work incentive = $0 + # Childcare deduction: $0 + # Countable = max($0 - $0, 0) = $0 + nm_works_countable_earned_income: 0 + +- name: Case 4, two-parent household with both working. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 9_600 # $800/month + is_tax_unit_head: true + is_parent: true + person2: + age: 33 + employment_income_before_lsr: 6_000 # $500/month + is_tax_unit_spouse: true + is_parent: true + person3: + age: 10 + spm_units: + spm_unit: + members: [person1, person2, person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Two-parent: $225 + 50% each + # + # Parent 1: $800 + # After flat: $800 - $225 = $575 + # After percentage: $575 * 0.50 = $287.50 + # + # Parent 2: $500 + # After flat: $500 - $225 = $275 + # After percentage: $275 * 0.50 = $137.50 + # + # Total after work incentive: $287.50 + $137.50 = $425 + # Childcare deduction: $0 + # Countable earned: $425 + nm_works_countable_earned_income: 425 + +- name: Case 5, self-employment income is treated as earned income. + period: 2024-01 + input: + people: + person1: + age: 35 + self_employment_income_before_lsr: 9_600 # $800/month + is_parent: true + person2: + age: 8 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Single parent: $125 + 50% of remainder + # Gross: $800 + # After flat: $800 - $125 = $675 + # After percentage: $675 * 0.50 = $337.50 + # Childcare deduction: $0 + # Countable earned: $337.50 + nm_works_countable_earned_income: 337.5 + +- name: Case 6, earnings with childcare expenses deducted. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month + is_parent: true + person2: + age: 3 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 1_500 # $125/month + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Gross: $1,000 + # Work incentive deduction: $125 + ($875 * 0.50) = $562.50 + # After work incentive: $1,000 - $562.50 = $437.50 + # Childcare deduction: min($125, $175) = $125 (age 3 max is $175) + # Countable earned: max($437.50 - $125, 0) = $312.50 + nm_works_countable_earned_income: 312.5 + +- name: Case 7, childcare deduction cannot exceed countable earned after work incentive. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 3_600 # $300/month + is_parent: true + person2: + age: 1 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 6_000 # $500/month + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Gross: $300 + # Work incentive deduction: $125 + ($175 * 0.50) = $212.50 + # After work incentive: $300 - $212.50 = $87.50 + # Childcare deduction: min($500, $200) = $200 (age 1 max is $200) + # Countable earned: max($87.50 - $200, 0) = $0 (floored at 0) + nm_works_countable_earned_income: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_countable_unearned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_countable_unearned_income.yaml new file mode 100644 index 00000000000..141189289dc --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_countable_unearned_income.yaml @@ -0,0 +1,101 @@ +- name: Case 1, no unearned income. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + nm_works_countable_unearned_income: 0 + +- name: Case 2, unearned income without child support is fully countable. + period: 2024-01 + input: + people: + person1: + age: 30 + social_security: 6_000 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # $6,000/12 = $500/month, no deduction + nm_works_countable_unearned_income: 500 + +- name: Case 3, child support at deduction boundary results in zero. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 1_800 + person2: + age: 10 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # $150/month = $100 passthrough + $50 disregard + # Countable: $150 - $150 = $0 + nm_works_countable_unearned_income: 0 + +- name: Case 4, child support one dollar above deduction. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 1_812 + person2: + age: 7 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # $151/month - $150 deduction = $1 + nm_works_countable_unearned_income: 1 + +- name: Case 5, mixed unearned income with child support. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 2_400 + social_security: 1_800 + person2: + age: 6 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Social security: $150/month (fully countable) + # Child support: $200/month - $150 deduction = $50 + # Total: $150 + $50 = $200 + nm_works_countable_unearned_income: 200 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_earned_income_deduction_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_earned_income_deduction_person.yaml new file mode 100644 index 00000000000..d9297e5b9ac --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/income/nm_works_earned_income_deduction_person.yaml @@ -0,0 +1,326 @@ +# New Mexico Works (TANF) Earned Income Deduction Unit Tests +# Tests the work incentive deduction calculation +# Source: 8.102.520.12 NMAC - Earned Income Deductions +# Single parent: $125 flat + 50% of remainder +# Two-parent: $225 flat + 50% of remainder (per parent) +# Other member: $125 flat + 50% of remainder + +- name: Case 1, single parent with no earnings has zero deduction. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 0 + is_parent: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # No earnings = no deduction + nm_works_earned_income_deduction_person: [0, 0] + +- name: Case 2, single parent with earnings below flat deduction amount. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 1_200 # $100/month + is_parent: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Single parent flat deduction: $125 + # Gross earnings: $100 + # $100 < $125, so deduction = $100 (capped at earnings) + nm_works_earned_income_deduction_person: [100, 0] + +- name: Case 3, single parent with moderate earnings. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 12_000 # $1,000/month + is_parent: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Single parent: $125 + 50% of remainder + # Gross earnings: $1,000 + # Step 1: $1,000 - $125 = $875 + # Step 2: $875 * 0.50 = $437.50 + # Total deduction: $125 + $437.50 = $562.50 + nm_works_earned_income_deduction_person: [562.5, 0] + +- name: Case 4, two-parent household with both working. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 9_600 # $800/month + is_tax_unit_head: true + is_parent: true + person2: + age: 33 + employment_income_before_lsr: 6_000 # $500/month + is_tax_unit_spouse: true + is_parent: true + person3: + age: 10 + spm_units: + spm_unit: + members: [person1, person2, person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Two-parent: $225 + 50% of remainder (each parent) + # + # Parent 1 ($800/month): + # Step 1: $800 - $225 = $575 + # Step 2: $575 * 0.50 = $287.50 + # Total deduction: $225 + $287.50 = $512.50 + # + # Parent 2 ($500/month): + # Step 1: $500 - $225 = $275 + # Step 2: $275 * 0.50 = $137.50 + # Total deduction: $225 + $137.50 = $362.50 + nm_works_earned_income_deduction_person: [512.5, 362.5, 0] + +- name: Case 5, two-parent household with one parent working. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 18_000 # $1,500/month + is_tax_unit_head: true + is_parent: true + person2: + age: 33 + employment_income_before_lsr: 0 + is_tax_unit_spouse: true + is_parent: true + person3: + age: 7 + spm_units: + spm_unit: + members: [person1, person2, person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Two-parent: $225 + 50% of remainder + # Parent 1 ($1,500/month): + # Step 1: $1,500 - $225 = $1,275 + # Step 2: $1,275 * 0.50 = $637.50 + # Total deduction: $225 + $637.50 = $862.50 + # Parent 2: $0 earnings = $0 deduction + nm_works_earned_income_deduction_person: [862.5, 0, 0] + +- name: Case 6, two-parent household with earnings below flat deduction. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 2_400 # $200/month + is_tax_unit_head: true + is_parent: true + person2: + age: 33 + employment_income_before_lsr: 1_200 # $100/month + is_tax_unit_spouse: true + is_parent: true + person3: + age: 5 + spm_units: + spm_unit: + members: [person1, person2, person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Two-parent flat deduction: $225 each + # Parent 1: $200 < $225, so deduction = $200 + # Parent 2: $100 < $225, so deduction = $100 + nm_works_earned_income_deduction_person: [200, 100, 0] + +# Edge Cases: Flat deduction boundaries and special scenarios + +- name: Case 7, single parent earnings exactly at flat deduction amount. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 1_500 # $125/month = exactly flat deduction + is_parent: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Single parent flat: $125 + # Gross: $125 = exactly flat amount + # After flat: $125 - $125 = $0 + # No percentage deduction applies (nothing left) + # Total deduction: $125 + nm_works_earned_income_deduction_person: [125, 0] + +- name: Case 8, single parent earnings one dollar above flat deduction. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 1_512 # $126/month + is_parent: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Single parent flat: $125 + # Gross: $126 + # After flat: $126 - $125 = $1 + # Percentage: $1 * 0.50 = $0.50 + # Total deduction: $125 + $0.50 = $125.50 + nm_works_earned_income_deduction_person: [125.5, 0] + +- name: Case 9, two-parent earnings exactly at flat deduction amount. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 2_700 # $225/month = exactly flat deduction + is_tax_unit_head: true + is_parent: true + person2: + age: 33 + employment_income_before_lsr: 2_700 # $225/month = exactly flat deduction + is_tax_unit_spouse: true + is_parent: true + person3: + age: 8 + spm_units: + spm_unit: + members: [person1, person2, person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Two-parent flat: $225 each + # Both parents: $225 = exactly flat amount + # After flat: $0 for each + # Total deduction: $225 each + nm_works_earned_income_deduction_person: [225, 225, 0] + +- name: Case 10, two-parent earnings one dollar above flat deduction. + period: 2024-01 + input: + people: + person1: + age: 35 + employment_income_before_lsr: 2_712 # $226/month + is_tax_unit_head: true + is_parent: true + person2: + age: 33 + employment_income_before_lsr: 0 + is_tax_unit_spouse: true + is_parent: true + person3: + age: 6 + spm_units: + spm_unit: + members: [person1, person2, person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Two-parent flat: $225 + # Gross: $226 + # After flat: $226 - $225 = $1 + # Percentage: $1 * 0.50 = $0.50 + # Total deduction: $225 + $0.50 = $225.50 + nm_works_earned_income_deduction_person: [225.5, 0, 0] + +- name: Case 11, very high earnings results in large deduction. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 60_000 # $5,000/month + is_parent: true + person2: + age: 5 + spm_units: + spm_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Single parent: $125 + 50% of remainder + # Gross: $5,000 + # After flat: $5,000 - $125 = $4,875 + # Percentage: $4,875 * 0.50 = $2,437.50 + # Total deduction: $125 + $2,437.50 = $2,562.50 + nm_works_earned_income_deduction_person: [2_562.5, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/integration.yaml new file mode 100644 index 00000000000..59291a5b934 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/integration.yaml @@ -0,0 +1,517 @@ +# New Mexico Works (TANF) Integration Tests +# Tests the full benefit calculation pipeline with realistic scenarios +# Source: 8.102 NMAC - Cash Assistance Programs + +- name: Case 1, single parent with one child and no income gets maximum benefit. + period: 2024-01 + input: + people: + person1: # Parent + age: 30 + is_parent: true + person2: # Child + age: 5 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Benefit Group Size: 2 + # Payment Standard for size 2: $439/month + # No income, so full benefit + nm_works_gross_income_eligible: true + nm_works_net_income_eligible: true + nm_works_eligible: true + nm_works: 439 + +- name: Case 2, single parent with two children and moderate earnings. + period: 2024-01 + input: + people: + person1: # Parent + age: 28 + employment_income_before_lsr: 12_000 # $1,000/month + is_parent: true + person2: # Child 1 + age: 7 + is_tax_unit_dependent: true + person3: # Child 2 + age: 4 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2, person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Benefit Group Size: 3 + # 85% FPL limit for size 3: $1,829/month + # Gross earned income: $1,000/month < $1,829 = eligible + # + # Earned income deduction (single parent): + # Step 1: $1,000 - $125 = $875 + # Step 2: $875 * 0.50 = $437.50 + # Net earned income: $875 - $437.50 = $437.50 + # + # Payment Standard for size 3: $549 + # Benefit = $549 - $437.50 = $111.50 + nm_works_gross_income_eligible: true + nm_works_earned_income_deduction_person: [562.5, 0, 0] + # $1000 gross - $437.50 countable = $562.50 deduction + nm_works_countable_income: 437.5 + nm_works_net_income_eligible: true + nm_works_eligible: true + nm_works: 111.5 + +- name: Case 3, single parent with three children and child care costs. + period: 2024-01 + input: + people: + person1: # Parent + age: 32 + employment_income_before_lsr: 18_000 # $1,500/month + is_parent: true + person2: # Child 1 (under 2) + age: 1 + is_tax_unit_dependent: true + person3: # Child 2 (age 2+) + age: 4 + is_tax_unit_dependent: true + person4: # Child 3 + age: 8 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + childcare_expenses: 4_800 # $400/month + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: NM + output: + # Benefit Group Size: 4 + # 85% FPL limit for size 4: $2,210/month + # Gross earned income: $1,500/month < $2,210 = eligible + # + # Earned income deduction (single parent): + # Step 1: $1,500 - $125 = $1,375 + # Step 2: $1,375 * 0.50 = $687.50 + # Net earned income: $1,375 - $687.50 = $687.50 + # + # Child care deduction (up to $200 under 2, $175 age 2+): + # Child 1 (age 1): $200 + # Child 2 (age 4): $175 (but capped by actual expense allocation) + # Total child care deduction: min($400, $200 + $175) = $375 + # + # Child care max: $200 (age 1) + $175 (age 4) + $175 (age 8) = $550 + # Actual expense: $400, so deduction = min($550, $400) = $400 + # Countable income: $687.50 - $400 = $287.50 + # Payment Standard for size 4: $663 + # Benefit = $663 - $287.50 = $375.50 + nm_works_gross_income_eligible: true + nm_works_net_income_eligible: true + nm_works_eligible: true + nm_works_childcare_deduction: 400 + nm_works_countable_income: 287.5 + nm_works: 375.5 + +- name: Case 4, two-parent household with two children. + period: 2024-01 + input: + people: + person1: # Parent 1 + age: 35 + employment_income_before_lsr: 9_600 # $800/month + is_tax_unit_head: true + is_parent: true + person2: # Parent 2 + age: 33 + employment_income_before_lsr: 6_000 # $500/month + is_tax_unit_spouse: true + is_parent: true + person3: # Child 1 + age: 10 + is_tax_unit_dependent: true + person4: # Child 2 + age: 6 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + households: + household: + members: [person1, person2, person3, person4] + state_code: NM + output: + # Benefit Group Size: 4 + # 85% FPL limit for size 4: $2,210/month + # Gross earned income: $800 + $500 = $1,300/month < $2,210 = eligible + # + # Earned income deduction (two-parent, each parent): + # Parent 1: $800 - $225 = $575, then $575 * 0.50 = $287.50, net = $287.50 + # Parent 2: $500 - $225 = $275, then $275 * 0.50 = $137.50, net = $137.50 + # Total net earned: $287.50 + $137.50 = $425 + # + # Payment Standard for size 4: $663 + # Benefit = $663 - $425 = $238 + nm_works_gross_income_eligible: true + nm_works_earned_income_deduction_person: [512.5, 362.5, 0, 0] + # Parent 1: $800 - $287.50 = $512.50 deduction + # Parent 2: $500 - $137.50 = $362.50 deduction + nm_works_countable_income: 425 + nm_works_net_income_eligible: true + nm_works_eligible: true + nm_works: 238 + +- name: Case 5, income at gross income limit threshold. + period: 2024-01 + input: + people: + person1: # Parent + age: 29 + employment_income_before_lsr: 21_948 # $1,829/month (exactly at 85% FPL for size 3) + is_parent: true + person2: # Child 1 + age: 12 + is_tax_unit_dependent: true + person3: # Child 2 + age: 9 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2, person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Benefit Group Size: 3 + # 85% FPL for size 3: 0.85 * $2,073.33 = $1,762.33/month + # Gross earned income: $1,829/month > $1,762.33 = NOT gross income eligible + # (Formula uses strict less-than, so above limit is ineligible) + nm_works_gross_income_eligible: false + nm_works_eligible: false + nm_works: 0 + +- name: Case 6, income exceeds gross income limit. + period: 2024-01 + input: + people: + person1: # Parent + age: 40 + employment_income_before_lsr: 30_000 # $2,500/month + is_parent: true + person2: # Child + age: 14 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Benefit Group Size: 2 + # 85% FPL limit for size 2: $1,448/month + # Gross earned income: $2,500/month > $1,448 = NOT eligible + nm_works_gross_income_eligible: false + nm_works_eligible: false + nm_works: 0 + +- name: Case 7, single parent with child support income and unearned income. + period: 2024-01 + input: + people: + person1: # Parent + age: 27 + employment_income_before_lsr: 6_000 # $500/month + child_support_received: 3_600 # $300/month + is_parent: true + person2: # Child + age: 3 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Benefit Group Size: 2 + # 85% FPL limit for size 2: $1,448/month + # Gross income: $500 + $300 = $800/month < $1,448 = eligible + # + # Earned income deduction (single parent): + # Step 1: $500 - $125 = $375 + # Step 2: $375 * 0.50 = $187.50 + # Net earned income: $375 - $187.50 = $187.50 + # + # Child support deduction: + # Child support passthrough: $100 (for 1 child) + # Child support disregard: $50 + # Net child support: $300 - $100 - $50 = $150 + # + # Total countable income: $187.50 + $150 = $337.50 + # Payment Standard for size 2: $439 + # Benefit = $439 - $337.50 = $101.50 + nm_works_gross_income_eligible: true + nm_works_countable_income: 337.5 + nm_works_net_income_eligible: true + nm_works_eligible: true + nm_works: 101.5 + +# Edge Case Integration Tests + +- name: Case 8, child exactly at age 2 with child care costs. + period: 2024-01 + input: + people: + person1: + age: 28 + employment_income_before_lsr: 9_600 # $800/month + is_parent: true + person2: + age: 2 # Exactly at age 2 boundary + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + childcare_expenses: 3_000 # $250/month + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Child care deduction for age 2+: $175/month max + # Actual expense: $250/month, capped at $175 + # + # Earned income deduction: $800 - $125 = $675, * 0.50 = $337.50 + # Total deduction: $125 + $337.50 = $462.50 + # Countable earned: $800 - $462.50 = $337.50 + # After child care: $337.50 - $175 = $162.50 + # + # Payment Standard: $439 + # Benefit: $439 - $162.50 = $276.50 + nm_works_childcare_deduction: 175 + nm_works_countable_income: 162.5 + nm_works_gross_income_eligible: true + nm_works_net_income_eligible: true + nm_works_eligible: true + nm_works: 276.5 + +- name: Case 10, single parent with two children and child support. + period: 2024-01 + input: + people: + person1: + age: 32 + employment_income_before_lsr: 4_800 # $400/month + child_support_received: 4_800 # $400/month + is_parent: true + person2: + age: 10 + is_tax_unit_dependent: true + person3: + age: 6 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2, person3] + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # 2 children: passthrough $200, disregard $50 + # Child support countable: $400 - $200 - $50 = $150 + # + # Earned income deduction (single parent): + # $400 - $125 = $275, * 0.50 = $137.50 + # Total deduction: $125 + $137.50 = $262.50 + # Countable earned: $137.50 + # + # Total countable: $137.50 + $150 = $287.50 + # Payment Standard for size 3: $549 + # Benefit: $549 - $287.50 = $261.50 + nm_works_countable_income: 287.5 + nm_works_gross_income_eligible: true + nm_works_net_income_eligible: true + nm_works_eligible: true + nm_works: 261.5 + +- name: Case 11, infant and toddler with child care and child support. + period: 2024-01 + input: + people: + person1: + age: 25 + employment_income_before_lsr: 10_800 # $900/month + child_support_received: 2_400 # $200/month + is_parent: true + person2: + age: 0 # Infant (under 2): $200 child care max + is_tax_unit_dependent: true + person3: + age: 2 # Toddler (age 2+): $175 child care max + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2, person3] + childcare_expenses: 6_000 # $500/month + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: NM + output: + # Child care: $200 (infant) + $175 (toddler) = $375 max + # Actual: $500, capped at $375 + # + # 2 children: passthrough $200, disregard $50 + # Child support countable: $200 - $200 - $50 = max(0, -$50) = $0 + # + # Earned income deduction (single parent): + # $900 - $125 = $775, * 0.50 = $387.50 + # Total deduction: $125 + $387.50 = $512.50 + # Countable earned before child care: $387.50 + # After child care: $387.50 - $375 = $12.50 + # + # Total countable: $12.50 + $0 = $12.50 + # Payment Standard for size 3: $549 + # Benefit: $549 - $12.50 = $536.50 + nm_works_childcare_deduction: 375 + nm_works_countable_income: 12.5 + nm_works_gross_income_eligible: true + nm_works_net_income_eligible: true + nm_works_eligible: true + nm_works: 536.5 + +- name: Case 12, earnings exactly at single-parent flat deduction. + period: 2024-01 + input: + people: + person1: + age: 30 + employment_income_before_lsr: 1_500 # $125/month = exactly flat deduction + is_parent: true + person2: + age: 5 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NM + output: + # Earnings exactly at flat deduction: $125 + # Deduction: min($125, $125) = $125 (flat only, no percentage) + # Countable earned: $0 + # + # Payment Standard for size 2: $439 + # Benefit: $439 - $0 = $439 + nm_works_earned_income_deduction_person: [125, 0] + nm_works_countable_income: 0 + nm_works_gross_income_eligible: true + nm_works_net_income_eligible: true + nm_works_eligible: true + nm_works: 439 + +- name: Case 13, very large household at maximum size. + period: 2024-01 + input: + people: + person1: + age: 45 + employment_income_before_lsr: 12_000 # $1,000/month + is_tax_unit_head: true + is_parent: true + person2: + age: 43 + is_tax_unit_spouse: true + is_parent: true + person3: + age: 17 + is_tax_unit_dependent: true + person4: + age: 15 + is_tax_unit_dependent: true + person5: + age: 13 + is_tax_unit_dependent: true + person6: + age: 11 + is_tax_unit_dependent: true + person7: + age: 9 + is_tax_unit_dependent: true + person8: + age: 7 + is_tax_unit_dependent: true + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + tax_units: + tax_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + state_code: NM + output: + # Size 8 household + # Payment Standard: $1,134 + # + # Two-parent earned income deduction: + # $1,000 - $225 = $775, * 0.50 = $387.50 + # Total deduction: $225 + $387.50 = $612.50 + # Countable: $387.50 + # + # Benefit: $1,134 - $387.50 = $746.50 + nm_works_earned_income_deduction_person: [612.5, 0, 0, 0, 0, 0, 0, 0] + nm_works_countable_income: 387.5 + nm_works_gross_income_eligible: true + nm_works_net_income_eligible: true + nm_works_eligible: true + nm_works: 746.5 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/nm_works.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/nm_works.yaml new file mode 100644 index 00000000000..b5d21c771b0 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/nm_works.yaml @@ -0,0 +1,65 @@ +- name: Case 1, ineligible receives zero benefit. + period: 2024-01 + input: + state_code: NM + nm_works_eligible: false + nm_works_maximum_benefit: 439 + nm_works_countable_income: 0 + output: + nm_works: 0 + +- name: Case 2, eligible with no income gets full benefit. + period: 2024-01 + input: + state_code: NM + nm_works_eligible: true + nm_works_maximum_benefit: 439 + nm_works_countable_income: 0 + output: + # $439 - $0 = $439 + nm_works: 439 + +- name: Case 3, benefit one dollar below standard. + period: 2024-01 + input: + state_code: NM + nm_works_eligible: true + nm_works_maximum_benefit: 439 + nm_works_countable_income: 438 + output: + # $439 - $438 = $1 + nm_works: 1 + +- name: Case 4, income at standard gets zero. + period: 2024-01 + input: + state_code: NM + nm_works_eligible: true + nm_works_maximum_benefit: 439 + nm_works_countable_income: 439 + output: + # $439 - $439 = $0 + nm_works: 0 + +- name: Case 5, income one dollar above standard gets zero. + period: 2024-01 + input: + state_code: NM + nm_works_eligible: true + nm_works_maximum_benefit: 439 + nm_works_countable_income: 440 + output: + # $439 - $440 = -$1, capped at $0 + nm_works: 0 + +- name: Case 6, size-1 household single adult gets full benefit. + period: 2024-01 + input: + state_code: NM + nm_works_eligible: true + nm_works_maximum_benefit: 327 + nm_works_countable_income: 0 + output: + # Size 1 payment standard = $327 + # $327 - $0 = $327 + nm_works: 327 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/nm_works_maximum_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/nm_works_maximum_benefit.yaml new file mode 100644 index 00000000000..3e909a6b2e0 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/hca/nm_works/nm_works_maximum_benefit.yaml @@ -0,0 +1,44 @@ +- name: Case 1, 2017 period with budgetary adjustment. + period: 2017-01 + input: + state_code: NM + spm_unit_size: 3 + output: + # 2015-08-01 values (7.5% adjustment): size 3 = $409 + nm_works_maximum_benefit: 409 + +- name: Case 2, 2019 period after adjustment removed. + period: 2019-01 + input: + state_code: NM + spm_unit_size: 3 + output: + # 2018-11-01 values (no adjustment): size 3 = $447 + nm_works_maximum_benefit: 447 + +- name: Case 3, 2024 period with 23% increase. + period: 2024-01 + input: + state_code: NM + spm_unit_size: 3 + output: + # 2023-08-01 values: size 3 = $549 + nm_works_maximum_benefit: 549 + +- name: Case 4, size 9 uses additional person increment. + period: 2024-01 + input: + state_code: NM + spm_unit_size: 9 + output: + # Size 8: $1,134 + 1 * $111 = $1,245 + nm_works_maximum_benefit: 1_245 + +- name: Case 5, size 10 uses additional person increment. + period: 2024-01 + input: + state_code: NM + spm_unit_size: 10 + output: + # Size 8: $1,134 + 2 * $111 = $1,356 + nm_works_maximum_benefit: 1_356 diff --git a/policyengine_us/variables/gov/states/nm/hca/nm_works/eligibility/nm_works_eligible.py b/policyengine_us/variables/gov/states/nm/hca/nm_works/eligibility/nm_works_eligible.py new file mode 100644 index 00000000000..4a16ea1d6a0 --- /dev/null +++ b/policyengine_us/variables/gov/states/nm/hca/nm_works/eligibility/nm_works_eligible.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class nm_works_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "New Mexico Works eligible" + definition_period = MONTH + reference = "https://www.srca.nm.gov/parts/title08/08.102.0400.html" + defined_for = StateCode.NM + + 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 + ) + resources_eligible = spm_unit("nm_works_resources_eligible", period) + gross_income_eligible = spm_unit( + "nm_works_gross_income_eligible", period + ) + net_income_eligible = spm_unit("nm_works_net_income_eligible", period) + + return ( + demographic_eligible + & immigration_eligible + & resources_eligible + & gross_income_eligible + & net_income_eligible + ) diff --git a/policyengine_us/variables/gov/states/nm/hca/nm_works/eligibility/nm_works_gross_income_eligible.py b/policyengine_us/variables/gov/states/nm/hca/nm_works/eligibility/nm_works_gross_income_eligible.py new file mode 100644 index 00000000000..ca15b304897 --- /dev/null +++ b/policyengine_us/variables/gov/states/nm/hca/nm_works/eligibility/nm_works_gross_income_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class nm_works_gross_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "New Mexico Works gross income eligible" + definition_period = MONTH + reference = "https://www.srca.nm.gov/parts/title08/08.102.0520.html" + defined_for = StateCode.NM + + def formula(spm_unit, period, parameters): + # Per 8.102.500.8(B) NMAC, gross income must be under 85% FPL + p = parameters(period).gov.states.nm.hca.nm_works.income.gross_limit + gross_income = spm_unit("nm_works_gross_income", period) + fpg = spm_unit("tanf_fpg", period) + return gross_income <= fpg * p.rate diff --git a/policyengine_us/variables/gov/states/nm/hca/nm_works/eligibility/nm_works_net_income_eligible.py b/policyengine_us/variables/gov/states/nm/hca/nm_works/eligibility/nm_works_net_income_eligible.py new file mode 100644 index 00000000000..93d813b6f79 --- /dev/null +++ b/policyengine_us/variables/gov/states/nm/hca/nm_works/eligibility/nm_works_net_income_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class nm_works_net_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "New Mexico Works net income eligible" + definition_period = MONTH + reference = "https://www.srca.nm.gov/parts/title08/08.102.0520.html" + defined_for = StateCode.NM + + def formula(spm_unit, period, parameters): + # Per 8.102.520.11 NMAC, countable income must be less than + # the standard of need (payment standard) + countable_income = spm_unit("nm_works_countable_income", period) + payment_standard = spm_unit("nm_works_maximum_benefit", period) + return countable_income <= payment_standard diff --git a/policyengine_us/variables/gov/states/nm/hca/nm_works/eligibility/nm_works_resources_eligible.py b/policyengine_us/variables/gov/states/nm/hca/nm_works/eligibility/nm_works_resources_eligible.py new file mode 100644 index 00000000000..4793e8ff773 --- /dev/null +++ b/policyengine_us/variables/gov/states/nm/hca/nm_works/eligibility/nm_works_resources_eligible.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class nm_works_resources_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "New Mexico Works resources eligible" + definition_period = MONTH + reference = "https://www.srca.nm.gov/parts/title08/08.102.0510.html" + defined_for = StateCode.NM + + def formula(spm_unit, period, parameters): + # Per 8.102.510.8 NMAC, resources/property limits: + # - Liquid resources must not exceed $1,500 + # - Non-liquid resources must not exceed $2,000 + # NOTE: Simplified check using total assets since liquid/non-liquid + # distinction is not currently modeled. Combined limit used. + p = parameters(period).gov.states.nm.hca.nm_works.resources.limit + assets = spm_unit("spm_unit_assets", period.this_year) + return assets <= p.liquid + p.non_liquid diff --git a/policyengine_us/variables/gov/states/nm/hca/nm_works/income/deductions/nm_works_child_support_deduction.py b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/deductions/nm_works_child_support_deduction.py new file mode 100644 index 00000000000..a0be18804e3 --- /dev/null +++ b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/deductions/nm_works_child_support_deduction.py @@ -0,0 +1,30 @@ +from policyengine_us.model_api import * + + +class nm_works_child_support_deduction(Variable): + value_type = float + entity = SPMUnit + label = "New Mexico Works child support deduction" + unit = USD + definition_period = MONTH + reference = ( + "https://www.srca.nm.gov/parts/title08/08.102.0520.html", + "https://www.hca.nm.gov/2023/01/10/human-services-department-to-pass-through-more-money-to-low-income-families/", + ) + defined_for = StateCode.NM + + def formula(spm_unit, period, parameters): + # Per 8.102.520.9.J NMAC: + # - $50 disregard on child support received + # - Passthrough: $100 for 1 child, $200 for 2+ children (since Jan 2023) + p = parameters( + period + ).gov.states.nm.hca.nm_works.income.deductions.child_support + + child_support_received = add( + spm_unit, period, ["child_support_received"] + ) + num_children = spm_unit("spm_unit_count_children", period.this_year) + + total_deduction = p.disregard + p.passthrough.calc(num_children) + return min_(child_support_received, total_deduction) diff --git a/policyengine_us/variables/gov/states/nm/hca/nm_works/income/deductions/nm_works_childcare_deduction.py b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/deductions/nm_works_childcare_deduction.py new file mode 100644 index 00000000000..8e272cb0e35 --- /dev/null +++ b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/deductions/nm_works_childcare_deduction.py @@ -0,0 +1,30 @@ +from policyengine_us.model_api import * + + +class nm_works_childcare_deduction(Variable): + value_type = float + entity = SPMUnit + label = "New Mexico Works childcare deduction" + unit = USD + definition_period = MONTH + reference = "https://www.srca.nm.gov/parts/title08/08.102.0520.html" + defined_for = StateCode.NM + + def formula(spm_unit, period, parameters): + # Per 8.102.520.12(D) NMAC, child care deduction varies by age: + # Under age 2: up to $200 + # Age 2 or older: up to $175 + p = parameters( + period + ).gov.states.nm.hca.nm_works.income.deductions.childcare + + person = spm_unit.members + is_dependent = person("is_tax_unit_dependent", period) + age = person("age", period.this_year) + childcare_expenses = spm_unit("childcare_expenses", period) + + # Max deduction per child based on age + childcare_max_per_child = p.amount.calc(age) * is_dependent + total_childcare_max = spm_unit.sum(childcare_max_per_child) + + return min_(childcare_expenses, total_childcare_max) diff --git a/policyengine_us/variables/gov/states/nm/hca/nm_works/income/earned/nm_works_countable_earned_income.py b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/earned/nm_works_countable_earned_income.py new file mode 100644 index 00000000000..ce1af7ef918 --- /dev/null +++ b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/earned/nm_works_countable_earned_income.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class nm_works_countable_earned_income(Variable): + value_type = float + entity = SPMUnit + label = "New Mexico Works countable earned income" + unit = USD + definition_period = MONTH + reference = "https://www.srca.nm.gov/parts/title08/08.102.0520.html" + defined_for = StateCode.NM + + def formula(spm_unit, period, parameters): + gross_earned = add(spm_unit, period, ["tanf_gross_earned_income"]) + earned_deduction = add( + spm_unit, period, ["nm_works_earned_income_deduction_person"] + ) + childcare_deduction = spm_unit("nm_works_childcare_deduction", period) + return max_(gross_earned - earned_deduction - childcare_deduction, 0) diff --git a/policyengine_us/variables/gov/states/nm/hca/nm_works/income/earned/nm_works_earned_income_deduction_person.py b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/earned/nm_works_earned_income_deduction_person.py new file mode 100644 index 00000000000..20ffe8b4692 --- /dev/null +++ b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/earned/nm_works_earned_income_deduction_person.py @@ -0,0 +1,42 @@ +from policyengine_us.model_api import * + + +class nm_works_earned_income_deduction_person(Variable): + value_type = float + entity = Person + label = "New Mexico Works earned income deduction (person)" + unit = USD + definition_period = MONTH + reference = "https://www.srca.nm.gov/parts/title08/08.102.0520.html" + defined_for = StateCode.NM + + def formula(person, period, parameters): + # Per 8.102.520.12(C) NMAC: + # Flat amount ($125 single-parent, $225 two-parent) + 50% of remainder + p = parameters( + period + ).gov.states.nm.hca.nm_works.income.deductions.work_incentive + + gross_earned = person("tanf_gross_earned_income", period) + + # Count adults in the SPM unit to determine single vs two-parent + spm_unit = person.spm_unit + adult_count = add(spm_unit, period, ["is_tax_unit_head_or_spouse"]) + + # Flat deduction depends on single vs two-parent + single_parent_flat = p.single_parent.amount + two_parent_flat = p.two_parent.amount + disregard_rate = p.rate + + # Head/spouse get $225 in two-parent families, $125 in single-parent + is_two_parent = adult_count > 1 + flat_amount = where(is_two_parent, two_parent_flat, single_parent_flat) + + # Step 1: Subtract flat amount (not to exceed earnings) + flat_deduction = min_(flat_amount, gross_earned) + after_flat = max_(gross_earned - flat_deduction, 0) + + # Step 2: 50% disregard on remainder + percentage_deduction = after_flat * disregard_rate + + return flat_deduction + percentage_deduction diff --git a/policyengine_us/variables/gov/states/nm/hca/nm_works/income/nm_works_countable_income.py b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/nm_works_countable_income.py new file mode 100644 index 00000000000..555e99c5fca --- /dev/null +++ b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/nm_works_countable_income.py @@ -0,0 +1,15 @@ +from policyengine_us.model_api import * + + +class nm_works_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "New Mexico Works countable income" + unit = USD + definition_period = MONTH + reference = "https://www.srca.nm.gov/parts/title08/08.102.0520.html" + defined_for = StateCode.NM + adds = [ + "nm_works_countable_earned_income", + "nm_works_countable_unearned_income", + ] diff --git a/policyengine_us/variables/gov/states/nm/hca/nm_works/income/nm_works_gross_income.py b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/nm_works_gross_income.py new file mode 100644 index 00000000000..be0f780d90e --- /dev/null +++ b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/nm_works_gross_income.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class nm_works_gross_income(Variable): + value_type = float + entity = SPMUnit + label = "New Mexico Works gross income" + unit = USD + definition_period = MONTH + reference = "https://www.srca.nm.gov/parts/title08/08.102.0520.html" + defined_for = StateCode.NM + + adds = ["tanf_gross_earned_income", "tanf_gross_unearned_income"] diff --git a/policyengine_us/variables/gov/states/nm/hca/nm_works/income/unearned/nm_works_countable_unearned_income.py b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/unearned/nm_works_countable_unearned_income.py new file mode 100644 index 00000000000..e2304f7f21a --- /dev/null +++ b/policyengine_us/variables/gov/states/nm/hca/nm_works/income/unearned/nm_works_countable_unearned_income.py @@ -0,0 +1,18 @@ +from policyengine_us.model_api import * + + +class nm_works_countable_unearned_income(Variable): + value_type = float + entity = SPMUnit + label = "New Mexico Works countable unearned income" + unit = USD + definition_period = MONTH + reference = "https://www.srca.nm.gov/parts/title08/08.102.0520.html" + defined_for = StateCode.NM + + def formula(spm_unit, period, parameters): + gross_unearned = add(spm_unit, period, ["tanf_gross_unearned_income"]) + child_support_deduction = spm_unit( + "nm_works_child_support_deduction", period + ) + return max_(gross_unearned - child_support_deduction, 0) diff --git a/policyengine_us/variables/gov/states/nm/hca/nm_works/nm_works.py b/policyengine_us/variables/gov/states/nm/hca/nm_works/nm_works.py new file mode 100644 index 00000000000..46a0cea1a80 --- /dev/null +++ b/policyengine_us/variables/gov/states/nm/hca/nm_works/nm_works.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class nm_works(Variable): + value_type = float + entity = SPMUnit + label = "New Mexico Works" + unit = USD + definition_period = MONTH + reference = ( + "https://www.srca.nm.gov/parts/title08/08.102.0620.html", + "https://www.hca.nm.gov/lookingforassistance/temporary_assistance_for_needy_families/", + ) + defined_for = "nm_works_eligible" + + def formula(spm_unit, period, parameters): + # Per 8.102.620 NMAC: + # Benefit = Payment Standard - Net Countable Income + maximum_benefit = spm_unit("nm_works_maximum_benefit", period) + countable_income = spm_unit("nm_works_countable_income", period) + return max_(maximum_benefit - countable_income, 0) diff --git a/policyengine_us/variables/gov/states/nm/hca/nm_works/nm_works_maximum_benefit.py b/policyengine_us/variables/gov/states/nm/hca/nm_works/nm_works_maximum_benefit.py new file mode 100644 index 00000000000..cd74f03be0a --- /dev/null +++ b/policyengine_us/variables/gov/states/nm/hca/nm_works/nm_works_maximum_benefit.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class nm_works_maximum_benefit(Variable): + value_type = float + entity = SPMUnit + label = "New Mexico Works maximum benefit (payment standard)" + unit = USD + definition_period = MONTH + reference = ( + "https://www.srca.nm.gov/parts/title08/08.102.0500.html", + "https://www.hca.nm.gov/2023/09/01/state-announces-a-23-percent-increase-in-cash-assistance-for-low-income-new-mexico-families/", + ) + defined_for = StateCode.NM + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nm.hca.nm_works.payment_standard + unit_size = spm_unit("spm_unit_size", period.this_year) + capped_size = min_(unit_size, p.max_table_size) + base_amount = p.amount[capped_size] + extra_persons = max_(unit_size - p.max_table_size, 0) + return base_amount + extra_persons * p.additional_person