diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..f6e36156084 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,7 @@ +- bump: minor + changes: + added: + - Adds New Jersey ANCHOR property tax relief program with income-based benefit amounts for homeowners and renters. + - Adds New Jersey Stay NJ senior property tax reimbursement program for eligible seniors aged 65+. + changed: + - Updates New Jersey income tax parameters with 2025 references including tax brackets, exemptions, deductions, and credits. diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/age_threshold.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/age_threshold.yaml new file mode 100644 index 00000000000..eb8d7554670 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/age_threshold.yaml @@ -0,0 +1,13 @@ +description: New Jersey provides additional benefits under the Affordable New Jersey Communities for Homeowners and Renters program to filers at or above this age. +values: + 2022-01-01: 65 + +metadata: + unit: year + period: year + label: New Jersey ANCHOR senior age threshold + reference: + - title: P.L. 2022 - ANCHOR Program + href: https://www.nj.gov/treasury/taxation/anchor/ + - title: ANCHOR Program - How Benefits Are Calculated + href: https://www.nj.gov/treasury/taxation/anchor/calculated.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/income_limit/lower.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/income_limit/lower.yaml new file mode 100644 index 00000000000..60ef2bb2999 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/income_limit/lower.yaml @@ -0,0 +1,13 @@ +description: New Jersey provides higher benefits under the Affordable New Jersey Communities for Homeowners and Renters program to homeowners with income at or below this amount. +values: + 2022-01-01: 150_000 + +metadata: + unit: currency-USD + period: year + label: New Jersey ANCHOR homeowner lower income threshold + reference: + - title: P.L. 2022 - ANCHOR Program + href: https://www.nj.gov/treasury/taxation/anchor/ + - title: ANCHOR Program - How Benefits Are Calculated + href: https://www.nj.gov/treasury/taxation/anchor/calculated.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/income_limit/upper.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/income_limit/upper.yaml new file mode 100644 index 00000000000..663d90f79b9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/income_limit/upper.yaml @@ -0,0 +1,13 @@ +description: New Jersey limits the Affordable New Jersey Communities for Homeowners and Renters program to homeowners with income at or below this amount. +values: + 2022-01-01: 250_000 + +metadata: + unit: currency-USD + period: year + label: New Jersey ANCHOR homeowner income limit + reference: + - title: P.L. 2022 - ANCHOR Program + href: https://www.nj.gov/treasury/taxation/anchor/ + - title: ANCHOR Program - How Benefits Are Calculated + href: https://www.nj.gov/treasury/taxation/anchor/calculated.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/non_senior/amount/lower_income.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/non_senior/amount/lower_income.yaml new file mode 100644 index 00000000000..6a8f93e5fb0 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/non_senior/amount/lower_income.yaml @@ -0,0 +1,13 @@ +description: New Jersey provides this amount to non-senior homeowners with lower income under the Affordable New Jersey Communities for Homeowners and Renters program. +values: + 2022-01-01: 1_500 + +metadata: + unit: currency-USD + period: year + label: New Jersey ANCHOR non-senior homeowner lower income benefit + reference: + - title: P.L. 2022 - ANCHOR Program + href: https://www.nj.gov/treasury/taxation/anchor/ + - title: ANCHOR Program - How Benefits Are Calculated + href: https://www.nj.gov/treasury/taxation/anchor/calculated.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/non_senior/amount/upper_income.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/non_senior/amount/upper_income.yaml new file mode 100644 index 00000000000..ea28848eeb7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/non_senior/amount/upper_income.yaml @@ -0,0 +1,13 @@ +description: New Jersey provides this amount to non-senior homeowners with higher income under the Affordable New Jersey Communities for Homeowners and Renters program. +values: + 2022-01-01: 1_000 + +metadata: + unit: currency-USD + period: year + label: New Jersey ANCHOR non-senior homeowner upper income benefit + reference: + - title: P.L. 2022 - ANCHOR Program + href: https://www.nj.gov/treasury/taxation/anchor/ + - title: ANCHOR Program - How Benefits Are Calculated + href: https://www.nj.gov/treasury/taxation/anchor/calculated.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/senior/amount/lower_income.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/senior/amount/lower_income.yaml new file mode 100644 index 00000000000..d7545f366ee --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/senior/amount/lower_income.yaml @@ -0,0 +1,13 @@ +description: New Jersey provides this amount to senior homeowners with lower income under the Affordable New Jersey Communities for Homeowners and Renters program. +values: + 2022-01-01: 1_750 + +metadata: + unit: currency-USD + period: year + label: New Jersey ANCHOR senior homeowner lower income benefit + reference: + - title: P.L. 2022 - ANCHOR Program + href: https://www.nj.gov/treasury/taxation/anchor/ + - title: ANCHOR Program - How Benefits Are Calculated + href: https://www.nj.gov/treasury/taxation/anchor/calculated.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/senior/amount/upper_income.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/senior/amount/upper_income.yaml new file mode 100644 index 00000000000..f9bbc35219a --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/homeowner/senior/amount/upper_income.yaml @@ -0,0 +1,13 @@ +description: New Jersey provides this amount to senior homeowners with higher income under the Affordable New Jersey Communities for Homeowners and Renters program. +values: + 2022-01-01: 1_250 + +metadata: + unit: currency-USD + period: year + label: New Jersey ANCHOR senior homeowner upper income benefit + reference: + - title: P.L. 2022 - ANCHOR Program + href: https://www.nj.gov/treasury/taxation/anchor/ + - title: ANCHOR Program - How Benefits Are Calculated + href: https://www.nj.gov/treasury/taxation/anchor/calculated.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/renter/income_limit.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/renter/income_limit.yaml new file mode 100644 index 00000000000..39496d22c05 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/renter/income_limit.yaml @@ -0,0 +1,13 @@ +description: New Jersey limits the Affordable New Jersey Communities for Homeowners and Renters program to renters with income at or below this amount. +values: + 2022-01-01: 150_000 + +metadata: + unit: currency-USD + period: year + label: New Jersey ANCHOR renter income limit + reference: + - title: P.L. 2022 - ANCHOR Program + href: https://www.nj.gov/treasury/taxation/anchor/ + - title: ANCHOR Program - How Benefits Are Calculated + href: https://www.nj.gov/treasury/taxation/anchor/calculated.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/renter/non_senior/amount.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/renter/non_senior/amount.yaml new file mode 100644 index 00000000000..3323014307f --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/renter/non_senior/amount.yaml @@ -0,0 +1,13 @@ +description: New Jersey provides this amount to non-senior renters under the Affordable New Jersey Communities for Homeowners and Renters program. +values: + 2022-01-01: 450 + +metadata: + unit: currency-USD + period: year + label: New Jersey ANCHOR non-senior renter benefit + reference: + - title: P.L. 2022 - ANCHOR Program + href: https://www.nj.gov/treasury/taxation/anchor/ + - title: ANCHOR Program - How Benefits Are Calculated + href: https://www.nj.gov/treasury/taxation/anchor/calculated.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/renter/senior/amount.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/renter/senior/amount.yaml new file mode 100644 index 00000000000..d7cc6dfb79a --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/anchor/renter/senior/amount.yaml @@ -0,0 +1,13 @@ +description: New Jersey provides this amount to senior renters under the Affordable New Jersey Communities for Homeowners and Renters program. +values: + 2022-01-01: 700 + +metadata: + unit: currency-USD + period: year + label: New Jersey ANCHOR senior renter benefit + reference: + - title: P.L. 2022 - ANCHOR Program + href: https://www.nj.gov/treasury/taxation/anchor/ + - title: ANCHOR Program - How Benefits Are Calculated + href: https://www.nj.gov/treasury/taxation/anchor/calculated.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/cdcc/rate.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/cdcc/rate.yaml index f875790696e..9dfeecbddec 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/credits/cdcc/rate.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/cdcc/rate.yaml @@ -16,6 +16,8 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=45 - title: 2024 Instructions for Form NJ-1040 (line 64) href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=46 + - title: 2025 NJ-1040 Instructions (Line 56) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=44 brackets: - threshold: 2021-01-01: -.inf diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/ctc/age_limit.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/ctc/age_limit.yaml index 2e1251638e8..d3a7ead6cc2 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/credits/ctc/age_limit.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/ctc/age_limit.yaml @@ -12,6 +12,8 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=46 - title: 2024 NJ-1040 Instructions (line 65) href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=46 + - title: 2025 NJ-1040 Instructions (Line 65) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=46 # New Jersey child tax credit was introduced in 2022 values: diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/ctc/amount.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/ctc/amount.yaml index 00848d5a2f9..0c7762f7e14 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/credits/ctc/amount.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/ctc/amount.yaml @@ -14,8 +14,10 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=46 - title: 2024 NJ-1040 Instructions (line 65) href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=46 + - title: 2025 NJ-1040 Instructions (Line 65) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=46 # New Jersey child tax credit was introduced in 2022 - + brackets: - threshold: 2022-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/eitc/eligibility/age/min.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/eitc/eligibility/age/min.yaml index 64ccf59d605..5089a4bd9bb 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/credits/eitc/eligibility/age/min.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/eitc/eligibility/age/min.yaml @@ -14,5 +14,7 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=45 - title: 2024 NJ-1040 Instructions (line 58) href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=44 + - title: 2025 NJ-1040 Instructions (Line 58) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=44 values: 2021-01-01: 18 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/eitc/match.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/eitc/match.yaml index 97aed898d1f..418a9a8a3a4 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/credits/eitc/match.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/eitc/match.yaml @@ -14,6 +14,8 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=45 - title: 2024 NJ-1040 Instructions (line 58) href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=44 + - title: 2025 NJ-1040 Instructions (Line 58) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=44 values: 2000-01-01: 0.1 2001-01-01: 0.15 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/property_tax/age_threshold.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/property_tax/age_threshold.yaml index b0b4b346c9f..62a2d39dd88 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/credits/property_tax/age_threshold.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/property_tax/age_threshold.yaml @@ -14,5 +14,7 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=52 - title: 2024 NJ-1040 Instructions - Property Tax Credit href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=51 + - title: 2025 NJ-1040 Instructions (Property Tax Credit) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=51 values: 2021-01-01: 65 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/property_tax/amount.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/property_tax/amount.yaml index a57f28f2dc5..13bb72fedfc 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/credits/property_tax/amount.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/property_tax/amount.yaml @@ -10,6 +10,8 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=44 - title: 2024 NJ-1040 Instructions (line 56) href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=51 + - title: 2025 NJ-1040 Instructions (Line 48) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=51 unit: currency-USD period: year label: New Jersey property tax credit amount diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/property_tax/income_limit.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/property_tax/income_limit.yaml index c0cf493f53b..d5ca93f9788 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/credits/property_tax/income_limit.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/property_tax/income_limit.yaml @@ -14,7 +14,9 @@ metadata: href: https://www.nj.gov/treasury/taxation/proptaxdeduc_credit.shtml - title: 2024 NJ-1040 Instructions - Property Tax Credit href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=51 - + - title: 2025 NJ-1040 Instructions (Property Tax Credit) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=51 + breakdown: - filing_status diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/staynj/age_threshold.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/staynj/age_threshold.yaml new file mode 100644 index 00000000000..affdb86445a --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/staynj/age_threshold.yaml @@ -0,0 +1,15 @@ +description: New Jersey limits the Stay NJ Property Tax Credit program to filers at or above this age. +values: + 2026-01-01: 65 + +metadata: + unit: year + period: year + label: New Jersey Stay NJ age threshold + reference: + - title: P.L. 2023, c.75 - Stay NJ Act + href: https://pub.njleg.state.nj.us/Bills/2022/PL23/75_.HTM + - title: P.L. 2024, c.88 - Stay NJ Amendment + href: https://www.nj.gov/treasury/taxation/staynj/index.shtml + - title: NJ Division of Taxation - Stay NJ Program + href: https://www.nj.gov/treasury/taxation/staynj/index.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/staynj/income_limit.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/staynj/income_limit.yaml new file mode 100644 index 00000000000..f5c795ad314 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/staynj/income_limit.yaml @@ -0,0 +1,15 @@ +description: New Jersey limits the Stay NJ Property Tax Credit program to filers with gross income below this amount. +values: + 2026-01-01: 500_000 + +metadata: + unit: currency-USD + period: year + label: New Jersey Stay NJ income limit + reference: + - title: P.L. 2023, c.75 - Stay NJ Act + href: https://pub.njleg.state.nj.us/Bills/2022/PL23/75_.HTM + - title: P.L. 2024, c.88 - Stay NJ Amendment + href: https://www.nj.gov/treasury/taxation/staynj/index.shtml + - title: NJ Division of Taxation - Stay NJ Program + href: https://www.nj.gov/treasury/taxation/staynj/index.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/staynj/max_benefit.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/staynj/max_benefit.yaml new file mode 100644 index 00000000000..569c4a51bd9 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/staynj/max_benefit.yaml @@ -0,0 +1,15 @@ +description: New Jersey limits the Stay NJ Property Tax Credit program benefit to this maximum amount. +values: + 2026-01-01: 6_500 + +metadata: + unit: currency-USD + period: year + label: New Jersey Stay NJ maximum benefit + reference: + - title: P.L. 2023, c.75 - Stay NJ Act + href: https://pub.njleg.state.nj.us/Bills/2022/PL23/75_.HTM + - title: P.L. 2024, c.88 - Stay NJ Amendment + href: https://www.nj.gov/treasury/taxation/staynj/index.shtml + - title: NJ Division of Taxation - Stay NJ Program + href: https://www.nj.gov/treasury/taxation/staynj/index.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/credits/staynj/rate.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/credits/staynj/rate.yaml new file mode 100644 index 00000000000..e77add91c50 --- /dev/null +++ b/policyengine_us/parameters/gov/states/nj/tax/income/credits/staynj/rate.yaml @@ -0,0 +1,15 @@ +description: New Jersey provides this share of property taxes paid as a credit under the Stay NJ Property Tax Credit program. +values: + 2026-01-01: 0.5 + +metadata: + unit: /1 + period: year + label: New Jersey Stay NJ benefit rate + reference: + - title: P.L. 2023, c.75 - Stay NJ Act + href: https://pub.njleg.state.nj.us/Bills/2022/PL23/75_.HTM + - title: P.L. 2024, c.88 - Stay NJ Amendment + href: https://www.nj.gov/treasury/taxation/staynj/index.shtml + - title: NJ Division of Taxation - Stay NJ Program + href: https://www.nj.gov/treasury/taxation/staynj/index.shtml diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/deductions/medical_expenses/rate.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/deductions/medical_expenses/rate.yaml index b0d719ec9f4..fbe12552274 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/deductions/medical_expenses/rate.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/deductions/medical_expenses/rate.yaml @@ -12,5 +12,7 @@ metadata: href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=23 - title: 2024 NJ-1040 Instructions (Worksheet F, Line 2) href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=25 + - title: 2025 NJ-1040 Instructions (Worksheet F, Line 2) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=25 values: 2021-01-01: 0.02 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/deductions/property_tax/limit.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/deductions/property_tax/limit.yaml index 52420c70b06..2392a8f4a4f 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/deductions/property_tax/limit.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/deductions/property_tax/limit.yaml @@ -12,6 +12,8 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=32 - title: Instructions for Form NJ-1040 (Worksheet H, Line 2) href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=32 + - title: 2025 NJ-1040 Instructions (Worksheet H, Line 2) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=32 values: 2021-01-01: 15_000 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/deductions/property_tax/qualifying_rent_fraction.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/deductions/property_tax/qualifying_rent_fraction.yaml index eb14fa524c3..096a98f9787 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/deductions/property_tax/qualifying_rent_fraction.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/deductions/property_tax/qualifying_rent_fraction.yaml @@ -12,5 +12,7 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=28 - title: 2024 NJ-1040 Instructions (line 40a) href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=30 + - title: 2025 NJ-1040 Instructions (Line 40a) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=30 values: 2021-01-01: 0.18 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/age_threshold.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/age_threshold.yaml index 177134239ec..d2aecc8ae00 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/age_threshold.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/age_threshold.yaml @@ -12,5 +12,7 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=21 - title: 2024 NJ-1040 Instructions Line 28a 28b href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=22 + - title: 2025 NJ-1040 Instructions (Lines 17-18) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=21 values: 2021-01-01: 62 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/max_amount.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/max_amount.yaml index b2bc368485c..9e595ad9a93 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/max_amount.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/max_amount.yaml @@ -18,6 +18,8 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=21 - title: 2024 NJ-1040 Instructions Line 28a 28b href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=22 + - title: 2025 NJ-1040 Instructions (Lines 17-18) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=21 breakdown: - filing_status SINGLE: diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/other_retirement_income/earned_income_threshold.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/other_retirement_income/earned_income_threshold.yaml index bfd30da1bb1..846bd23484f 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/other_retirement_income/earned_income_threshold.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/other_retirement_income/earned_income_threshold.yaml @@ -9,5 +9,7 @@ metadata: href: https://law.justia.com/codes/new-jersey/2022/title-54a/section-54a-6-15/ - title: 2024 NJ-1040 Instructions Line 28b href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=22 + - title: 2025 NJ-1040 Instructions (Line 18) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=22 values: 2021-01-01: 3_000 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/head_of_household.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/head_of_household.yaml index 6b9a1d16090..48cdddcf693 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/head_of_household.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/head_of_household.yaml @@ -12,6 +12,8 @@ metadata: href: https://www.nj.gov/treasury/taxation/pdf/other_forms/tgi-ee/2022/1040i.pdf#page=22 - title: 2023 NJ-1040 Instructions Line 28a href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=21 + - title: 2025 NJ-1040 Instructions (Line 17) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=21 brackets: - threshold: 2021-01-01: -.inf diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/joint.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/joint.yaml index 0dced9e846c..6c6cc404553 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/joint.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/joint.yaml @@ -12,6 +12,8 @@ metadata: href: https://www.nj.gov/treasury/taxation/pdf/other_forms/tgi-ee/2022/1040i.pdf#page=22 - title: 2023 NJ-1040 Instructions Line 28a href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=21 + - title: 2025 NJ-1040 Instructions (Line 17) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=21 brackets: - threshold: 2021-01-01: -.inf diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/separate.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/separate.yaml index e9a1386e59b..b343de03cf3 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/separate.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/separate.yaml @@ -12,6 +12,8 @@ metadata: href: https://www.nj.gov/treasury/taxation/pdf/other_forms/tgi-ee/2022/1040i.pdf#page=22 - title: 2023 NJ-1040 Instructions Line 28a href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=21 + - title: 2025 NJ-1040 Instructions (Line 17) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=21 brackets: - threshold: 2021-01-01: -.inf diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/single.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/single.yaml index 6b9a1d16090..48cdddcf693 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/single.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/single.yaml @@ -12,6 +12,8 @@ metadata: href: https://www.nj.gov/treasury/taxation/pdf/other_forms/tgi-ee/2022/1040i.pdf#page=22 - title: 2023 NJ-1040 Instructions Line 28a href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=21 + - title: 2025 NJ-1040 Instructions (Line 17) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=21 brackets: - threshold: 2021-01-01: -.inf diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/surviving_spouse.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/surviving_spouse.yaml index 6b9a1d16090..48cdddcf693 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/surviving_spouse.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/pension/percentage/surviving_spouse.yaml @@ -12,6 +12,8 @@ metadata: href: https://www.nj.gov/treasury/taxation/pdf/other_forms/tgi-ee/2022/1040i.pdf#page=22 - title: 2023 NJ-1040 Instructions Line 28a href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=21 + - title: 2025 NJ-1040 Instructions (Line 17) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=21 brackets: - threshold: 2021-01-01: -.inf diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/special_exclusion/amount.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/special_exclusion/amount.yaml index 1c4603d0363..74aebdfaf70 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/special_exclusion/amount.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exclusions/retirement/special_exclusion/amount.yaml @@ -14,8 +14,8 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=22 - title: 2024 NJ-1040 Instructions (line 28b) href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=22 - - + - title: 2025 NJ-1040 Instructions (Line 18) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=22 SINGLE: 2021-01-01: 3_000 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/blind_or_disabled/amount.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/blind_or_disabled/amount.yaml index 308099fa8ea..a5b71b1d9d9 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/blind_or_disabled/amount.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/blind_or_disabled/amount.yaml @@ -14,5 +14,7 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=8 - title: 2024 NJ-1040 Instructions Line 8 href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=10 + - title: 2025 NJ-1040 Instructions (Line 9) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=8 values: 2021-01-01: 1_000 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/dependents/amount.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/dependents/amount.yaml index 5f47785479f..eed35ed06c5 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/dependents/amount.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/dependents/amount.yaml @@ -14,5 +14,7 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=8 - title: 2024 NJ-1040 Instructions Line 10–11 href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=8 + - title: 2025 NJ-1040 Instructions (Lines 10-11) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=8 values: 2021-01-01: 1_500 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/dependents_attending_college/age_threshold.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/dependents_attending_college/age_threshold.yaml index aeb65a75926..b6d07ff32ca 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/dependents_attending_college/age_threshold.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/dependents_attending_college/age_threshold.yaml @@ -13,5 +13,7 @@ metadata: href: https://www.nj.gov/treasury/taxation/pdf/other_forms/tgi-ee/2022/1040i.pdf#page=8 - title: 2024 NJ-1040 Instructions Line 12 href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=10 + - title: 2025 NJ-1040 Instructions (Line 12) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=8 values: 2021-01-01: 22 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/dependents_attending_college/amount.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/dependents_attending_college/amount.yaml index 379ecfa0027..84e35b1b92c 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/dependents_attending_college/amount.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/dependents_attending_college/amount.yaml @@ -14,5 +14,7 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=8 - title: 2024 NJ-1040 Instructions Line 12 href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=8 + - title: 2025 NJ-1040 Instructions (Line 12) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=8 values: 2021-01-01: 1_000 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/regular/amount.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/regular/amount.yaml index f2f8d8c39f4..5f086324537 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/regular/amount.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/regular/amount.yaml @@ -14,6 +14,8 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=8 - title: 2024 NJ-1040 Instructions Line 6 href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=8 + - title: 2025 NJ-1040 Instructions (Line 6) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=8 breakdown: - filing_status diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/senior/age_threshold.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/senior/age_threshold.yaml index fcfef849612..bb76c0fdea5 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/senior/age_threshold.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/senior/age_threshold.yaml @@ -14,5 +14,7 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=8 - title: 2024 NJ-1040 Instructions Line 7 href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=10 + - title: 2025 NJ-1040 Instructions (Line 8) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=8 values: 2021-01-01: 65 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/senior/amount.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/senior/amount.yaml index a70b6486b5b..b595a95e342 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/senior/amount.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/exemptions/senior/amount.yaml @@ -14,5 +14,7 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=8 - title: 2024 NJ-1040 Instructions Line 7 href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=8 + - title: 2025 NJ-1040 Instructions (Line 8) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=8 values: 2021-01-01: 1_000 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/filing_threshold.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/filing_threshold.yaml index 64a0c6467e5..14150d7746f 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/filing_threshold.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/filing_threshold.yaml @@ -13,6 +13,8 @@ metadata: href: https://lis.njleg.state.nj.us/nxt/gateway.dll?f=templates&fn=default.htm&vid=Publish:10.1048/Enu - title: 2024 NJ-1040 Instructions (filing threshold) href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=5 + - title: 2025 NJ-1040 Instructions (Filing Requirements) + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=5 SINGLE: 2021-01-01: 10_000 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/main/head_of_household.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/main/head_of_household.yaml index cebfc6a85b2..ac62db77040 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/main/head_of_household.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/main/head_of_household.yaml @@ -3,7 +3,7 @@ metadata: type: marginal_rate threshold_unit: currency-USD rate_unit: /1 - label: New Jersey State income tax rates for joint filers + label: New Jersey State income tax rates for head of household filers reference: - title: 2022 New Jersey Revised Statutes - Title 54A - New Jersey Gross Income Tax Act Section 54A:2-1 - Imposition of tax href: https://law.justia.com/codes/new-jersey/2022/title-54a/section-54a-2-1/ @@ -13,6 +13,8 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=63 - title: 2024 New Jersey Gross Income Tax — Tax Rate Schedules href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=65 + - title: 2025 NJ-1040 Instructions - Tax Rate Schedules + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=65 brackets: - threshold: 1991-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/main/joint.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/main/joint.yaml index 642c9b0b21c..9508571d723 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/main/joint.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/main/joint.yaml @@ -13,6 +13,8 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=63 - title: 2024 New Jersey Gross Income Tax — Tax Rate Schedules href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=65 + - title: 2025 NJ-1040 Instructions - Tax Rate Schedules + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=65 brackets: - threshold: 1991-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/main/separate.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/main/separate.yaml index 182b6bf55d8..8611741d139 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/main/separate.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/main/separate.yaml @@ -1,9 +1,9 @@ -description: Progressive rate schedule for a single filer in New Jersey. +description: Progressive rate schedule for a married filing separately filer in New Jersey. metadata: type: marginal_rate threshold_unit: currency-USD rate_unit: /1 - label: New Jersey State income tax rates for single filers + label: New Jersey State income tax rates for married filing separately filers reference: - title: 2022 New Jersey Revised Statutes - Title 54A - New Jersey Gross Income Tax Act Section 54A:2-1 - Imposition of tax href: https://law.justia.com/codes/new-jersey/2022/title-54a/section-54a-2-1/ @@ -13,6 +13,8 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=63 - title: 2024 New Jersey Gross Income Tax — Tax Rate Schedules href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=65 + - title: 2025 NJ-1040 Instructions - Tax Rate Schedules + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=65 brackets: - threshold: 1991-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/main/single.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/main/single.yaml index 6e7320b536b..74fab0467c8 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/main/single.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/main/single.yaml @@ -13,6 +13,8 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=63 - title: 2024 NJ-1040 Instructions (line 26) href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=65 + - title: 2025 NJ-1040 Instructions - Tax Rate Schedules + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=65 brackets: - threshold: 1991-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/nj/tax/income/main/surviving_spouse.yaml b/policyengine_us/parameters/gov/states/nj/tax/income/main/surviving_spouse.yaml index 229e3119700..21510a9904d 100644 --- a/policyengine_us/parameters/gov/states/nj/tax/income/main/surviving_spouse.yaml +++ b/policyengine_us/parameters/gov/states/nj/tax/income/main/surviving_spouse.yaml @@ -3,7 +3,7 @@ metadata: type: marginal_rate threshold_unit: currency-USD rate_unit: /1 - label: New Jersey State income tax rates for joint filers + label: New Jersey State income tax rates for surviving spouse filers reference: - title: 2022 New Jersey Revised Statutes - Title 54A - New Jersey Gross Income Tax Act Section 54A:2-1 - Imposition of tax href: https://law.justia.com/codes/new-jersey/2022/title-54a/section-54a-2-1/ @@ -13,6 +13,8 @@ metadata: href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=63 - title: 2024 NJ-1040 Instructions (line 26) href: https://www.state.nj.us/treasury/taxation/pdf/current/1040i.pdf#page=65 + - title: 2025 NJ-1040 Instructions - Tax Rate Schedules + href: https://www.nj.gov/treasury/taxation/pdf/current/1040i.pdf#page=65 brackets: - threshold: 1991-01-01: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/anchor/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/anchor/integration.yaml new file mode 100644 index 00000000000..de916e533a8 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/anchor/integration.yaml @@ -0,0 +1,208 @@ +# Integration tests for New Jersey ANCHOR Program +# Tests the full calculation pipeline from income to eligibility to benefit +# ANCHOR: Affordable New Jersey Communities for Homeowners and Renters + +- name: Case 1, senior homeowner couple with moderate income. + period: 2024 + input: + people: + person1: + age: 68 + employment_income: 60_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + person2: + age: 65 + employment_income: 40_000 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1, person2] + state_fips: 34 # New Jersey + output: + # Combined income: $60,000 + $40,000 = $100,000 + # Income $100K <= $150K lower threshold + # Homeowner + Senior (age 68 >= 65 or age 65 >= 65) + # Benefit: $1,750 (senior homeowner lower income) + nj_anchor_eligible: true + nj_anchor: 1_750 + +- name: Case 2, non-senior homeowner with higher income. + period: 2024 + input: + people: + person1: + age: 50 + employment_income: 180_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITHOUT_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $180K > $150K but <= $250K upper threshold + # Non-senior homeowner (age 50 < 65) + # Benefit: $1,000 (non-senior homeowner upper income) + nj_anchor_eligible: true + nj_anchor: 1_000 + +- name: Case 3, senior renter with low income. + period: 2024 + input: + people: + person1: + age: 72 + social_security: 24_000 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Income: $24,000 (Social Security) + # Income $24K <= $150K renter threshold + # Senior renter (age 72 >= 65) + # Benefit: $700 (senior renter) + nj_anchor_eligible: true + nj_anchor: 700 + +- name: Case 4, non-senior renter at income threshold. + period: 2024 + input: + people: + person1: + age: 35 + employment_income: 150_000 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $150K at renter threshold (at threshold = eligible) + # Non-senior renter (age 35 < 65) + # Benefit: $450 (non-senior renter) + nj_anchor_eligible: true + nj_anchor: 450 + +- name: Case 5, renter with income above threshold is ineligible. + period: 2024 + input: + people: + person1: + age: 45 + employment_income: 160_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $160K > $150K renter limit + # Ineligible - exceeds renter income limit + # Benefit: $0 + nj_anchor_eligible: false + nj_anchor: 0 + +- name: Case 6, homeowner with income above limit is ineligible. + period: 2024 + input: + people: + person1: + age: 55 + employment_income: 300_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $300K > $250K homeowner limit + # Ineligible - exceeds homeowner income limit + # Benefit: $0 + nj_anchor_eligible: false + nj_anchor: 0 + +- name: Case 7, family with children homeowner lower income tier. + period: 2024 + input: + people: + person1: + age: 42 + employment_income: 80_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + person2: + age: 40 + employment_income: 50_000 + is_tax_unit_spouse: true + person3: + age: 12 + is_tax_unit_dependent: true + person4: + age: 8 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2, person3, person4] + spm_units: + spm_unit: + members: [person1, person2, person3, person4] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1, person2, person3, person4] + state_fips: 34 + output: + # Combined income: $80K + $50K = $130K + # Income $130K <= $150K lower threshold + # Non-senior homeowner (ages 42, 40 < 65) + # Benefit: $1,500 (non-senior homeowner lower income) + nj_anchor_eligible: true + nj_anchor: 1_500 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/anchor/nj_anchor.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/anchor/nj_anchor.yaml new file mode 100644 index 00000000000..0e8c07b1e09 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/anchor/nj_anchor.yaml @@ -0,0 +1,688 @@ +# Unit tests for nj_anchor variable +# Tests benefit amounts for ANCHOR (Affordable New Jersey Communities for Homeowners and Renters) +# Benefits: +# Homeowners lower income (<=$150K): Non-senior $1,500, Senior $1,750 +# Homeowners upper income ($150K-$250K): Non-senior $1,000, Senior $1,250 +# Renters (<=$150K): Non-senior $450, Senior $700 +# Above income limits: $0 + +- name: Case 1, senior homeowner with lower income receives $1,750. + period: 2024 + input: + people: + person1: + age: 65 + employment_income: 100_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 # New Jersey + output: + # Senior homeowner, income $100K <= $150K threshold + # Benefit: $1,750 (senior homeowner lower income tier) + nj_anchor: 1_750 + +- name: Case 2, non-senior homeowner with lower income receives $1,500. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 100_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Non-senior homeowner, income $100K <= $150K threshold + # Benefit: $1,500 (non-senior homeowner lower income tier) + nj_anchor: 1_500 + +- name: Case 3, senior homeowner with upper income receives $1,250. + period: 2024 + input: + people: + person1: + age: 70 + employment_income: 200_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITHOUT_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Senior homeowner, income $200K > $150K but <= $250K + # Benefit: $1,250 (senior homeowner upper income tier) + nj_anchor: 1_250 + +- name: Case 4, non-senior homeowner with upper income receives $1,000. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 200_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Non-senior homeowner, income $200K > $150K but <= $250K + # Benefit: $1,000 (non-senior homeowner upper income tier) + nj_anchor: 1_000 + +- name: Case 5, senior renter with income below threshold receives $700. + period: 2024 + input: + people: + person1: + age: 65 + employment_income: 100_000 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Senior renter, income $100K <= $150K threshold + # Benefit: $700 (senior renter) + nj_anchor: 700 + +- name: Case 6, non-senior renter with income below threshold receives $450. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 100_000 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Non-senior renter, income $100K <= $150K threshold + # Benefit: $450 (non-senior renter) + nj_anchor: 450 + +- name: Case 7, homeowner with income above upper limit receives $0. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 260_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Homeowner, income $260K > $250K upper limit + # Benefit: $0 (ineligible) + nj_anchor: 0 + +- name: Case 8, renter with income above limit receives $0. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 160_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Renter, income $160K > $150K limit + # Benefit: $0 (ineligible) + nj_anchor: 0 + +- name: Case 9, homeowner at lower income threshold receives lower income benefit. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 150_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Non-senior homeowner, income $150K at threshold + # Benefit: $1,500 (at threshold = lower income tier) + nj_anchor: 1_500 + +- name: Case 10, homeowner at upper income threshold is eligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 250_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Non-senior homeowner, income $250K at upper threshold + # Benefit: $1,000 (upper income tier at limit) + nj_anchor: 1_000 + +- name: Case 11, senior at age 64 receives non-senior benefit. + period: 2024 + input: + people: + person1: + age: 64 + employment_income: 100_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Age 64 < 65 threshold, not senior + # Benefit: $1,500 (non-senior homeowner lower income) + nj_anchor: 1_500 + +# ============================================================================== +# EDGE CASES - Boundary conditions and corner cases +# ============================================================================== + +- name: Edge case 1, homeowner income exactly one dollar above $150,000 gets upper tier. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 150_001 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Non-senior homeowner, income $150,001 > $150K threshold (uses <=) + # Switches to upper income tier: $1,000 + nj_anchor: 1_000 + +- name: Edge case 2, senior homeowner income exactly one dollar above $150,000. + period: 2024 + input: + people: + person1: + age: 66 + employment_income: 150_001 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Senior homeowner, income $150,001 > $150K threshold + # Switches to upper income tier: $1,250 + nj_anchor: 1_250 + +- name: Edge case 3, homeowner income exactly one dollar above $250,000 is ineligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 250_001 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $250,001 > $250,000 upper limit - ineligible + nj_anchor: 0 + +- name: Edge case 4, renter income exactly one dollar above $150,000 is ineligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 150_001 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Renter income $150,001 > $150K limit - ineligible + nj_anchor: 0 + +- name: Edge case 5, homeowner with zero income receives lower tier benefit. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 0 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Non-senior homeowner, income $0 <= $150K + # Lower income tier: $1,500 + nj_anchor: 1_500 + +- name: Edge case 6, senior homeowner with zero income receives senior lower tier. + period: 2024 + input: + people: + person1: + age: 70 + employment_income: 0 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Senior homeowner, income $0 <= $150K + # Senior lower income tier: $1,750 + nj_anchor: 1_750 + +- name: Edge case 7, renter with zero income receives non-senior benefit. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 0 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Non-senior renter, income $0 <= $150K + # Non-senior renter benefit: $450 + nj_anchor: 450 + +- name: Edge case 8, senior renter with zero income receives senior benefit. + period: 2024 + input: + people: + person1: + age: 67 + employment_income: 0 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Senior renter, income $0 <= $150K + # Senior renter benefit: $700 + nj_anchor: 700 + +- name: Edge case 9, very high income homeowner receives $0. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 1_000_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $1M far exceeds all limits + nj_anchor: 0 + +- name: Edge case 10, age exactly 65 receives senior benefit. + period: 2024 + input: + people: + person1: + age: 65 + employment_income: 100_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Age 65 >= 65 threshold (uses >=) + # Senior homeowner lower income: $1,750 + nj_anchor: 1_750 + +- name: Edge case 11, couple where only spouse is 65 plus receives senior benefit. + period: 2024 + input: + people: + person1: + age: 50 + employment_income: 100_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + person2: + age: 66 + employment_income: 0 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1, person2] + state_fips: 34 + output: + # Uses greater_age_head_spouse = max(50, 66) = 66 >= 65 + # Senior homeowner lower income tier: $1,750 + nj_anchor: 1_750 + +- name: Edge case 12, mixed household paying both rent and property taxes receives $0. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 100_000 + real_estate_taxes: 5_000 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_fips: 34 + output: + # Implementation: is_homeowner = pays_taxes & ~pays_rent + # is_renter = pays_rent & ~pays_taxes + # Both conditions fail - neither homeowner nor renter + nj_anchor: 0 + +- name: Edge case 13, person who neither owns nor rents receives $0. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 50_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + # No rent - defaults to 0 + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Not homeowner (no property taxes) and not renter (no rent paid) + # Formula: is_homeowner = pays_taxes & ~pays_rent = false + # Formula: is_renter = pays_rent & ~pays_taxes = false + # Neither category qualifies + nj_anchor: 0 + +- name: Edge case 14, renter at income threshold receives full benefit. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 150_000 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Non-senior renter, income exactly at $150K limit (uses <=) + # Non-senior renter benefit: $450 + nj_anchor: 450 + +- name: Edge case 15, senior renter at income threshold receives full benefit. + period: 2024 + input: + people: + person1: + age: 68 + employment_income: 150_000 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Senior renter, income exactly at $150K limit (uses <=) + # Senior renter benefit: $700 + nj_anchor: 700 + +- name: Edge case 16, senior homeowner at upper income threshold. + period: 2024 + input: + people: + person1: + age: 72 + employment_income: 250_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Senior homeowner, income $250K at upper limit (uses <=) + # Senior homeowner upper income tier: $1,250 + nj_anchor: 1_250 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/anchor/nj_anchor_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/anchor/nj_anchor_eligible.yaml new file mode 100644 index 00000000000..faea3c8d7d3 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/anchor/nj_anchor_eligible.yaml @@ -0,0 +1,461 @@ +# Unit tests for nj_anchor_eligible variable +# Tests eligibility for ANCHOR (Affordable New Jersey Communities for Homeowners and Renters) +# Eligibility: Homeowners with income <= $250,000 OR Renters with income <= $150,000 + +- name: Case 1, homeowner with income below lower threshold is eligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 100_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 # New Jersey + output: + nj_anchor_eligible: true + +- name: Case 2, homeowner with income between lower and upper threshold is eligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 200_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITHOUT_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + nj_anchor_eligible: true + +- name: Case 3, homeowner with income at upper threshold is eligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 250_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + nj_anchor_eligible: true + +- name: Case 4, homeowner with income above upper threshold is ineligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 260_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + nj_anchor_eligible: false + +- name: Case 5, renter with income below threshold is eligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 100_000 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + nj_anchor_eligible: true + +- name: Case 6, renter with income at threshold is eligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 150_000 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + nj_anchor_eligible: true + +- name: Case 7, renter with income above threshold is ineligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 160_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + nj_anchor_eligible: false + +- name: Case 8, senior homeowner with lower income is eligible. + period: 2024 + input: + people: + person1: + age: 65 + employment_income: 100_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + nj_anchor_eligible: true + +- name: Case 9, senior renter with income at threshold is eligible. + period: 2024 + input: + people: + person1: + age: 70 + employment_income: 150_000 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + nj_anchor_eligible: true + +# ============================================================================== +# EDGE CASES - Boundary conditions and corner cases +# ============================================================================== + +- name: Edge case 1, homeowner with income exactly one dollar above $250,000 is ineligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 250_001 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $250,001 > $250,000 upper limit (uses <=) + nj_anchor_eligible: false + +- name: Edge case 2, homeowner with income exactly one dollar above $150,000 lower threshold. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 150_001 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $150,001 > $150,000 (still eligible, just upper tier for benefits) + nj_anchor_eligible: true + +- name: Edge case 3, renter with income exactly one dollar above $150,000 is ineligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 150_001 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $150,001 > $150,000 renter limit (uses <=) + nj_anchor_eligible: false + +- name: Edge case 4, homeowner with zero income is eligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 0 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Zero income is below all thresholds + nj_anchor_eligible: true + +- name: Edge case 5, renter with zero income is eligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 0 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Zero income is below all thresholds + nj_anchor_eligible: true + +- name: Edge case 6, very high income homeowner is ineligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 1_000_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $1M far exceeds $250,000 limit + nj_anchor_eligible: false + +- name: Edge case 7, very high income renter is ineligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 500_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $500K far exceeds $150,000 limit + nj_anchor_eligible: false + +- name: Edge case 8, mixed household both pays rent and property taxes is ineligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 100_000 + real_estate_taxes: 5_000 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_fips: 34 + output: + # Implementation: is_homeowner = pays_taxes & ~pays_rent + # is_renter = pays_rent & ~pays_taxes + # Both pay taxes AND rent - neither qualifies + nj_anchor_eligible: false + +- name: Edge case 9, couple where spouse is 65 plus and head is under 65. + period: 2024 + input: + people: + person1: + age: 50 + employment_income: 100_000 + real_estate_taxes: 5_000 + is_tax_unit_head: true + person2: + age: 66 + employment_income: 0 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1, person2] + state_fips: 34 + output: + # Eligibility based on income and tenure only (age affects benefit amount) + # Income $100K <= $250,000 limit, homeowner + nj_anchor_eligible: true + +- name: Edge case 10, person who neither owns nor rents is ineligible. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 50_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + # No rent - defaults to 0 + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Not homeowner (no property taxes) and not renter (no rent paid) + # Formula: is_homeowner = pays_taxes & ~pays_rent = false + # Formula: is_renter = pays_rent & ~pays_taxes = false + # Neither category qualifies + nj_anchor_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/staynj/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/staynj/integration.yaml new file mode 100644 index 00000000000..48f5ba5e6d1 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/staynj/integration.yaml @@ -0,0 +1,207 @@ +# Integration tests for New Jersey Stay NJ Property Tax Credit +# Tests the full calculation pipeline from income to eligibility to benefit +# Stay NJ: 50% of property taxes paid, maximum $6,500, age 65+, income < $500K +# Note: Stay NJ begins in 2026 + +- name: Case 1, senior couple homeowner with moderate income and property tax. + period: 2026 + input: + people: + person1: + age: 68 + employment_income: 100_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + person2: + age: 66 + employment_income: 50_000 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1, person2] + state_fips: 34 # New Jersey + output: + # Combined income: $100K + $50K = $150K < $500K limit + # At least one person age 68 >= 65 + # Homeowner with mortgage + # Property tax: $10,000 + # Benefit: 50% * $10,000 = $5,000 + nj_staynj_eligible: true + nj_staynj: 5_000 + +- name: Case 2, wealthy senior homeowner capped at maximum. + period: 2026 + input: + people: + person1: + age: 72 + employment_income: 400_000 + real_estate_taxes: 25_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITHOUT_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $400K < $500K limit + # Age 72 >= 65 + # Property tax: $25,000 + # 50% * $25,000 = $12,500 > $6,500 max + # Capped at: $6,500 + nj_staynj_eligible: true + nj_staynj: 6_500 + +- name: Case 3, retiree with Social Security income and property tax. + period: 2026 + input: + people: + person1: + age: 75 + social_security: 36_000 + real_estate_taxes: 8_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income: $36K (Social Security) < $500K + # Age 75 >= 65 + # Property tax: $8,000 + # 50% * $8,000 = $4,000 + nj_staynj_eligible: true + nj_staynj: 4_000 + +- name: Case 4, non-senior homeowner is ineligible. + period: 2026 + input: + people: + person1: + age: 60 + employment_income: 150_000 + real_estate_taxes: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Age 60 < 65 - fails age requirement + # Even though income and homeownership qualify + # Ineligible + nj_staynj_eligible: false + nj_staynj: 0 + +- name: Case 5, senior renter is ineligible. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 80_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Age 70 >= 65 - passes age + # Income $80K < $500K - passes income + # RENTER - fails homeowner requirement + # Stay NJ is only for homeowners + nj_staynj_eligible: false + nj_staynj: 0 + +- name: Case 6, high-income senior homeowner is ineligible. + period: 2026 + input: + people: + person1: + age: 67 + employment_income: 550_000 + real_estate_taxes: 20_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $550K >= $500K limit + # Fails income requirement + nj_staynj_eligible: false + nj_staynj: 0 + +- name: Case 7, couple where one spouse is 65 plus and one is under 65. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 80_000 + real_estate_taxes: 11_000 + is_tax_unit_head: true + person2: + age: 58 + employment_income: 70_000 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1, person2] + state_fips: 34 + output: + # At least one spouse (person1) is 65+ + # Combined income: $80K + $70K = $150K < $500K + # Homeowner + # Property tax: $11,000 + # 50% * $11,000 = $5,500 + nj_staynj_eligible: true + nj_staynj: 5_500 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/staynj/nj_staynj.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/staynj/nj_staynj.yaml new file mode 100644 index 00000000000..903fdbd1b75 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/staynj/nj_staynj.yaml @@ -0,0 +1,603 @@ +# Unit tests for nj_staynj variable +# Tests benefit amounts for Stay NJ Property Tax Credit +# Benefit: 50% of property taxes paid, maximum $6,500 +# Note: Stay NJ begins in 2026 + +- name: Case 1, eligible senior receives 50 percent of property tax. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 100_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 # New Jersey + output: + # Property tax: $10,000 + # Benefit: 50% * $10,000 = $5,000 (under $6,500 max) + nj_staynj: 5_000 + +- name: Case 2, benefit capped at maximum of $6,500. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 200_000 + real_estate_taxes: 20_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITHOUT_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Property tax: $20,000 + # 50% * $20,000 = $10,000 + # Capped at max: $6,500 + nj_staynj: 6_500 + +- name: Case 3, benefit exactly at maximum threshold. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 150_000 + real_estate_taxes: 13_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Property tax: $13,000 + # 50% * $13,000 = $6,500 (exactly at max) + nj_staynj: 6_500 + +- name: Case 4, low property tax results in low benefit. + period: 2026 + input: + people: + person1: + age: 68 + employment_income: 80_000 + real_estate_taxes: 4_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Property tax: $4,000 + # 50% * $4,000 = $2,000 + nj_staynj: 2_000 + +- name: Case 5, ineligible due to age receives $0. + period: 2026 + input: + people: + person1: + age: 64 + employment_income: 100_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Age 64 < 65 - ineligible + nj_staynj: 0 + +- name: Case 6, ineligible due to income receives $0. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 600_000 + real_estate_taxes: 15_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $600K >= $500K limit - ineligible + nj_staynj: 0 + +- name: Case 7, ineligible renter receives $0. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 100_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Renter - ineligible for Stay NJ + nj_staynj: 0 + +- name: Case 8, zero property tax means zero benefit. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 100_000 + real_estate_taxes: 0 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITHOUT_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # 50% * $0 = $0 + nj_staynj: 0 + +- name: Case 9, senior at income just below limit is eligible. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 499_000 + real_estate_taxes: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $499K < $500K limit - eligible + # 50% * $12,000 = $6,000 + nj_staynj: 6_000 + +# ============================================================================== +# EDGE CASES - Boundary conditions and corner cases +# ============================================================================== + +- name: Edge case 1, property tax exactly $13,000 where 50 percent equals cap. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 100_000 + real_estate_taxes: 13_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # 50% * $13,000 = $6,500 exactly at cap + nj_staynj: 6_500 + +- name: Edge case 2, property tax one dollar above cap threshold. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 100_000 + real_estate_taxes: 13_001 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # 50% * $13,001 = $6,500.50 > $6,500 cap + # Capped at $6,500 + nj_staynj: 6_500 + +- name: Edge case 3, property tax one dollar below cap threshold. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 100_000 + real_estate_taxes: 12_999 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # 50% * $12,999 = $6,499.50 (under cap) + nj_staynj: 6_499.5 + +- name: Edge case 4, very high property tax capped at maximum. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 200_000 + real_estate_taxes: 50_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # 50% * $50,000 = $25,000 + # Capped at max: $6,500 + nj_staynj: 6_500 + +- name: Edge case 5, income exactly $499,999 one dollar below limit. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 499_999 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $499,999 < $500,000 (strict less than) - eligible + # 50% * $10,000 = $5,000 + nj_staynj: 5_000 + +- name: Edge case 6, income exactly at $500,000 limit is ineligible. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 500_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $500,000 NOT < $500,000 (strict less than) - ineligible + nj_staynj: 0 + +- name: Edge case 7, age exactly 65 at boundary. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 100_000 + real_estate_taxes: 8_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Age 65 >= 65 (uses >=) - eligible + # 50% * $8,000 = $4,000 + nj_staynj: 4_000 + +- name: Edge case 8, zero income still receives benefit. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 0 + real_estate_taxes: 6_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $0 < $500K - eligible + # 50% * $6,000 = $3,000 + nj_staynj: 3_000 + +- name: Edge case 9, very low property tax. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 100_000 + real_estate_taxes: 100 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # 50% * $100 = $50 + nj_staynj: 50 + +- name: Edge case 10, couple where only spouse is 65 plus. + period: 2026 + input: + people: + person1: + age: 50 + employment_income: 100_000 + real_estate_taxes: 14_000 + is_tax_unit_head: true + person2: + age: 66 + employment_income: 0 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1, person2] + state_fips: 34 + output: + # Uses greater_age_head_spouse = max(50, 66) = 66 >= 65 + # 50% * $14,000 = $7,000 > $6,500 cap + # Capped at $6,500 + nj_staynj: 6_500 + +- name: Edge case 11, mixed household paying both rent and taxes receives $0. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 100_000 + real_estate_taxes: 5_000 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_fips: 34 + output: + # Implementation: is_homeowner = pays_taxes & ~pays_rent + # Pays both - is_homeowner = false - ineligible + nj_staynj: 0 + +- name: Edge case 12, very high income senior is ineligible. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 1_000_000 + real_estate_taxes: 30_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $1M far exceeds $500K limit - ineligible + nj_staynj: 0 + +- name: Edge case 13, property tax at $1 gives minimal benefit. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 100_000 + real_estate_taxes: 1 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # 50% * $1 = $0.50 + nj_staynj: 0.5 + +- name: Edge case 14, property tax just under double cap triggers cap. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 100_000 + real_estate_taxes: 12_998 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # 50% * $12,998 = $6,499 (under cap) + nj_staynj: 6_499 + +- name: Edge case 15, senior who neither owns nor rents is ineligible. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 50_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + # No rent - defaults to 0 + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Not homeowner (no property taxes) and not renter (no rent paid) + # Formula: is_homeowner = pays_taxes & ~pays_rent = false + # Ineligible + nj_staynj: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/staynj/nj_staynj_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/staynj/nj_staynj_eligible.yaml new file mode 100644 index 00000000000..8f0a71fc54d --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/nj/tax/income/credits/staynj/nj_staynj_eligible.yaml @@ -0,0 +1,453 @@ +# Unit tests for nj_staynj_eligible variable +# Tests eligibility for Stay NJ Property Tax Credit +# Eligibility: Age 65+, homeowner, income < $500,000 (strict less than) +# Note: Stay NJ begins in 2026 + +- name: Case 1, senior homeowner with income below limit is eligible. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 100_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 # New Jersey + output: + nj_staynj_eligible: true + +- name: Case 2, senior homeowner with higher income is eligible. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 400_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITHOUT_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Age 70 >= 65, homeowner, income $400K < $500K + nj_staynj_eligible: true + +- name: Case 3, senior homeowner with income at limit is ineligible. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 500_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $500K is at limit (must be LESS than $500K) + nj_staynj_eligible: false + +- name: Case 4, senior homeowner with income above limit is ineligible. + period: 2026 + input: + people: + person1: + age: 68 + employment_income: 600_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $600K > $500K limit + nj_staynj_eligible: false + +- name: Case 5, non-senior age 64 is ineligible regardless of other factors. + period: 2026 + input: + people: + person1: + age: 64 + employment_income: 100_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Age 64 < 65 threshold + nj_staynj_eligible: false + +- name: Case 6, senior renter is ineligible. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 100_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Must be homeowner (RENTER is ineligible) + nj_staynj_eligible: false + +- name: Case 7, young non-homeowner is ineligible. + period: 2026 + input: + people: + person1: + age: 45 + employment_income: 100_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Age 45 < 65 AND renter - fails both requirements + nj_staynj_eligible: false + +- name: Case 8, senior couple where one is under 65. + period: 2026 + input: + people: + person1: + age: 67 + employment_income: 100_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + person2: + age: 63 + employment_income: 50_000 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1, person2] + state_fips: 34 + output: + # At least one person is age 67 >= 65, homeowner, income $150K < $500K + nj_staynj_eligible: true + +# ============================================================================== +# EDGE CASES - Boundary conditions and corner cases +# ============================================================================== + +- name: Edge case 1, income exactly $499,999 one dollar below limit is eligible. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 499_999 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $499,999 < $500,000 (strict less than) - eligible + nj_staynj_eligible: true + +- name: Edge case 2, income exactly $500,001 one dollar above limit is ineligible. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 500_001 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $500,001 > $500,000 limit - ineligible + nj_staynj_eligible: false + +- name: Edge case 3, age exactly 65 at threshold is eligible. + period: 2026 + input: + people: + person1: + age: 65 + employment_income: 100_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Age 65 >= 65 (uses >=) - eligible + nj_staynj_eligible: true + +- name: Edge case 4, zero income is eligible. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 0 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $0 < $500K - eligible + nj_staynj_eligible: true + +- name: Edge case 5, very high income is ineligible. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 1_000_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Income $1M far exceeds $500K limit + nj_staynj_eligible: false + +- name: Edge case 6, couple where only spouse is 65 plus is eligible. + period: 2026 + input: + people: + person1: + age: 50 + employment_income: 100_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + person2: + age: 66 + employment_income: 0 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1, person2] + state_fips: 34 + output: + # Uses greater_age_head_spouse = max(50, 66) = 66 >= 65 + # Homeowner, income $100K < $500K + nj_staynj_eligible: true + +- name: Edge case 7, homeowner who also pays rent is ineligible. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 100_000 + real_estate_taxes: 5_000 + rent: 12_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + households: + household: + members: [person1] + state_fips: 34 + output: + # Implementation: is_homeowner = pays_taxes & ~pays_rent + # Pays both taxes AND rent - is_homeowner = false + nj_staynj_eligible: false + +- name: Edge case 8, person who neither owns nor rents is ineligible. + period: 2026 + input: + people: + person1: + age: 70 + employment_income: 50_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + # No rent - defaults to 0 + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: RENTER + households: + household: + members: [person1] + state_fips: 34 + output: + # Not homeowner (no property taxes) and not renter (no rent paid) + # Formula: is_homeowner = pays_taxes & ~pays_rent = false + # Ineligible + nj_staynj_eligible: false + +- name: Edge case 9, couple with both under 65 is ineligible. + period: 2026 + input: + people: + person1: + age: 64 + employment_income: 100_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + person2: + age: 62 + employment_income: 50_000 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + spm_units: + spm_unit: + members: [person1, person2] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1, person2] + state_fips: 34 + output: + # greater_age_head_spouse = max(64, 62) = 64 < 65 - ineligible + nj_staynj_eligible: false + +- name: Edge case 10, very old senior is eligible. + period: 2026 + input: + people: + person1: + age: 95 + employment_income: 50_000 + real_estate_taxes: 10_000 + is_tax_unit_head: true + tax_units: + tax_unit: + members: [person1] + spm_units: + spm_unit: + members: [person1] + spm_unit_tenure_type: OWNER_WITH_MORTGAGE + households: + household: + members: [person1] + state_fips: 34 + output: + # Age 95 >= 65, homeowner, income $50K < $500K + nj_staynj_eligible: true diff --git a/policyengine_us/variables/gov/states/nj/tax/income/credits/anchor/nj_anchor.py b/policyengine_us/variables/gov/states/nj/tax/income/credits/anchor/nj_anchor.py new file mode 100644 index 00000000000..8644a7e9b97 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/tax/income/credits/anchor/nj_anchor.py @@ -0,0 +1,58 @@ +from policyengine_us.model_api import * + + +class nj_anchor(Variable): + value_type = float + entity = TaxUnit + label = "New Jersey ANCHOR benefit" + unit = USD + definition_period = YEAR + reference = ( + "https://www.nj.gov/treasury/taxation/anchor/", + "https://www.nj.gov/treasury/taxation/anchor/calculated.shtml", + ) + defined_for = "nj_anchor_eligible" + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.nj.tax.income.credits.anchor + + # Get gross income + gross_income = add(tax_unit, period, ["nj_gross_income"]) + + # Determine if senior (age 65+ for head or spouse) + greater_age = tax_unit("greater_age_head_spouse", period) + is_senior = greater_age >= p.age_threshold + + # Determine if homeowner or renter + pays_property_taxes = add(tax_unit, period, ["real_estate_taxes"]) > 0 + pays_rent = tax_unit("rents", period) + is_homeowner = pays_property_taxes & ~pays_rent + is_renter = pays_rent & ~pays_property_taxes + + # Determine income tier for homeowners + lower_income = gross_income <= p.homeowner.income_limit.lower + + # Calculate homeowner benefit amounts + homeowner_senior_amount = where( + lower_income, + p.homeowner.senior.amount.lower_income, + p.homeowner.senior.amount.upper_income, + ) + homeowner_non_senior_amount = where( + lower_income, + p.homeowner.non_senior.amount.lower_income, + p.homeowner.non_senior.amount.upper_income, + ) + homeowner_amount = where( + is_senior, homeowner_senior_amount, homeowner_non_senior_amount + ) + + # Calculate renter benefit amounts + renter_amount = where( + is_senior, p.renter.senior.amount, p.renter.non_senior.amount + ) + + # Return benefit based on tenure type + return where( + is_homeowner, homeowner_amount, where(is_renter, renter_amount, 0) + ) diff --git a/policyengine_us/variables/gov/states/nj/tax/income/credits/anchor/nj_anchor_eligible.py b/policyengine_us/variables/gov/states/nj/tax/income/credits/anchor/nj_anchor_eligible.py new file mode 100644 index 00000000000..b6f7a8d15fe --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/tax/income/credits/anchor/nj_anchor_eligible.py @@ -0,0 +1,35 @@ +from policyengine_us.model_api import * + + +class nj_anchor_eligible(Variable): + value_type = bool + entity = TaxUnit + label = "New Jersey ANCHOR program eligibility" + definition_period = YEAR + reference = ( + "https://www.nj.gov/treasury/taxation/anchor/", + "https://www.nj.gov/treasury/taxation/anchor/calculated.shtml", + ) + defined_for = StateCode.NJ + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.nj.tax.income.credits.anchor + + # Get gross income at tax unit level + gross_income = add(tax_unit, period, ["nj_gross_income"]) + + # Determine if homeowner or renter based on property taxes and rent + pays_property_taxes = add(tax_unit, period, ["real_estate_taxes"]) > 0 + pays_rent = tax_unit("rents", period) + is_homeowner = pays_property_taxes & ~pays_rent + is_renter = pays_rent & ~pays_property_taxes + + # Check income eligibility based on tenure type + homeowner_income_eligible = is_homeowner & ( + gross_income <= p.homeowner.income_limit.upper + ) + renter_income_eligible = is_renter & ( + gross_income <= p.renter.income_limit + ) + + return homeowner_income_eligible | renter_income_eligible diff --git a/policyengine_us/variables/gov/states/nj/tax/income/credits/staynj/nj_staynj.py b/policyengine_us/variables/gov/states/nj/tax/income/credits/staynj/nj_staynj.py new file mode 100644 index 00000000000..a8e104ba8f6 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/tax/income/credits/staynj/nj_staynj.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class nj_staynj(Variable): + value_type = float + entity = TaxUnit + label = "New Jersey Stay NJ Property Tax Credit" + unit = USD + definition_period = YEAR + reference = ( + "https://pub.njleg.state.nj.us/Bills/2022/PL23/75_.HTM", + "https://www.nj.gov/treasury/taxation/staynj/index.shtml", + ) + defined_for = "nj_staynj_eligible" + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.nj.tax.income.credits.staynj + + # Calculate 50% of property taxes paid + property_taxes = add(tax_unit, period, ["real_estate_taxes"]) + calculated_benefit = property_taxes * p.rate + + # Cap at maximum benefit + return min_(calculated_benefit, p.max_benefit) diff --git a/policyengine_us/variables/gov/states/nj/tax/income/credits/staynj/nj_staynj_eligible.py b/policyengine_us/variables/gov/states/nj/tax/income/credits/staynj/nj_staynj_eligible.py new file mode 100644 index 00000000000..4d40f177582 --- /dev/null +++ b/policyengine_us/variables/gov/states/nj/tax/income/credits/staynj/nj_staynj_eligible.py @@ -0,0 +1,31 @@ +from policyengine_us.model_api import * + + +class nj_staynj_eligible(Variable): + value_type = bool + entity = TaxUnit + label = "New Jersey Stay NJ Property Tax Credit program eligibility" + definition_period = YEAR + reference = ( + "https://pub.njleg.state.nj.us/Bills/2022/PL23/75_.HTM", + "https://www.nj.gov/treasury/taxation/staynj/index.shtml", + ) + defined_for = StateCode.NJ + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.nj.tax.income.credits.staynj + + # Age 65+ for head or spouse + greater_age = tax_unit("greater_age_head_spouse", period) + age_eligible = greater_age >= p.age_threshold + + # Gross income below limit (strict less than per statute) + gross_income = add(tax_unit, period, ["nj_gross_income"]) + income_eligible = gross_income < p.income_limit + + # Must be homeowner (pays property taxes, not renter) + pays_property_taxes = add(tax_unit, period, ["real_estate_taxes"]) > 0 + pays_rent = tax_unit("rents", period) + is_homeowner = pays_property_taxes & ~pays_rent + + return age_eligible & income_eligible & is_homeowner