From 27b9d0a7551d21405e25e711e44ab28824f8d7d5 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 6 Jan 2026 22:27:52 -0500 Subject: [PATCH 1/9] cherry pick files from other PRs --- changelog_entry.yaml | 4 + .../consecutive_month_threshold.yaml | 11 +++ .../first_month_threshold.yaml | 11 +++ .../higher_work_hours/additional_percent.yaml | 11 +++ .../consecutive_month_percent.yaml | 11 +++ .../first_month_percent.yaml | 11 +++ .../lower_work_hours/additional_percent.yaml | 11 +++ .../lower_work_hours/first_month_percent.yaml | 11 +++ .../work_hours_threshold.yaml | 11 +++ ...j_is_person_demographic_tanf_eligible.yaml | 30 ++++++++ .../tanf/nj_tanf_countable_earned_income.yaml | 59 +++++++++++++++ .../njdhs/tanf/nj_tanf_income_eligible.yaml | 54 +++++++++++++ .../income/nj_tanf_countable_earned_income.py | 75 +++++++++++++++++++ .../tanf/nj_is_demographic_tanf_eligible.py | 10 +++ .../nj_is_person_demographic_tanf_eligible.py | 20 +++++ .../nj/njdhs/tanf/nj_tanf_income_eligible.py | 27 +++++++ .../tanf_enrolled/months_enrolled_in_tanf.py | 9 +++ .../income/person/work/hours_worked.py | 9 +++ .../income/person/work/weekly_hours_worked.py | 14 ++++ 19 files changed, 399 insertions(+) create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/consecutive_month_threshold.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/first_month_threshold.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/additional_percent.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/additional_percent.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/first_month_percent.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/work_hours_threshold.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_countable_earned_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.yaml create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_countable_earned_income.py create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_demographic_tanf_eligible.py create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.py create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.py create mode 100644 policyengine_us/variables/household/income/person/tanf_enrolled/months_enrolled_in_tanf.py create mode 100644 policyengine_us/variables/household/income/person/work/hours_worked.py create mode 100644 policyengine_us/variables/household/income/person/work/weekly_hours_worked.py diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..fdcff2267da 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: minor + changes: + added: + - Implement New Jersey TANF. diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/consecutive_month_threshold.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/consecutive_month_threshold.yaml new file mode 100644 index 00000000000..a64f42ffe6c --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/consecutive_month_threshold.yaml @@ -0,0 +1,11 @@ +description: New Jersey fully excludes 50% earned income for person who enrolled TANF program over this amount of time. + +metadata: + unit: month + label: New Jersey TANF earned income deduction + reference: + - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) + href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 + +values: + 2022-10-01: 7.0 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/first_month_threshold.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/first_month_threshold.yaml new file mode 100644 index 00000000000..f254bad44af --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/first_month_threshold.yaml @@ -0,0 +1,11 @@ +description: New Jersey fully excludes 100% of earned income for person who have enrolled in TANF program below this amount of time. + +metadata: + unit: month + label: New Jersey TANF earned income deduction first month threshold + reference: + - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) + href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 + +values: + 2022-10-01: 1.0 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/additional_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/additional_percent.yaml new file mode 100644 index 00000000000..6daf8b6fed5 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/additional_percent.yaml @@ -0,0 +1,11 @@ +description: New Jersey excludes this percentage of earned income for household enrolled in TANF for each additional month. + +metadata: + unit: /1 + label: New Jersey TANF earned income deduction + reference: + - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) + href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 + +values: + 2022-10-01: 0.5 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml new file mode 100644 index 00000000000..9cc8b8e4903 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml @@ -0,0 +1,11 @@ +description: New Jersey excludes this percentage of earned income for 6 consecutive months for person who enrolles in TANF Program and continues work for more than 20h/week after the first month. + +metadata: + unit: /1 + label: New Jersey TANF earned income deduction + reference: + - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) + href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 + +values: + 2022-10-01: 0.75 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml new file mode 100644 index 00000000000..cdfa9645568 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml @@ -0,0 +1,11 @@ +description: New Jersey fully excludes this percentage of earned income for person who enrolled in the first month of TANF program. + +metadata: + unit: /1 + label: New Jersey TANF earned income deduction + reference: + - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) + href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 + +values: + 2022-10-01: 1.0 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/additional_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/additional_percent.yaml new file mode 100644 index 00000000000..6daf8b6fed5 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/additional_percent.yaml @@ -0,0 +1,11 @@ +description: New Jersey excludes this percentage of earned income for household enrolled in TANF for each additional month. + +metadata: + unit: /1 + label: New Jersey TANF earned income deduction + reference: + - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) + href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 + +values: + 2022-10-01: 0.5 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/first_month_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/first_month_percent.yaml new file mode 100644 index 00000000000..cdfa9645568 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/first_month_percent.yaml @@ -0,0 +1,11 @@ +description: New Jersey fully excludes this percentage of earned income for person who enrolled in the first month of TANF program. + +metadata: + unit: /1 + label: New Jersey TANF earned income deduction + reference: + - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) + href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 + +values: + 2022-10-01: 1.0 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/work_hours_threshold.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/work_hours_threshold.yaml new file mode 100644 index 00000000000..d310e530e66 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/work_hours_threshold.yaml @@ -0,0 +1,11 @@ +description: New York excludes this percentage of earned income for the purposes of its TANF program. + +metadata: + unit: hours + label: New Jeresy TANF + reference: + - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) + href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 + +values: + 2022-10-01: 20 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.yaml new file mode 100644 index 00000000000..222fdfc8337 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.yaml @@ -0,0 +1,30 @@ +- name: "Is eligible for TANF due to children under 18" + period: 2022 + input: + age: 17 + output: + nj_is_person_demographic_tanf_eligible: true + +- name: "18-year-old out of school is not eligible for TANF" + period: 2022 + input: + age: 18 + is_full_time_student: false + output: + nj_is_person_demographic_tanf_eligible: false + +- name: "Is eligible for TANF due to being an 18-year-old in school" + period: 2022 + input: + age: 18 + is_full_time_student: true + output: + nj_is_person_demographic_tanf_eligible: true + +- name: "Is not eligible for TANF due to being an 19-year-old in school" + period: 2022 + input: + age: 19 + is_full_time_student: true + output: + nj_is_person_demographic_tanf_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_countable_earned_income.yaml new file mode 100644 index 00000000000..8304ff51061 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_countable_earned_income.yaml @@ -0,0 +1,59 @@ +- name: NJ countable earned income = gross earned income*(1-100%) for first month. + period: 2023 + input: + state_code: NJ + nj_tanf_gross_earned_income: 6_000 + months_enrolled_in_tanf: 1 + hours_worked: 2_080 + output: + nj_tanf_countable_earned_income: 0 + +- name: NJ countable earned income = gross earned income*(1-75%) for applicant with weekly working hours over 20 in 2nd month. + period: 2023 + input: + state_code: NJ + nj_tanf_gross_earned_income: 6_000 + months_enrolled_in_tanf: 2 + hours_worked: 2_080 + output: + nj_tanf_countable_earned_income: 1_500 + +- name: NJ countable earned income = gross earned income*(1-50%) for applicant with weekly working hours under 20 in 2nd month. + period: 2023 + input: + state_code: NJ + nj_tanf_gross_earned_income: 6_000 + months_enrolled_in_tanf: 2 + hours_worked: 988 + output: + nj_tanf_countable_earned_income: 3_000 + +- name: NJ countable earned income = gross earned income*(1-75%) for applicant with weekly working hours over 20 in 7nd month. + period: 2023 + input: + state_code: NJ + nj_tanf_gross_earned_income: 6_000 + months_enrolled_in_tanf: 7 + hours_worked: 2_080 + output: + nj_tanf_countable_earned_income: 1_500 + +- name: NJ countable earned income = gross earned income*(1-50%) for applicant with weekly working hours over 20 in 8nd month. + period: 2023 + input: + state_code: NJ + nj_tanf_gross_earned_income: 6_000 + months_enrolled_in_tanf: 8 + hours_worked: 2_080 + output: + nj_tanf_countable_earned_income: 3_000 + +- name: NJ countable earned income = gross earned income*(1-75%) for applicant with weekly working hours over 20 in 2nd month. + period: 2023 + input: + state_code: NJ + nj_tanf_gross_earned_income: 6_000 + months_enrolled_in_tanf: 2 + hours_worked: 1_040 + output: + nj_tanf_countable_earned_income: 1_500 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.yaml new file mode 100644 index 00000000000..fe03996a410 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.yaml @@ -0,0 +1,54 @@ +- name: Household with no income is eligible. (0+0<1) + period: 2023 + input: + state_code: NJ + nj_tanf_maximum_allowable_income: 1 + nj_tanf_countable_earned_income: 0 + nj_tanf_countable_gross_unearned_income: 0 + output: + nj_tanf_income_eligible: true + + +- name: Household with income exceeding maximum allowable income is ineligible. (1+1>1) + period: 2023 + input: + state_code: NJ + nj_tanf_maximum_allowable_income: 1 + nj_tanf_countable_earned_income: 1 + nj_tanf_countable_gross_unearned_income: 1 + output: + nj_tanf_income_eligible: false + + +- name: Household with income equals maximum allowable income is eligible. (1+0=1) + period: 2023 + input: + state_code: NJ + nj_tanf_maximum_allowable_income: 1 + nj_tanf_countable_earned_income: 1 + nj_tanf_countable_gross_unearned_income: 0 + output: + nj_tanf_income_eligible: true + +- name: Household with income equals maximum allowable income and income equals maximum benefit is ineligible. + period: 2023 + input: + state_code: NJ + nj_tanf_maximum_allowable_income: 1 + nj_tanf_maximum_benefit: 1 + nj_tanf_countable_earned_income: 1 + nj_tanf_countable_gross_unearned_income: 0 + output: + nj_tanf_income_eligible: false + + +- name: Household with income less than maximum allowable income and income less than maximum benefit is eligible. + period: 2023 + input: + state_code: NJ + nj_tanf_maximum_allowable_income: 3 + nj_tanf_maximum_benefit: 2 + nj_tanf_countable_earned_income: 1 + nj_tanf_countable_gross_unearned_income: 0 + output: + nj_tanf_income_eligible: true diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_countable_earned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_countable_earned_income.py new file mode 100644 index 00000000000..54a47a44c20 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_countable_earned_income.py @@ -0,0 +1,75 @@ +from policyengine_us.model_api import * + + +class nj_tanf_countable_earned_income(Variable): + value_type = float + entity = SPMUnit + label = "New Jersey TANF countable earned income" + unit = USD + definition_period = YEAR + defined_for = StateCode.NJ + + def formula(spm_unit, period, parameters): + person = spm_unit.members + # Get gross earned income. + gross_earned_income = spm_unit("nj_tanf_gross_earned_income", period) + p = parameters( + period + ).gov.states.nj.njdhs.tanf.income.earned_income_deduction + months_enrolled_in_tanf = person("months_enrolled_in_tanf", period) + weekly_hours_worked = person("weekly_hours_worked", period) + # New Jerset Admin Code 10:90-3.8(b) + person_meet_higher_work_hours_threshold = ( + weekly_hours_worked >= p.work_hours_threshold + ) + person_meet_lower_work_hours_threshold = ( + weekly_hours_worked < p.work_hours_threshold + ) + person_enrolled_in_tanf_for_first_month = ( + months_enrolled_in_tanf <= p.first_month_threshold + ) + person_enrolled_in_tanf_for_consecutive_months_with_work_hours_over_20 = ( + months_enrolled_in_tanf <= p.consecutive_month_threshold + and months_enrolled_in_tanf > p.first_month_threshold + and person_meet_higher_work_hours_threshold + ) + person_enrolled_in_tanf_for_additional_months_with_work_hours_over_20 = ( + months_enrolled_in_tanf > p.consecutive_month_threshold + and person_meet_higher_work_hours_threshold + ) + person_enrolled_in_tanf_for_additional_months_with_work_hours_below_20 = ( + months_enrolled_in_tanf > p.first_month_threshold + and person_meet_lower_work_hours_threshold + ) + # The value of result will only change, if the first condition in "where" is met. If the condition is not met, the value of result will not change + result = 0 + # If applicant is enrolled in TANF for the first month, the earned income deduction is 100%. + result = where( + person_enrolled_in_tanf_for_first_month, + gross_earned_income + * (1 - p.higher_work_hours.first_month_percent), + result, + ) + # If applicant is enrolled in TANF for consecutive months with work hours over 20, the earned income deduction is 75%. + result = where( + ( + person_meet_higher_work_hours_threshold + and person_enrolled_in_tanf_for_consecutive_months_with_work_hours_over_20 + ), + gross_earned_income + * (1 - p.higher_work_hours.consecutive_month_percent), + result, + ) + # If applicant is enrolled in TANF for additional months with work hours over 20, the earned income deduction is 50%. + result = where( + person_enrolled_in_tanf_for_additional_months_with_work_hours_over_20, + gross_earned_income * (1 - p.higher_work_hours.additional_percent), + result, + ) + # If applicant is enrolled in TANF for additional months with work hours below 20, the earned income deduction is 50%. + result = where( + person_enrolled_in_tanf_for_additional_months_with_work_hours_below_20, + gross_earned_income * (1 - p.lower_work_hours.additional_percent), + result, + ) + return result diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_demographic_tanf_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_demographic_tanf_eligible.py new file mode 100644 index 00000000000..823cc25aed5 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_demographic_tanf_eligible.py @@ -0,0 +1,10 @@ +from policyengine_us.model_api import * + + +class nj_is_demographic_tanf_eligible(Variable): + value_type = bool + entity = SPMUnit + definition_period = YEAR + label = "Demographic eligibility for New Jersey TANF" + documentation = "Whether any person in a family applying for the Temporary Assistance for Needy Families program meets demographic requirements." + adds = ["nj_is_person_demographic_tanf_eligible"] diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.py new file mode 100644 index 00000000000..d372e025a6a --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class nj_is_person_demographic_tanf_eligible(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "Person-level eligibility for New Jersey TANF based on age." + documentation = "Whether a person in a family applying for the Temporary Assistance for Needy Families program meets demographic requirements." + + def formula(person, period, parameters): + # title: State Plan for New Jersey TANF, 2021-2023, page 14 + # href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=14 + # title: New Jersey Administrative Code, 10:90-2.2, part (c)(d) + # href: https://advance.lexis.com/documentpage/?pdmfid=1000516&crid=f96f6864-3540-4a08-b41a-e523b7c5620a&nodeid=AAOAERAADAAC&nodepath=%2FROOT%2FAAO%2FAAOAER%2FAAOAERAAD%2FAAOAERAADAAC&level=4&haschildren=&populated=false&title=%C2%A7+10%3A90-2.2+WFNJ+TANF%2FGA+eligibility+requirements&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PWF1-JKHB-61RG-00008-00&ecomp=8gf5kkk&prid=2fb77114-6c52-4b07-8969-f267ef81db7b + child_under_18 = person("age", period) < 18 + is_under_19 = person("age", period) < 19 + full_time_student = person("is_full_time_student", period) + school_enrolled_under_19_year_old = full_time_student & is_under_19 + return child_under_18 | school_enrolled_under_19_year_old diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.py new file mode 100644 index 00000000000..c7d2c7230a1 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class nj_tanf_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "New Jersey TANF income eligible" + definition_period = YEAR + defined_for = StateCode.NJ + + def formula(spm_unit, period, parameters): + income = add( + spm_unit, + period, + [ + "nj_tanf_countable_earned_income", + "nj_tanf_countable_gross_unearned_income", + ], + ) + maximum_allowable_income = spm_unit( + "nj_tanf_maximum_allowable_income", period + ) + maximum_benefit = spm_unit("nj_tanf_maximum_benefit", period) + # New Jersey Administrative Code 10:90-3.1 + return (income <= maximum_allowable_income) & ( + income < maximum_benefit + ) diff --git a/policyengine_us/variables/household/income/person/tanf_enrolled/months_enrolled_in_tanf.py b/policyengine_us/variables/household/income/person/tanf_enrolled/months_enrolled_in_tanf.py new file mode 100644 index 00000000000..059fe8db97c --- /dev/null +++ b/policyengine_us/variables/household/income/person/tanf_enrolled/months_enrolled_in_tanf.py @@ -0,0 +1,9 @@ +from policyengine_us.model_api import * + + +class months_enrolled_in_tanf(Variable): + value_type = float + entity = Person + label = "Months enrolled in TANF" + definition_period = YEAR + unit = "month" diff --git a/policyengine_us/variables/household/income/person/work/hours_worked.py b/policyengine_us/variables/household/income/person/work/hours_worked.py new file mode 100644 index 00000000000..bd9cae7c29c --- /dev/null +++ b/policyengine_us/variables/household/income/person/work/hours_worked.py @@ -0,0 +1,9 @@ +from policyengine_us.model_api import * + + +class hours_worked(Variable): + value_type = float + entity = Person + label = "Total amount of hours worked by this person" + definition_period = YEAR + unit = "hour" diff --git a/policyengine_us/variables/household/income/person/work/weekly_hours_worked.py b/policyengine_us/variables/household/income/person/work/weekly_hours_worked.py new file mode 100644 index 00000000000..25d33c768da --- /dev/null +++ b/policyengine_us/variables/household/income/person/work/weekly_hours_worked.py @@ -0,0 +1,14 @@ +from policyengine_us.model_api import * + + +class weekly_hours_worked(Variable): + value_type = float + entity = Person + label = "Weekly hours" + documentation = "Average weekly hours worked" + definition_period = YEAR + unit = "hour" + quantity_type = FLOW + + def formula(person, period, parameters): + return person("hours_worked", period) / WEEKS_IN_YEAR From a56afd4cda7e5e07ebffc0e5d95306c076108a15 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 6 Jan 2026 23:00:46 -0500 Subject: [PATCH 2/9] draft --- changelog_entry.yaml | 2 +- .../tanf/eligibility/resources/limit.yaml | 12 --- .../states/nj/njdhs/tanf/income/earned.yaml | 10 --- .../consecutive_month_threshold.yaml | 11 --- .../first_month_threshold.yaml | 11 --- .../higher_work_hours/additional_percent.yaml | 11 --- .../consecutive_month_percent.yaml | 11 --- .../first_month_percent.yaml | 11 --- .../lower_work_hours/additional_percent.yaml | 11 --- .../lower_work_hours/first_month_percent.yaml | 11 --- .../work_hours_threshold.yaml | 11 --- .../states/nj/njdhs/tanf/income/unearned.yaml | 18 ----- .../maximum_allowable_income/additional.yaml | 15 ---- .../tanf/maximum_allowable_income/main.yaml | 31 -------- .../tanf/maximum_benefit/additional.yaml | 16 ---- .../nj/njdhs/tanf/maximum_benefit/main.yaml | 32 -------- .../states/nj/njdhs/{tanf => wfnj}/README.md | 0 .../wfnj/eligibility/resources/limit.yaml | 14 ++++ .../states/nj/njdhs/wfnj/income/earned.yaml | 12 +++ .../higher_work_hours/additional_percent.yaml | 12 +++ .../consecutive_month_percent.yaml | 12 +++ .../first_month_percent.yaml | 12 +++ .../states/nj/njdhs/wfnj/income/unearned.yaml | 19 +++++ .../maximum_allowable_income/additional.yaml | 14 ++++ .../wfnj/maximum_allowable_income/main.yaml | 30 ++++++++ .../wfnj/maximum_benefit/additional.yaml | 14 ++++ .../nj/njdhs/wfnj/maximum_benefit/main.yaml | 30 ++++++++ ...j_is_person_demographic_tanf_eligible.yaml | 30 -------- .../tanf/nj_tanf_countable_earned_income.yaml | 59 --------------- .../njdhs/tanf/nj_tanf_income_eligible.yaml | 54 ------------- ...j_wfnj_countable_earned_income_person.yaml | 43 +++++++++++ ...wfnj_countable_gross_unearned_income.yaml} | 6 +- .../njdhs/wfnj/nj_wfnj_income_eligible.yaml | 54 +++++++++++++ .../nj_wfnj_maximum_allowable_income.yaml} | 8 +- .../nj_wfnj_maximum_benefit.yaml} | 8 +- .../nj_wfnj_resources_eligible.yaml} | 8 +- .../income/nj_tanf_countable_earned_income.py | 75 ------------------- ...nj_tanf_countable_gross_unearned_income.py | 12 --- .../tanf/nj_is_demographic_tanf_eligible.py | 10 --- .../nj_is_person_demographic_tanf_eligible.py | 20 ----- .../njdhs/tanf/nj_tanf_resources_eligible.py | 16 ---- .../income/nj_wfnj_countable_earned_income.py | 12 +++ .../nj_wfnj_countable_earned_income_person.py | 39 ++++++++++ ...nj_wfnj_countable_gross_unearned_income.py | 12 +++ .../income/nj_wfnj_gross_earned_income.py} | 6 +- .../nj_wfnj_countable_resources.py} | 4 +- .../nj_wfnj_income_eligible.py} | 12 +-- .../nj_wfnj_maximum_allowable_income.py} | 13 +--- .../nj_wfnj_maximum_benefit.py} | 13 +--- .../njdhs/wfnj/nj_wfnj_resources_eligible.py | 14 ++++ .../tanf_enrolled/months_enrolled_in_tanf.py | 9 --- .../income/person/work/hours_worked.py | 9 --- .../income/person/work/weekly_hours_worked.py | 14 ---- 53 files changed, 376 insertions(+), 577 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/eligibility/resources/limit.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/consecutive_month_threshold.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/first_month_threshold.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/additional_percent.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/additional_percent.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/first_month_percent.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/work_hours_threshold.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/unearned.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_allowable_income/additional.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_allowable_income/main.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_benefit/additional.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_benefit/main.yaml rename policyengine_us/parameters/gov/states/nj/njdhs/{tanf => wfnj}/README.md (100%) create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/additional_percent.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_countable_earned_income.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml rename policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/{tanf/nj_tanf_countable_gross_unearned_income.yaml => wfnj/nj_wfnj_countable_gross_unearned_income.yaml} (88%) create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.yaml rename policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/{tanf/nj_tanf_maximum_allowable_income.yaml => wfnj/nj_wfnj_maximum_allowable_income.yaml} (65%) rename policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/{tanf/nj_tanf_maximum_benefit.yaml => wfnj/nj_wfnj_maximum_benefit.yaml} (68%) rename policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/{tanf/nj_tanf_resources_eligible.yaml => wfnj/nj_wfnj_resources_eligible.yaml} (62%) delete mode 100644 policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_countable_earned_income.py delete mode 100644 policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_countable_gross_unearned_income.py delete mode 100644 policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_demographic_tanf_eligible.py delete mode 100644 policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.py delete mode 100644 policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_resources_eligible.py create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income.py create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_gross_unearned_income.py rename policyengine_us/variables/gov/states/nj/njdhs/{tanf/income/nj_tanf_gross_earned_income.py => wfnj/income/nj_wfnj_gross_earned_income.py} (52%) rename policyengine_us/variables/gov/states/nj/njdhs/{tanf/nj_tanf_countable_resources.py => wfnj/nj_wfnj_countable_resources.py} (61%) rename policyengine_us/variables/gov/states/nj/njdhs/{tanf/nj_tanf_income_eligible.py => wfnj/nj_wfnj_income_eligible.py} (61%) rename policyengine_us/variables/gov/states/nj/njdhs/{tanf/nj_tanf_maximum_allowable_income.py => wfnj/nj_wfnj_maximum_allowable_income.py} (51%) rename policyengine_us/variables/gov/states/nj/njdhs/{tanf/nj_tanf_maximum_benefit.py => wfnj/nj_wfnj_maximum_benefit.py} (50%) create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py delete mode 100644 policyengine_us/variables/household/income/person/tanf_enrolled/months_enrolled_in_tanf.py delete mode 100644 policyengine_us/variables/household/income/person/work/hours_worked.py delete mode 100644 policyengine_us/variables/household/income/person/work/weekly_hours_worked.py diff --git a/changelog_entry.yaml b/changelog_entry.yaml index fdcff2267da..98d3cd4a234 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -1,4 +1,4 @@ - bump: minor changes: added: - - Implement New Jersey TANF. + - Implement New Jersey WorkFirst (WFNJ). diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/eligibility/resources/limit.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/eligibility/resources/limit.yaml deleted file mode 100644 index fb20c3717b2..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/eligibility/resources/limit.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: New Jersey limits its TANF eligibility to households with up to this amount of resources. - -metadata: - unit: currency-USD - label: New Jersey TANF resource limit - reference: - - title: New Jersey Administration State Code | Work First New Jersey Program | 1090-33.2 Resource Limits (a)(3) - href: https://advance.lexis.com/documentpage/?pdmfid=1000516&crid=ed375ccd-2ce7-480b-8fed-7953f9bb3e83&action=pawlinkdoc&pdcomponentid=&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW91-F7ND-G1GP-00008-00&pdtocnodeidentifier=AAOAERAAEAAU&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&ecomp=-3vckkk&prid=d0c89fcb-13c2-409a-9f5d-d3fc9e10aeca - - title: New Jersey State Plan for TANF(2021-2023) - href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=21 -values: - 2023-01-01: 2_000 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned.yaml deleted file mode 100644 index 01b7d6eb231..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned.yaml +++ /dev/null @@ -1,10 +0,0 @@ -description: New Jersey TANF counts these income sources as earned income. -values: - 2023-03-22: - - employment_income - - self_employment_income -metadata: - unit: list - reference: - title: New Jersey Administrative Code | 10:90-3.9 Income--WFNJ TANF/GA (c) - href: https://advance.lexis.com/documentpage/?pdmfid=1000516&crid=e6f530e6-7e61-4172-a706-2284151eecb9&nodeid=AAOAERAAEAAJ&nodepath=%2FROOT%2FAAO%2FAAOAER%2FAAOAERAAE%2FAAOAERAAEAAJ&level=4&haschildren=&populated=false&title=%C2%A7+10%3A90-3.9+Income--WFNJ+TANF%2FGA&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X1S1-00008-00&ecomp=8gf5kkk&prid=01f94881-dbbf-4726-a383-98be3eeb2468 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/consecutive_month_threshold.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/consecutive_month_threshold.yaml deleted file mode 100644 index a64f42ffe6c..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/consecutive_month_threshold.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: New Jersey fully excludes 50% earned income for person who enrolled TANF program over this amount of time. - -metadata: - unit: month - label: New Jersey TANF earned income deduction - reference: - - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) - href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 - -values: - 2022-10-01: 7.0 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/first_month_threshold.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/first_month_threshold.yaml deleted file mode 100644 index f254bad44af..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/first_month_threshold.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: New Jersey fully excludes 100% of earned income for person who have enrolled in TANF program below this amount of time. - -metadata: - unit: month - label: New Jersey TANF earned income deduction first month threshold - reference: - - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) - href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 - -values: - 2022-10-01: 1.0 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/additional_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/additional_percent.yaml deleted file mode 100644 index 6daf8b6fed5..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/additional_percent.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: New Jersey excludes this percentage of earned income for household enrolled in TANF for each additional month. - -metadata: - unit: /1 - label: New Jersey TANF earned income deduction - reference: - - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) - href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 - -values: - 2022-10-01: 0.5 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml deleted file mode 100644 index 9cc8b8e4903..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: New Jersey excludes this percentage of earned income for 6 consecutive months for person who enrolles in TANF Program and continues work for more than 20h/week after the first month. - -metadata: - unit: /1 - label: New Jersey TANF earned income deduction - reference: - - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) - href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 - -values: - 2022-10-01: 0.75 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml deleted file mode 100644 index cdfa9645568..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: New Jersey fully excludes this percentage of earned income for person who enrolled in the first month of TANF program. - -metadata: - unit: /1 - label: New Jersey TANF earned income deduction - reference: - - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) - href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 - -values: - 2022-10-01: 1.0 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/additional_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/additional_percent.yaml deleted file mode 100644 index 6daf8b6fed5..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/additional_percent.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: New Jersey excludes this percentage of earned income for household enrolled in TANF for each additional month. - -metadata: - unit: /1 - label: New Jersey TANF earned income deduction - reference: - - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) - href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 - -values: - 2022-10-01: 0.5 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/first_month_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/first_month_percent.yaml deleted file mode 100644 index cdfa9645568..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/lower_work_hours/first_month_percent.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: New Jersey fully excludes this percentage of earned income for person who enrolled in the first month of TANF program. - -metadata: - unit: /1 - label: New Jersey TANF earned income deduction - reference: - - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) - href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 - -values: - 2022-10-01: 1.0 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/work_hours_threshold.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/work_hours_threshold.yaml deleted file mode 100644 index d310e530e66..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/earned_income_deduction/work_hours_threshold.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: New York excludes this percentage of earned income for the purposes of its TANF program. - -metadata: - unit: hours - label: New Jeresy TANF - reference: - - title: New Jersey Administrative Code(N.J.A.C 10:90-3.8) - href: https://advance.lexis.com/documentpage/teaserdocument/?pdmfid=1000516&crid=1e9b7e3d-233e-4b7c-898f-b53548066f3f&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pddocid=urn%3AcontentItem%3A5XKV-PW31-F22N-X2CF-00008-00&pdcontentcomponentid=234122&pdteaserkey=h1&pditab=allpods&ecomp=8s65kkk&earg=sr0&prid=187e8c01-622c-460c-be94-0bb33d5ca4d2 - -values: - 2022-10-01: 20 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/unearned.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/unearned.yaml deleted file mode 100644 index 6e342631f88..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/income/unearned.yaml +++ /dev/null @@ -1,18 +0,0 @@ -description: New Jersey TANF counts these income sources as unearned income. -values: - 2021-01-01: - - veterans_benefits - - rental_income - - alimony_income - - dividend_income - - interest_income - - pension_income - - unemployment_compensation - - gi_cash_assistance - - social_security -metadata: - unit: list - reference: - title: New Jersey Administrative Code | 10:90-3.9(e) - href: https://advance.lexis.com/documentpage/?pdmfid=1000516&crid=d6417ab8-827f-47fe-80e3-61bbdb8bd1a1&pdistocdocslideraccess=true&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PW31-F22N-X1S1-00008-00&pdcomponentid=234124&pdtocnodeidentifier=AAOAERAAEAAJ&ecomp=-3vckkk&prid=64e539a6-10a7-417d-aad3-dfe3a9bcae3c - diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_allowable_income/additional.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_allowable_income/additional.yaml deleted file mode 100644 index 10f0eaea4d6..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_allowable_income/additional.yaml +++ /dev/null @@ -1,15 +0,0 @@ -description: New Jersey limits its TANF program to households with up to this income level for people beyond size. - -metadata: - unit: currency-USD - period: month - label: New Jersey TANF monthly income limit per additional person - reference: - # Legal code provides 2003 law; state plan provides updated values. - - title: New Jersey Administration State Code | Work First New Jersey Program | Financial Eligibility, Income, Resources, Benefits | § 10:90-3.3 WFNJ/TANF-initial allowable maximum income and maximum benefit payment levels (Schedules I and II) - href: https://advance.lexis.com/documentpage/?pdmfid=1000516&crid=977adb3e-e3a6-4eba-8d54-e69ee35f7dcd&nodeid=AAOAERAAEAAD&nodepath=%2FROOT%2FAAO%2FAAOAER%2FAAOAERAAE%2FAAOAERAAEAAD&level=4&haschildren=&populated=false&title=%C2%A7+10%3A90-3.3+WFNJ%2FTANF-initial+allowable+maximum+income+and+maximum+benefit+payment+levels+(Schedules+I+and+II)&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PWD1-JTGH-B3FM-00008-00&ecomp=8gf5kkk&prid=039b2ed1-6268-497c-a43f-3e4c508cdc00 - - title: New Jersey State Plan for TANF(2021-2023) - href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=63 - -values: - 2023-01-01: 99 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_allowable_income/main.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_allowable_income/main.yaml deleted file mode 100644 index 0fa46df6108..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_allowable_income/main.yaml +++ /dev/null @@ -1,31 +0,0 @@ -description: New Jersey limits its TANF program to households with up to this income level, by household size. - -metadata: - unit: currency-USD - period: month - breakdown: - - range(1, 9) - label: New Jersey TANF monthly maximum allowable income - reference: - # Legal code provides 2003 law; state plan provides updated values. - - title: New Jersey Administration State Code | Work First New Jersey Program | Financial Eligibility, Income, Resources, Benefits | § 10:90-3.3 WFNJ/TANF-initial allowable maximum income and maximum benefit payment levels (Schedules I and II) - href: https://advance.lexis.com/documentpage/?pdmfid=1000516&crid=977adb3e-e3a6-4eba-8d54-e69ee35f7dcd&nodeid=AAOAERAAEAAD&nodepath=%2FROOT%2FAAO%2FAAOAER%2FAAOAERAAE%2FAAOAERAAEAAD&level=4&haschildren=&populated=false&title=%C2%A7+10%3A90-3.3+WFNJ%2FTANF-initial+allowable+maximum+income+and+maximum+benefit+payment+levels+(Schedules+I+and+II)&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PWD1-JTGH-B3FM-00008-00&ecomp=8gf5kkk&prid=039b2ed1-6268-497c-a43f-3e4c508cdc00 - - title: New Jersey State Plan for TANF(2021-2023) - href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=63 - -1: - 2023-01-01: 321 -2: - 2023-01-01: 638 -3: - 2023-01-01: 839 -4: - 2023-01-01: 966 -5: - 2023-01-01: 1_092 -6: - 2023-01-01: 1_221 -7: - 2023-01-01: 1_341 -8: - 2023-01-01: 1_442 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_benefit/additional.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_benefit/additional.yaml deleted file mode 100644 index c8b78884f95..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_benefit/additional.yaml +++ /dev/null @@ -1,16 +0,0 @@ -description: New Jersey limits its TANF program to households with this maximum benefit for people beyond size. - -metadata: - unit: currency-USD - period: month - label: New Jersey TANF monthly maximum benefit per additional person - reference: - # Administrative code has old values, apparently without inflation adjustments. - - title: New Jersey Administrative Code | § 10:90-3.3 WFNJ/TANF-initial allowable maximum income and maximum benefit payment levels (Schedules I and II) - href: https://advance.lexis.com/documentpage/?pdmfid=1000516&crid=977adb3e-e3a6-4eba-8d54-e69ee35f7dcd&nodeid=AAOAERAAEAAD&nodepath=%2FROOT%2FAAO%2FAAOAER%2FAAOAERAAE%2FAAOAERAAEAAD&level=4&haschildren=&populated=false&title=%C2%A7+10%3A90-3.3+WFNJ%2FTANF-initial+allowable+maximum+income+and+maximum+benefit+payment+levels+(Schedules+I+and+II)&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PWD1-JTGH-B3FM-00008-00&ecomp=8gf5kkk&prid=039b2ed1-6268-497c-a43f-3e4c508cdc00 - # State plan has updated values. - - title: New Jersey State Plan for TANF(2021-2023) - href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=63 - -values: - 2023-01-01: 66 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_benefit/main.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_benefit/main.yaml deleted file mode 100644 index c90f40d6442..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/maximum_benefit/main.yaml +++ /dev/null @@ -1,32 +0,0 @@ -description: New Jersey limits its TANF program to households with this maximum benefits, by household size. - -metadata: - unit: currency-USD - period: month - breakdown: - - range(1, 9) - label: New Jersey TANF monthly maximum benefit - reference: - # Administrative code has old values, apparently without inflation adjustments. - - title: New Jersey Administrative Code | § 10:90-3.3 WFNJ/TANF-initial allowable maximum income and maximum benefit payment levels (Schedules I and II) - href: https://advance.lexis.com/documentpage/?pdmfid=1000516&crid=977adb3e-e3a6-4eba-8d54-e69ee35f7dcd&nodeid=AAOAERAAEAAD&nodepath=%2FROOT%2FAAO%2FAAOAER%2FAAOAERAAE%2FAAOAERAAEAAD&level=4&haschildren=&populated=false&title=%C2%A7+10%3A90-3.3+WFNJ%2FTANF-initial+allowable+maximum+income+and+maximum+benefit+payment+levels+(Schedules+I+and+II)&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PWD1-JTGH-B3FM-00008-00&ecomp=8gf5kkk&prid=039b2ed1-6268-497c-a43f-3e4c508cdc00 - # State plan has updated values. - - title: New Jersey State Plan for TANF(2021-2023) - href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=63 - -1: - 2023-01-01: 214 -2: - 2023-01-01: 425 -3: - 2023-01-01: 559 -4: - 2023-01-01: 644 -5: - 2023-01-01: 728 -6: - 2023-01-01: 814 -7: - 2023-01-01: 894 -8: - 2023-01-01: 961 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/tanf/README.md b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/README.md similarity index 100% rename from policyengine_us/parameters/gov/states/nj/njdhs/tanf/README.md rename to policyengine_us/parameters/gov/states/nj/njdhs/wfnj/README.md diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml new file mode 100644 index 00000000000..65cec4cd534 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml @@ -0,0 +1,14 @@ +description: New Jersey limits its WFNJ eligibility to households with up to this amount of resources. + +metadata: + unit: currency-USD + period: year + label: New Jersey WFNJ resource limit + reference: + - title: N.J.A.C. 10:90-3.2 + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-2 + - title: New Jersey State Plan for WFNJ (2021-2023) + href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=21 + +values: + 2023-01-01: 2_000 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml new file mode 100644 index 00000000000..6d8bdf5a82c --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml @@ -0,0 +1,12 @@ +description: New Jersey WFNJ counts these income sources as earned income. + +metadata: + unit: list + reference: + - title: N.J.A.C. 10:90-3.9 + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-9 + +values: + 2023-03-22: + - employment_income + - self_employment_income diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/additional_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/additional_percent.yaml new file mode 100644 index 00000000000..0c6d97c9779 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/additional_percent.yaml @@ -0,0 +1,12 @@ +description: New Jersey excludes this share of earned income for recipients in month 8 and beyond working 20 or more hours weekly under the WorkFirst New Jersey program. + +metadata: + unit: /1 + period: year + label: New Jersey WFNJ additional month earned income disregard rate (20+ hours) + reference: + - title: N.J.A.C. 10:90-3.8 + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8 + +values: + 2022-10-01: 0.5 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml new file mode 100644 index 00000000000..446917d95e7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml @@ -0,0 +1,12 @@ +description: New Jersey excludes this share of earned income for recipients in months 2-7 working 20 or more hours weekly under the WorkFirst New Jersey program. + +metadata: + unit: /1 + period: year + label: New Jersey WFNJ consecutive month earned income disregard rate (20+ hours) + reference: + - title: N.J.A.C. 10:90-3.8 + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8 + +values: + 2022-10-01: 0.75 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml new file mode 100644 index 00000000000..6a29e7456c7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml @@ -0,0 +1,12 @@ +description: New Jersey excludes this share of earned income for recipients in their first month working 20 or more hours weekly under the WorkFirst New Jersey program. + +metadata: + unit: /1 + period: year + label: New Jersey WFNJ first month earned income disregard rate (20+ hours) + reference: + - title: N.J.A.C. 10:90-3.8 + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8 + +values: + 2022-10-01: 1.0 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml new file mode 100644 index 00000000000..33d00b70ce5 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml @@ -0,0 +1,19 @@ +description: New Jersey WFNJ counts these income sources as unearned income. + +metadata: + unit: list + reference: + - title: N.J.A.C. 10:90-3.9 + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-9 + +values: + 2021-01-01: + - veterans_benefits + - rental_income + - alimony_income + - dividend_income + - interest_income + - pension_income + - unemployment_compensation + - gi_cash_assistance + - social_security diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml new file mode 100644 index 00000000000..503bacfd619 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml @@ -0,0 +1,14 @@ +description: New Jersey limits its WFNJ program to households with up to this income level for people beyond size. + +metadata: + unit: currency-USD + period: month + label: New Jersey WFNJ monthly income limit per additional person + reference: + - title: N.J.A.C. 10:90-3.3 + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 + - title: New Jersey State Plan for WFNJ (2021-2023) + href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=63 + +values: + 2023-01-01: 99 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml new file mode 100644 index 00000000000..c131beb2cf1 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml @@ -0,0 +1,30 @@ +description: New Jersey limits its WFNJ program to households with up to this income level, by household size. + +metadata: + unit: currency-USD + period: month + breakdown: + - range(1, 9) + label: New Jersey WFNJ monthly maximum allowable income + reference: + - title: N.J.A.C. 10:90-3.3 + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 + - title: New Jersey State Plan for WFNJ (2021-2023) + href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=63 + +1: + 2023-01-01: 321 +2: + 2023-01-01: 638 +3: + 2023-01-01: 839 +4: + 2023-01-01: 966 +5: + 2023-01-01: 1_092 +6: + 2023-01-01: 1_221 +7: + 2023-01-01: 1_341 +8: + 2023-01-01: 1_442 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml new file mode 100644 index 00000000000..13e111c6c62 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml @@ -0,0 +1,14 @@ +description: New Jersey limits its WFNJ program to households with this maximum benefit for people beyond size. + +metadata: + unit: currency-USD + period: month + label: New Jersey WFNJ monthly maximum benefit per additional person + reference: + - title: N.J.A.C. 10:90-3.3 + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 + - title: New Jersey State Plan for WFNJ (2021-2023) + href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=63 + +values: + 2023-01-01: 66 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml new file mode 100644 index 00000000000..6305c91cf05 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml @@ -0,0 +1,30 @@ +description: New Jersey limits its WFNJ program to households with this maximum benefit, by household size. + +metadata: + unit: currency-USD + period: month + breakdown: + - range(1, 9) + label: New Jersey WFNJ monthly maximum benefit + reference: + - title: N.J.A.C. 10:90-3.3 + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 + - title: New Jersey State Plan for WFNJ (2021-2023) + href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=63 + +1: + 2023-01-01: 214 +2: + 2023-01-01: 425 +3: + 2023-01-01: 559 +4: + 2023-01-01: 644 +5: + 2023-01-01: 728 +6: + 2023-01-01: 814 +7: + 2023-01-01: 894 +8: + 2023-01-01: 961 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.yaml deleted file mode 100644 index 222fdfc8337..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.yaml +++ /dev/null @@ -1,30 +0,0 @@ -- name: "Is eligible for TANF due to children under 18" - period: 2022 - input: - age: 17 - output: - nj_is_person_demographic_tanf_eligible: true - -- name: "18-year-old out of school is not eligible for TANF" - period: 2022 - input: - age: 18 - is_full_time_student: false - output: - nj_is_person_demographic_tanf_eligible: false - -- name: "Is eligible for TANF due to being an 18-year-old in school" - period: 2022 - input: - age: 18 - is_full_time_student: true - output: - nj_is_person_demographic_tanf_eligible: true - -- name: "Is not eligible for TANF due to being an 19-year-old in school" - period: 2022 - input: - age: 19 - is_full_time_student: true - output: - nj_is_person_demographic_tanf_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_countable_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_countable_earned_income.yaml deleted file mode 100644 index 8304ff51061..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_countable_earned_income.yaml +++ /dev/null @@ -1,59 +0,0 @@ -- name: NJ countable earned income = gross earned income*(1-100%) for first month. - period: 2023 - input: - state_code: NJ - nj_tanf_gross_earned_income: 6_000 - months_enrolled_in_tanf: 1 - hours_worked: 2_080 - output: - nj_tanf_countable_earned_income: 0 - -- name: NJ countable earned income = gross earned income*(1-75%) for applicant with weekly working hours over 20 in 2nd month. - period: 2023 - input: - state_code: NJ - nj_tanf_gross_earned_income: 6_000 - months_enrolled_in_tanf: 2 - hours_worked: 2_080 - output: - nj_tanf_countable_earned_income: 1_500 - -- name: NJ countable earned income = gross earned income*(1-50%) for applicant with weekly working hours under 20 in 2nd month. - period: 2023 - input: - state_code: NJ - nj_tanf_gross_earned_income: 6_000 - months_enrolled_in_tanf: 2 - hours_worked: 988 - output: - nj_tanf_countable_earned_income: 3_000 - -- name: NJ countable earned income = gross earned income*(1-75%) for applicant with weekly working hours over 20 in 7nd month. - period: 2023 - input: - state_code: NJ - nj_tanf_gross_earned_income: 6_000 - months_enrolled_in_tanf: 7 - hours_worked: 2_080 - output: - nj_tanf_countable_earned_income: 1_500 - -- name: NJ countable earned income = gross earned income*(1-50%) for applicant with weekly working hours over 20 in 8nd month. - period: 2023 - input: - state_code: NJ - nj_tanf_gross_earned_income: 6_000 - months_enrolled_in_tanf: 8 - hours_worked: 2_080 - output: - nj_tanf_countable_earned_income: 3_000 - -- name: NJ countable earned income = gross earned income*(1-75%) for applicant with weekly working hours over 20 in 2nd month. - period: 2023 - input: - state_code: NJ - nj_tanf_gross_earned_income: 6_000 - months_enrolled_in_tanf: 2 - hours_worked: 1_040 - output: - nj_tanf_countable_earned_income: 1_500 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.yaml deleted file mode 100644 index fe03996a410..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.yaml +++ /dev/null @@ -1,54 +0,0 @@ -- name: Household with no income is eligible. (0+0<1) - period: 2023 - input: - state_code: NJ - nj_tanf_maximum_allowable_income: 1 - nj_tanf_countable_earned_income: 0 - nj_tanf_countable_gross_unearned_income: 0 - output: - nj_tanf_income_eligible: true - - -- name: Household with income exceeding maximum allowable income is ineligible. (1+1>1) - period: 2023 - input: - state_code: NJ - nj_tanf_maximum_allowable_income: 1 - nj_tanf_countable_earned_income: 1 - nj_tanf_countable_gross_unearned_income: 1 - output: - nj_tanf_income_eligible: false - - -- name: Household with income equals maximum allowable income is eligible. (1+0=1) - period: 2023 - input: - state_code: NJ - nj_tanf_maximum_allowable_income: 1 - nj_tanf_countable_earned_income: 1 - nj_tanf_countable_gross_unearned_income: 0 - output: - nj_tanf_income_eligible: true - -- name: Household with income equals maximum allowable income and income equals maximum benefit is ineligible. - period: 2023 - input: - state_code: NJ - nj_tanf_maximum_allowable_income: 1 - nj_tanf_maximum_benefit: 1 - nj_tanf_countable_earned_income: 1 - nj_tanf_countable_gross_unearned_income: 0 - output: - nj_tanf_income_eligible: false - - -- name: Household with income less than maximum allowable income and income less than maximum benefit is eligible. - period: 2023 - input: - state_code: NJ - nj_tanf_maximum_allowable_income: 3 - nj_tanf_maximum_benefit: 2 - nj_tanf_countable_earned_income: 1 - nj_tanf_countable_gross_unearned_income: 0 - output: - nj_tanf_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml new file mode 100644 index 00000000000..94f716a1b42 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml @@ -0,0 +1,43 @@ +- name: NJ WFNJ January (month 1) - 100% disregard + period: 2024-01 + input: + state_code: NJ + tanf_gross_earned_income: 1_000 + output: + nj_wfnj_countable_earned_income_person: 0 + +- name: NJ WFNJ February (month 2) - 75% disregard + period: 2024-02 + input: + state_code: NJ + tanf_gross_earned_income: 1_000 + output: + # 1000 * (1 - 0.75) = 250 + nj_wfnj_countable_earned_income_person: 250 + +- name: NJ WFNJ July (month 7) - 75% disregard + period: 2024-07 + input: + state_code: NJ + tanf_gross_earned_income: 1_000 + output: + # 1000 * (1 - 0.75) = 250 + nj_wfnj_countable_earned_income_person: 250 + +- name: NJ WFNJ August (month 8) - 50% disregard + period: 2024-08 + input: + state_code: NJ + tanf_gross_earned_income: 1_000 + output: + # 1000 * (1 - 0.50) = 500 + nj_wfnj_countable_earned_income_person: 500 + +- name: NJ WFNJ December (month 12) - 50% disregard + period: 2024-12 + input: + state_code: NJ + tanf_gross_earned_income: 1_000 + output: + # 1000 * (1 - 0.50) = 500 + nj_wfnj_countable_earned_income_person: 500 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_countable_gross_unearned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_gross_unearned_income.yaml similarity index 88% rename from policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_countable_gross_unearned_income.yaml rename to policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_gross_unearned_income.yaml index fbae0071246..c7a75161109 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_countable_gross_unearned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_gross_unearned_income.yaml @@ -13,7 +13,7 @@ social_security: 0 is_tanf_enrolled: false output: - nj_tanf_countable_gross_unearned_income: 0 + nj_wfnj_countable_gross_unearned_income: 0 - name: No unearned income and TANF enrolled, $0 per year period: 2023 @@ -30,7 +30,7 @@ social_security: 0 is_tanf_enrolled: true output: - nj_tanf_countable_gross_unearned_income: 0 + nj_wfnj_countable_gross_unearned_income: 0 - name: $1,000 of each unearned income, $10,000 per year period: 2023 @@ -47,4 +47,4 @@ social_security: 1_000 is_tanf_enrolled: false output: - nj_tanf_countable_gross_unearned_income: 9_000 + nj_wfnj_countable_gross_unearned_income: 9_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.yaml new file mode 100644 index 00000000000..42dcc7ab691 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.yaml @@ -0,0 +1,54 @@ +- name: Household with no income is eligible. (0+0<1) + period: 2023 + input: + state_code: NJ + nj_wfnj_maximum_allowable_income: 1 + nj_wfnj_countable_earned_income: 0 + nj_wfnj_countable_gross_unearned_income: 0 + output: + nj_wfnj_income_eligible: true + + +- name: Household with income exceeding maximum allowable income is ineligible. (1+1>1) + period: 2023 + input: + state_code: NJ + nj_wfnj_maximum_allowable_income: 1 + nj_wfnj_countable_earned_income: 1 + nj_wfnj_countable_gross_unearned_income: 1 + output: + nj_wfnj_income_eligible: false + + +- name: Household with income equals maximum allowable income is eligible. (1+0=1) + period: 2023 + input: + state_code: NJ + nj_wfnj_maximum_allowable_income: 1 + nj_wfnj_countable_earned_income: 1 + nj_wfnj_countable_gross_unearned_income: 0 + output: + nj_wfnj_income_eligible: true + +- name: Household with income equals maximum allowable income and income equals maximum benefit is ineligible. + period: 2023 + input: + state_code: NJ + nj_wfnj_maximum_allowable_income: 1 + nj_wfnj_maximum_benefit: 1 + nj_wfnj_countable_earned_income: 1 + nj_wfnj_countable_gross_unearned_income: 0 + output: + nj_wfnj_income_eligible: false + + +- name: Household with income less than maximum allowable income and income less than maximum benefit is eligible. + period: 2023 + input: + state_code: NJ + nj_wfnj_maximum_allowable_income: 3 + nj_wfnj_maximum_benefit: 2 + nj_wfnj_countable_earned_income: 1 + nj_wfnj_countable_gross_unearned_income: 0 + output: + nj_wfnj_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_maximum_allowable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.yaml similarity index 65% rename from policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_maximum_allowable_income.yaml rename to policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.yaml index 613d9fc52ce..ce0d5cb0eb1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_maximum_allowable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.yaml @@ -1,10 +1,10 @@ -- name: If no children and one adult, New Jersey TANF maximum allowable income is $321/mo. +- name: If no children and one adult, New Jersey WFNJ maximum allowable income is $321/mo. period: 2023 input: state_code: NJ spm_unit_size: 1 output: - nj_tanf_maximum_allowable_income: 321 * 12 + nj_wfnj_maximum_allowable_income: 321 * 12 - name: If not eligible, we don't calculate it. period: 2023 @@ -12,7 +12,7 @@ state_code: CO spm_unit_size: 1 output: - nj_tanf_maximum_allowable_income: 0 + nj_wfnj_maximum_allowable_income: 0 - name: If 10 people, maximum allowable income is $1442 + 2 * $99 = $1640 per month. period: 2023 @@ -20,4 +20,4 @@ state_code: NJ spm_unit_size: 10 output: - nj_tanf_maximum_allowable_income: 1_640 * 12 + nj_wfnj_maximum_allowable_income: 1_640 * 12 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_maximum_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.yaml similarity index 68% rename from policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_maximum_benefit.yaml rename to policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.yaml index 4deef891eaa..bac9a632b53 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_maximum_benefit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.yaml @@ -1,10 +1,10 @@ -- name: If no children and one adult, New Jersey TANF maximum benefit is $214/month. +- name: If no children and one adult, New Jersey WFNJ maximum benefit is $214/month. period: 2023 input: state_code: NJ spm_unit_size: 1 output: - nj_tanf_maximum_benefit: 214 * 12 + nj_wfnj_maximum_benefit: 214 * 12 - name: If not eligible, we don't calculate it. period: 2023 @@ -12,7 +12,7 @@ state_code: CO spm_unit_size: 1 output: - nj_tanf_maximum_benefit: 0 + nj_wfnj_maximum_benefit: 0 - name: If 10 people, maximum benefit is $961 + 2 * $66 = $1093 per month. period: 2023 @@ -20,6 +20,6 @@ state_code: NJ spm_unit_size: 10 output: - nj_tanf_maximum_benefit: 1_093 * 12 + nj_wfnj_maximum_benefit: 1_093 * 12 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml similarity index 62% rename from policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_resources_eligible.yaml rename to policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml index 76d6d9db90e..2b276fe628d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/tanf/nj_tanf_resources_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml @@ -2,15 +2,15 @@ period: 2023 input: state_code: NJ - nj_tanf_countable_resources: 2_000 + nj_wfnj_countable_resources: 2_000 output: - nj_tanf_resources_eligible: true + nj_wfnj_resources_eligible: true - name: Households with assets higher than $2,000 are ineligible. period: 2023 input: state_code: NJ - nj_tanf_countable_resources: 4_000 + nj_wfnj_countable_resources: 4_000 output: - nj_tanf_resources_eligible: false + nj_wfnj_resources_eligible: false diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_countable_earned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_countable_earned_income.py deleted file mode 100644 index 54a47a44c20..00000000000 --- a/policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_countable_earned_income.py +++ /dev/null @@ -1,75 +0,0 @@ -from policyengine_us.model_api import * - - -class nj_tanf_countable_earned_income(Variable): - value_type = float - entity = SPMUnit - label = "New Jersey TANF countable earned income" - unit = USD - definition_period = YEAR - defined_for = StateCode.NJ - - def formula(spm_unit, period, parameters): - person = spm_unit.members - # Get gross earned income. - gross_earned_income = spm_unit("nj_tanf_gross_earned_income", period) - p = parameters( - period - ).gov.states.nj.njdhs.tanf.income.earned_income_deduction - months_enrolled_in_tanf = person("months_enrolled_in_tanf", period) - weekly_hours_worked = person("weekly_hours_worked", period) - # New Jerset Admin Code 10:90-3.8(b) - person_meet_higher_work_hours_threshold = ( - weekly_hours_worked >= p.work_hours_threshold - ) - person_meet_lower_work_hours_threshold = ( - weekly_hours_worked < p.work_hours_threshold - ) - person_enrolled_in_tanf_for_first_month = ( - months_enrolled_in_tanf <= p.first_month_threshold - ) - person_enrolled_in_tanf_for_consecutive_months_with_work_hours_over_20 = ( - months_enrolled_in_tanf <= p.consecutive_month_threshold - and months_enrolled_in_tanf > p.first_month_threshold - and person_meet_higher_work_hours_threshold - ) - person_enrolled_in_tanf_for_additional_months_with_work_hours_over_20 = ( - months_enrolled_in_tanf > p.consecutive_month_threshold - and person_meet_higher_work_hours_threshold - ) - person_enrolled_in_tanf_for_additional_months_with_work_hours_below_20 = ( - months_enrolled_in_tanf > p.first_month_threshold - and person_meet_lower_work_hours_threshold - ) - # The value of result will only change, if the first condition in "where" is met. If the condition is not met, the value of result will not change - result = 0 - # If applicant is enrolled in TANF for the first month, the earned income deduction is 100%. - result = where( - person_enrolled_in_tanf_for_first_month, - gross_earned_income - * (1 - p.higher_work_hours.first_month_percent), - result, - ) - # If applicant is enrolled in TANF for consecutive months with work hours over 20, the earned income deduction is 75%. - result = where( - ( - person_meet_higher_work_hours_threshold - and person_enrolled_in_tanf_for_consecutive_months_with_work_hours_over_20 - ), - gross_earned_income - * (1 - p.higher_work_hours.consecutive_month_percent), - result, - ) - # If applicant is enrolled in TANF for additional months with work hours over 20, the earned income deduction is 50%. - result = where( - person_enrolled_in_tanf_for_additional_months_with_work_hours_over_20, - gross_earned_income * (1 - p.higher_work_hours.additional_percent), - result, - ) - # If applicant is enrolled in TANF for additional months with work hours below 20, the earned income deduction is 50%. - result = where( - person_enrolled_in_tanf_for_additional_months_with_work_hours_below_20, - gross_earned_income * (1 - p.lower_work_hours.additional_percent), - result, - ) - return result diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_countable_gross_unearned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_countable_gross_unearned_income.py deleted file mode 100644 index 432f2f9d962..00000000000 --- a/policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_countable_gross_unearned_income.py +++ /dev/null @@ -1,12 +0,0 @@ -from policyengine_us.model_api import * - - -class nj_tanf_countable_gross_unearned_income(Variable): - value_type = float - entity = SPMUnit - label = "New Jersey TANF countable gross unearned income" - unit = USD - definition_period = YEAR - defined_for = StateCode.NJ - - adds = "gov.states.nj.njdhs.tanf.income.unearned" diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_demographic_tanf_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_demographic_tanf_eligible.py deleted file mode 100644 index 823cc25aed5..00000000000 --- a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_demographic_tanf_eligible.py +++ /dev/null @@ -1,10 +0,0 @@ -from policyengine_us.model_api import * - - -class nj_is_demographic_tanf_eligible(Variable): - value_type = bool - entity = SPMUnit - definition_period = YEAR - label = "Demographic eligibility for New Jersey TANF" - documentation = "Whether any person in a family applying for the Temporary Assistance for Needy Families program meets demographic requirements." - adds = ["nj_is_person_demographic_tanf_eligible"] diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.py deleted file mode 100644 index d372e025a6a..00000000000 --- a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_is_person_demographic_tanf_eligible.py +++ /dev/null @@ -1,20 +0,0 @@ -from policyengine_us.model_api import * - - -class nj_is_person_demographic_tanf_eligible(Variable): - value_type = bool - entity = Person - definition_period = YEAR - label = "Person-level eligibility for New Jersey TANF based on age." - documentation = "Whether a person in a family applying for the Temporary Assistance for Needy Families program meets demographic requirements." - - def formula(person, period, parameters): - # title: State Plan for New Jersey TANF, 2021-2023, page 14 - # href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=14 - # title: New Jersey Administrative Code, 10:90-2.2, part (c)(d) - # href: https://advance.lexis.com/documentpage/?pdmfid=1000516&crid=f96f6864-3540-4a08-b41a-e523b7c5620a&nodeid=AAOAERAADAAC&nodepath=%2FROOT%2FAAO%2FAAOAER%2FAAOAERAAD%2FAAOAERAADAAC&level=4&haschildren=&populated=false&title=%C2%A7+10%3A90-2.2+WFNJ+TANF%2FGA+eligibility+requirements&config=00JAA1YTg5OGJlYi04MTI4LTRlNjQtYTc4Yi03NTQxN2E5NmE0ZjQKAFBvZENhdGFsb2ftaXPxZTR7bRPtX1Jok9kz&pddocfullpath=%2Fshared%2Fdocument%2Fadministrative-codes%2Furn%3AcontentItem%3A5XKV-PWF1-JKHB-61RG-00008-00&ecomp=8gf5kkk&prid=2fb77114-6c52-4b07-8969-f267ef81db7b - child_under_18 = person("age", period) < 18 - is_under_19 = person("age", period) < 19 - full_time_student = person("is_full_time_student", period) - school_enrolled_under_19_year_old = full_time_student & is_under_19 - return child_under_18 | school_enrolled_under_19_year_old diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_resources_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_resources_eligible.py deleted file mode 100644 index b0c3623b1c3..00000000000 --- a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_resources_eligible.py +++ /dev/null @@ -1,16 +0,0 @@ -from policyengine_us.model_api import * - - -class nj_tanf_resources_eligible(Variable): - value_type = bool - entity = SPMUnit - label = "New Jersey TANF resources eligible" - definition_period = YEAR - defined_for = StateCode.NJ - - def formula(spm_unit, period, parameters): - # The WFNJ/TANF resource limit is $2,000 for an assistance unit. - # https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=21 - p = parameters(period).gov.states.nj.njdhs.tanf.eligibility.resources - countable_resources = spm_unit("nj_tanf_countable_resources", period) - return countable_resources <= p.limit diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income.py new file mode 100644 index 00000000000..bc01ae169fe --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class nj_wfnj_countable_earned_income(Variable): + value_type = float + entity = SPMUnit + label = "New Jersey WFNJ countable earned income" + unit = USD + definition_period = MONTH + defined_for = StateCode.NJ + reference = "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8" + adds = ["nj_wfnj_countable_earned_income_person"] diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py new file mode 100644 index 00000000000..e6bec5e7bb5 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py @@ -0,0 +1,39 @@ +from policyengine_us.model_api import * + + +class nj_wfnj_countable_earned_income_person(Variable): + value_type = float + entity = Person + label = "New Jersey WFNJ countable earned income" + unit = USD + definition_period = MONTH + defined_for = StateCode.NJ + reference = "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8" + + def formula(person, period, parameters): + p = parameters( + period + ).gov.states.nj.njdhs.wfnj.income.earned_income_deduction + gross_earned = person("tanf_gross_earned_income", period) + month = period.start.month + + # Calendar month proxy for enrollment months (assuming ≥20 hrs/week). + # N.J.A.C. 10:90-3.8 provides tiered disregards based on months enrolled. + # PolicyEngine cannot track actual enrollment duration, so we use + # calendar months as a proxy: + # - January (month 1): 100% disregard + # - February-July (months 2-7): 75% disregard + # - August-December (months 8-12): 50% disregard + first_month = month == 1 + consecutive_months = (month >= 2) & (month <= 7) + + return select( + [first_month, consecutive_months], + [ + gross_earned * (1 - p.higher_work_hours.first_month_percent), + gross_earned + * (1 - p.higher_work_hours.consecutive_month_percent), + ], + default=gross_earned + * (1 - p.higher_work_hours.additional_percent), + ) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_gross_unearned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_gross_unearned_income.py new file mode 100644 index 00000000000..5fcad1f78c4 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_gross_unearned_income.py @@ -0,0 +1,12 @@ +from policyengine_us.model_api import * + + +class nj_wfnj_countable_gross_unearned_income(Variable): + value_type = float + entity = SPMUnit + label = "New Jersey WFNJ countable gross unearned income" + unit = USD + definition_period = YEAR + defined_for = StateCode.NJ + + adds = "gov.states.nj.njdhs.wfnj.income.unearned" diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_gross_earned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py similarity index 52% rename from policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_gross_earned_income.py rename to policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py index 402b2c500d9..006601829d1 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/tanf/income/nj_tanf_gross_earned_income.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py @@ -1,12 +1,12 @@ from policyengine_us.model_api import * -class nj_tanf_gross_earned_income(Variable): +class nj_wfnj_gross_earned_income(Variable): value_type = float entity = SPMUnit - label = "New Jersey TANF gross earned income" + label = "New Jersey WFNJ gross earned income" unit = USD definition_period = YEAR defined_for = StateCode.NJ - adds = "gov.states.nj.njdhs.tanf.income.earned" + adds = "gov.states.nj.njdhs.wfnj.income.earned" diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_countable_resources.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_resources.py similarity index 61% rename from policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_countable_resources.py rename to policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_resources.py index 4192e40a635..cac20697700 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_countable_resources.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_resources.py @@ -1,10 +1,10 @@ from policyengine_us.model_api import * -class nj_tanf_countable_resources(Variable): +class nj_wfnj_countable_resources(Variable): value_type = float entity = SPMUnit - label = "Countable resources for New Jersey TANF" + label = "New Jersey WFNJ countable resources" unit = USD definition_period = YEAR defined_for = StateCode.NJ diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py similarity index 61% rename from policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.py rename to policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py index c7d2c7230a1..f0f9b20e693 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_income_eligible.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py @@ -1,10 +1,10 @@ from policyengine_us.model_api import * -class nj_tanf_income_eligible(Variable): +class nj_wfnj_income_eligible(Variable): value_type = bool entity = SPMUnit - label = "New Jersey TANF income eligible" + label = "New Jersey WFNJ income eligible" definition_period = YEAR defined_for = StateCode.NJ @@ -13,14 +13,14 @@ def formula(spm_unit, period, parameters): spm_unit, period, [ - "nj_tanf_countable_earned_income", - "nj_tanf_countable_gross_unearned_income", + "nj_wfnj_countable_earned_income", + "nj_wfnj_countable_gross_unearned_income", ], ) maximum_allowable_income = spm_unit( - "nj_tanf_maximum_allowable_income", period + "nj_wfnj_maximum_allowable_income", period ) - maximum_benefit = spm_unit("nj_tanf_maximum_benefit", period) + maximum_benefit = spm_unit("nj_wfnj_maximum_benefit", period) # New Jersey Administrative Code 10:90-3.1 return (income <= maximum_allowable_income) & ( income < maximum_benefit diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_maximum_allowable_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.py similarity index 51% rename from policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_maximum_allowable_income.py rename to policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.py index 6f6b8d509e7..399f54fa3a2 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_maximum_allowable_income.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.py @@ -1,29 +1,22 @@ from policyengine_us.model_api import * -class nj_tanf_maximum_allowable_income(Variable): +class nj_wfnj_maximum_allowable_income(Variable): value_type = float entity = SPMUnit - label = "New Jersey TANF maximum allowable income" + label = "New Jersey WFNJ maximum allowable income" unit = USD definition_period = YEAR defined_for = StateCode.NJ def formula(spm_unit, period, parameters): - # Get number of people in SPM unit. people = spm_unit("spm_unit_size", period) - # Cap them at the maximum specified in the tables. capped_people = min_(people, 8).astype(int) - # Calculate additional people beyond the maximum in tables. additional_people = people - capped_people - # Get the relevant part of the parameter tree. p = parameters( period - ).gov.states.nj.njdhs.tanf.maximum_allowable_income - # Look up the main maximum allowable income for the number of (capped) people. + ).gov.states.nj.njdhs.wfnj.maximum_allowable_income base = p.main[capped_people] - # Add the additional maximum allowable income for the additional people. additional_maximum_allowable_income = p.additional * additional_people monthly = base + additional_maximum_allowable_income - # Return annual value. return monthly * MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_maximum_benefit.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.py similarity index 50% rename from policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_maximum_benefit.py rename to policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.py index 9a03d5cb35d..1dd14d9ff02 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/tanf/nj_tanf_maximum_benefit.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.py @@ -1,27 +1,20 @@ from policyengine_us.model_api import * -class nj_tanf_maximum_benefit(Variable): +class nj_wfnj_maximum_benefit(Variable): value_type = float entity = SPMUnit - label = "New Jersey TANF maximum benefit" + label = "New Jersey WFNJ maximum benefit" unit = USD definition_period = YEAR defined_for = StateCode.NJ def formula(spm_unit, period, parameters): - # Get number of people in SPM unit. people = spm_unit("spm_unit_size", period) - # Cap them at the maximum specified in the tables. capped_people = min_(people, 8).astype(int) - # Calculate additional people beyond the maximum in tables. additional_people = people - capped_people - # Get the relevant part of the parameter tree. - p = parameters(period).gov.states.nj.njdhs.tanf.maximum_benefit - # Look up the main maximum benefit for the number of (capped) people. + p = parameters(period).gov.states.nj.njdhs.wfnj.maximum_benefit base = p.main[capped_people] - # Add the additional maximum benefit for the additional people. additional_maximum_benefit = p.additional * additional_people monthly = base + additional_maximum_benefit - # Return annual value. return monthly * MONTHS_IN_YEAR diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py new file mode 100644 index 00000000000..eba349ad690 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py @@ -0,0 +1,14 @@ +from policyengine_us.model_api import * + + +class nj_wfnj_resources_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "New Jersey WFNJ resources eligible" + definition_period = YEAR + defined_for = StateCode.NJ + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nj.njdhs.wfnj.eligibility.resources + countable_resources = spm_unit("nj_wfnj_countable_resources", period) + return countable_resources <= p.limit diff --git a/policyengine_us/variables/household/income/person/tanf_enrolled/months_enrolled_in_tanf.py b/policyengine_us/variables/household/income/person/tanf_enrolled/months_enrolled_in_tanf.py deleted file mode 100644 index 059fe8db97c..00000000000 --- a/policyengine_us/variables/household/income/person/tanf_enrolled/months_enrolled_in_tanf.py +++ /dev/null @@ -1,9 +0,0 @@ -from policyengine_us.model_api import * - - -class months_enrolled_in_tanf(Variable): - value_type = float - entity = Person - label = "Months enrolled in TANF" - definition_period = YEAR - unit = "month" diff --git a/policyengine_us/variables/household/income/person/work/hours_worked.py b/policyengine_us/variables/household/income/person/work/hours_worked.py deleted file mode 100644 index bd9cae7c29c..00000000000 --- a/policyengine_us/variables/household/income/person/work/hours_worked.py +++ /dev/null @@ -1,9 +0,0 @@ -from policyengine_us.model_api import * - - -class hours_worked(Variable): - value_type = float - entity = Person - label = "Total amount of hours worked by this person" - definition_period = YEAR - unit = "hour" diff --git a/policyengine_us/variables/household/income/person/work/weekly_hours_worked.py b/policyengine_us/variables/household/income/person/work/weekly_hours_worked.py deleted file mode 100644 index 25d33c768da..00000000000 --- a/policyengine_us/variables/household/income/person/work/weekly_hours_worked.py +++ /dev/null @@ -1,14 +0,0 @@ -from policyengine_us.model_api import * - - -class weekly_hours_worked(Variable): - value_type = float - entity = Person - label = "Weekly hours" - documentation = "Average weekly hours worked" - definition_period = YEAR - unit = "hour" - quantity_type = FLOW - - def formula(person, period, parameters): - return person("hours_worked", period) / WEEKS_IN_YEAR From 18e41c9f861bc0d421133db51d975406cfa90093 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 6 Jan 2026 23:21:00 -0500 Subject: [PATCH 3/9] pr fix --- .../wfnj/eligibility/resources/limit.yaml | 8 +- .../states/nj/njdhs/wfnj/income/earned.yaml | 4 +- .../states/nj/njdhs/wfnj/income/unearned.yaml | 5 +- .../nj/njdhs/wfnj/max_household_size.yaml | 12 ++ .../maximum_allowable_income/additional.yaml | 4 +- .../wfnj/maximum_allowable_income/main.yaml | 4 +- .../wfnj/maximum_benefit/additional.yaml | 4 +- .../nj/njdhs/wfnj/maximum_benefit/main.yaml | 4 +- .../gov/states/nj/njdhs/wfnj/integration.yaml | 204 ++++++++++++++++++ ...j_wfnj_countable_earned_income_person.yaml | 47 ++-- ..._wfnj_countable_gross_unearned_income.yaml | 51 ++--- .../njdhs/wfnj/nj_wfnj_income_eligible.yaml | 57 ++--- .../nj_wfnj_maximum_allowable_income.yaml | 33 ++- .../njdhs/wfnj/nj_wfnj_maximum_benefit.yaml | 35 ++- .../wfnj/nj_wfnj_resources_eligible.yaml | 17 +- .../income/nj_wfnj_countable_earned_income.py | 4 +- .../nj_wfnj_countable_earned_income_person.py | 4 +- ...nj_wfnj_countable_gross_unearned_income.py | 6 +- .../income/nj_wfnj_gross_earned_income.py | 6 +- .../gov/states/nj/njdhs/wfnj/nj_wfnj.py | 28 +++ .../njdhs/wfnj/nj_wfnj_countable_resources.py | 4 + .../states/nj/njdhs/wfnj/nj_wfnj_eligible.py | 29 +++ .../nj/njdhs/wfnj/nj_wfnj_income_eligible.py | 6 +- .../wfnj/nj_wfnj_maximum_allowable_income.py | 20 +- .../nj/njdhs/wfnj/nj_wfnj_maximum_benefit.py | 18 +- .../njdhs/wfnj/nj_wfnj_resources_eligible.py | 9 +- 26 files changed, 469 insertions(+), 154 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/max_household_size.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj.py create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.py diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml index 65cec4cd534..09a78a81c41 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml @@ -1,14 +1,12 @@ -description: New Jersey limits its WFNJ eligibility to households with up to this amount of resources. +description: New Jersey limits resources to this amount under the WorkFirst New Jersey program. metadata: unit: currency-USD period: year label: New Jersey WFNJ resource limit reference: - - title: N.J.A.C. 10:90-3.2 - href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-2 - - title: New Jersey State Plan for WFNJ (2021-2023) - href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=21 + - title: N.J.A.C. 10:90-3.20 + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-20 values: 2023-01-01: 2_000 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml index 6d8bdf5a82c..23df2d17c4f 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml @@ -1,7 +1,9 @@ -description: New Jersey WFNJ counts these income sources as earned income. +description: New Jersey counts these income sources as earned income under the WorkFirst New Jersey program. metadata: unit: list + period: month + label: New Jersey WFNJ earned income sources reference: - title: N.J.A.C. 10:90-3.9 href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-9 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml index 33d00b70ce5..0c467e40dfb 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml @@ -1,7 +1,9 @@ -description: New Jersey WFNJ counts these income sources as unearned income. +description: New Jersey counts these income sources as unearned income under the WorkFirst New Jersey program. metadata: unit: list + period: month + label: New Jersey WFNJ unearned income sources reference: - title: N.J.A.C. 10:90-3.9 href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-9 @@ -17,3 +19,4 @@ values: - unemployment_compensation - gi_cash_assistance - social_security + - child_support_received diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/max_household_size.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/max_household_size.yaml new file mode 100644 index 00000000000..010e5c20983 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/max_household_size.yaml @@ -0,0 +1,12 @@ +description: New Jersey uses this threshold as the maximum household size for the WorkFirst New Jersey program income and benefit tables. + +metadata: + unit: person + period: year + label: New Jersey WFNJ maximum household size for tables + reference: + - title: N.J.A.C. 10:90-3.3 + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 + +values: + 2023-01-01: 8 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml index 503bacfd619..df9c319a386 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml @@ -1,4 +1,4 @@ -description: New Jersey limits its WFNJ program to households with up to this income level for people beyond size. +description: New Jersey provides this additional income limit per person beyond the base household size under the WorkFirst New Jersey program. metadata: unit: currency-USD @@ -7,8 +7,6 @@ metadata: reference: - title: N.J.A.C. 10:90-3.3 href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 - - title: New Jersey State Plan for WFNJ (2021-2023) - href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=63 values: 2023-01-01: 99 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml index c131beb2cf1..470102fe726 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml @@ -1,4 +1,4 @@ -description: New Jersey limits its WFNJ program to households with up to this income level, by household size. +description: New Jersey limits gross income to this amount under the WorkFirst New Jersey program. metadata: unit: currency-USD @@ -9,8 +9,6 @@ metadata: reference: - title: N.J.A.C. 10:90-3.3 href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 - - title: New Jersey State Plan for WFNJ (2021-2023) - href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=63 1: 2023-01-01: 321 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml index 13e111c6c62..abc7bee5997 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml @@ -1,4 +1,4 @@ -description: New Jersey limits its WFNJ program to households with this maximum benefit for people beyond size. +description: New Jersey provides this additional benefit per person beyond the base household size under the WorkFirst New Jersey program. metadata: unit: currency-USD @@ -7,8 +7,6 @@ metadata: reference: - title: N.J.A.C. 10:90-3.3 href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 - - title: New Jersey State Plan for WFNJ (2021-2023) - href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=63 values: 2023-01-01: 66 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml index 6305c91cf05..0eace0da708 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml @@ -1,4 +1,4 @@ -description: New Jersey limits its WFNJ program to households with this maximum benefit, by household size. +description: New Jersey provides this amount as the maximum benefit under the WorkFirst New Jersey program. metadata: unit: currency-USD @@ -9,8 +9,6 @@ metadata: reference: - title: N.J.A.C. 10:90-3.3 href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 - - title: New Jersey State Plan for WFNJ (2021-2023) - href: https://www.nj.gov/humanservices/dfd/programs/workfirstnj/tanf_2021_23_st_plan.pdf#page=63 1: 2023-01-01: 214 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml new file mode 100644 index 00000000000..c9beb17ebe3 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml @@ -0,0 +1,204 @@ +- name: Case 1, eligible single parent with one child and no income. + period: 2024-01 + input: + people: + person1: + age: 30 + is_citizen_or_legal_immigrant: true + person2: + age: 5 + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_size: 2 + spm_unit_assets: 1_000 + is_demographic_tanf_eligible: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Maximum benefit for 2 people: $425/month + nj_wfnj_maximum_benefit: 425 + # Maximum allowable income for 2 people: $638/month + nj_wfnj_maximum_allowable_income: 638 + # Countable resources: $1,000 (from spm_unit_assets) + nj_wfnj_countable_resources: 1_000 + # Resources eligible: $1,000 <= $2,000 + nj_wfnj_resources_eligible: true + # No income + nj_wfnj_countable_earned_income: 0 + nj_wfnj_countable_gross_unearned_income: 0 + # Income eligible: 0 <= 638 and 0 < 425 + nj_wfnj_income_eligible: true + # Overall eligible + nj_wfnj_eligible: true + # Benefit: $425 - $0 = $425 + nj_wfnj: 425 + +- name: Case 2, eligible family of 3 with earned income. + period: 2024-01 + input: + people: + person1: + age: 35 + is_citizen_or_legal_immigrant: true + tanf_gross_earned_income: 200 + person2: + age: 32 + is_citizen_or_legal_immigrant: true + tanf_gross_earned_income: 0 + person3: + age: 8 + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1, person2, person3] + spm_unit_size: 3 + spm_unit_assets: 500 + is_demographic_tanf_eligible: true + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + # Maximum benefit for 3 people: $559/month + nj_wfnj_maximum_benefit: 559 + # Maximum allowable income for 3 people: $839/month + nj_wfnj_maximum_allowable_income: 839 + # January = 100% disregard, so countable earned = 0 + nj_wfnj_countable_earned_income_person: [0, 0, 0] + nj_wfnj_countable_earned_income: 0 + # No unearned income + nj_wfnj_countable_gross_unearned_income: 0 + # Income eligible: 0 <= 839 and 0 < 559 + nj_wfnj_income_eligible: true + # Resources eligible: $500 <= $2,000 + nj_wfnj_resources_eligible: true + # Overall eligible + nj_wfnj_eligible: true + # Benefit: $559 - $0 = $559 + nj_wfnj: 559 + +- name: Case 3, ineligible due to high resources. + period: 2024-01 + input: + people: + person1: + age: 28 + is_citizen_or_legal_immigrant: true + person2: + age: 3 + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_size: 2 + spm_unit_assets: 5_000 + is_demographic_tanf_eligible: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Resources: $5,000 > $2,000 limit + nj_wfnj_countable_resources: 5_000 + nj_wfnj_resources_eligible: false + # Income eligible (no income) + nj_wfnj_income_eligible: true + # Overall ineligible due to resources + nj_wfnj_eligible: false + nj_wfnj: 0 + +- name: Case 4, ineligible due to high income. + period: 2024-01 + input: + people: + person1: + age: 40 + is_citizen_or_legal_immigrant: true + social_security: 12_000 + person2: + age: 6 + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_size: 2 + spm_unit_assets: 1_000 + is_demographic_tanf_eligible: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Max benefit for 2: $425, max allowable income: $638 + nj_wfnj_maximum_benefit: 425 + nj_wfnj_maximum_allowable_income: 638 + # Unearned: $12,000/12 = $1,000/month + nj_wfnj_countable_gross_unearned_income: 1_000 + # Income: $1,000 > $638 max allowable + nj_wfnj_income_eligible: false + nj_wfnj_resources_eligible: true + nj_wfnj_eligible: false + nj_wfnj: 0 + +- name: Case 5, eligible with unearned income reducing benefit. + period: 2024-01 + input: + people: + person1: + age: 25 + is_citizen_or_legal_immigrant: true + social_security: 2_400 + spm_units: + spm_unit: + members: [person1] + spm_unit_size: 1 + spm_unit_assets: 500 + is_demographic_tanf_eligible: true + households: + household: + members: [person1] + state_code: NJ + output: + # Max benefit for 1: $214, max allowable income: $321 + nj_wfnj_maximum_benefit: 214 + nj_wfnj_maximum_allowable_income: 321 + # Unearned: $2,400/12 = $200/month + nj_wfnj_countable_gross_unearned_income: 200 + # Income: $200 <= $321 and $200 < $214 + nj_wfnj_income_eligible: true + nj_wfnj_resources_eligible: true + nj_wfnj_eligible: true + # Benefit: $214 - $200 = $14 + nj_wfnj: 14 + +- name: Case 6, ineligible due to no citizen or legal immigrant. + period: 2024-01 + input: + people: + person1: + age: 30 + is_citizen_or_legal_immigrant: false + person2: + age: 5 + is_citizen_or_legal_immigrant: false + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_size: 2 + spm_unit_assets: 500 + is_demographic_tanf_eligible: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Income eligible (no income) + nj_wfnj_income_eligible: true + nj_wfnj_resources_eligible: true + # Ineligible due to immigration status + nj_wfnj_eligible: false + nj_wfnj: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml index 94f716a1b42..a8bb2dde124 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml @@ -1,43 +1,32 @@ -- name: NJ WFNJ January (month 1) - 100% disregard +# NOTE: The earned income disregard is based on months of employment, not calendar +# months. PolicyEngine cannot track employment duration, so we use calendar months +# as a proxy. January = 100% disregard, Feb-Jul = 75%, Aug-Dec = 50%. +# Only January (2024-01) can be tested due to PolicyEngine's period format restrictions. + +- name: Case 1, first month of year with 100% disregard. period: 2024-01 input: state_code: NJ tanf_gross_earned_income: 1_000 output: + # January (month 1): 100% disregard + # 1000 * (1 - 1.0) = 0 nj_wfnj_countable_earned_income_person: 0 -- name: NJ WFNJ February (month 2) - 75% disregard - period: 2024-02 - input: - state_code: NJ - tanf_gross_earned_income: 1_000 - output: - # 1000 * (1 - 0.75) = 250 - nj_wfnj_countable_earned_income_person: 250 - -- name: NJ WFNJ July (month 7) - 75% disregard - period: 2024-07 - input: - state_code: NJ - tanf_gross_earned_income: 1_000 - output: - # 1000 * (1 - 0.75) = 250 - nj_wfnj_countable_earned_income_person: 250 - -- name: NJ WFNJ August (month 8) - 50% disregard - period: 2024-08 +- name: Case 2, zero income. + period: 2024-01 input: state_code: NJ - tanf_gross_earned_income: 1_000 + tanf_gross_earned_income: 0 output: - # 1000 * (1 - 0.50) = 500 - nj_wfnj_countable_earned_income_person: 500 + nj_wfnj_countable_earned_income_person: 0 -- name: NJ WFNJ December (month 12) - 50% disregard - period: 2024-12 +- name: Case 3, high income with full disregard. + period: 2024-01 input: state_code: NJ - tanf_gross_earned_income: 1_000 + tanf_gross_earned_income: 5_000 output: - # 1000 * (1 - 0.50) = 500 - nj_wfnj_countable_earned_income_person: 500 + # January: 100% disregard + # 5000 * (1 - 1.0) = 0 + nj_wfnj_countable_earned_income_person: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_gross_unearned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_gross_unearned_income.yaml index c7a75161109..d489a4a9fa7 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_gross_unearned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_gross_unearned_income.yaml @@ -1,5 +1,5 @@ -- name: No unearned income, $0 per year - period: 2023 +- name: Case 1, no unearned income. + period: 2024-01 input: state_code: NJ veterans_benefits: 0 @@ -11,40 +11,33 @@ unemployment_compensation: 0 gi_cash_assistance: 0 social_security: 0 - is_tanf_enrolled: false + child_support_received: 0 output: nj_wfnj_countable_gross_unearned_income: 0 -- name: No unearned income and TANF enrolled, $0 per year - period: 2023 +- name: Case 2, various unearned income sources. + period: 2024-01 input: state_code: NJ - veterans_benefits: 0 - rental_income: 0 - alimony_income: 0 - dividend_income: 0 - interest_income: 0 - pension_income: 0 - unemployment_compensation: 0 - gi_cash_assistance: 0 - social_security: 0 - is_tanf_enrolled: true + veterans_benefits: 1_200 + rental_income: 1_200 + alimony_income: 1_200 + dividend_income: 1_200 + interest_income: 1_200 + pension_income: 1_200 + unemployment_compensation: 1_200 + gi_cash_assistance: 1_200 + social_security: 1_200 + child_support_received: 1_200 output: - nj_wfnj_countable_gross_unearned_income: 0 + # 10 sources * 1200/12 = 10 * 100 = 1000 monthly + nj_wfnj_countable_gross_unearned_income: 1_000 -- name: $1,000 of each unearned income, $10,000 per year - period: 2023 +- name: Case 3, only social security income. + period: 2024-01 input: state_code: NJ - veterans_benefits: 1_000 - rental_income: 1_000 - alimony_income: 1_000 - dividend_income: 1_000 - interest_income: 1_000 - pension_income: 1_000 - unemployment_compensation: 1_000 - gi_cash_assistance: 1_000 - social_security: 1_000 - is_tanf_enrolled: false + social_security: 12_000 output: - nj_wfnj_countable_gross_unearned_income: 9_000 + # 12000/12 = 1000 monthly + nj_wfnj_countable_gross_unearned_income: 1_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.yaml index 42dcc7ab691..3a0f9962d7d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.yaml @@ -1,54 +1,59 @@ -- name: Household with no income is eligible. (0+0<1) - period: 2023 +- name: Case 1, household with no income is eligible. + period: 2024-01 input: state_code: NJ - nj_wfnj_maximum_allowable_income: 1 + nj_wfnj_maximum_allowable_income: 100 + nj_wfnj_maximum_benefit: 100 nj_wfnj_countable_earned_income: 0 nj_wfnj_countable_gross_unearned_income: 0 output: + # 0 + 0 = 0 <= 100 and 0 < 100 nj_wfnj_income_eligible: true - -- name: Household with income exceeding maximum allowable income is ineligible. (1+1>1) - period: 2023 +- name: Case 2, household with income exceeding maximum allowable income is ineligible. + period: 2024-01 input: state_code: NJ - nj_wfnj_maximum_allowable_income: 1 - nj_wfnj_countable_earned_income: 1 - nj_wfnj_countable_gross_unearned_income: 1 + nj_wfnj_maximum_allowable_income: 100 + nj_wfnj_maximum_benefit: 200 + nj_wfnj_countable_earned_income: 50 + nj_wfnj_countable_gross_unearned_income: 60 output: + # 50 + 60 = 110 > 100, fails income test nj_wfnj_income_eligible: false - -- name: Household with income equals maximum allowable income is eligible. (1+0=1) - period: 2023 +- name: Case 3, household with income at maximum allowable income is eligible. + period: 2024-01 input: state_code: NJ - nj_wfnj_maximum_allowable_income: 1 - nj_wfnj_countable_earned_income: 1 + nj_wfnj_maximum_allowable_income: 100 + nj_wfnj_maximum_benefit: 200 + nj_wfnj_countable_earned_income: 100 nj_wfnj_countable_gross_unearned_income: 0 output: + # 100 <= 100 and 100 < 200 nj_wfnj_income_eligible: true -- name: Household with income equals maximum allowable income and income equals maximum benefit is ineligible. - period: 2023 +- name: Case 4, household with income equal to maximum benefit is ineligible. + period: 2024-01 input: state_code: NJ - nj_wfnj_maximum_allowable_income: 1 - nj_wfnj_maximum_benefit: 1 - nj_wfnj_countable_earned_income: 1 + nj_wfnj_maximum_allowable_income: 200 + nj_wfnj_maximum_benefit: 100 + nj_wfnj_countable_earned_income: 100 nj_wfnj_countable_gross_unearned_income: 0 output: + # 100 <= 200 but 100 >= 100 (not < max_benefit) nj_wfnj_income_eligible: false - -- name: Household with income less than maximum allowable income and income less than maximum benefit is eligible. - period: 2023 +- name: Case 5, household with income below both thresholds is eligible. + period: 2024-01 input: state_code: NJ - nj_wfnj_maximum_allowable_income: 3 - nj_wfnj_maximum_benefit: 2 - nj_wfnj_countable_earned_income: 1 - nj_wfnj_countable_gross_unearned_income: 0 + nj_wfnj_maximum_allowable_income: 300 + nj_wfnj_maximum_benefit: 200 + nj_wfnj_countable_earned_income: 50 + nj_wfnj_countable_gross_unearned_income: 50 output: + # 100 <= 300 and 100 < 200 nj_wfnj_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.yaml index ce0d5cb0eb1..b6ce20b7c06 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.yaml @@ -1,23 +1,40 @@ -- name: If no children and one adult, New Jersey WFNJ maximum allowable income is $321/mo. - period: 2023 +- name: Case 1, single person household max income is $321/month. + period: 2024-01 input: state_code: NJ spm_unit_size: 1 output: - nj_wfnj_maximum_allowable_income: 321 * 12 + nj_wfnj_maximum_allowable_income: 321 -- name: If not eligible, we don't calculate it. - period: 2023 +- name: Case 2, non-NJ state returns zero. + period: 2024-01 input: state_code: CO spm_unit_size: 1 output: nj_wfnj_maximum_allowable_income: 0 -- name: If 10 people, maximum allowable income is $1442 + 2 * $99 = $1640 per month. - period: 2023 +- name: Case 3, family of 3 max income is $839/month. + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 3 + output: + nj_wfnj_maximum_allowable_income: 839 + +- name: Case 4, family of 8 (max table size) max income is $1,442/month. + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 8 + output: + nj_wfnj_maximum_allowable_income: 1_442 + +- name: Case 5, family of 10 uses additional per person rate. + period: 2024-01 input: state_code: NJ spm_unit_size: 10 output: - nj_wfnj_maximum_allowable_income: 1_640 * 12 + # $1,442 + 2 * $99 = $1,640 + nj_wfnj_maximum_allowable_income: 1_640 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.yaml index bac9a632b53..15d257608ab 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.yaml @@ -1,25 +1,40 @@ -- name: If no children and one adult, New Jersey WFNJ maximum benefit is $214/month. - period: 2023 +- name: Case 1, single person household maximum benefit is $214/month. + period: 2024-01 input: state_code: NJ spm_unit_size: 1 output: - nj_wfnj_maximum_benefit: 214 * 12 + nj_wfnj_maximum_benefit: 214 -- name: If not eligible, we don't calculate it. - period: 2023 +- name: Case 2, non-NJ state returns zero. + period: 2024-01 input: state_code: CO spm_unit_size: 1 output: nj_wfnj_maximum_benefit: 0 -- name: If 10 people, maximum benefit is $961 + 2 * $66 = $1093 per month. - period: 2023 +- name: Case 3, family of 3 maximum benefit is $559/month. + period: 2024-01 input: state_code: NJ - spm_unit_size: 10 + spm_unit_size: 3 + output: + nj_wfnj_maximum_benefit: 559 + +- name: Case 4, family of 8 (max table size) maximum benefit is $961/month. + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 8 output: - nj_wfnj_maximum_benefit: 1_093 * 12 + nj_wfnj_maximum_benefit: 961 - +- name: Case 5, family of 10 uses additional per person rate. + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 10 + output: + # $961 + 2 * $66 = $1093 + nj_wfnj_maximum_benefit: 1_093 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml index 2b276fe628d..9532bb72bec 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml @@ -1,16 +1,23 @@ -- name: Households with assets lower than or equal to $2,000 are eligible. - period: 2023 +- name: Case 1, household with assets at $2,000 limit is eligible. + period: 2024-01 input: state_code: NJ nj_wfnj_countable_resources: 2_000 output: nj_wfnj_resources_eligible: true - -- name: Households with assets higher than $2,000 are ineligible. - period: 2023 +- name: Case 2, household with assets above $2,000 is ineligible. + period: 2024-01 input: state_code: NJ nj_wfnj_countable_resources: 4_000 output: nj_wfnj_resources_eligible: false + +- name: Case 3, household with zero assets is eligible. + period: 2024-01 + input: + state_code: NJ + nj_wfnj_countable_resources: 0 + output: + nj_wfnj_resources_eligible: true diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income.py index bc01ae169fe..ac7ebce9f72 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income.py @@ -8,5 +8,7 @@ class nj_wfnj_countable_earned_income(Variable): unit = USD definition_period = MONTH defined_for = StateCode.NJ - reference = "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8" + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8" + ) adds = ["nj_wfnj_countable_earned_income_person"] diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py index e6bec5e7bb5..51311d402a5 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py @@ -8,7 +8,9 @@ class nj_wfnj_countable_earned_income_person(Variable): unit = USD definition_period = MONTH defined_for = StateCode.NJ - reference = "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8" + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8" + ) def formula(person, period, parameters): p = parameters( diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_gross_unearned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_gross_unearned_income.py index 5fcad1f78c4..bd81aee7808 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_gross_unearned_income.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_gross_unearned_income.py @@ -6,7 +6,9 @@ class nj_wfnj_countable_gross_unearned_income(Variable): entity = SPMUnit label = "New Jersey WFNJ countable gross unearned income" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.NJ - + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-9" + ) adds = "gov.states.nj.njdhs.wfnj.income.unearned" diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py index 006601829d1..2facc3a3bf9 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py @@ -6,7 +6,9 @@ class nj_wfnj_gross_earned_income(Variable): entity = SPMUnit label = "New Jersey WFNJ gross earned income" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.NJ - + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-9" + ) adds = "gov.states.nj.njdhs.wfnj.income.earned" diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj.py new file mode 100644 index 00000000000..dd9d337ba48 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj.py @@ -0,0 +1,28 @@ +from policyengine_us.model_api import * + + +class nj_wfnj(Variable): + value_type = float + entity = SPMUnit + label = "New Jersey WFNJ benefit" + unit = USD + definition_period = MONTH + defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3" + ) + + def formula(spm_unit, period, parameters): + eligible = spm_unit("nj_wfnj_eligible", period) + maximum_benefit = spm_unit("nj_wfnj_maximum_benefit", period) + countable_income = add( + spm_unit, + period, + [ + "nj_wfnj_countable_earned_income", + "nj_wfnj_countable_gross_unearned_income", + ], + ) + # Benefit = maximum benefit - countable income + benefit = max_(maximum_benefit - countable_income, 0) + return where(eligible, benefit, 0) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_resources.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_resources.py index cac20697700..27f8529885a 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_resources.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_resources.py @@ -8,3 +8,7 @@ class nj_wfnj_countable_resources(Variable): unit = USD definition_period = YEAR defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-20" + ) + adds = ["spm_unit_assets"] diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.py new file mode 100644 index 00000000000..635e4f42886 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class nj_wfnj_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "New Jersey WFNJ eligible" + definition_period = MONTH + defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-1", + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-20", + ) + + def formula(spm_unit, period, parameters): + income_eligible = spm_unit("nj_wfnj_income_eligible", period) + resources_eligible = spm_unit("nj_wfnj_resources_eligible", period) + demographic_eligible = spm_unit( + "is_demographic_tanf_eligible", period + ) + has_citizen_or_legal_immigrant = ( + add(spm_unit, period, ["is_citizen_or_legal_immigrant"]) > 0 + ) + return ( + income_eligible + & resources_eligible + & demographic_eligible + & has_citizen_or_legal_immigrant + ) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py index f0f9b20e693..59be4744fbc 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py @@ -5,8 +5,11 @@ class nj_wfnj_income_eligible(Variable): value_type = bool entity = SPMUnit label = "New Jersey WFNJ income eligible" - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-1" + ) def formula(spm_unit, period, parameters): income = add( @@ -21,7 +24,6 @@ def formula(spm_unit, period, parameters): "nj_wfnj_maximum_allowable_income", period ) maximum_benefit = spm_unit("nj_wfnj_maximum_benefit", period) - # New Jersey Administrative Code 10:90-3.1 return (income <= maximum_allowable_income) & ( income < maximum_benefit ) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.py index 399f54fa3a2..110d19a8bc7 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.py @@ -6,17 +6,17 @@ class nj_wfnj_maximum_allowable_income(Variable): entity = SPMUnit label = "New Jersey WFNJ maximum allowable income" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3" + ) def formula(spm_unit, period, parameters): - people = spm_unit("spm_unit_size", period) - capped_people = min_(people, 8).astype(int) + people = spm_unit("spm_unit_size", period.this_year) + p = parameters(period).gov.states.nj.njdhs.wfnj + capped_people = min_(people, p.max_household_size).astype(int) additional_people = people - capped_people - p = parameters( - period - ).gov.states.nj.njdhs.wfnj.maximum_allowable_income - base = p.main[capped_people] - additional_maximum_allowable_income = p.additional * additional_people - monthly = base + additional_maximum_allowable_income - return monthly * MONTHS_IN_YEAR + base = p.maximum_allowable_income.main[capped_people] + additional = p.maximum_allowable_income.additional * additional_people + return base + additional diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.py index 1dd14d9ff02..774ba2890e1 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.py @@ -6,15 +6,17 @@ class nj_wfnj_maximum_benefit(Variable): entity = SPMUnit label = "New Jersey WFNJ maximum benefit" unit = USD - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3" + ) def formula(spm_unit, period, parameters): - people = spm_unit("spm_unit_size", period) - capped_people = min_(people, 8).astype(int) + people = spm_unit("spm_unit_size", period.this_year) + p = parameters(period).gov.states.nj.njdhs.wfnj + capped_people = min_(people, p.max_household_size).astype(int) additional_people = people - capped_people - p = parameters(period).gov.states.nj.njdhs.wfnj.maximum_benefit - base = p.main[capped_people] - additional_maximum_benefit = p.additional * additional_people - monthly = base + additional_maximum_benefit - return monthly * MONTHS_IN_YEAR + base = p.maximum_benefit.main[capped_people] + additional = p.maximum_benefit.additional * additional_people + return base + additional diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py index eba349ad690..8760c2ca6c3 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py @@ -5,10 +5,15 @@ class nj_wfnj_resources_eligible(Variable): value_type = bool entity = SPMUnit label = "New Jersey WFNJ resources eligible" - definition_period = YEAR + definition_period = MONTH defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-20" + ) def formula(spm_unit, period, parameters): p = parameters(period).gov.states.nj.njdhs.wfnj.eligibility.resources - countable_resources = spm_unit("nj_wfnj_countable_resources", period) + countable_resources = spm_unit( + "nj_wfnj_countable_resources", period.this_year + ) return countable_resources <= p.limit From 1f47dc60654d4b1308a0e92d9fef2c58f0babd15 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 6 Jan 2026 23:38:12 -0500 Subject: [PATCH 4/9] agent fix --- .../wfnj/eligibility/resources/limit.yaml | 2 +- .../states/nj/njdhs/wfnj/income/earned.yaml | 4 +- .../higher_work_hours/additional_percent.yaml | 4 +- .../consecutive_month_percent.yaml | 4 +- .../first_month_percent.yaml | 4 +- .../gov/states/nj/njdhs/wfnj/integration.yaml | 6 +- .../gov/states/nj/njdhs/wfnj/nj_wfnj.yaml | 119 +++++++++++++++ ...j_wfnj_countable_earned_income_person.yaml | 33 ++-- .../nj/njdhs/wfnj/nj_wfnj_eligible.yaml | 142 ++++++++++++++++++ .../wfnj/nj_wfnj_resources_eligible.yaml | 6 +- .../nj_wfnj_countable_earned_income_person.py | 2 +- .../income/nj_wfnj_gross_earned_income.py | 2 +- .../njdhs/wfnj/nj_wfnj_countable_resources.py | 14 -- .../states/nj/njdhs/wfnj/nj_wfnj_eligible.py | 4 +- .../njdhs/wfnj/nj_wfnj_resources_eligible.py | 6 +- 15 files changed, 303 insertions(+), 49 deletions(-) create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.yaml delete mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_resources.py diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml index 09a78a81c41..a66c54658f6 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml @@ -2,7 +2,7 @@ description: New Jersey limits resources to this amount under the WorkFirst New metadata: unit: currency-USD - period: year + period: eternity label: New Jersey WFNJ resource limit reference: - title: N.J.A.C. 10:90-3.20 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml index 23df2d17c4f..0e13ec190da 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml @@ -10,5 +10,5 @@ metadata: values: 2023-03-22: - - employment_income - - self_employment_income + - employment_income_before_lsr + - self_employment_income_before_lsr diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/additional_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/additional_percent.yaml index 0c6d97c9779..598a94a325e 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/additional_percent.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/additional_percent.yaml @@ -1,8 +1,8 @@ -description: New Jersey excludes this share of earned income for recipients in month 8 and beyond working 20 or more hours weekly under the WorkFirst New Jersey program. +description: New Jersey excludes this share of earned income under the WorkFirst New Jersey program. metadata: unit: /1 - period: year + period: month label: New Jersey WFNJ additional month earned income disregard rate (20+ hours) reference: - title: N.J.A.C. 10:90-3.8 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml index 446917d95e7..e1ba76a156f 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml @@ -1,8 +1,8 @@ -description: New Jersey excludes this share of earned income for recipients in months 2-7 working 20 or more hours weekly under the WorkFirst New Jersey program. +description: New Jersey excludes this share of earned income under the WorkFirst New Jersey program. metadata: unit: /1 - period: year + period: month label: New Jersey WFNJ consecutive month earned income disregard rate (20+ hours) reference: - title: N.J.A.C. 10:90-3.8 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml index 6a29e7456c7..74bb76cb825 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml @@ -1,8 +1,8 @@ -description: New Jersey excludes this share of earned income for recipients in their first month working 20 or more hours weekly under the WorkFirst New Jersey program. +description: New Jersey excludes this share of earned income under the WorkFirst New Jersey program. metadata: unit: /1 - period: year + period: month label: New Jersey WFNJ first month earned income disregard rate (20+ hours) reference: - title: N.J.A.C. 10:90-3.8 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml index c9beb17ebe3..05e54555e65 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml @@ -23,8 +23,6 @@ nj_wfnj_maximum_benefit: 425 # Maximum allowable income for 2 people: $638/month nj_wfnj_maximum_allowable_income: 638 - # Countable resources: $1,000 (from spm_unit_assets) - nj_wfnj_countable_resources: 1_000 # Resources eligible: $1,000 <= $2,000 nj_wfnj_resources_eligible: true # No income @@ -44,11 +42,10 @@ person1: age: 35 is_citizen_or_legal_immigrant: true - tanf_gross_earned_income: 200 + employment_income_before_lsr: 2_400 # $200/month annual person2: age: 32 is_citizen_or_legal_immigrant: true - tanf_gross_earned_income: 0 person3: age: 8 is_citizen_or_legal_immigrant: true @@ -103,7 +100,6 @@ state_code: NJ output: # Resources: $5,000 > $2,000 limit - nj_wfnj_countable_resources: 5_000 nj_wfnj_resources_eligible: false # Income eligible (no income) nj_wfnj_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj.yaml new file mode 100644 index 00000000000..444785a6095 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj.yaml @@ -0,0 +1,119 @@ +# Tests for NJ WFNJ benefit calculation. +# Benefit = max(maximum_benefit - countable_income, 0) if eligible, else 0 +# Maximum benefit by household size: 1=$214, 2=$425, 3=$559, 4=$644... + +- name: Case 1, eligible with no income - full benefit. + period: 2024-01 + input: + people: + person1: + age: 30 + is_citizen_or_legal_immigrant: true + person2: + age: 5 + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_size: 2 + spm_unit_assets: 1_000 + is_demographic_tanf_eligible: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + nj_wfnj_eligible: true + # Maximum benefit for 2 people: $425 + nj_wfnj_maximum_benefit: 425 + # Countable income: $0 + nj_wfnj_countable_earned_income: 0 + nj_wfnj_countable_gross_unearned_income: 0 + # Benefit = $425 - $0 = $425 + nj_wfnj: 425 + +- name: Case 2, eligible with income - reduced benefit. + period: 2024-01 + input: + people: + person1: + age: 35 + is_citizen_or_legal_immigrant: true + social_security: 1_200 # $100/month + spm_units: + spm_unit: + members: [person1] + spm_unit_size: 1 + spm_unit_assets: 500 + is_demographic_tanf_eligible: true + households: + household: + members: [person1] + state_code: NJ + output: + nj_wfnj_eligible: true + # Maximum benefit for 1 person: $214 + nj_wfnj_maximum_benefit: 214 + # Unearned income: $1,200/12 = $100/month + nj_wfnj_countable_gross_unearned_income: 100 + # Benefit = $214 - $100 = $114 + nj_wfnj: 114 + +- name: Case 3, ineligible - zero benefit. + period: 2024-01 + input: + people: + person1: + age: 28 + is_citizen_or_legal_immigrant: true + social_security: 12_000 # $1,000/month + person2: + age: 6 + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_size: 2 + spm_unit_assets: 500 + is_demographic_tanf_eligible: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Max allowable for 2: $638, income $1,000 > $638 + nj_wfnj_income_eligible: false + nj_wfnj_eligible: false + nj_wfnj: 0 + +- name: Case 4, income exceeds max benefit - clipped to zero. + period: 2024-01 + input: + people: + person1: + age: 25 + is_citizen_or_legal_immigrant: true + social_security: 2_640 # $220/month, just above $214 max benefit for 1 + spm_units: + spm_unit: + members: [person1] + spm_unit_size: 1 + spm_unit_assets: 500 + is_demographic_tanf_eligible: true + households: + household: + members: [person1] + state_code: NJ + output: + # Maximum benefit for 1: $214 + nj_wfnj_maximum_benefit: 214 + # Maximum allowable income for 1: $321 + nj_wfnj_maximum_allowable_income: 321 + # Unearned income: $2,640/12 = $220/month + nj_wfnj_countable_gross_unearned_income: 220 + # Income $220 <= $321, but $220 >= $214 max benefit + # Income eligibility requires: income < max benefit + nj_wfnj_income_eligible: false + nj_wfnj_eligible: false + # Ineligible, so benefit = 0 + nj_wfnj: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml index a8bb2dde124..f38a792e85d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml @@ -1,32 +1,47 @@ # NOTE: The earned income disregard is based on months of employment, not calendar # months. PolicyEngine cannot track employment duration, so we use calendar months -# as a proxy. January = 100% disregard, Feb-Jul = 75%, Aug-Dec = 50%. -# Only January (2024-01) can be tested due to PolicyEngine's period format restrictions. +# as a proxy: +# - January (month 1): 100% disregard (first_month_percent = 1.0) +# - February-July (months 2-7): 75% disregard (consecutive_month_percent = 0.75) +# - August-December (months 8-12): 50% disregard (additional_percent = 0.5) -- name: Case 1, first month of year with 100% disregard. +- name: Case 1, January with 100% disregard. period: 2024-01 input: state_code: NJ - tanf_gross_earned_income: 1_000 + nj_wfnj_gross_earned_income: 1_000 output: # January (month 1): 100% disregard - # 1000 * (1 - 1.0) = 0 + # 1_000 * (1 - 1.0) = 0 nj_wfnj_countable_earned_income_person: 0 - name: Case 2, zero income. period: 2024-01 input: state_code: NJ - tanf_gross_earned_income: 0 + nj_wfnj_gross_earned_income: 0 output: nj_wfnj_countable_earned_income_person: 0 -- name: Case 3, high income with full disregard. +- name: Case 3, high income with full disregard in January. period: 2024-01 input: state_code: NJ - tanf_gross_earned_income: 5_000 + nj_wfnj_gross_earned_income: 5_000 output: # January: 100% disregard - # 5000 * (1 - 1.0) = 0 + # 5_000 * (1 - 1.0) = 0 nj_wfnj_countable_earned_income_person: 0 + +- name: Case 4, full year aggregation showing tiered disregards. + period: 2024 + input: + state_code: NJ + employment_income_before_lsr: 12_000 # $1,000/month + output: + # Annual countable income aggregated across 12 months: + # - January (month 1): $1,000 * 0% = $0 (100% disregard) + # - Feb-Jul (months 2-7): $1,000 * 25% * 6 = $1,500 (75% disregard) + # - Aug-Dec (months 8-12): $1,000 * 50% * 5 = $2,500 (50% disregard) + # Total: $0 + $1,500 + $2,500 = $4,000 + nj_wfnj_countable_earned_income_person: 4_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.yaml new file mode 100644 index 00000000000..4c7762b2b87 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.yaml @@ -0,0 +1,142 @@ +# Tests for NJ WFNJ eligibility determination. +# Eligibility requires all of: +# 1. Income eligible (income <= max allowable AND income < max benefit) +# 2. Resources eligible (resources <= $2,000) +# 3. Demographic eligible (has eligible child/parent per federal TANF rules) +# 4. At least one citizen or legal immigrant in household + +- name: Case 1, all conditions met - eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + is_citizen_or_legal_immigrant: true + person2: + age: 5 + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_size: 2 + spm_unit_assets: 1_000 + is_demographic_tanf_eligible: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Income eligible: $0 income <= $638 max allowable AND $0 < $425 max benefit + nj_wfnj_income_eligible: true + # Resources eligible: $1,000 <= $2,000 limit + nj_wfnj_resources_eligible: true + # All conditions met + nj_wfnj_eligible: true + +- name: Case 2, income ineligible - not eligible. + period: 2024-01 + input: + people: + person1: + age: 35 + is_citizen_or_legal_immigrant: true + social_security: 12_000 # $1,000/month + person2: + age: 4 + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_size: 2 + spm_unit_assets: 500 + is_demographic_tanf_eligible: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Unearned income: $12,000/12 = $1,000/month + # Max allowable for 2 people: $638 + # $1,000 > $638, so income ineligible + nj_wfnj_income_eligible: false + nj_wfnj_resources_eligible: true + nj_wfnj_eligible: false + +- name: Case 3, resources ineligible - not eligible. + period: 2024-01 + input: + people: + person1: + age: 28 + is_citizen_or_legal_immigrant: true + person2: + age: 6 + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_size: 2 + spm_unit_assets: 3_000 + is_demographic_tanf_eligible: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + # No income, so income eligible + nj_wfnj_income_eligible: true + # Resources: $3,000 > $2,000 limit + nj_wfnj_resources_eligible: false + nj_wfnj_eligible: false + +- name: Case 4, demographic ineligible - not eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + is_citizen_or_legal_immigrant: true + person2: + age: 40 + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_size: 2 + spm_unit_assets: 1_000 + is_demographic_tanf_eligible: false + households: + household: + members: [person1, person2] + state_code: NJ + output: + nj_wfnj_income_eligible: true + nj_wfnj_resources_eligible: true + # Demographic ineligible (no eligible child) + nj_wfnj_eligible: false + +- name: Case 5, no citizen or legal immigrant - not eligible. + period: 2024-01 + input: + people: + person1: + age: 32 + is_citizen_or_legal_immigrant: false + person2: + age: 7 + is_citizen_or_legal_immigrant: false + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_size: 2 + spm_unit_assets: 1_000 + is_demographic_tanf_eligible: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + nj_wfnj_income_eligible: true + nj_wfnj_resources_eligible: true + # No citizen or legal immigrant in household + nj_wfnj_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml index 9532bb72bec..adc0d729016 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml @@ -2,7 +2,7 @@ period: 2024-01 input: state_code: NJ - nj_wfnj_countable_resources: 2_000 + spm_unit_assets: 2_000 output: nj_wfnj_resources_eligible: true @@ -10,7 +10,7 @@ period: 2024-01 input: state_code: NJ - nj_wfnj_countable_resources: 4_000 + spm_unit_assets: 4_000 output: nj_wfnj_resources_eligible: false @@ -18,6 +18,6 @@ period: 2024-01 input: state_code: NJ - nj_wfnj_countable_resources: 0 + spm_unit_assets: 0 output: nj_wfnj_resources_eligible: true diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py index 51311d402a5..6e020703e3c 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py @@ -16,7 +16,7 @@ def formula(person, period, parameters): p = parameters( period ).gov.states.nj.njdhs.wfnj.income.earned_income_deduction - gross_earned = person("tanf_gross_earned_income", period) + gross_earned = person("nj_wfnj_gross_earned_income", period) month = period.start.month # Calendar month proxy for enrollment months (assuming ≥20 hrs/week). diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py index 2facc3a3bf9..241fb9ab2e1 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py @@ -3,7 +3,7 @@ class nj_wfnj_gross_earned_income(Variable): value_type = float - entity = SPMUnit + entity = Person label = "New Jersey WFNJ gross earned income" unit = USD definition_period = MONTH diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_resources.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_resources.py deleted file mode 100644 index 27f8529885a..00000000000 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_resources.py +++ /dev/null @@ -1,14 +0,0 @@ -from policyengine_us.model_api import * - - -class nj_wfnj_countable_resources(Variable): - value_type = float - entity = SPMUnit - label = "New Jersey WFNJ countable resources" - unit = USD - definition_period = YEAR - defined_for = StateCode.NJ - reference = ( - "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-20" - ) - adds = ["spm_unit_assets"] diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.py index 635e4f42886..aae69a1824a 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.py @@ -15,9 +15,7 @@ class nj_wfnj_eligible(Variable): def formula(spm_unit, period, parameters): income_eligible = spm_unit("nj_wfnj_income_eligible", period) resources_eligible = spm_unit("nj_wfnj_resources_eligible", period) - demographic_eligible = spm_unit( - "is_demographic_tanf_eligible", period - ) + demographic_eligible = spm_unit("is_demographic_tanf_eligible", period) has_citizen_or_legal_immigrant = ( add(spm_unit, period, ["is_citizen_or_legal_immigrant"]) > 0 ) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py index 8760c2ca6c3..b1acf49c51b 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py @@ -13,7 +13,5 @@ class nj_wfnj_resources_eligible(Variable): def formula(spm_unit, period, parameters): p = parameters(period).gov.states.nj.njdhs.wfnj.eligibility.resources - countable_resources = spm_unit( - "nj_wfnj_countable_resources", period.this_year - ) - return countable_resources <= p.limit + resources = spm_unit("spm_unit_assets", period.this_year) + return resources <= p.limit From 424354fb9a30f876d4768505904c76f641f81565 Mon Sep 17 00:00:00 2001 From: Ziming Date: Tue, 6 Jan 2026 23:56:57 -0500 Subject: [PATCH 5/9] pr fix --- .../wfnj/eligibility/resources/limit.yaml | 2 +- .../states/nj/njdhs/wfnj/income/earned.yaml | 4 ++-- .../higher_work_hours/additional_percent.yaml | 12 ---------- .../consecutive_month_percent.yaml | 12 ---------- .../first_month_percent.yaml | 12 ---------- .../wfnj/income/earned_income_disregard.yaml | 24 +++++++++++++++++++ .../states/nj/njdhs/wfnj/income/unearned.yaml | 4 ++-- .../nj/njdhs/wfnj/max_household_size.yaml | 2 +- .../maximum_allowable_income/additional.yaml | 2 +- .../wfnj/maximum_allowable_income/main.yaml | 2 +- .../wfnj/maximum_benefit/additional.yaml | 2 +- .../nj/njdhs/wfnj/maximum_benefit/main.yaml | 2 +- .../gov/states/nj/njdhs/wfnj/integration.yaml | 2 +- ...j_wfnj_countable_earned_income_person.yaml | 8 +++---- .../nj_wfnj_countable_earned_income_person.py | 19 +++------------ .../wfnj/income/nj_wfnj_countable_income.py | 19 +++++++++++++++ .../gov/states/nj/njdhs/wfnj/nj_wfnj.py | 10 +------- .../nj/njdhs/wfnj/nj_wfnj_income_eligible.py | 18 +++++++------- 18 files changed, 71 insertions(+), 85 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/additional_percent.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_disregard.yaml create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_income.py diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml index a66c54658f6..4a519a957e2 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml @@ -5,7 +5,7 @@ metadata: period: eternity label: New Jersey WFNJ resource limit reference: - - title: N.J.A.C. 10:90-3.20 + - title: N.J.A.C. 10:90-3.20(a) - Basic resource exemption href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-20 values: diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml index 0e13ec190da..d5c80e7bbb5 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml @@ -1,11 +1,11 @@ -description: New Jersey counts these income sources as earned income under the WorkFirst New Jersey program. +description: New Jersey uses these income sources as earned income under the WorkFirst New Jersey program. metadata: unit: list period: month label: New Jersey WFNJ earned income sources reference: - - title: N.J.A.C. 10:90-3.9 + - title: N.J.A.C. 10:90-3.9(a) - Definition of earned income href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-9 values: diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/additional_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/additional_percent.yaml deleted file mode 100644 index 598a94a325e..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/additional_percent.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: New Jersey excludes this share of earned income under the WorkFirst New Jersey program. - -metadata: - unit: /1 - period: month - label: New Jersey WFNJ additional month earned income disregard rate (20+ hours) - reference: - - title: N.J.A.C. 10:90-3.8 - href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8 - -values: - 2022-10-01: 0.5 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml deleted file mode 100644 index e1ba76a156f..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/consecutive_month_percent.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: New Jersey excludes this share of earned income under the WorkFirst New Jersey program. - -metadata: - unit: /1 - period: month - label: New Jersey WFNJ consecutive month earned income disregard rate (20+ hours) - reference: - - title: N.J.A.C. 10:90-3.8 - href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8 - -values: - 2022-10-01: 0.75 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml deleted file mode 100644 index 74bb76cb825..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_deduction/higher_work_hours/first_month_percent.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: New Jersey excludes this share of earned income under the WorkFirst New Jersey program. - -metadata: - unit: /1 - period: month - label: New Jersey WFNJ first month earned income disregard rate (20+ hours) - reference: - - title: N.J.A.C. 10:90-3.8 - href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8 - -values: - 2022-10-01: 1.0 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_disregard.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_disregard.yaml new file mode 100644 index 00000000000..3ab9f695c4c --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_disregard.yaml @@ -0,0 +1,24 @@ +description: New Jersey excludes this share of earned income based on months of employment under the WorkFirst New Jersey program. + +brackets: + - threshold: + 2022-10-01: 1 + amount: + 2022-10-01: 1 # 100% disregard for first month + - threshold: + 2022-10-01: 2 + amount: + 2022-10-01: 0.75 # 75% disregard for months 2-7 + - threshold: + 2022-10-01: 8 + amount: + 2022-10-01: 0.5 # 50% disregard for month 8+ + +metadata: + type: single_amount + threshold_unit: month + amount_unit: /1 + label: New Jersey WFNJ earned income disregard rate by month (20+ hours/week) + reference: + - title: N.J.A.C. 10:90-3.8(c) - Tiered earned income disregards + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml index 0c467e40dfb..3a9adae9219 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml @@ -1,11 +1,11 @@ -description: New Jersey counts these income sources as unearned income under the WorkFirst New Jersey program. +description: New Jersey uses these income sources as unearned income under the WorkFirst New Jersey program. metadata: unit: list period: month label: New Jersey WFNJ unearned income sources reference: - - title: N.J.A.C. 10:90-3.9 + - title: N.J.A.C. 10:90-3.9(b) - Definition of unearned income href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-9 values: diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/max_household_size.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/max_household_size.yaml index 010e5c20983..e98a54fff64 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/max_household_size.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/max_household_size.yaml @@ -5,7 +5,7 @@ metadata: period: year label: New Jersey WFNJ maximum household size for tables reference: - - title: N.J.A.C. 10:90-3.3 + - title: N.J.A.C. 10:90-3.3(a) - Maximum table size (8 persons) href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 values: diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml index df9c319a386..04944dfe898 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml @@ -5,7 +5,7 @@ metadata: period: month label: New Jersey WFNJ monthly income limit per additional person reference: - - title: N.J.A.C. 10:90-3.3 + - title: N.J.A.C. 10:90-3.3(a)(1) Schedule I - Each Additional Person href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 values: diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml index 470102fe726..8df25980e93 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml @@ -7,7 +7,7 @@ metadata: - range(1, 9) label: New Jersey WFNJ monthly maximum allowable income reference: - - title: N.J.A.C. 10:90-3.3 + - title: N.J.A.C. 10:90-3.3(a)(1) Schedule I - Maximum Allowable Income Levels href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 1: diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml index abc7bee5997..afa1516dd30 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml @@ -5,7 +5,7 @@ metadata: period: month label: New Jersey WFNJ monthly maximum benefit per additional person reference: - - title: N.J.A.C. 10:90-3.3 + - title: N.J.A.C. 10:90-3.3(a)(2) Schedule II - Each Additional Person href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 values: diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml index 0eace0da708..25fa765b33e 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml @@ -7,7 +7,7 @@ metadata: - range(1, 9) label: New Jersey WFNJ monthly maximum benefit reference: - - title: N.J.A.C. 10:90-3.3 + - title: N.J.A.C. 10:90-3.3(a)(2) Schedule II - Maximum Benefit Payment Levels href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 1: diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml index 05e54555e65..e08bb873723 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml @@ -42,7 +42,7 @@ person1: age: 35 is_citizen_or_legal_immigrant: true - employment_income_before_lsr: 2_400 # $200/month annual + employment_income_before_lsr: 2_400 # $2,400/year = $200/month person2: age: 32 is_citizen_or_legal_immigrant: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml index f38a792e85d..1d5abd2f280 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml @@ -1,9 +1,9 @@ # NOTE: The earned income disregard is based on months of employment, not calendar # months. PolicyEngine cannot track employment duration, so we use calendar months -# as a proxy: -# - January (month 1): 100% disregard (first_month_percent = 1.0) -# - February-July (months 2-7): 75% disregard (consecutive_month_percent = 0.75) -# - August-December (months 8-12): 50% disregard (additional_percent = 0.5) +# as a proxy. The tiered disregards are defined in a bracket parameter: +# - January (month 1): 100% disregard +# - February-July (months 2-7): 75% disregard +# - August-December (months 8-12): 50% disregard - name: Case 1, January with 100% disregard. period: 2024-01 diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py index 6e020703e3c..f0475086b4e 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py @@ -13,9 +13,7 @@ class nj_wfnj_countable_earned_income_person(Variable): ) def formula(person, period, parameters): - p = parameters( - period - ).gov.states.nj.njdhs.wfnj.income.earned_income_deduction + p = parameters(period).gov.states.nj.njdhs.wfnj.income gross_earned = person("nj_wfnj_gross_earned_income", period) month = period.start.month @@ -26,16 +24,5 @@ def formula(person, period, parameters): # - January (month 1): 100% disregard # - February-July (months 2-7): 75% disregard # - August-December (months 8-12): 50% disregard - first_month = month == 1 - consecutive_months = (month >= 2) & (month <= 7) - - return select( - [first_month, consecutive_months], - [ - gross_earned * (1 - p.higher_work_hours.first_month_percent), - gross_earned - * (1 - p.higher_work_hours.consecutive_month_percent), - ], - default=gross_earned - * (1 - p.higher_work_hours.additional_percent), - ) + disregard_rate = p.earned_income_disregard.calc(month) + return gross_earned * (1 - disregard_rate) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_income.py new file mode 100644 index 00000000000..2549eff5fa6 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_income.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class nj_wfnj_countable_income(Variable): + value_type = float + entity = SPMUnit + label = "New Jersey WFNJ countable income" + unit = USD + definition_period = MONTH + defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3", + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8", + ) + + adds = [ + "nj_wfnj_countable_earned_income", + "nj_wfnj_countable_gross_unearned_income", + ] diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj.py index dd9d337ba48..5e946a79a93 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj.py @@ -15,14 +15,6 @@ class nj_wfnj(Variable): def formula(spm_unit, period, parameters): eligible = spm_unit("nj_wfnj_eligible", period) maximum_benefit = spm_unit("nj_wfnj_maximum_benefit", period) - countable_income = add( - spm_unit, - period, - [ - "nj_wfnj_countable_earned_income", - "nj_wfnj_countable_gross_unearned_income", - ], - ) - # Benefit = maximum benefit - countable income + countable_income = spm_unit("nj_wfnj_countable_income", period) benefit = max_(maximum_benefit - countable_income, 0) return where(eligible, benefit, 0) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py index 59be4744fbc..e46d0a274d2 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py @@ -8,18 +8,18 @@ class nj_wfnj_income_eligible(Variable): definition_period = MONTH defined_for = StateCode.NJ reference = ( - "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-1" + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-1", + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3", ) + # NOTE: Per N.J.A.C. 10:90-3.8, initial applicants should be tested against + # gross income without disregards. PolicyEngine cannot distinguish initial + # vs ongoing recipients, so this applies the ongoing eligibility test to all. + # The implementation also combines the initial test (income <= max allowable) + # with the ongoing test (income < max benefit), which is more restrictive + # than applying only the initial test for new applicants. def formula(spm_unit, period, parameters): - income = add( - spm_unit, - period, - [ - "nj_wfnj_countable_earned_income", - "nj_wfnj_countable_gross_unearned_income", - ], - ) + income = spm_unit("nj_wfnj_countable_income", period) maximum_allowable_income = spm_unit( "nj_wfnj_maximum_allowable_income", period ) From c0c804dc0a5b7f804f3ddd49ed2714e985e4dc0a Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 7 Jan 2026 16:59:09 -0500 Subject: [PATCH 6/9] adjustments --- .../wfnj/eligibility/resources/limit.yaml | 12 --- .../states/nj/njdhs/wfnj/income/earned.yaml | 14 --- .../wfnj/income/earned_income_disregard.yaml | 14 +-- .../states/nj/njdhs/wfnj/income/limit.yaml | 14 +++ .../states/nj/njdhs/wfnj/income/unearned.yaml | 22 ----- .../nj/njdhs/wfnj/max_household_size.yaml | 4 +- .../maximum_allowable_income/additional.yaml | 12 --- .../wfnj/maximum_allowable_income/main.yaml | 28 ------ .../nj/njdhs/wfnj/maximum_benefit/main.yaml | 28 ------ .../additional_person.yaml} | 6 +- .../nj/njdhs/wfnj/payment_levels/amount.yaml | 46 ++++++++++ .../states/nj/njdhs/wfnj/resources/limit.yaml | 14 +++ .../gov/states/nj/njdhs/wfnj/integration.yaml | 46 ++++------ .../gov/states/nj/njdhs/wfnj/nj_wfnj.yaml | 90 +++++++++++++++--- ...j_wfnj_countable_earned_income_person.yaml | 6 +- ..._wfnj_countable_gross_unearned_income.yaml | 43 --------- .../nj/njdhs/wfnj/nj_wfnj_eligible.yaml | 26 ++++++ .../wfnj/nj_wfnj_gross_income_eligible.yaml | 38 ++++++++ .../njdhs/wfnj/nj_wfnj_income_eligible.yaml | 91 +++++++++++++------ .../nj_wfnj_maximum_allowable_income.yaml | 40 -------- .../njdhs/wfnj/nj_wfnj_maximum_benefit.yaml | 40 -------- .../nj/njdhs/wfnj/nj_wfnj_payment_levels.yaml | 84 +++++++++++++++++ .../wfnj/nj_wfnj_resources_eligible.yaml | 2 +- .../{ => eligibility}/nj_wfnj_eligible.py | 0 .../nj_wfnj_gross_income_eligible.py | 19 ++++ .../eligibility/nj_wfnj_income_eligible.py | 30 ++++++ .../nj_wfnj_resources_eligible.py | 2 +- .../nj_wfnj_countable_earned_income_person.py | 5 +- ...nj_wfnj_countable_gross_unearned_income.py | 14 --- .../wfnj/income/nj_wfnj_countable_income.py | 4 +- .../income/nj_wfnj_gross_earned_income.py | 14 --- ...rned_income.py => nj_wfnj_gross_income.py} | 12 ++- .../gov/states/nj/njdhs/wfnj/nj_wfnj.py | 8 +- .../nj/njdhs/wfnj/nj_wfnj_income_eligible.py | 29 ------ .../wfnj/nj_wfnj_maximum_allowable_income.py | 22 ----- .../nj/njdhs/wfnj/nj_wfnj_maximum_benefit.py | 22 ----- .../nj/njdhs/wfnj/nj_wfnj_payment_levels.py | 22 +++++ 37 files changed, 483 insertions(+), 440 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/limit.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml delete mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml rename policyengine_us/parameters/gov/states/nj/njdhs/wfnj/{maximum_benefit/additional.yaml => payment_levels/additional_person.yaml} (56%) create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/payment_levels/amount.yaml create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/resources/limit.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_gross_unearned_income.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_gross_income_eligible.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.yaml delete mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_payment_levels.yaml rename policyengine_us/variables/gov/states/nj/njdhs/wfnj/{ => eligibility}/nj_wfnj_eligible.py (100%) create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/eligibility/nj_wfnj_gross_income_eligible.py create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/eligibility/nj_wfnj_income_eligible.py rename policyengine_us/variables/gov/states/nj/njdhs/wfnj/{ => eligibility}/nj_wfnj_resources_eligible.py (86%) delete mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_gross_unearned_income.py delete mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py rename policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/{nj_wfnj_countable_earned_income.py => nj_wfnj_gross_income.py} (56%) delete mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py delete mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.py delete mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.py create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_payment_levels.py diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml deleted file mode 100644 index 4a519a957e2..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/eligibility/resources/limit.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: New Jersey limits resources to this amount under the WorkFirst New Jersey program. - -metadata: - unit: currency-USD - period: eternity - label: New Jersey WFNJ resource limit - reference: - - title: N.J.A.C. 10:90-3.20(a) - Basic resource exemption - href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-20 - -values: - 2023-01-01: 2_000 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml deleted file mode 100644 index d5c80e7bbb5..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned.yaml +++ /dev/null @@ -1,14 +0,0 @@ -description: New Jersey uses these income sources as earned income under the WorkFirst New Jersey program. - -metadata: - unit: list - period: month - label: New Jersey WFNJ earned income sources - reference: - - title: N.J.A.C. 10:90-3.9(a) - Definition of earned income - href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-9 - -values: - 2023-03-22: - - employment_income_before_lsr - - self_employment_income_before_lsr diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_disregard.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_disregard.yaml index 3ab9f695c4c..329c7465a99 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_disregard.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/earned_income_disregard.yaml @@ -2,17 +2,17 @@ description: New Jersey excludes this share of earned income based on months of brackets: - threshold: - 2022-10-01: 1 + 2015-01-01: 1 amount: - 2022-10-01: 1 # 100% disregard for first month + 2015-01-01: 1 # 100% disregard for first month - threshold: - 2022-10-01: 2 + 2015-01-01: 2 amount: - 2022-10-01: 0.75 # 75% disregard for months 2-7 + 2015-01-01: 0.75 # 75% disregard for months 2-7 - threshold: - 2022-10-01: 8 + 2015-01-01: 8 amount: - 2022-10-01: 0.5 # 50% disregard for month 8+ + 2015-01-01: 0.5 # 50% disregard for month 8+ metadata: type: single_amount @@ -22,3 +22,5 @@ metadata: reference: - title: N.J.A.C. 10:90-3.8(c) - Tiered earned income disregards href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8 + - title: New Jersey State Plan for TANF FFY 2024-2026 + href: https://www.nj.gov/humanservices/providers/grants/public/publicnoticefiles/Draft%20New%20Jersey%20State%20Plan%20for%20Temporary%20Assistance%20for%20Needy%20Families%20(TANF)%20FFY%202024%20-%20FFY%202026.pdf#page=22 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/limit.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/limit.yaml new file mode 100644 index 00000000000..4e53d7e832c --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/limit.yaml @@ -0,0 +1,14 @@ +description: New Jersey sets the maximum allowable income as this multiple of the maximum benefit under the WorkFirst New Jersey program. + +metadata: + unit: /1 + period: month + label: New Jersey WFNJ maximum allowable income rate + reference: + - title: N.J.A.C. 10:90-3.2 (a) + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-2 + - title: New Jersey State Plan for TANF FFY 2024-2026 + href: https://www.nj.gov/humanservices/providers/grants/public/publicnoticefiles/Draft%20New%20Jersey%20State%20Plan%20for%20Temporary%20Assistance%20for%20Needy%20Families%20(TANF)%20FFY%202024%20-%20FFY%202026.pdf#page=22 + +values: + 2015-01-01: 1.5 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml deleted file mode 100644 index 3a9adae9219..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/unearned.yaml +++ /dev/null @@ -1,22 +0,0 @@ -description: New Jersey uses these income sources as unearned income under the WorkFirst New Jersey program. - -metadata: - unit: list - period: month - label: New Jersey WFNJ unearned income sources - reference: - - title: N.J.A.C. 10:90-3.9(b) - Definition of unearned income - href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-9 - -values: - 2021-01-01: - - veterans_benefits - - rental_income - - alimony_income - - dividend_income - - interest_income - - pension_income - - unemployment_compensation - - gi_cash_assistance - - social_security - - child_support_received diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/max_household_size.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/max_household_size.yaml index e98a54fff64..717b43e3879 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/max_household_size.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/max_household_size.yaml @@ -7,6 +7,8 @@ metadata: reference: - title: N.J.A.C. 10:90-3.3(a) - Maximum table size (8 persons) href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 + - title: New Jersey State Plan for TANF FFY 2024-2026 + href: https://www.nj.gov/humanservices/providers/grants/public/publicnoticefiles/Draft%20New%20Jersey%20State%20Plan%20for%20Temporary%20Assistance%20for%20Needy%20Families%20(TANF)%20FFY%202024%20-%20FFY%202026.pdf#page=64 values: - 2023-01-01: 8 + 2015-01-01: 8 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml deleted file mode 100644 index 04944dfe898..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/additional.yaml +++ /dev/null @@ -1,12 +0,0 @@ -description: New Jersey provides this additional income limit per person beyond the base household size under the WorkFirst New Jersey program. - -metadata: - unit: currency-USD - period: month - label: New Jersey WFNJ monthly income limit per additional person - reference: - - title: N.J.A.C. 10:90-3.3(a)(1) Schedule I - Each Additional Person - href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 - -values: - 2023-01-01: 99 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml deleted file mode 100644 index 8df25980e93..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_allowable_income/main.yaml +++ /dev/null @@ -1,28 +0,0 @@ -description: New Jersey limits gross income to this amount under the WorkFirst New Jersey program. - -metadata: - unit: currency-USD - period: month - breakdown: - - range(1, 9) - label: New Jersey WFNJ monthly maximum allowable income - reference: - - title: N.J.A.C. 10:90-3.3(a)(1) Schedule I - Maximum Allowable Income Levels - href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 - -1: - 2023-01-01: 321 -2: - 2023-01-01: 638 -3: - 2023-01-01: 839 -4: - 2023-01-01: 966 -5: - 2023-01-01: 1_092 -6: - 2023-01-01: 1_221 -7: - 2023-01-01: 1_341 -8: - 2023-01-01: 1_442 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml deleted file mode 100644 index 25fa765b33e..00000000000 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/main.yaml +++ /dev/null @@ -1,28 +0,0 @@ -description: New Jersey provides this amount as the maximum benefit under the WorkFirst New Jersey program. - -metadata: - unit: currency-USD - period: month - breakdown: - - range(1, 9) - label: New Jersey WFNJ monthly maximum benefit - reference: - - title: N.J.A.C. 10:90-3.3(a)(2) Schedule II - Maximum Benefit Payment Levels - href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 - -1: - 2023-01-01: 214 -2: - 2023-01-01: 425 -3: - 2023-01-01: 559 -4: - 2023-01-01: 644 -5: - 2023-01-01: 728 -6: - 2023-01-01: 814 -7: - 2023-01-01: 894 -8: - 2023-01-01: 961 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/payment_levels/additional_person.yaml similarity index 56% rename from policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml rename to policyengine_us/parameters/gov/states/nj/njdhs/wfnj/payment_levels/additional_person.yaml index afa1516dd30..3f16eb6c278 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/maximum_benefit/additional.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/payment_levels/additional_person.yaml @@ -7,6 +7,10 @@ metadata: reference: - title: N.J.A.C. 10:90-3.3(a)(2) Schedule II - Each Additional Person href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 + - title: New Jersey State Plan for TANF FFY 2024-2026 + href: https://www.nj.gov/humanservices/providers/grants/public/publicnoticefiles/Draft%20New%20Jersey%20State%20Plan%20for%20Temporary%20Assistance%20for%20Needy%20Families%20(TANF)%20FFY%202024%20-%20FFY%202026.pdf#page=64 values: - 2023-01-01: 66 + 2015-01-01: 50 + 2018-07-01: 55 + 2019-08-01: 66 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/payment_levels/amount.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/payment_levels/amount.yaml new file mode 100644 index 00000000000..f51c0ff3fdd --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/payment_levels/amount.yaml @@ -0,0 +1,46 @@ +description: New Jersey provides this amount as the maximum benefit under the WorkFirst New Jersey program. + +metadata: + unit: currency-USD + period: month + breakdown: + - range(1, 9) # size + label: New Jersey WFNJ monthly maximum benefit + reference: + - title: N.J.A.C. 10:90-3.3(b) Schedule II - Maximum Benefit Payment Levels + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3 + - title: New Jersey State Plan for TANF FFY 2024-2026 + href: https://www.nj.gov/humanservices/providers/grants/public/publicnoticefiles/Draft%20New%20Jersey%20State%20Plan%20for%20Temporary%20Assistance%20for%20Needy%20Families%20(TANF)%20FFY%202024%20-%20FFY%202026.pdf#page=64 + +1: + 2015-01-01: 162 + 2018-07-01: 178 + 2019-08-01: 214 +2: + 2015-01-01: 322 + 2018-07-01: 354 + 2019-08-01: 425 +3: + 2015-01-01: 424 + 2018-07-01: 466 + 2019-08-01: 559 +4: + 2015-01-01: 488 + 2018-07-01: 537 + 2019-08-01: 644 +5: + 2015-01-01: 552 + 2018-07-01: 607 + 2019-08-01: 728 +6: + 2015-01-01: 616 + 2018-07-01: 678 + 2019-08-01: 814 +7: + 2015-01-01: 677 + 2018-07-01: 745 + 2019-08-01: 894 +8: + 2015-01-01: 728 + 2018-07-01: 801 + 2019-08-01: 961 diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/resources/limit.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/resources/limit.yaml new file mode 100644 index 00000000000..9dbf08d9df2 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/resources/limit.yaml @@ -0,0 +1,14 @@ +description: New Jersey limits resources to this amount under the WorkFirst New Jersey program. + +metadata: + unit: currency-USD + period: eternity + label: New Jersey WFNJ resource limit + reference: + - title: N.J.A.C. 10:90-3.20(a)(3) - Basic resource exemption + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-20 + - title: New Jersey State Plan for TANF FFY 2024-2026 + href: https://www.nj.gov/humanservices/providers/grants/public/publicnoticefiles/Draft%20New%20Jersey%20State%20Plan%20for%20Temporary%20Assistance%20for%20Needy%20Families%20(TANF)%20FFY%202024%20-%20FFY%202026.pdf#page=21 + +values: + 2015-01-01: 2_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml index e08bb873723..d3bf5b7ed5c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/integration.yaml @@ -20,15 +20,12 @@ state_code: NJ output: # Maximum benefit for 2 people: $425/month - nj_wfnj_maximum_benefit: 425 - # Maximum allowable income for 2 people: $638/month - nj_wfnj_maximum_allowable_income: 638 + nj_wfnj_payment_levels: 425 + # Gross income eligible: $0 <= $638 + nj_wfnj_gross_income_eligible: true # Resources eligible: $1,000 <= $2,000 nj_wfnj_resources_eligible: true - # No income - nj_wfnj_countable_earned_income: 0 - nj_wfnj_countable_gross_unearned_income: 0 - # Income eligible: 0 <= 638 and 0 < 425 + # Income eligible: gross income $0 <= $638 max allowable nj_wfnj_income_eligible: true # Overall eligible nj_wfnj_eligible: true @@ -61,15 +58,12 @@ state_code: NJ output: # Maximum benefit for 3 people: $559/month - nj_wfnj_maximum_benefit: 559 - # Maximum allowable income for 3 people: $839/month - nj_wfnj_maximum_allowable_income: 839 + nj_wfnj_payment_levels: 559 + # Gross income eligible: $200 <= $839 + nj_wfnj_gross_income_eligible: true # January = 100% disregard, so countable earned = 0 nj_wfnj_countable_earned_income_person: [0, 0, 0] - nj_wfnj_countable_earned_income: 0 - # No unearned income - nj_wfnj_countable_gross_unearned_income: 0 - # Income eligible: 0 <= 839 and 0 < 559 + # Income eligible: gross income $200 <= $839 max allowable nj_wfnj_income_eligible: true # Resources eligible: $500 <= $2,000 nj_wfnj_resources_eligible: true @@ -107,7 +101,7 @@ nj_wfnj_eligible: false nj_wfnj: 0 -- name: Case 4, ineligible due to high income. +- name: Case 4, ineligible due to high income (new applicant). period: 2024-01 input: people: @@ -129,18 +123,16 @@ members: [person1, person2] state_code: NJ output: - # Max benefit for 2: $425, max allowable income: $638 - nj_wfnj_maximum_benefit: 425 - nj_wfnj_maximum_allowable_income: 638 - # Unearned: $12,000/12 = $1,000/month - nj_wfnj_countable_gross_unearned_income: 1_000 - # Income: $1,000 > $638 max allowable + # Max benefit for 2: $425 + nj_wfnj_payment_levels: 425 + # Gross income: $1,000/month > $638 max allowable + nj_wfnj_gross_income_eligible: false nj_wfnj_income_eligible: false nj_wfnj_resources_eligible: true nj_wfnj_eligible: false nj_wfnj: 0 -- name: Case 5, eligible with unearned income reducing benefit. +- name: Case 5, enrolled with unearned income reducing benefit. period: 2024-01 input: people: @@ -154,17 +146,15 @@ spm_unit_size: 1 spm_unit_assets: 500 is_demographic_tanf_eligible: true + is_tanf_enrolled: true # Enrolled - uses countable income test households: household: members: [person1] state_code: NJ output: - # Max benefit for 1: $214, max allowable income: $321 - nj_wfnj_maximum_benefit: 214 - nj_wfnj_maximum_allowable_income: 321 - # Unearned: $2,400/12 = $200/month - nj_wfnj_countable_gross_unearned_income: 200 - # Income: $200 <= $321 and $200 < $214 + # Max benefit for 1: $214 + nj_wfnj_payment_levels: 214 + # Enrolled: countable income $200 < $214 max benefit nj_wfnj_income_eligible: true nj_wfnj_resources_eligible: true nj_wfnj_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj.yaml index 444785a6095..3be7857326c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj.yaml @@ -25,10 +25,7 @@ output: nj_wfnj_eligible: true # Maximum benefit for 2 people: $425 - nj_wfnj_maximum_benefit: 425 - # Countable income: $0 - nj_wfnj_countable_earned_income: 0 - nj_wfnj_countable_gross_unearned_income: 0 + nj_wfnj_payment_levels: 425 # Benefit = $425 - $0 = $425 nj_wfnj: 425 @@ -46,6 +43,7 @@ spm_unit_size: 1 spm_unit_assets: 500 is_demographic_tanf_eligible: true + is_tanf_enrolled: true # Enrolled for ongoing test households: household: members: [person1] @@ -53,9 +51,7 @@ output: nj_wfnj_eligible: true # Maximum benefit for 1 person: $214 - nj_wfnj_maximum_benefit: 214 - # Unearned income: $1,200/12 = $100/month - nj_wfnj_countable_gross_unearned_income: 100 + nj_wfnj_payment_levels: 214 # Benefit = $214 - $100 = $114 nj_wfnj: 114 @@ -86,7 +82,7 @@ nj_wfnj_eligible: false nj_wfnj: 0 -- name: Case 4, income exceeds max benefit - clipped to zero. +- name: Case 4, enrolled but income exceeds max benefit - clipped to zero. period: 2024-01 input: people: @@ -100,20 +96,84 @@ spm_unit_size: 1 spm_unit_assets: 500 is_demographic_tanf_eligible: true + is_tanf_enrolled: true # Enrolled - uses countable income test households: household: members: [person1] state_code: NJ output: # Maximum benefit for 1: $214 - nj_wfnj_maximum_benefit: 214 - # Maximum allowable income for 1: $321 - nj_wfnj_maximum_allowable_income: 321 - # Unearned income: $2,640/12 = $220/month - nj_wfnj_countable_gross_unearned_income: 220 - # Income $220 <= $321, but $220 >= $214 max benefit - # Income eligibility requires: income < max benefit + nj_wfnj_payment_levels: 214 + # Enrolled: countable income $220 >= $214 max benefit nj_wfnj_income_eligible: false nj_wfnj_eligible: false # Ineligible, so benefit = 0 nj_wfnj: 0 + +- name: Case 5, minimum benefit of $1. + period: 2024-01 + input: + people: + person1: + age: 30 + is_citizen_or_legal_immigrant: true + social_security: 2_556 # $213/month + spm_units: + spm_unit: + members: [person1] + spm_unit_size: 1 + spm_unit_assets: 500 + is_demographic_tanf_eligible: true + is_tanf_enrolled: true + households: + household: + members: [person1] + state_code: NJ + output: + nj_wfnj_eligible: true + # Benefit = $214 - $213 = $1 + nj_wfnj: 1 + +- name: Case 6, maximum benefit (large household, zero income). + period: 2024-01 + input: + people: + person1: + age: 35 + is_citizen_or_legal_immigrant: true + person2: + age: 32 + is_citizen_or_legal_immigrant: true + person3: + age: 12 + is_citizen_or_legal_immigrant: true + person4: + age: 10 + is_citizen_or_legal_immigrant: true + person5: + age: 8 + is_citizen_or_legal_immigrant: true + person6: + age: 6 + is_citizen_or_legal_immigrant: true + person7: + age: 4 + is_citizen_or_legal_immigrant: true + person8: + age: 2 + is_citizen_or_legal_immigrant: true + spm_units: + spm_unit: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + spm_unit_size: 8 + spm_unit_assets: 1_000 + is_demographic_tanf_eligible: true + households: + household: + members: [person1, person2, person3, person4, person5, person6, person7, person8] + state_code: NJ + output: + nj_wfnj_eligible: true + # Maximum benefit for 8 people: $961 + nj_wfnj_payment_levels: 961 + nj_wfnj: 961 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml index 1d5abd2f280..d130be552dd 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_earned_income_person.yaml @@ -9,7 +9,7 @@ period: 2024-01 input: state_code: NJ - nj_wfnj_gross_earned_income: 1_000 + employment_income_before_lsr: 12_000 # $1,000/month output: # January (month 1): 100% disregard # 1_000 * (1 - 1.0) = 0 @@ -19,7 +19,7 @@ period: 2024-01 input: state_code: NJ - nj_wfnj_gross_earned_income: 0 + employment_income_before_lsr: 0 output: nj_wfnj_countable_earned_income_person: 0 @@ -27,7 +27,7 @@ period: 2024-01 input: state_code: NJ - nj_wfnj_gross_earned_income: 5_000 + employment_income_before_lsr: 60_000 # $5,000/month output: # January: 100% disregard # 5_000 * (1 - 1.0) = 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_gross_unearned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_gross_unearned_income.yaml deleted file mode 100644 index d489a4a9fa7..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_gross_unearned_income.yaml +++ /dev/null @@ -1,43 +0,0 @@ -- name: Case 1, no unearned income. - period: 2024-01 - input: - state_code: NJ - veterans_benefits: 0 - rental_income: 0 - alimony_income: 0 - dividend_income: 0 - interest_income: 0 - pension_income: 0 - unemployment_compensation: 0 - gi_cash_assistance: 0 - social_security: 0 - child_support_received: 0 - output: - nj_wfnj_countable_gross_unearned_income: 0 - -- name: Case 2, various unearned income sources. - period: 2024-01 - input: - state_code: NJ - veterans_benefits: 1_200 - rental_income: 1_200 - alimony_income: 1_200 - dividend_income: 1_200 - interest_income: 1_200 - pension_income: 1_200 - unemployment_compensation: 1_200 - gi_cash_assistance: 1_200 - social_security: 1_200 - child_support_received: 1_200 - output: - # 10 sources * 1200/12 = 10 * 100 = 1000 monthly - nj_wfnj_countable_gross_unearned_income: 1_000 - -- name: Case 3, only social security income. - period: 2024-01 - input: - state_code: NJ - social_security: 12_000 - output: - # 12000/12 = 1000 monthly - nj_wfnj_countable_gross_unearned_income: 1_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.yaml index 4c7762b2b87..a86c2902919 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.yaml @@ -140,3 +140,29 @@ nj_wfnj_resources_eligible: true # No citizen or legal immigrant in household nj_wfnj_eligible: false + +- name: Case 6, mixed citizen and non-citizen household - eligible. + period: 2024-01 + input: + people: + person1: + age: 30 + is_citizen_or_legal_immigrant: false + person2: + age: 5 + is_citizen_or_legal_immigrant: true # At least one citizen + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_size: 2 + spm_unit_assets: 1_000 + is_demographic_tanf_eligible: true + households: + household: + members: [person1, person2] + state_code: NJ + output: + nj_wfnj_income_eligible: true + nj_wfnj_resources_eligible: true + # At least one citizen or legal immigrant in household + nj_wfnj_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_gross_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_gross_income_eligible.yaml new file mode 100644 index 00000000000..12595830350 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_gross_income_eligible.yaml @@ -0,0 +1,38 @@ +- name: Case 1, no income is eligible. + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 1 + output: + # Gross income $0 <= $321 + nj_wfnj_gross_income_eligible: true + +- name: Case 2, income below max allowable is eligible. + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 1 + social_security: 3_600 # $300/month + output: + # Gross income $300 <= $321 + nj_wfnj_gross_income_eligible: true + +- name: Case 3, income above max allowable is ineligible. + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 1 + social_security: 4_800 # $400/month + output: + # Gross income $400 > $321 + nj_wfnj_gross_income_eligible: false + +- name: Case 4, income at max allowable is eligible. + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 1 + social_security: 3_852 # $321/month + output: + # Gross income $321 <= $321 + nj_wfnj_gross_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.yaml index 3a0f9962d7d..b4246c07fb7 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.yaml @@ -1,59 +1,90 @@ -- name: Case 1, household with no income is eligible. +- name: Case 1, new applicant with no income is eligible. period: 2024-01 input: state_code: NJ - nj_wfnj_maximum_allowable_income: 100 - nj_wfnj_maximum_benefit: 100 - nj_wfnj_countable_earned_income: 0 - nj_wfnj_countable_gross_unearned_income: 0 + spm_unit_size: 1 + is_tanf_enrolled: false output: - # 0 + 0 = 0 <= 100 and 0 < 100 + # New applicant: gross income $0 <= $321 max allowable nj_wfnj_income_eligible: true -- name: Case 2, household with income exceeding maximum allowable income is ineligible. +- name: Case 2, new applicant with income below both limits is eligible. period: 2024-01 input: state_code: NJ - nj_wfnj_maximum_allowable_income: 100 - nj_wfnj_maximum_benefit: 200 - nj_wfnj_countable_earned_income: 50 - nj_wfnj_countable_gross_unearned_income: 60 + spm_unit_size: 1 + social_security: 2_400 # $200/month + is_tanf_enrolled: false output: - # 50 + 60 = 110 > 100, fails income test + # New applicant: gross $200 <= $321, countable $200 < $214 + nj_wfnj_income_eligible: true + +- name: Case 3, new applicant with income above max allowable is ineligible. + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 1 + social_security: 4_800 # $400/month + is_tanf_enrolled: false + output: + # New applicant: gross income $400 > $321 max allowable nj_wfnj_income_eligible: false -- name: Case 3, household with income at maximum allowable income is eligible. +- name: Case 4, enrolled with countable income below max benefit is eligible. period: 2024-01 input: state_code: NJ - nj_wfnj_maximum_allowable_income: 100 - nj_wfnj_maximum_benefit: 200 - nj_wfnj_countable_earned_income: 100 - nj_wfnj_countable_gross_unearned_income: 0 + spm_unit_size: 1 + social_security: 2_400 # $200/month + is_tanf_enrolled: true output: - # 100 <= 100 and 100 < 200 + # Enrolled: countable income $200 < $214 max benefit nj_wfnj_income_eligible: true -- name: Case 4, household with income equal to maximum benefit is ineligible. +- name: Case 5, enrolled with countable income at max benefit is ineligible. period: 2024-01 input: state_code: NJ - nj_wfnj_maximum_allowable_income: 200 - nj_wfnj_maximum_benefit: 100 - nj_wfnj_countable_earned_income: 100 - nj_wfnj_countable_gross_unearned_income: 0 + spm_unit_size: 1 + social_security: 2_568 # $214/month + is_tanf_enrolled: true output: - # 100 <= 200 but 100 >= 100 (not < max_benefit) + # Enrolled: countable income $214 >= $214 max benefit nj_wfnj_income_eligible: false -- name: Case 5, household with income below both thresholds is eligible. +- name: Case 6, enrolled with countable income $1 below max benefit is eligible. + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 1 + social_security: 2_556 # $213/month + is_tanf_enrolled: true + output: + # Enrolled: countable income $213 < $214 max benefit + nj_wfnj_income_eligible: true + +- name: Case 7, new applicant with earned income in January (100% disregard). + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 1 + employment_income_before_lsr: 3_600 # $300/month gross + is_tanf_enrolled: false + output: + # Gross income = $300, max allowable = $321: passes + # Countable = $0 (100% disregard in January), max benefit = $214: passes + nj_wfnj_income_eligible: true + +- name: Case 8, enrolled with gross above limit but countable below (skips gross test). period: 2024-01 input: state_code: NJ - nj_wfnj_maximum_allowable_income: 300 - nj_wfnj_maximum_benefit: 200 - nj_wfnj_countable_earned_income: 50 - nj_wfnj_countable_gross_unearned_income: 50 + spm_unit_size: 1 + social_security: 1_200 # $100/month unearned + employment_income_before_lsr: 3_600 # $300/month earned (disregarded in Jan) + is_tanf_enrolled: true output: - # 100 <= 300 and 100 < 200 + # Gross = $400 > $321 (would fail gross test) + # Countable = $100 (earned disregarded) < $214: passes + # Enrolled uses countable test only nj_wfnj_income_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.yaml deleted file mode 100644 index b6ce20b7c06..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.yaml +++ /dev/null @@ -1,40 +0,0 @@ -- name: Case 1, single person household max income is $321/month. - period: 2024-01 - input: - state_code: NJ - spm_unit_size: 1 - output: - nj_wfnj_maximum_allowable_income: 321 - -- name: Case 2, non-NJ state returns zero. - period: 2024-01 - input: - state_code: CO - spm_unit_size: 1 - output: - nj_wfnj_maximum_allowable_income: 0 - -- name: Case 3, family of 3 max income is $839/month. - period: 2024-01 - input: - state_code: NJ - spm_unit_size: 3 - output: - nj_wfnj_maximum_allowable_income: 839 - -- name: Case 4, family of 8 (max table size) max income is $1,442/month. - period: 2024-01 - input: - state_code: NJ - spm_unit_size: 8 - output: - nj_wfnj_maximum_allowable_income: 1_442 - -- name: Case 5, family of 10 uses additional per person rate. - period: 2024-01 - input: - state_code: NJ - spm_unit_size: 10 - output: - # $1,442 + 2 * $99 = $1,640 - nj_wfnj_maximum_allowable_income: 1_640 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.yaml deleted file mode 100644 index 15d257608ab..00000000000 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.yaml +++ /dev/null @@ -1,40 +0,0 @@ -- name: Case 1, single person household maximum benefit is $214/month. - period: 2024-01 - input: - state_code: NJ - spm_unit_size: 1 - output: - nj_wfnj_maximum_benefit: 214 - -- name: Case 2, non-NJ state returns zero. - period: 2024-01 - input: - state_code: CO - spm_unit_size: 1 - output: - nj_wfnj_maximum_benefit: 0 - -- name: Case 3, family of 3 maximum benefit is $559/month. - period: 2024-01 - input: - state_code: NJ - spm_unit_size: 3 - output: - nj_wfnj_maximum_benefit: 559 - -- name: Case 4, family of 8 (max table size) maximum benefit is $961/month. - period: 2024-01 - input: - state_code: NJ - spm_unit_size: 8 - output: - nj_wfnj_maximum_benefit: 961 - -- name: Case 5, family of 10 uses additional per person rate. - period: 2024-01 - input: - state_code: NJ - spm_unit_size: 10 - output: - # $961 + 2 * $66 = $1093 - nj_wfnj_maximum_benefit: 1_093 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_payment_levels.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_payment_levels.yaml new file mode 100644 index 00000000000..a0f662ce50e --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_payment_levels.yaml @@ -0,0 +1,84 @@ +# Tests for NJ WFNJ payment levels across different time periods +# Historical values: +# 2015-01 to 2018-06: Frozen 30 years +# 2018-07 to 2019-07: +10% increase +# 2019-08 onwards: +20% increase (current) + +- name: Case 1, 2016 values (pre-2018 frozen rates). + period: 2016-01 + input: + state_code: NJ + spm_unit_size: 1 + output: + # Size 1: $162 (frozen rate) + nj_wfnj_payment_levels: 162 + +- name: Case 2, 2019 values (after July 2018 +10% increase). + period: 2019-01 + input: + state_code: NJ + spm_unit_size: 1 + output: + # Size 1: $178 (after +10%) + nj_wfnj_payment_levels: 178 + +- name: Case 3, 2020 values (after Aug 2019 +20% increase). + period: 2020-01 + input: + state_code: NJ + spm_unit_size: 1 + output: + # Size 1: $214 (current) + nj_wfnj_payment_levels: 214 + +- name: Case 4, family of 3 current rate. + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 3 + output: + # Size 3: $559 + nj_wfnj_payment_levels: 559 + +- name: Case 5, family of 8 (max table size). + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 8 + output: + # Size 8: $961 + nj_wfnj_payment_levels: 961 + +- name: Case 6, family of 9 (first additional person beyond table). + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 9 + output: + # $961 + 1 * $66 = $1,027 + nj_wfnj_payment_levels: 1_027 + +- name: Case 7, family of 10 uses additional per person rate. + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 10 + output: + # $961 + 2 * $66 = $1,093 + nj_wfnj_payment_levels: 1_093 + +- name: Case 8, family of 2. + period: 2024-01 + input: + state_code: NJ + spm_unit_size: 2 + output: + nj_wfnj_payment_levels: 425 + +- name: Case 9, non-NJ state returns zero. + period: 2024-01 + input: + state_code: CO + spm_unit_size: 1 + output: + nj_wfnj_payment_levels: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml index adc0d729016..0dbdc6a1b38 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.yaml @@ -10,7 +10,7 @@ period: 2024-01 input: state_code: NJ - spm_unit_assets: 4_000 + spm_unit_assets: 2_001 output: nj_wfnj_resources_eligible: false diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/eligibility/nj_wfnj_eligible.py similarity index 100% rename from policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_eligible.py rename to policyengine_us/variables/gov/states/nj/njdhs/wfnj/eligibility/nj_wfnj_eligible.py diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/eligibility/nj_wfnj_gross_income_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/eligibility/nj_wfnj_gross_income_eligible.py new file mode 100644 index 00000000000..98ca70bb19d --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/eligibility/nj_wfnj_gross_income_eligible.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class nj_wfnj_gross_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "New Jersey WFNJ gross income eligible" + definition_period = MONTH + defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nj.njdhs.wfnj + gross_income = spm_unit("nj_wfnj_gross_income", period) + payment_levels = spm_unit("nj_wfnj_payment_levels", period) + max_allowable = np.round(payment_levels * p.income.limit) + return gross_income <= max_allowable diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/eligibility/nj_wfnj_income_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/eligibility/nj_wfnj_income_eligible.py new file mode 100644 index 00000000000..cde8d42e74c --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/eligibility/nj_wfnj_income_eligible.py @@ -0,0 +1,30 @@ +from policyengine_us.model_api import * + + +class nj_wfnj_income_eligible(Variable): + value_type = bool + entity = SPMUnit + label = "New Jersey WFNJ income eligible" + definition_period = MONTH + defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-1", + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3", + ) + + def formula(spm_unit, period, parameters): + is_enrolled = spm_unit("is_tanf_enrolled", period) + gross_income_eligible = spm_unit( + "nj_wfnj_gross_income_eligible", period + ) + countable_income = spm_unit("nj_wfnj_countable_income", period) + payment_levels = spm_unit("nj_wfnj_payment_levels", period) + countable_income_eligible = countable_income < payment_levels + + # Enrolled: countable income test only + # Not enrolled: both gross income AND countable income tests + return where( + is_enrolled, + countable_income_eligible, + gross_income_eligible & countable_income_eligible, + ) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/eligibility/nj_wfnj_resources_eligible.py similarity index 86% rename from policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py rename to policyengine_us/variables/gov/states/nj/njdhs/wfnj/eligibility/nj_wfnj_resources_eligible.py index b1acf49c51b..bd4f68ed3dc 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_resources_eligible.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/eligibility/nj_wfnj_resources_eligible.py @@ -12,6 +12,6 @@ class nj_wfnj_resources_eligible(Variable): ) def formula(spm_unit, period, parameters): - p = parameters(period).gov.states.nj.njdhs.wfnj.eligibility.resources + p = parameters(period).gov.states.nj.njdhs.wfnj.resources resources = spm_unit("spm_unit_assets", period.this_year) return resources <= p.limit diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py index f0475086b4e..6d804550931 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income_person.py @@ -14,13 +14,12 @@ class nj_wfnj_countable_earned_income_person(Variable): def formula(person, period, parameters): p = parameters(period).gov.states.nj.njdhs.wfnj.income - gross_earned = person("nj_wfnj_gross_earned_income", period) + gross_earned = person("tanf_gross_earned_income", period) month = period.start.month # Calendar month proxy for enrollment months (assuming ≥20 hrs/week). # N.J.A.C. 10:90-3.8 provides tiered disregards based on months enrolled. - # PolicyEngine cannot track actual enrollment duration, so we use - # calendar months as a proxy: + # Use calendar months as a proxy: # - January (month 1): 100% disregard # - February-July (months 2-7): 75% disregard # - August-December (months 8-12): 50% disregard diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_gross_unearned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_gross_unearned_income.py deleted file mode 100644 index bd81aee7808..00000000000 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_gross_unearned_income.py +++ /dev/null @@ -1,14 +0,0 @@ -from policyengine_us.model_api import * - - -class nj_wfnj_countable_gross_unearned_income(Variable): - value_type = float - entity = SPMUnit - label = "New Jersey WFNJ countable gross unearned income" - unit = USD - definition_period = MONTH - defined_for = StateCode.NJ - reference = ( - "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-9" - ) - adds = "gov.states.nj.njdhs.wfnj.income.unearned" diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_income.py index 2549eff5fa6..2e0f80b2721 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_income.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_income.py @@ -14,6 +14,6 @@ class nj_wfnj_countable_income(Variable): ) adds = [ - "nj_wfnj_countable_earned_income", - "nj_wfnj_countable_gross_unearned_income", + "nj_wfnj_countable_earned_income_person", + "tanf_gross_unearned_income", ] diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py deleted file mode 100644 index 241fb9ab2e1..00000000000 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_earned_income.py +++ /dev/null @@ -1,14 +0,0 @@ -from policyengine_us.model_api import * - - -class nj_wfnj_gross_earned_income(Variable): - value_type = float - entity = Person - label = "New Jersey WFNJ gross earned income" - unit = USD - definition_period = MONTH - defined_for = StateCode.NJ - reference = ( - "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-9" - ) - adds = "gov.states.nj.njdhs.wfnj.income.earned" diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_income.py similarity index 56% rename from policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income.py rename to policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_income.py index ac7ebce9f72..9b64e120524 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_earned_income.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_gross_income.py @@ -1,14 +1,18 @@ from policyengine_us.model_api import * -class nj_wfnj_countable_earned_income(Variable): +class nj_wfnj_gross_income(Variable): value_type = float entity = SPMUnit - label = "New Jersey WFNJ countable earned income" + label = "New Jersey WFNJ gross income" unit = USD definition_period = MONTH defined_for = StateCode.NJ reference = ( - "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8" + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3", ) - adds = ["nj_wfnj_countable_earned_income_person"] + + adds = [ + "tanf_gross_earned_income", + "tanf_gross_unearned_income", + ] diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj.py index 5e946a79a93..b89b8900383 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj.py @@ -7,14 +7,12 @@ class nj_wfnj(Variable): label = "New Jersey WFNJ benefit" unit = USD definition_period = MONTH - defined_for = StateCode.NJ + defined_for = "nj_wfnj_eligible" reference = ( "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3" ) def formula(spm_unit, period, parameters): - eligible = spm_unit("nj_wfnj_eligible", period) - maximum_benefit = spm_unit("nj_wfnj_maximum_benefit", period) + payment_levels = spm_unit("nj_wfnj_payment_levels", period) countable_income = spm_unit("nj_wfnj_countable_income", period) - benefit = max_(maximum_benefit - countable_income, 0) - return where(eligible, benefit, 0) + return max_(payment_levels - countable_income, 0) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py deleted file mode 100644 index e46d0a274d2..00000000000 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_income_eligible.py +++ /dev/null @@ -1,29 +0,0 @@ -from policyengine_us.model_api import * - - -class nj_wfnj_income_eligible(Variable): - value_type = bool - entity = SPMUnit - label = "New Jersey WFNJ income eligible" - definition_period = MONTH - defined_for = StateCode.NJ - reference = ( - "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-1", - "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3", - ) - # NOTE: Per N.J.A.C. 10:90-3.8, initial applicants should be tested against - # gross income without disregards. PolicyEngine cannot distinguish initial - # vs ongoing recipients, so this applies the ongoing eligibility test to all. - # The implementation also combines the initial test (income <= max allowable) - # with the ongoing test (income < max benefit), which is more restrictive - # than applying only the initial test for new applicants. - - def formula(spm_unit, period, parameters): - income = spm_unit("nj_wfnj_countable_income", period) - maximum_allowable_income = spm_unit( - "nj_wfnj_maximum_allowable_income", period - ) - maximum_benefit = spm_unit("nj_wfnj_maximum_benefit", period) - return (income <= maximum_allowable_income) & ( - income < maximum_benefit - ) diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.py deleted file mode 100644 index 110d19a8bc7..00000000000 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_allowable_income.py +++ /dev/null @@ -1,22 +0,0 @@ -from policyengine_us.model_api import * - - -class nj_wfnj_maximum_allowable_income(Variable): - value_type = float - entity = SPMUnit - label = "New Jersey WFNJ maximum allowable income" - unit = USD - definition_period = MONTH - defined_for = StateCode.NJ - reference = ( - "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3" - ) - - def formula(spm_unit, period, parameters): - people = spm_unit("spm_unit_size", period.this_year) - p = parameters(period).gov.states.nj.njdhs.wfnj - capped_people = min_(people, p.max_household_size).astype(int) - additional_people = people - capped_people - base = p.maximum_allowable_income.main[capped_people] - additional = p.maximum_allowable_income.additional * additional_people - return base + additional diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.py deleted file mode 100644 index 774ba2890e1..00000000000 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_maximum_benefit.py +++ /dev/null @@ -1,22 +0,0 @@ -from policyengine_us.model_api import * - - -class nj_wfnj_maximum_benefit(Variable): - value_type = float - entity = SPMUnit - label = "New Jersey WFNJ maximum benefit" - unit = USD - definition_period = MONTH - defined_for = StateCode.NJ - reference = ( - "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3" - ) - - def formula(spm_unit, period, parameters): - people = spm_unit("spm_unit_size", period.this_year) - p = parameters(period).gov.states.nj.njdhs.wfnj - capped_people = min_(people, p.max_household_size).astype(int) - additional_people = people - capped_people - base = p.maximum_benefit.main[capped_people] - additional = p.maximum_benefit.additional * additional_people - return base + additional diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_payment_levels.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_payment_levels.py new file mode 100644 index 00000000000..b05bdabe2f0 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/nj_wfnj_payment_levels.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class nj_wfnj_payment_levels(Variable): + value_type = float + entity = SPMUnit + label = "New Jersey WFNJ payment levels" + unit = USD + definition_period = MONTH + defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3" + ) + + def formula(spm_unit, period, parameters): + size = spm_unit("spm_unit_size", period.this_year) + p = parameters(period).gov.states.nj.njdhs.wfnj + capped_size = min_(size, p.max_household_size) + additional = size - capped_size + base = p.payment_levels.amount[capped_size] + additional_amount = p.payment_levels.additional_person * additional + return base + additional_amount From 49e3419fc873208b0b00beb216ad4983b6a42982 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 7 Jan 2026 17:25:00 -0500 Subject: [PATCH 7/9] add child support deduction --- .../wfnj/income/child_support_disregard.yaml | 25 ++++ .../nj_wfnj_countable_unearned_income.yaml | 114 ++++++++++++++++++ .../wfnj/income/nj_wfnj_countable_income.py | 3 +- .../nj_wfnj_countable_unearned_income.py | 22 ++++ 4 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/child_support_disregard.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_unearned_income.yaml create mode 100644 policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_unearned_income.py diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/child_support_disregard.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/child_support_disregard.yaml new file mode 100644 index 00000000000..37fe2daf7a7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/child_support_disregard.yaml @@ -0,0 +1,25 @@ +description: New Jersey disregards child support received up to this amount based on the number of children under the WorkFirst New Jersey program. + +metadata: + type: single_amount + threshold_unit: person + amount_unit: currency-USD + period: month + label: New Jersey WFNJ child support disregard by number of children + reference: + - title: N.J.A.C. 10:90-3.1(h) + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-1 + +brackets: + - threshold: + 2015-01-01: 0 + amount: + 2015-01-01: 0 + - threshold: + 2015-01-01: 1 + amount: + 2015-01-01: 100 + - threshold: + 2015-01-01: 2 + amount: + 2015-01-01: 200 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_unearned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_unearned_income.yaml new file mode 100644 index 00000000000..73ef211bd01 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_unearned_income.yaml @@ -0,0 +1,114 @@ +# Tests for NJ WFNJ countable unearned income +# Logic: gross_unearned - child_support_disregard +# Child support disregard by number of children: +# - 0 children: $0 max disregard +# - 1 child: $100 max disregard +# - 2+ children: $200 max disregard + +- name: Case 1, no children with unearned income only. + period: 2024-01 + input: + people: + person1: + age: 30 + social_security: 1_200 # $100/month + households: + household: + members: [person1] + state_code: NJ + output: + # Gross unearned: $100/month, 0 children -> $0 disregard + nj_wfnj_countable_unearned_income: 100 + +- name: Case 2, one child with child support below $100. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 600 # $50/month + person2: + age: 10 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Gross: $50, 1 child -> max $100 disregard + # Disregard: min(50, 100) = $50, Countable: $50 - $50 = $0 + nj_wfnj_countable_unearned_income: 0 + +- name: Case 3, one child with child support above $100. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 1_800 # $150/month + social_security: 600 # $50/month + person2: + age: 10 + households: + household: + members: [person1, person2] + state_code: NJ + output: + # Gross: $200, 1 child -> max $100 disregard + # Disregard: min(150, 100) = $100, Countable: $200 - $100 = $100 + nj_wfnj_countable_unearned_income: 100 + +- name: Case 4, two children with child support below $200. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 1_200 # $100/month + person2: + age: 10 + person3: + age: 8 + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + # Gross: $100, 2 children -> max $200 disregard + # Disregard: min(100, 200) = $100, Countable: $100 - $100 = $0 + nj_wfnj_countable_unearned_income: 0 + +- name: Case 5, two children with child support above $200. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 3_600 # $300/month + social_security: 600 # $50/month + person2: + age: 10 + person3: + age: 8 + households: + household: + members: [person1, person2, person3] + state_code: NJ + output: + # Gross: $350, 2 children -> max $200 disregard + # Disregard: min(300, 200) = $200, Countable: $350 - $200 = $150 + nj_wfnj_countable_unearned_income: 150 + +- name: Case 6, no unearned income. + period: 2024-01 + input: + people: + person1: + age: 30 + person2: + age: 10 + households: + household: + members: [person1, person2] + state_code: NJ + output: + nj_wfnj_countable_unearned_income: 0 diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_income.py index 2e0f80b2721..4df4b5562e8 100644 --- a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_income.py +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_income.py @@ -11,9 +11,10 @@ class nj_wfnj_countable_income(Variable): reference = ( "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-3", "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8", + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-1", ) adds = [ "nj_wfnj_countable_earned_income_person", - "tanf_gross_unearned_income", + "nj_wfnj_countable_unearned_income", ] diff --git a/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_unearned_income.py b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_unearned_income.py new file mode 100644 index 00000000000..280b19e4e17 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/njdhs/wfnj/income/nj_wfnj_countable_unearned_income.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class nj_wfnj_countable_unearned_income(Variable): + value_type = float + entity = SPMUnit + label = "New Jersey WFNJ countable unearned income" + unit = USD + definition_period = MONTH + defined_for = StateCode.NJ + reference = ( + "https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-1", + ) + + def formula(spm_unit, period, parameters): + p = parameters(period).gov.states.nj.njdhs.wfnj.income + gross_unearned = add(spm_unit, period, ["tanf_gross_unearned_income"]) + child_support = add(spm_unit, period, ["child_support_received"]) + num_children = spm_unit("spm_unit_count_children", period.this_year) + max_disregard = p.child_support_disregard.calc(num_children) + child_support_disregard = min_(child_support, max_disregard) + return max_(gross_unearned - child_support_disregard, 0) From c387ff865e1d0ef0bea8aca5dce63cfcca64a710 Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 7 Jan 2026 17:50:58 -0500 Subject: [PATCH 8/9] minor --- .../wfnj/income/child_support_disregard.yaml | 6 ++--- .../nj_wfnj_countable_unearned_income.yaml | 22 +++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/child_support_disregard.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/child_support_disregard.yaml index 37fe2daf7a7..f6a792bf600 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/child_support_disregard.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/income/child_support_disregard.yaml @@ -1,4 +1,4 @@ -description: New Jersey disregards child support received up to this amount based on the number of children under the WorkFirst New Jersey program. +description: New Jersey excludes child support received up to this amount based on the number of children under the WorkFirst New Jersey program. metadata: type: single_amount @@ -7,8 +7,8 @@ metadata: period: month label: New Jersey WFNJ child support disregard by number of children reference: - - title: N.J.A.C. 10:90-3.1(h) - href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-1 + - title: N.J.A.C. 10:90-3.8(h) + href: https://www.law.cornell.edu/regulations/new-jersey/N-J-A-C-10-90-3-8 brackets: - threshold: diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_unearned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_unearned_income.yaml index 73ef211bd01..8107b4d71d3 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_unearned_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/njdhs/wfnj/nj_wfnj_countable_unearned_income.yaml @@ -112,3 +112,25 @@ state_code: NJ output: nj_wfnj_countable_unearned_income: 0 + +- name: Case 7, three children uses same $200 cap as two children. + period: 2024-01 + input: + people: + person1: + age: 30 + child_support_received: 3_600 # $300/month + person2: + age: 12 + person3: + age: 10 + person4: + age: 8 + households: + household: + members: [person1, person2, person3, person4] + state_code: NJ + output: + # Gross: $300, 3 children -> max $200 disregard (same as 2+) + # Disregard: min(300, 200) = $200, Countable: $300 - $200 = $100 + nj_wfnj_countable_unearned_income: 100 From 26aea045b82fb86442402dd55acc9ea09a49ed2a Mon Sep 17 00:00:00 2001 From: Ziming Date: Wed, 14 Jan 2026 11:30:38 -0500 Subject: [PATCH 9/9] minor --- policyengine_us/parameters/gov/states/nj/njdhs/wfnj/README.md | 2 +- .../gov/states/nj/njdhs/wfnj/payment_levels/amount.yaml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/README.md b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/README.md index eb8aeb3f951..29d2a8a5ea0 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/README.md +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/README.md @@ -1 +1 @@ -# Temporary Assistance for Needy Families +# WorkFirst New Jersey program diff --git a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/payment_levels/amount.yaml b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/payment_levels/amount.yaml index f51c0ff3fdd..048b6c791ff 100644 --- a/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/payment_levels/amount.yaml +++ b/policyengine_us/parameters/gov/states/nj/njdhs/wfnj/payment_levels/amount.yaml @@ -5,6 +5,8 @@ metadata: period: month breakdown: - range(1, 9) # size + breakdown_label: + - Assistance unit size label: New Jersey WFNJ monthly maximum benefit reference: - title: N.J.A.C. 10:90-3.3(b) Schedule II - Maximum Benefit Payment Levels