diff --git a/changelog.d/statute-first-state-income-tax.fixed.md b/changelog.d/statute-first-state-income-tax.fixed.md new file mode 100644 index 00000000000..5b2a9861eec --- /dev/null +++ b/changelog.d/statute-first-state-income-tax.fixed.md @@ -0,0 +1 @@ +Follow the statute where state forms differ: New Mexico's senior medical exemption needs expenses over $28,000; Vermont's 2021 low-income child care credit needs AGI under the threshold; the New York and New York City household credits count the federal exemptions of married, head-of-household and surviving-spouse filers instead of denying the credit when a filer can be claimed (Tax Law 606(b), 1310(d)), and the New York City credit for a married couple filing separately uses the couple's AGI and exemptions, and separate filers get exactly one-half of both household credits (Tax Law 606(b)(3)(C), 1310(d)(3)(C)) rather than the tables' rounded halves; Puerto Rico's earned income credit uses Hacienda's 2024 and 2025 inflation-adjusted schedules; and the New York City household credit gives negative AGI the lowest bracket's amount. diff --git a/policyengine_us/parameters/gov/local/ny/nyc/tax/income/credits/household/flat_amount.yaml b/policyengine_us/parameters/gov/local/ny/nyc/tax/income/credits/household/flat_amount.yaml index 8ff0f54f145..b66bbc6aa4b 100644 --- a/policyengine_us/parameters/gov/local/ny/nyc/tax/income/credits/household/flat_amount.yaml +++ b/policyengine_us/parameters/gov/local/ny/nyc/tax/income/credits/household/flat_amount.yaml @@ -15,7 +15,7 @@ metadata: href: https://www.tax.ny.gov/pdf/current_forms/it/it201i.pdf#page=20 brackets: - threshold: - 2022-01-01: -1 + 2022-01-01: -.inf amount: 2022-01-01: 15 - threshold: diff --git a/policyengine_us/parameters/gov/local/ny/nyc/tax/income/credits/household/other_per_dependent.yaml b/policyengine_us/parameters/gov/local/ny/nyc/tax/income/credits/household/other_per_dependent.yaml index ede9c2334d5..3a7af369bbf 100644 --- a/policyengine_us/parameters/gov/local/ny/nyc/tax/income/credits/household/other_per_dependent.yaml +++ b/policyengine_us/parameters/gov/local/ny/nyc/tax/income/credits/household/other_per_dependent.yaml @@ -1,9 +1,9 @@ -description: NYC provides a household credit of this amount per dependent for joint, suriving spouse, and head of household filers. +description: NYC provides a household credit of this amount per exemption for joint, surviving spouse, head of household and, before halving, separate filers. metadata: type: single_amount threshold_unit: currency-USD amount_unit: currency-USD - label: NYC Household Credit for joint, suriving spouse, and head of household filers. + label: NYC Household Credit per exemption for non-single filers reference: - title: Instructions for Form IT-201, 2022 href: https://www.tax.ny.gov/pdf/2022/printable-pdfs/inc/it201i-2022.pdf#page=17 @@ -15,7 +15,7 @@ metadata: href: https://www.tax.ny.gov/pdf/current_forms/it/it201i.pdf#page=20 brackets: - threshold: - 2022-01-01: -1 + 2022-01-01: -.inf amount: 2022-01-01: 30 - threshold: diff --git a/policyengine_us/parameters/gov/local/ny/nyc/tax/income/credits/household/separate_per_dependent.yaml b/policyengine_us/parameters/gov/local/ny/nyc/tax/income/credits/household/separate_per_dependent.yaml index 93b9f764442..8d4a2739796 100644 --- a/policyengine_us/parameters/gov/local/ny/nyc/tax/income/credits/household/separate_per_dependent.yaml +++ b/policyengine_us/parameters/gov/local/ny/nyc/tax/income/credits/household/separate_per_dependent.yaml @@ -1,4 +1,8 @@ -description: NYC provides a household credit of this amount per dependent for separate filers. +description: IT-201 Table 6 lists this NYC household credit amount per dependent for separate filers. +# Not used by nyc_household_credit: Tax Law 1310(d) gives a separate filer +# "one-half the credit otherwise allowed his or her household", which the +# model computes from the married amounts (other_per_dependent). Table 6 +# rounds the half amount per exemption, which can differ by a dollar or more. metadata: type: single_amount threshold_unit: currency-USD @@ -15,7 +19,7 @@ metadata: href: https://www.tax.ny.gov/pdf/current_forms/it/it201i.pdf#page=20 brackets: - threshold: - 2022-01-01: -1 + 2022-01-01: -.inf amount: 2022-01-01: 15 - threshold: diff --git a/policyengine_us/parameters/gov/states/nm/tax/income/exemptions/unreimbursed_medical_care_expense/min_expenses.yaml b/policyengine_us/parameters/gov/states/nm/tax/income/exemptions/unreimbursed_medical_care_expense/min_expenses.yaml index 5aaca843301..d02feaad554 100644 --- a/policyengine_us/parameters/gov/states/nm/tax/income/exemptions/unreimbursed_medical_care_expense/min_expenses.yaml +++ b/policyengine_us/parameters/gov/states/nm/tax/income/exemptions/unreimbursed_medical_care_expense/min_expenses.yaml @@ -1,4 +1,4 @@ -description: New Mexico provides the unreimbursed medical care expense exemption for filers with expenses at or above this amount. +description: New Mexico provides the unreimbursed medical care expense exemption for filers with expenses above this amount. values: 2005-01-01: 28_000 metadata: diff --git a/policyengine_us/parameters/gov/states/vt/tax/income/credits/cdcc/income_limit_in_effect.yaml b/policyengine_us/parameters/gov/states/vt/tax/income/credits/cdcc/income_limit_in_effect.yaml index 3e736d244b6..3e7124523e0 100644 --- a/policyengine_us/parameters/gov/states/vt/tax/income/credits/cdcc/income_limit_in_effect.yaml +++ b/policyengine_us/parameters/gov/states/vt/tax/income/credits/cdcc/income_limit_in_effect.yaml @@ -1,4 +1,4 @@ -description: Vermont limits the Child and Dependent Care Credit to filers with adjusted gross income at or below the low-income threshold when this is in effect. +description: Vermont limits the Child and Dependent Care Credit to filers with adjusted gross income below the low-income threshold when this is in effect. values: # Through 2021 the Vermont credit under 32 V.S.A. § 5828c was the low-income # child and dependent care credit, limited to filers with AGI below the diff --git a/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/max_amount.yaml b/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/max_amount.yaml index ce5d03dd662..324c3e19ee4 100644 --- a/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/max_amount.yaml +++ b/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/max_amount.yaml @@ -4,18 +4,26 @@ brackets: 2023-01-01: 0 amount: 2023-01-01: 1_656 + 2024-01-01: 1_745 + 2025-01-01: 1_794 - threshold: 2023-01-01: 1 amount: 2023-01-01: 3_864 + 2024-01-01: 4_071 + 2025-01-01: 4_186 - threshold: 2023-01-01: 2 amount: 2023-01-01: 6_072 + 2024-01-01: 6_400 + 2025-01-01: 6_576 - threshold: 2023-01-01: 3 amount: 2023-01-01: 7_173 + 2024-01-01: 7_563 + 2025-01-01: 7_774 metadata: amount_unit: currency-USD threshold_unit: child @@ -23,7 +31,12 @@ metadata: label: Puerto Rico earned income credit max amount period: year reference: - # discrepancy: legal statute max amount doesn't correspond with tax form values + - title: "Hacienda Boletín Informativo de Rentas Internas 24-04, inflation adjustment to the earned income credit for 2024 #page 1-3" + href: https://hacienda.pr.gov/sites/default/files/publicaciones/2024/12/bi_ri_24-04_-_credito_por_trabajo_-_ajuste_por_inflacion_2024_firmada_23-dic-2024.pdf#page=1 + - title: "Hacienda Boletín Informativo de Rentas Internas 26-01, inflation adjustment to the earned income credit for 2025 #page 1-3" + href: https://hacienda.pr.gov/sites/default/files/publicaciones/2026/02/bi_ri_26-01_ajuste_por_inflacion_al_credito_por_trabajo_para_el_ano_2025_signed.pdf#page=1 + - title: P.R. Internal Revenue Code § 1052.01(i), 13 L.P.R.A. § 30211(i) (inflation adjustment as adjusted by the federal IRS) + href: https://docs.pr.gov/files/OCIF/LEYES-REGLAMENTOS-CARTAS-CIRCULARES/Leyes-delegan-Facultad-OCIF/Ley%20N%C3%BAm.%201-2011%20-%20C%C3%B3digo%20de%20Rentas%20Internas%20para%20un%20Nuevo%20Puerto%20Rico.pdf#page=300 - title: P.R. Laws tit. 13, § 30211 (1)-(6) href: https://law.justia.com/codes/puerto-rico/title-thirteen/subtitle-17/part-ii/chapter-1007/subchapter-b/30211/ - title: Schedule CT Individual, Earned Income Credit, 2023 diff --git a/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/phase_out/threshold/joint.yaml b/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/phase_out/threshold/joint.yaml index b8742b1404a..4d136070e9a 100644 --- a/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/phase_out/threshold/joint.yaml +++ b/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/phase_out/threshold/joint.yaml @@ -5,18 +5,26 @@ brackets: 2023-01-01: 0 amount: 2023-01-01: 19_870 + 2024-01-01: 20_940 + 2025-01-01: 21_530 - threshold: 2023-01-01: 1 amount: 2023-01-01: 24_280 + 2024-01-01: 25_590 + 2025-01-01: 26_310 - threshold: 2023-01-01: 2 amount: 2023-01-01: 27_590 + 2024-01-01: 29_080 + 2025-01-01: 29_900 - threshold: 2023-01-01: 3 amount: 2023-01-01: 27_590 + 2024-01-01: 29_080 + 2025-01-01: 29_900 metadata: amount_unit: currency-USD threshold_unit: child @@ -24,8 +32,13 @@ metadata: label: Puerto Rico earned income credit phase out threshold period: year reference: + - title: "Hacienda Boletín Informativo de Rentas Internas 24-04, inflation adjustment to the earned income credit for 2024 #page 1-3" + href: https://hacienda.pr.gov/sites/default/files/publicaciones/2024/12/bi_ri_24-04_-_credito_por_trabajo_-_ajuste_por_inflacion_2024_firmada_23-dic-2024.pdf#page=1 + - title: "Hacienda Boletín Informativo de Rentas Internas 26-01, inflation adjustment to the earned income credit for 2025 #page 1-3" + href: https://hacienda.pr.gov/sites/default/files/publicaciones/2026/02/bi_ri_26-01_ajuste_por_inflacion_al_credito_por_trabajo_para_el_ano_2025_signed.pdf#page=1 + - title: P.R. Internal Revenue Code § 1052.01(i), 13 L.P.R.A. § 30211(i) (inflation adjustment as adjusted by the federal IRS) + href: https://docs.pr.gov/files/OCIF/LEYES-REGLAMENTOS-CARTAS-CIRCULARES/Leyes-delegan-Facultad-OCIF/Ley%20N%C3%BAm.%201-2011%20-%20C%C3%B3digo%20de%20Rentas%20Internas%20para%20un%20Nuevo%20Puerto%20Rico.pdf#page=300 - title: Schedule CT Individual, Earned Income Credit, 2023 href: https://hacienda.pr.gov/sites/default/files/schedule_ct_rev._jul_5_23_informative_-_instructions.pdf#page=2 - # discrepancy: legal statute phase out thresholds do not correspond with tax form values - title: P.R. Laws tit. 13, § 30211 (1) - (6) href: https://law.justia.com/codes/puerto-rico/title-thirteen/subtitle-17/part-ii/chapter-1007/subchapter-b/30211/ diff --git a/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/phase_out/threshold/single.yaml b/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/phase_out/threshold/single.yaml index 3f25534d252..0446792fce9 100644 --- a/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/phase_out/threshold/single.yaml +++ b/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/phase_out/threshold/single.yaml @@ -5,18 +5,26 @@ brackets: 2023-01-01: 0 amount: 2023-01-01: 17_660 + 2024-01-01: 18_610 + 2025-01-01: 19_130 - threshold: 2023-01-01: 1 amount: 2023-01-01: 19_870 + 2024-01-01: 20_940 + 2025-01-01: 21_530 - threshold: 2023-01-01: 2 amount: 2023-01-01: 23_180 + 2024-01-01: 24_430 + 2025-01-01: 25_110 - threshold: 2023-01-01: 3 amount: 2023-01-01: 23_180 + 2024-01-01: 24_430 + 2025-01-01: 25_110 metadata: amount_unit: currency-USD threshold_unit: child @@ -24,8 +32,13 @@ metadata: label: Puerto Rico earned income credit phase out threshold period: year reference: + - title: "Hacienda Boletín Informativo de Rentas Internas 24-04, inflation adjustment to the earned income credit for 2024 #page 1-3" + href: https://hacienda.pr.gov/sites/default/files/publicaciones/2024/12/bi_ri_24-04_-_credito_por_trabajo_-_ajuste_por_inflacion_2024_firmada_23-dic-2024.pdf#page=1 + - title: "Hacienda Boletín Informativo de Rentas Internas 26-01, inflation adjustment to the earned income credit for 2025 #page 1-3" + href: https://hacienda.pr.gov/sites/default/files/publicaciones/2026/02/bi_ri_26-01_ajuste_por_inflacion_al_credito_por_trabajo_para_el_ano_2025_signed.pdf#page=1 + - title: P.R. Internal Revenue Code § 1052.01(i), 13 L.P.R.A. § 30211(i) (inflation adjustment as adjusted by the federal IRS) + href: https://docs.pr.gov/files/OCIF/LEYES-REGLAMENTOS-CARTAS-CIRCULARES/Leyes-delegan-Facultad-OCIF/Ley%20N%C3%BAm.%201-2011%20-%20C%C3%B3digo%20de%20Rentas%20Internas%20para%20un%20Nuevo%20Puerto%20Rico.pdf#page=300 - title: Schedule CT Individual, Earned Income Credit, 2023 href: https://hacienda.pr.gov/sites/default/files/schedule_ct_rev._jul_5_23_informative_-_instructions.pdf#page=2 - # discrepancy: legal statute phase out thresholds do not correspond with tax form values - title: P.R. Laws tit. 13, § 30211 (1) - (6) href: https://law.justia.com/codes/puerto-rico/title-thirteen/subtitle-17/part-ii/chapter-1007/subchapter-b/30211/ diff --git a/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/unearned_income/limit.yaml b/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/unearned_income/limit.yaml index 6ed10b22989..d2151145b09 100644 --- a/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/unearned_income/limit.yaml +++ b/policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/unearned_income/limit.yaml @@ -1,4 +1,4 @@ -description: Puerto Rico limits the earned income credit to filers with unearned income below this threshold. +description: Puerto Rico limits the earned income credit to filers with unearned income at or below this threshold. values: 2023-01-01: 10_000 metadata: @@ -6,7 +6,9 @@ metadata: label: Puerto Rico earned income credit unearned income limit period: year reference: - # discrepancy: legal statute lists unearned income as 2_200 + # Section 1052.01(e) keeps older $2,200 wording but adds a proviso for + # taxable years after 2020 allowing other income, including exempt + # unearned income, equal to or below $10,000. - title: P.R. Laws tit. 13, § 30211 (6)(e) href: https://law.justia.com/codes/puerto-rico/title-thirteen/subtitle-17/part-ii/chapter-1007/subchapter-b/30211/ - title: Schedule CT Individual, Earned Income Credit, 2023 diff --git a/policyengine_us/tests/code_health/test_source_conflicts.py b/policyengine_us/tests/code_health/test_source_conflicts.py index b2f15532b65..3c662116dc7 100644 --- a/policyengine_us/tests/code_health/test_source_conflicts.py +++ b/policyengine_us/tests/code_health/test_source_conflicts.py @@ -141,12 +141,8 @@ "policyengine_us/parameters/gov/states/wi/tax/income/credits/homestead/income/disqualified_loss_sources.yaml": 1, "policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/eligibility/min.yaml": 1, "policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/eligibility/separate_filer.yaml": 1, - "policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/max_amount.yaml": 1, "policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/phase_in_rate.yaml": 1, "policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/phase_out/rate.yaml": 1, - "policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/phase_out/threshold/joint.yaml": 1, - "policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/phase_out/threshold/single.yaml": 1, - "policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/unearned_income/limit.yaml": 1, "policyengine_us/parameters/gov/territories/pr/tax/income/gradual_adjustment/exemption_rate.yaml": 1, "policyengine_us/parameters/gov/territories/pr/tax/income/gradual_adjustment/threshold.yaml": 1, "policyengine_us/parameters/gov/usda/snap/eligibility/waiting_period/subject_immigration_statuses.yaml": 1, @@ -158,6 +154,7 @@ "policyengine_us/variables/gov/irs/tax_unit_is_required_to_file.py": 1, "policyengine_us/variables/gov/local/ca/cc/ga/ca_cc_general_assistance_maximum_grant.py": 1, "policyengine_us/variables/gov/local/ca/cc/ga/eligibility/ca_cc_general_assistance_eligible.py": 1, + "policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/household/nyc_household_credit.py": 2, "policyengine_us/variables/gov/states/ar/ade/oec/sra/rates/ar_sra_daily_copay.py": 1, "policyengine_us/variables/gov/states/ca/hbex/premium_subsidy/ca_premium_subsidy_applicable_percentage.py": 1, "policyengine_us/variables/gov/states/ct/tax/income/rebate/ct_child_tax_rebate.py": 1, @@ -171,6 +168,8 @@ "policyengine_us/variables/gov/states/mn/dcyf/mfip/income/earned/mn_mfip_dependent_care_deduction.py": 1, "policyengine_us/variables/gov/states/mn/tax/income/deductions/mn_itemized_deductions.py": 1, "policyengine_us/variables/gov/states/mo/dese/ccs/eligibility/mo_ccs_income_eligible.py": 1, + "policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.py": 1, + "policyengine_us/variables/gov/states/ny/tax/income/credits/ny_household_credit_potential.py": 2, "policyengine_us/variables/gov/states/sc/tax/income/subtractions/retirement/sc_retirement_deduction_survivors.py": 1, "policyengine_us/variables/gov/states/vt/tax/income/credits/cdcc/vt_low_income_cdcc_eligible.py": 1, "policyengine_us/variables/gov/states/wa/dor/property_tax_exemption/senior_disabled/wa_pte_categorical_eligible.py": 1, diff --git a/policyengine_us/tests/core/test_medical_expense_premium_conservation.py b/policyengine_us/tests/core/test_medical_expense_premium_conservation.py index f5be96ce466..a6fb3942079 100644 --- a/policyengine_us/tests/core/test_medical_expense_premium_conservation.py +++ b/policyengine_us/tests/core/test_medical_expense_premium_conservation.py @@ -399,7 +399,10 @@ def _state_simulation(cases, reference_system, with_se_deduction): # deduction. The oracle preserves the supplied amount exactly as main # does; only the computed path restores an applied federal exclusion. main_base = case["subtotal"] if supplied else gross + # The credit (NMSA 7-2-18.13) takes expenses of $28,000 or more; the + # exemption (NMSA 7-2-5.9(A)) takes expenses that "exceed" $28,000. senior_eligible = case["age"] >= 65 and main_base >= 28_000 + senior_exemption_eligible = case["age"] >= 65 and main_base > 28_000 denominator = 2 if case["filing_status"] == "SEPARATE" else 1 for state in ("ND", "NM"): @@ -468,7 +471,7 @@ def _state_simulation(cases, reference_system, with_se_deduction): ) # NMSA 7-2-5.9 and PIT-ADJ line 18 allow the full exemption. expectations["nm_medical_expense_exemption"].append( - 3_000 if state == "NM" and senior_eligible else 0 + 3_000 if state == "NM" and senior_exemption_eligible else 0 ) simulation = Simulation( tax_benefit_system=reference_system, diff --git a/policyengine_us/tests/core/test_nm_ctc_children_medical_exemption_invariants.py b/policyengine_us/tests/core/test_nm_ctc_children_medical_exemption_invariants.py index 96154868af8..c778364bfcb 100644 --- a/policyengine_us/tests/core/test_nm_ctc_children_medical_exemption_invariants.py +++ b/policyengine_us/tests/core/test_nm_ctc_children_medical_exemption_invariants.py @@ -4,8 +4,9 @@ by IRC 152(c), which has no taxpayer identification number requirement, so `nm_ctc_qualifying_children` counts 152(c) children whatever their Social Security number status. NMSA 7-2-5.9 gives $3,000 to a filer or spouse 65 or -older with at least $28,000 of medical care expenses (the PIT-ADJ reading of -the threshold), with no halving for married filing separately. +older with more than $28,000 of medical care expenses (NMSA 7-2-5.9(A); the +PIT-ADJ instructions' "$28,000 or more" is not followed), with no halving for +married filing separately. For households drawn by Hypothesis and a seeded population, in 2023-2026: @@ -25,8 +26,8 @@ 5. Separate filing: a single adult filing separately gets half of `nm_ctc` (7-2-18.34(G)) and the whole `nm_medical_expense_exemption`. 6. Reference exemption: `nm_medical_expense_exemption` is $3,000 exactly when - a filer (not a dependent) is 65 or older and medical expenses are at least - $28,000, and 0 otherwise. + a filer (not a dependent) is 65 or older and medical expenses are more than + $28,000 (NMSA 7-2-5.9(A)), and 0 otherwise. """ import numpy as np @@ -182,7 +183,7 @@ def unit(adults, dependents, expenses=0.0): unit([adult(25), adult(20)], [dependent(22, student=True)]), # The only 65+ person is a dependent parent. unit([adult(40)], [elderly_parent], expenses=30_000.0), - # A 65+ filer with exactly $28,000 of expenses. + # A 65+ filer with exactly $28,000 of expenses (not over $28,000). unit([adult(70)], [], expenses=28_000.0), ] @@ -268,7 +269,8 @@ def _reference_exemption(unit): if unit["state"] != "NM": return 0 filer_65 = any(a["age"] >= 65 for a in unit["adults"]) - return EXEMPTION * (filer_65 and unit["medical_expenses"] >= MIN_EXPENSES) + # NMSA 7-2-5.9(A): expenses that "exceed" $28,000. + return EXEMPTION * (filer_65 and unit["medical_expenses"] > MIN_EXPENSES) def _describe(unit): @@ -336,7 +338,7 @@ def _assert_coverage(drawn_units, credit, exemption): u["state"] == "NM" and all(a["age"] < 65 for a in u["adults"]) and any(d["age"] >= 65 for d in u["dependents"]) - and u["medical_expenses"] >= MIN_EXPENSES + and u["medical_expenses"] > MIN_EXPENSES for u in drawn_units ] ) diff --git a/policyengine_us/tests/core/test_state_medical_expense_input_deletion.py b/policyengine_us/tests/core/test_state_medical_expense_input_deletion.py index 8f700ae0cae..c48a55b7835 100644 --- a/policyengine_us/tests/core/test_state_medical_expense_input_deletion.py +++ b/policyengine_us/tests/core/test_state_medical_expense_input_deletion.py @@ -69,13 +69,14 @@ def test_nd_paid_cost_base_after_medical_subtotal_deletion(delete_subtotal): @pytest.mark.parametrize("delete_subtotal", SUBTOTAL_DELETION_CASES) def test_nm_senior_benefits_after_medical_subtotal_deletion(delete_subtotal): - simulation = _simulation("NM", other_expenses=22_000) + simulation = _simulation("NM", other_expenses=22_001) if delete_subtotal: simulation.delete_arrays("itemized_medical_expenses", PERIOD) - # The recomputed federal subtotal is 27,000, but restoring its 1,000 - # exclusion meets NM's 28,000 paid-cost threshold. Calculate both before - # asserting to preserve evidence. + # The recomputed federal subtotal is 27,001, but restoring its 1,000 + # exclusion gives 28,001 of paid costs, which meets the credit's $28,000 + # threshold and exceeds the exemption's. Calculate both before asserting + # to preserve evidence. benefits = tuple( simulation.calculate(variable, PERIOD).item() for variable in ( diff --git a/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/household/nyc_household_credit.yaml b/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/household/nyc_household_credit.yaml index badd48577b1..7ff3c1be8e3 100644 --- a/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/household/nyc_household_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/household/nyc_household_credit.yaml @@ -186,52 +186,84 @@ output: nyc_household_credit: 0 -- name: Separate filers making $15k or less get $15 per tax unit dependent (size=2). +# Tax Law 1310(d) and IT-201 Table 6: a married couple filing separately is +# one household, keyed on federal AGI and dependents "from both returns" plus +# one for each spouse, and each spouse gets half the household amount. +- name: Separate filers with household AGI of $15k or less get half of $30 per exemption of the couple. period: 2022 absolute_error_margin: 0 input: state_code: NY in_nyc: true - adjusted_gross_income: 15_000 + adjusted_gross_income: 7_500 + spouse_separate_adjusted_gross_income: 7_500 filing_status: SEPARATE tax_unit_size: 2 + spouse_separate_tax_unit_size: 2 output: - nyc_household_credit: 30 + # Household AGI $15,000: $30 x (2 + 2) = $120, halved. + nyc_household_credit: 60 -- name: Separate filers making $18k get $8 per tax unit dependent (size=4). +- name: Separate filers with household AGI of $18k get half of $15 per exemption of the couple. period: 2022 - absolute_error_margin: 3 # Table has some rounding. + absolute_error_margin: 0 input: state_code: NY in_nyc: true - adjusted_gross_income: 18_000 + adjusted_gross_income: 9_000 + spouse_separate_adjusted_gross_income: 9_000 filing_status: SEPARATE tax_unit_size: 4 + spouse_separate_tax_unit_size: 4 output: - nyc_household_credit: 32 + # Household AGI $18,000: the married amount is $15 per exemption, so the + # household credit is $15 x 8 = $120 and each spouse gets half, $60. + # IT-201 Table 6 rounds the half amount to $8 per exemption ($53 + $8 = + # $61 with its over-seven note); the model follows Tax Law 1310(d). + nyc_household_credit: 60 -- name: Separate filers making $21k get $5 per tax unit dependent. +- name: Separate filers with household AGI of $21k get half of $10 per exemption of the couple. period: 2022 - absolute_error_margin: 3 # Table has some rounding. + absolute_error_margin: 0 input: state_code: NY in_nyc: true - adjusted_gross_income: 21_000 + adjusted_gross_income: 10_500 + spouse_separate_adjusted_gross_income: 10_500 filing_status: SEPARATE tax_unit_size: 6 + spouse_separate_tax_unit_size: 6 output: - nyc_household_credit: 30 + # Household AGI $21,000: $10 x (6 + 6) = $120, halved. + nyc_household_credit: 60 -- name: Separate filers making over $22.5k gets no credit. +- name: Separate filers with household AGI over $22.5k get no credit. period: 2022 absolute_error_margin: 0 input: state_code: NY in_nyc: true - adjusted_gross_income: 22_501 + adjusted_gross_income: 11_251 + spouse_separate_adjusted_gross_income: 11_251 filing_status: SEPARATE tax_unit_size: 4 + spouse_separate_tax_unit_size: 4 + output: + nyc_household_credit: 0 + +- name: A separate filer's own AGI alone does not set the bracket. + period: 2022 + absolute_error_margin: 0 + input: + state_code: NY + in_nyc: true + adjusted_gross_income: 15_000 + spouse_separate_adjusted_gross_income: 15_000 + filing_status: SEPARATE + tax_unit_size: 2 + spouse_separate_tax_unit_size: 2 output: + # Household AGI $30,000 is over $22,500. nyc_household_credit: 0 @@ -273,7 +305,7 @@ output: nyc_household_credit: 15 -- name: 2025 joint return with one claimable spouse gets no NYC household credit (the claimable spouse is the head) +- name: 2025 joint return with one claimable spouse counts the other spouse's exemption for the NYC credit (the claimable spouse is the head) period: 2025 input: people: @@ -298,9 +330,12 @@ state_code: NY in_nyc: true output: - nyc_household_credit: 0 + # Tax Law 1310(d) counts the exemptions the couple is entitled to: one. + # $30 x 1. IT-201 line 48 would deny the credit; the model follows the + # statute. + nyc_household_credit: 30 -- name: 2025 joint return with one claimable spouse gets no NYC household credit (the claimable spouse is the spouse) +- name: 2025 joint return with one claimable spouse counts the other spouse's exemption for the NYC credit (the claimable spouse is the spouse) period: 2025 input: people: @@ -325,7 +360,7 @@ state_code: NY in_nyc: true output: - nyc_household_credit: 0 + nyc_household_credit: 30 - name: 2025 joint return with neither spouse claimable gets the NYC household credit period: 2025 @@ -350,6 +385,81 @@ # $30 x 2. nyc_household_credit: 60 +# Tax Law 1310(d): only an unmarried individual is excluded for being +# claimable; other households count the exemptions they are entitled to. +- name: 2025 separate filer who can be claimed gets half the household credit for the spouse's exemption + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 5_000 + claimed_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [person_a] + filing_status: SEPARATE + households: + household: + members: [person_a] + state_code: NY + in_nyc: true + output: + # Household AGI $10,000 (the spouse's return is assumed alike); the + # couple's exemptions: 0 for the claimable filer plus 1 for the spouse. + # $30 x 1, halved. + nyc_household_credit: 15 + +- name: 2025 joint return where both spouses can be claimed has no exemptions for the NYC credit + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 5_000 + claimed_as_dependent_on_another_return: true + person_b: + age: 22 + employment_income: 5_000 + claimed_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + households: + household: + members: [person_a, person_b] + state_code: NY + in_nyc: true + output: + nyc_household_credit: 0 + +- name: 2025 head of household who can be claimed counts the dependent's exemption + period: 2025 + input: + people: + parent: + age: 22 + employment_income: 10_000 + claimed_as_dependent_on_another_return: true + child: + age: 2 + tax_units: + tax_unit: + members: [parent, child] + filing_status: HEAD_OF_HOUSEHOLD + # The would-be claimant need not file, so the parent may still claim + # the child (Publication 501, Dependent Taxpayer Test). + head_or_spouse_is_dependent_elsewhere_without_filing_exception: false + households: + household: + members: [parent, child] + state_code: NY + in_nyc: true + output: + # One exemption (the child); $30 x 1. + nyc_household_credit: 30 + - name: 2020 NYC household credit uses recomputed federal AGI period: 2020 input: @@ -371,3 +481,70 @@ # federal AGI (IT-201 line 19a) is 12,600, over it. adjusted_gross_income: 12_300 nyc_household_credit: 0 + +- name: 2025 surviving spouse who can be claimed counts the dependent's exemption + # Tax Law 1310(d)(3)(B): a surviving spouse is a household in its own right. + period: 2025 + input: + people: + parent: + age: 22 + employment_income: 10_000 + claimed_as_dependent_on_another_return: true + child: + age: 2 + tax_units: + tax_unit: + members: [parent, child] + filing_status: SURVIVING_SPOUSE + head_or_spouse_is_dependent_elsewhere_without_filing_exception: false + households: + household: + members: [parent, child] + state_code: NY + in_nyc: true + output: + # One exemption (the child); $30 x 1. + nyc_household_credit: 30 + +- name: Separate filers get exactly half the household credit, not Table 6's rounded amount + period: 2022 + absolute_error_margin: 0 + input: + state_code: NY + in_nyc: true + adjusted_gross_income: 8_000 + spouse_separate_adjusted_gross_income: 8_000 + filing_status: SEPARATE + tax_unit_size: 1 + spouse_separate_tax_unit_size: 2 + output: + # Household AGI $16,000 is over $15,000 and not over $17,500: $25 per + # exemption. $25 x (1 + 2) = $75, halved: $37.50 (Table 6 prints $38). + nyc_household_credit: 37.5 + +- name: A single filer with negative AGI gets the lowest-bracket NYC credit + # The 1310(d) table's first row is "Not over $10,000", which includes + # zero and negative AGI. + period: 2025 + absolute_error_margin: 0 + input: + state_code: NY + in_nyc: true + adjusted_gross_income: -5_000 + filing_status: SINGLE + output: + nyc_household_credit: 15 + +- name: A joint return with negative AGI gets the lowest-bracket NYC credit per exemption + period: 2025 + absolute_error_margin: 0 + input: + state_code: NY + in_nyc: true + adjusted_gross_income: -5_000 + filing_status: JOINT + tax_unit_size: 2 + output: + # $30 x 2. + nyc_household_credit: 60 diff --git a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.yaml b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.yaml index fbc36a3d88e..c0abdd891c8 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.yaml @@ -15,10 +15,12 @@ age: 65 medicare_enrolled: false health_insurance_premiums: 6_000 - other_medical_expenses: 22_000 + other_medical_expenses: 22_001 self_employed_health_insurance_ald: 1_000 output: - itemized_medical_expenses: 27_000 + # Gross paid: 6,000 + 22,001 = 28,001, over $28,000; the federal + # subtotal (27,001) excludes the 1,000 deducted premium. + itemized_medical_expenses: 27_001 nm_medical_expense_exemption: 3_000 - name: New Mexico senior exemption preserves caller-supplied medical expenses @@ -27,7 +29,7 @@ state_code: NM age: 65 medicare_enrolled: false - itemized_medical_expenses: 28_000 + itemized_medical_expenses: 28_001 output: nm_medical_expense_exemption: 3_000 @@ -58,7 +60,7 @@ input: state_code: NM age: 65 - other_medical_expenses: 28_000 + other_medical_expenses: 28_001 filing_status: JOINT output: nm_medical_expense_exemption: 3_000 @@ -68,7 +70,7 @@ input: state_code: NM age: 65 - other_medical_expenses: 28_000 + other_medical_expenses: 28_001 filing_status: SEPARATE output: # Neither NMSA 7-2-5.9 nor the PIT-ADJ line 18 instructions halve the @@ -87,7 +89,7 @@ # PIT-ADJ line 18: "enter $3,000 on line 18 to claim the exemption". nm_medical_expense_exemption: 3_000 -- name: 2025 expenses of exactly $28,000 qualify under the PIT-ADJ instructions +- name: 2025 expenses of exactly $28,000 do not qualify under the statute period: 2025 input: state_code: NM @@ -96,8 +98,20 @@ other_medical_expenses: 28_000 filing_status: SINGLE output: - # PIT-ADJ line 18: expenses "of $28,000 or more". NMSA 7-2-5.9(A) says - # expenses that "exceed" $28,000, which would give 0 here. + # NMSA 7-2-5.9(A): expenses that "exceed twenty-eight thousand dollars". + # The PIT-ADJ line 18 instructions say "of $28,000 or more", which would + # give 3,000; the model follows the statute. + nm_medical_expense_exemption: 0 + +- name: 2025 expenses one dollar over $28,000 qualify + period: 2025 + input: + state_code: NM + age: 70 + medicare_enrolled: false + other_medical_expenses: 28_001 + filing_status: SINGLE + output: nm_medical_expense_exemption: 3_000 - name: 2025 expenses one dollar under $28,000 do not qualify diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_household_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_household_credit.yaml index 75ecd16039e..4258a8850b0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_household_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_household_credit.yaml @@ -31,9 +31,10 @@ ny_income_tax_before_credits: 1000000 output: ny_household_credit: 35 -- name: 2-person married filing separately tax unit with $16,000 income receives half - of a 4-person's with $32,000 income (above), rounded up. +- name: 2-person married filing separately tax unit with $16,000 income receives exactly + half of a 4-person's with $32,000 income (above). period: 2021 + absolute_error_margin: 0 input: state_code: NY adjusted_gross_income: 16000 @@ -43,7 +44,10 @@ spouse_separate_tax_unit_size: 2 ny_income_tax_before_credits: 1000000 output: - ny_household_credit: 18 + # Combined AGI $32,000 is "not over $32,000": $20 base + $5 x (4 - 1) = + # $35. Tax Law 606(b)(3)(C) gives one-half, $17.50; IT-201 Table 3 rounds + # it up to $18. The model follows the statute. + ny_household_credit: 17.5 - name: Simple ny_household_credit test absolute_error_margin: 0.01 period: 2021 @@ -127,7 +131,7 @@ output: ny_household_credit_potential: 45 -- name: 2025 joint return with one claimable spouse gets no household credit (the claimable spouse is the head) +- name: 2025 joint return with one claimable spouse counts the other spouse's exemption (the claimable spouse is the head) period: 2025 input: people: @@ -151,10 +155,13 @@ members: [person_a, person_b] state_code: NY output: - # Item C is one box per return; either spouse marks it. - ny_household_credit_potential: 0 + # Tax Law 606(b) counts the exemptions the couple is entitled to: one, + # for the spouse who cannot be claimed. $60 base at $10,000 of AGI plus + # $15 x (1 - 1). IT-201 line 40 would deny the credit because item C is + # marked; the model follows the statute. + ny_household_credit_potential: 60 -- name: 2025 joint return with one claimable spouse gets no household credit (the claimable spouse is the spouse) +- name: 2025 joint return with one claimable spouse counts the other spouse's exemption (the claimable spouse is the spouse) period: 2025 input: people: @@ -178,7 +185,7 @@ members: [person_b, person_a] state_code: NY output: - ny_household_credit_potential: 0 + ny_household_credit_potential: 60 - name: 2025 joint return with neither spouse claimable gets the household credit period: 2025 @@ -201,3 +208,125 @@ output: # $60 + $15 x (2 - 1). ny_household_credit_potential: 75 + +# Tax Law 606(b)(3)(B): a husband and wife, a head of household and a +# surviving spouse are households in their own right; only an unmarried +# individual is excluded for being claimable. IT-201 line 40 denies every +# return with item C marked; the model follows the statute. +- name: 2025 separate filer who can be claimed counts the couple's exemptions + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 5_000 + claimed_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [person_a] + filing_status: SEPARATE + households: + household: + members: [person_a] + state_code: NY + output: + # Combined AGI $10,000 (the spouse's separate return is assumed alike); + # exemptions: 0 for the claimable filer plus 1 for the spouse's unit. + # $60 base + $15 x (1 - 1) = $60, halved for a separate return. + ny_household_credit_potential: 30 + +- name: 2025 joint return where both spouses can be claimed reduces the base by one additional amount + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 5_000 + claimed_as_dependent_on_another_return: true + person_b: + age: 22 + employment_income: 5_000 + claimed_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + households: + household: + members: [person_a, person_b] + state_code: NY + output: + # No exemptions: $60 base + $15 x (0 - 1) = $45. + ny_household_credit_potential: 45 + +- name: 2025 head of household who can be claimed counts the dependent's exemption + period: 2025 + input: + people: + parent: + age: 22 + employment_income: 10_000 + claimed_as_dependent_on_another_return: true + child: + age: 2 + tax_units: + tax_unit: + members: [parent, child] + filing_status: HEAD_OF_HOUSEHOLD + # The would-be claimant need not file, so the parent may still claim + # the child (Publication 501, Dependent Taxpayer Test). + head_or_spouse_is_dependent_elsewhere_without_filing_exception: false + households: + household: + members: [parent, child] + state_code: NY + output: + # One exemption: $60 base + $15 x (1 - 1). + ny_household_credit_potential: 60 + +- name: 2025 surviving spouse who can be claimed counts the dependent's exemption + # Tax Law 606(b)(3)(B): a surviving spouse is a household in its own right. + period: 2025 + input: + people: + parent: + age: 22 + employment_income: 10_000 + claimed_as_dependent_on_another_return: true + child: + age: 2 + tax_units: + tax_unit: + members: [parent, child] + filing_status: SURVIVING_SPOUSE + head_or_spouse_is_dependent_elsewhere_without_filing_exception: false + households: + household: + members: [parent, child] + state_code: NY + output: + # One exemption (the child): $60 base + $15 x (1 - 1). + ny_household_credit_potential: 60 + +- name: 2025 separate filer gets exactly one-half of the household credit, not Table 3's rounded amount + period: 2025 + absolute_error_margin: 0 + input: + people: + person_a: + age: 40 + employment_income: 2_500 + tax_units: + tax_unit: + members: [person_a] + filing_status: SEPARATE + households: + household: + members: [person_a] + state_code: NY + output: + # Combined AGI $2,500 + $2,500 = $5,000 (the spouse's separate return is + # assumed alike), which is "not over $5,000"; exemptions 1 + 1 = 2. + # Household amount: $90 base + $15 x (2 - 1) = $105. Tax Law 606(b)(3)(C) + # gives one-half, $52.50; IT-201 Table 3 prints $53 for two exemptions. + ny_household_credit_potential: 52.5 diff --git a/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/credits/cdcc/vt_low_income_cdcc_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/credits/cdcc/vt_low_income_cdcc_eligible.yaml index 2bd8ce741df..0dc4cac1263 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/credits/cdcc/vt_low_income_cdcc_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/credits/cdcc/vt_low_income_cdcc_eligible.yaml @@ -1,3 +1,8 @@ +# 32 V.S.A. 5828c as in effect for 2021: federal adjusted gross income "less +# than $30,000.00 (or $40,000.00 for married, filing jointly)". The 2021 +# Schedule IN-112 says "$30,000 (or $40,000 for Married Filing Jointly) or +# less"; the model follows the statute, so income at the threshold does not +# qualify. - name: Vermont low-income CDCC single filer not eligible period: 2021 input: @@ -7,12 +12,21 @@ output: vt_low_income_cdcc_eligible: false -- name: Vermont low-income CDCC single filer eligible +- name: Vermont low-income CDCC single filer at the threshold not eligible period: 2021 input: state_code: VT adjusted_gross_income: 30_000 filing_status: SINGLE + output: + vt_low_income_cdcc_eligible: false + +- name: Vermont low-income CDCC single filer below the threshold eligible + period: 2021 + input: + state_code: VT + adjusted_gross_income: 29_999 + filing_status: SINGLE output: vt_low_income_cdcc_eligible: true @@ -25,14 +39,20 @@ output: vt_low_income_cdcc_eligible: false -- name: Vermont low-income CDCC joint filer eligible +- name: Vermont low-income CDCC joint filer at the threshold not eligible period: 2021 input: state_code: VT adjusted_gross_income: 40_000 filing_status: JOINT output: - vt_low_income_cdcc_eligible: true + vt_low_income_cdcc_eligible: false - - +- name: Vermont low-income CDCC joint filer below the threshold eligible + period: 2021 + input: + state_code: VT + adjusted_gross_income: 39_999 + filing_status: JOINT + output: + vt_low_income_cdcc_eligible: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/credits/cdcc/vt_nonrefundable_cdcc.yaml b/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/credits/cdcc/vt_nonrefundable_cdcc.yaml index 9d3ba433591..d49b377f41d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/credits/cdcc/vt_nonrefundable_cdcc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/credits/cdcc/vt_nonrefundable_cdcc.yaml @@ -26,3 +26,29 @@ state_code: VT output: vt_nonrefundable_cdcc: 0 + +- name: Vermont 2021 single filer at exactly $30,000 takes the nonrefundable credit + # The pre-2022 5828c test is AGI "less than $30,000.00", so a filer at the + # threshold is not low-income eligible and takes 24% of the federal credit. + period: 2021 + input: + capped_cdcc: 1_000 + adjusted_gross_income: 30_000 + filing_status: SINGLE + state_code: VT + output: + vt_low_income_cdcc_eligible: false + vt_low_income_cdcc: 0 + vt_nonrefundable_cdcc: 240 # 1,000 * 0.24 + +- name: Vermont 2021 joint filer at exactly $40,000 takes the nonrefundable credit + period: 2021 + input: + capped_cdcc: 1_000 + adjusted_gross_income: 40_000 + filing_status: JOINT + state_code: VT + output: + vt_low_income_cdcc_eligible: false + vt_low_income_cdcc: 0 + vt_nonrefundable_cdcc: 240 # 1,000 * 0.24 diff --git a/policyengine_us/tests/policy/baseline/gov/territories/pr/tax/income/credits/earned_income/integration.yaml b/policyengine_us/tests/policy/baseline/gov/territories/pr/tax/income/credits/earned_income/integration.yaml index 218cfb9da86..90853e2571d 100644 --- a/policyengine_us/tests/policy/baseline/gov/territories/pr/tax/income/credits/earned_income/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/territories/pr/tax/income/credits/earned_income/integration.yaml @@ -1,5 +1,5 @@ - name: integration test 1, a married couple with 2 dependents - period: 2024 + period: 2023 input: people: person1: @@ -29,7 +29,7 @@ pr_earned_income_credit: 6_072 - name: integration test 2, individual with 4 dependents - period: 2024 + period: 2023 input: people: person1: diff --git a/policyengine_us/tests/policy/baseline/gov/territories/pr/tax/income/credits/earned_income/pr_earned_income_credit.yaml b/policyengine_us/tests/policy/baseline/gov/territories/pr/tax/income/credits/earned_income/pr_earned_income_credit.yaml index 78abde891bf..92fbdcf688d 100644 --- a/policyengine_us/tests/policy/baseline/gov/territories/pr/tax/income/credits/earned_income/pr_earned_income_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/territories/pr/tax/income/credits/earned_income/pr_earned_income_credit.yaml @@ -25,7 +25,7 @@ pr_earned_income_credit: 0 - name: Eligible person, 0 children with max credit - period: 2024 + period: 2023 input: people: person1: @@ -45,7 +45,7 @@ pr_earned_income_credit: 1_656 - name: Eligible person, 1 child and higher bracket - period: 2024 + period: 2023 input: people: person1: @@ -68,7 +68,7 @@ pr_earned_income_credit: 2_483.004 - name: Eligible person, 0 child and filing jointly - period: 2024 + period: 2023 input: people: person1: @@ -91,7 +91,7 @@ pr_earned_income_credit: 1_656 - name: Eligible person, 1 child, filing jointly, higher bracket - period: 2024 + period: 2023 input: people: person1: @@ -152,7 +152,7 @@ pr_earned_income_credit: 0 - name: Eligible HEAD_OF_HOUSEHOLD filer gets the individual phase-out threshold - period: 2024 + period: 2023 input: people: person1: @@ -176,7 +176,7 @@ pr_earned_income_credit: 1_656 - name: Eligible SURVIVING_SPOUSE filer gets the joint phase-out threshold - period: 2024 + period: 2023 input: people: person1: @@ -198,3 +198,70 @@ # (joint threshold = 19_870), so the full max credit applies. output: pr_earned_income_credit: 1_656 + +# Section 1052.01(i) indexes the credit "según ajustado por el Servicio de +# Rentas Internas Federal"; Hacienda publishes the adjusted amounts in BI RI +# 24-04 (2024) and BI RI 26-01 (2025). +- name: 2024 three or more children, single, phase-out under the 2024 threshold + period: 2024 + input: + people: + person1: + pr_gross_income_person: 25_000 + is_tax_unit_head_or_spouse: true + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + eitc_child_count: 3 + pr_earned_income_credit_eligible: true + households: + household: + members: [person1] + state_code: PR + output: + # 2024 maximum $7,563 less 34.21% of ($25,000 - $24,430) = $194.997. + pr_earned_income_credit: 7_368.003 + +- name: 2025 three or more children, single, under the 2025 threshold + period: 2025 + input: + people: + person1: + pr_gross_income_person: 25_000 + is_tax_unit_head_or_spouse: true + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + eitc_child_count: 3 + pr_earned_income_credit_eligible: true + households: + household: + members: [person1] + state_code: PR + output: + # $25,000 is under the $25,110 threshold, so the $7,774 maximum applies + # (the 2023 schedule would give $7,173 - 34.21% x $1,820 = $6,550.378). + pr_earned_income_credit: 7_774 + +- name: 2025 one child, joint, phase-out over the 2025 threshold + period: 2025 + input: + people: + person1: + pr_gross_income_person: 30_000 + is_tax_unit_head_or_spouse: true + tax_units: + tax_unit: + members: [person1] + filing_status: JOINT + eitc_child_count: 1 + pr_earned_income_credit_eligible: true + households: + household: + members: [person1] + state_code: PR + output: + # $4,186 less 26.92% of ($30,000 - $26,310) = $993.348. + pr_earned_income_credit: 3_192.652 diff --git a/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/household/nyc_household_credit.py b/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/household/nyc_household_credit.py index 3f470e086f5..253f1f58895 100644 --- a/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/household/nyc_household_credit.py +++ b/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/household/nyc_household_credit.py @@ -8,6 +8,10 @@ class nyc_household_credit(Variable): unit = USD definition_period = YEAR defined_for = "in_nyc" + reference = ( + "https://www.nysenate.gov/legislation/laws/TAX/1310", + "https://www.tax.ny.gov/pdf/2025/inc/it201i_2025.pdf#page=13", + ) def formula(tax_unit, period, parameters): # Recomputed federal AGI (IT-201 line 19a), which differs from @@ -20,15 +24,32 @@ def formula(tax_unit, period, parameters): # Then get the household credit part of the parameter tree. p = parameters(period).gov.local.ny.nyc.tax.income.credits.household - # Then get their number of people. - tax_unit_size = tax_unit("tax_unit_size", period) - filing_statuses = filing_status.possible_values - # Tax Law 1310(d) excludes an individual whom another taxpayer can - # claim as a dependent; IT-201 line 48: "If you marked the Yes box at - # item C ... you do not qualify for this credit". + # Tax Law 1310(d) counts the exemptions each household is entitled to + # and excludes, among unmarried individuals, one whom another taxpayer + # can claim; a husband and wife, a head of household and a surviving + # spouse are households in their own right. At line 48 the IT-201 + # instructions say "If you marked the Yes box at item C ... you do not + # qualify for this credit" for every return; the model follows the + # statute. dependent_filer = tax_unit("head_or_spouse_is_dependent_elsewhere", period) + single = filing_status == filing_statuses.SINGLE + exemptions = tax_unit("exemptions_count", period) + # A husband and wife filing separately are one household: 1310(d) + # aggregates "their federal adjusted gross incomes ... irrespective + # of whether joint or separate city income tax returns are filed", + # and each spouse gets "one-half the credit otherwise allowed his or + # her household" (IT-201 Table 6: AGI and dependents "from both + # returns", plus one for each spouse). The model has no record of the + # other spouse's return, so it is assumed alike, as for New York + # State: its AGI and its unit's size are added. + separate_agi = federal_agi + tax_unit( + "spouse_separate_adjusted_gross_income", period + ) + separate_exemptions = exemptions + tax_unit( + "spouse_separate_tax_unit_size", period + ) amount = select( [ filing_status == filing_statuses.SINGLE, @@ -37,12 +58,19 @@ def formula(tax_unit, period, parameters): [ # Single filers get a flat amount. p.flat_amount.calc(federal_agi, right=True), - # Separate filers get an amount for each person in the tax - # unit, varying with AGI. - p.separate_per_dependent.calc(federal_agi, right=True) * tax_unit_size, + # Tax Law 1310(d)(3)(C) gives a separate filer "one-half the + # credit otherwise allowed his or her household": the married + # amount per exemption at the couple's AGI, times the couple's + # exemptions, halved. The IT-201 instructions say under Table 6 + # that "The credit amounts have been rounded", and the table's + # half amounts can differ by a dollar or more; the model + # follows the statute. + p.other_per_dependent.calc(separate_agi, right=True) + * separate_exemptions + / 2, ], # Joint, head of household, and surviving spouse filers have a different - # amount per person, varying with AGI. - default=p.other_per_dependent.calc(federal_agi, right=True) * tax_unit_size, + # amount per exemption, varying with AGI. + default=p.other_per_dependent.calc(federal_agi, right=True) * exemptions, ) - return where(dependent_filer, 0, amount) + return where(dependent_filer & single, 0, amount) diff --git a/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.py b/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.py index 1efcc1a8ac3..7b7d8c53b41 100644 --- a/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.py +++ b/policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.py @@ -50,10 +50,10 @@ def formula(tax_unit, period, parameters): filer = person("is_tax_unit_head_or_spouse", period) age_eligible = tax_unit.any(filer & (age >= p.age_eligibility)) # NMSA 7-2-5.9(A) requires expenses that "exceed twenty-eight thousand - # dollars ($28,000)"; PIT-ADJ line 18 instructions allow expenses "of - # $28,000 or more". This keeps the instructions' reading, under which - # expenses of exactly $28,000 qualify, until the conflict is resolved. - expense_eligible = medical_expense >= p.min_expenses + # dollars ($28,000)", but the PIT-ADJ line 18 instructions say expenses + # "of $28,000 or more" qualify. The model follows the statute, so + # expenses of exactly $28,000 do not qualify. + expense_eligible = medical_expense > p.min_expenses eligible = age_eligible & expense_eligible # Neither 7-2-5.9 nor the PIT-ADJ line 18 instructions halve the # exemption for married individuals filing separately. Sections that diff --git a/policyengine_us/variables/gov/states/ny/tax/income/credits/ny_household_credit_potential.py b/policyengine_us/variables/gov/states/ny/tax/income/credits/ny_household_credit_potential.py index d6e79046274..b722c9b0339 100644 --- a/policyengine_us/variables/gov/states/ny/tax/income/credits/ny_household_credit_potential.py +++ b/policyengine_us/variables/gov/states/ny/tax/income/credits/ny_household_credit_potential.py @@ -25,27 +25,41 @@ def formula(tax_unit, period, parameters): # Use `right=True` to reflect "over...but not over". amount_if_single = p.single.calc(agi, right=True) single_amount = single * amount_if_single - # All others are based on AGI & size. - # In the case of married filing separate, based on the combined AGI and size. - size = add( - tax_unit, - period, - ["tax_unit_size", "spouse_separate_tax_unit_size"], - ) + # All others are based on AGI and the number of exemptions. Tax Law + # 606(b)(2)(B) and (3)(B) count "the number of exemptions for which + # the taxpayer (or in the case of a husband and wife, taxpayers) is + # entitled to a deduction" for federal purposes, which leaves out a + # filer whom another taxpayer can claim (exemptions_count). A married + # couple filing separately uses the couple's combined AGI and + # exemptions; the model has no record of the other spouse's + # claimability, so the spouse's separate unit counts at its size. separate = filing_status == filing_statuses.SEPARATE + size = tax_unit("exemptions_count", period) + tax_unit( + "spouse_separate_tax_unit_size", period + ) non_single_base = p.non_single.base.calc(agi, right=True) non_single_additional = p.non_single.additional.calc(agi, right=True) - total_amount_if_not_single = non_single_base + non_single_additional * ( - size - 1 - ) - amount_if_not_single = np.ceil( - total_amount_if_not_single / where(separate, 2, 1) + # The statute adds the additional amount for each exemption beyond one. + # With no exemptions (both spouses of a refund-only joint return can + # be claimed) that is one less than none, so the base is reduced; + # the credit is not negative. + total_amount_if_not_single = max_( + non_single_base + non_single_additional * (size - 1), 0 ) + # Tax Law 606(b)(3)(C) permits a husband or wife filing a separate + # return "one-half the credit otherwise allowed his or her household". + # The IT-201 instructions say under Table 3 that "The credit amounts + # have been rounded", and the table rounds each half up to a whole + # dollar; the model follows the statute. + amount_if_not_single = total_amount_if_not_single / where(separate, 2, 1) non_single_amount = amount_if_not_single * ~single - # Tax Law 606(b)(3)(B) excludes an individual for whom a deduction - # under IRC 151(c) "is allowable to another taxpayer", and IT-201 line - # 40 says "If you marked the Yes box at item C ... you do not qualify - # for this credit". Item C is one box per return; this formula reads - # it as marked when either spouse of a joint return can be claimed. + # Tax Law 606(b)(3)(B) defines a household as a husband and wife, a + # head of household, a surviving spouse, or an unmarried individual + # for whom a deduction under IRC 151(c) is not "allowable to another + # taxpayer". Only a single filer is excluded for being claimable; the + # other households count only the exemptions they are entitled to. + # The IT-201 instructions say at line 40, "If you marked the Yes box at + # item C ... you do not qualify for this credit", for every return; the + # model follows the statute. dependent_filer = tax_unit("head_or_spouse_is_dependent_elsewhere", period) - return where(dependent_filer, 0, single_amount + non_single_amount) + return where(dependent_filer & single, 0, single_amount + non_single_amount) diff --git a/policyengine_us/variables/gov/states/vt/tax/income/credits/cdcc/vt_cdcc.py b/policyengine_us/variables/gov/states/vt/tax/income/credits/cdcc/vt_cdcc.py index 6b613164326..cf92b44d838 100644 --- a/policyengine_us/variables/gov/states/vt/tax/income/credits/cdcc/vt_cdcc.py +++ b/policyengine_us/variables/gov/states/vt/tax/income/credits/cdcc/vt_cdcc.py @@ -27,10 +27,11 @@ def formula(tax_unit, period, parameters): federal_cdcc = tax_unit("pre_obbba_capped_cdcc", period) else: federal_cdcc = tax_unit("capped_cdcc", period) - # 2022 Act 138 raised the 5828c match to 72 percent but retained the - # low-income adjusted gross income cap and the certified-facility - # requirement for 2022; 2023 Act 72 removed them effective 2023. We - # do not track facility certification or in-state care at the moment. + # 2022 Act 138, Sec. 3 raised the 5828c match to 72 percent and struck + # the low-income AGI cap, retroactive to January 1, 2022 under Sec. + # 13(b), so from 2022 there is no income test (see + # income_limit_in_effect). We do not track facility certification or + # in-state care at the moment. if p.income_limit_in_effect: income_eligible = tax_unit("vt_low_income_cdcc_eligible", period) return income_eligible * federal_cdcc * p.rate diff --git a/policyengine_us/variables/gov/states/vt/tax/income/credits/cdcc/vt_low_income_cdcc_eligible.py b/policyengine_us/variables/gov/states/vt/tax/income/credits/cdcc/vt_low_income_cdcc_eligible.py index 5299936f491..574eab62fa0 100644 --- a/policyengine_us/variables/gov/states/vt/tax/income/credits/cdcc/vt_low_income_cdcc_eligible.py +++ b/policyengine_us/variables/gov/states/vt/tax/income/credits/cdcc/vt_low_income_cdcc_eligible.py @@ -9,6 +9,8 @@ class vt_low_income_cdcc_eligible(Variable): reference = ( "https://tax.vermont.gov/sites/tax/files/documents/IN-112-2021.pdf#page=2", "https://law.justia.com/codes/vermont/2021/title-32/chapter-151/section-5828c/", + # 2022 Act 138 section 3 reproduces the pre-2022 text it amended. + "https://legislature.vermont.gov/Documents/2022/Docs/ACTS/ACT138/ACT138%20As%20Enacted.pdf#page=3", ) defined_for = StateCode.VT @@ -17,5 +19,9 @@ def formula(tax_unit, period, parameters): filing_status = tax_unit("filing_status", period) federal_agi_threshold = p.income_threshold[filing_status] federal_agi = tax_unit("adjusted_gross_income", period) - # Law says "less than" but tax form says "$x or less". We apply form rules. - return federal_agi <= federal_agi_threshold + # 32 V.S.A. 5828c (as in effect through 2021) requires federal adjusted + # gross income "less than $30,000.00 (or $40,000.00 for married, + # filing jointly)", but the 2021 Schedule IN-112 form says "$30,000 (or + # $40,000 for Married Filing Jointly) or less". The model follows the + # statute. + return federal_agi < federal_agi_threshold diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 6025a2b3e21..8e9ebdd5903 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -7269,13 +7269,13 @@ candidates: - id: us-nm:medical-expense-exemption-28000-boundary program: income-tax years: - from: 2023 + from: 2021 type: tax question: Must medical expenses exceed $28,000, or does exactly $28,000 qualify for the exemption? sources: - kind: statute - citation: NMSA 7-2-5.9(A) - url: null + citation: NMSA 7-2-5.9(A) (TRD Income Tax Act compilation, rev. July 2023, PDF p. 41) + url: https://klvg4oyd4j.execute-api.us-west-2.amazonaws.com/prod/PublicFiles/34821a9573ca43e7b06dfad20f5183fd/856ebf4b-3814-49dd-8631-ebe579d6a42b/Personal%20Income%20Tax.pdf#page=41 - kind: instructions citation: 2025 PIT-ADJ line 18 instructions url: https://realfile.tax.newmexico.gov/2025pit-adj-ins.pdf#page=5 @@ -7287,16 +7287,20 @@ candidates: other: Expenses of $28,000 or more qualify. example: At exactly $28,000 of expenses, the statute gives no exemption and the instructions give a $3,000 exemption. pe_us: - follows: conflicting-source + follows: statute code: - policyengine_us/variables/gov/states/nm/tax/income/exemptions/nm_medical_expense_exemption.py prs: - https://github.com/PolicyEngine/policyengine-us/pull/10047 - https://github.com/PolicyEngine/policyengine-us/pull/10088 - state: ruled - note: 'PE-US follows the instructions: expenses of exactly $28,000 qualify, and the formula''s comment records - the statute''s "exceed" wording (nm_medical_expense_exemption.py). An October 2026 ruling accepted the instructions; - the later statute-first rule requires a strict greater-than threshold.' + - https://github.com/PolicyEngine/policyengine-us/pull/10300 + state: ruled + note: 'An October 2026 ruling accepted the instructions; under the later statute-first rule PE-US follows the statute + (#10300): expenses must exceed $28,000, so exactly $28,000 gives no exemption (nm_medical_expense_exemption.py). + The companion 65+ medical care credit (7-2-18.13) keeps its own "$28,000 or more" test. The instructions direct + filers to claim the exemption at $28,000 of expenses or more, so a return filed as instructed differs from the + model at exactly $28,000. The years start at 2021, the first year the model computes nm_medical_expense_exemption; the + statute''s text dates from Laws 2005, ch. 104, § 6.' - id: us-nm:mixed-spouse-dependent-credit-tests program: income-tax years: @@ -7527,22 +7531,56 @@ candidates: citation: IT-201 instructions, line 40 (household credit) and item C url: https://www.tax.ny.gov/pdf/2025/inc/it201i_2025.pdf#page=12 readings: - statute: An exemption-count or whole-household reading preserves some or all of the credit. + statute: Only an unmarried individual whom another taxpayer can claim is excluded from the household definition; + a husband and wife, a head of household and a surviving spouse count the exemptions they are entitled to, and + a spouse filing separately gets one-half the household's credit on the couple's combined AGI. other: The instructions deny the credit when either spouse can be claimed. - example: The test household receives $0 under the instructions, $60 state/$30 NYC by exemption count, or $75 state/$60 - NYC by whole household. + example: A joint return with one claimable spouse, AGI $10,000 and no dependents receives $0 under the instructions + and $60 state / $30 NYC by exemption count. pe_us: - follows: conflicting-source + follows: statute code: - policyengine_us/variables/gov/states/ny/tax/income/credits/ny_household_credit_potential.py - policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/household/nyc_household_credit.py prs: - https://github.com/PolicyEngine/policyengine-us/pull/10090 + - https://github.com/PolicyEngine/policyengine-us/pull/10300 + state: ruled + note: 'An October 2026 ruling accepted the instructions; under the later statute-first rule PE-US follows Tax Law + 606(b)(3)(B) and 1310(d)(3)(B) (#10300): only claimable single filers are zeroed, other households count their + federal exemptions (exemptions_count), and NYC separate filers get half the married credit on the couple''s AGI + and exemptions. The instructions direct filers who mark item C Yes not to claim the credit, so a return filed as + instructed differs from the model for these households.' +- id: us-ny:household-credit-separate-return-halving + program: income-tax + years: + from: 2015 + type: tax + question: Does a married individual filing a separate return get exactly one-half of the household credit, or the + half amounts that IT-201 Tables 3 and 6 round up to whole dollars? + sources: + - kind: statute + citation: N.Y. Tax Law 606(b)(3)(C); 1310(d)(3)(C) + url: https://www.nysenate.gov/legislation/laws/TAX/606 + - kind: instructions + citation: IT-201 instructions, 2025, household credit Tables 3 and 6 and their Note 5 ("The credit amounts have + been rounded"), under lines 40 and 48 + url: https://www.tax.ny.gov/forms/html-instructions/2025/it/it201i-2025.htm#line-40 + readings: + statute: Each spouse gets one-half the credit otherwise allowed the household, unrounded. + other: Tables 3 and 6 round each half amount up to a whole dollar. + example: New York City, combined AGI $16,000 and three exemptions, gives $37.50 by the statute and $38 by Table 6; + New York State, combined AGI $5,000 and two exemptions, gives $52.50 by the statute and $53 by Table 3. + pe_us: + follows: statute + code: + - policyengine_us/variables/gov/states/ny/tax/income/credits/ny_household_credit_potential.py + - policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/household/nyc_household_credit.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10300 state: ruled - note: 'PE-US follows the instructions: the New York and New York City household credits are zero when either spouse - can be claimed, reading item C as marked for the whole return (ny_household_credit_potential.py, nyc_household_credit.py). - An October 2026 ruling accepted the instructions; the statute-first rule requires a model change after resolving - the statutory allocation.' + note: Both credits halve exactly, as the statute says; the tables round for the form. Section 606 authorizes + nearest-dollar tables only for the real property tax credit. - id: us-ny:real-property-credit-claimable-spouse program: income-tax years: @@ -8824,31 +8862,6 @@ candidates: prs: [] state: unreviewed note: Verify whether statutory silence permits the filing-status restriction; no individual policy ruling is supplied. -- id: us-pr:eitc-unearned-income-limit - program: income-tax - years: - from: 2023 - type: tax - question: Is Puerto Rico's EITC unearned-income limit the statute's $2,200 or Schedule CT's $10,000? - sources: - - kind: statute - citation: P.R. Laws tit. 13, § 30211(6)(e) - url: https://law.justia.com/codes/puerto-rico/title-thirteen/subtitle-17/part-ii/chapter-1007/subchapter-b/30211/ - - kind: instructions - citation: Schedule CT Individual, Earned Income Credit, 2023, page 4 - url: https://hacienda.pr.gov/sites/default/files/schedule_ct_rev._jul_5_23_informative_-_instructions.pdf#page=4 - readings: - statute: Filers with unearned income at or above $2,200 lose the credit. - other: The limit is $10,000. - example: A filer with $5,000 unearned income passes the form's limit but fails the supplied statutory limit. - pe_us: - follows: conflicting-source - code: - - policyengine_us/parameters/gov/territories/pr/tax/income/credits/earned_income/unearned_income/limit.yaml - prs: [] - state: unreviewed - note: The statute-first rule requires changing the $10,000 form-based limit to the statutory limit; confirm applicable - years and the boundary test. - id: us-ri:liheap-income-floor-vs-smi-limit program: liheap years: @@ -10852,13 +10865,15 @@ candidates: program: income-tax years: from: 2021 + to: 2021 type: tax question: Does AGI exactly equal to the low-income child-care-credit threshold qualify under the form despite the statute requiring income below it? sources: - kind: statute - citation: 32 V.S.A. § 5828c - url: https://law.justia.com/codes/vermont/2021/title-32/chapter-151/section-5828c/ + citation: 32 V.S.A. § 5828c as in effect through 2021 (text struck by 2022 Act 138, Sec. 3; Sec. 13(b) makes the + change retroactive to January 1, 2022) + url: https://legislature.vermont.gov/Documents/2022/Docs/ACTS/ACT138/ACT138%20As%20Enacted.pdf#page=3 - kind: form citation: Vermont Schedule IN-112, 2021, page 2 url: https://tax.vermont.gov/sites/tax/files/documents/IN-112-2021.pdf#page=2 @@ -10866,13 +10881,16 @@ candidates: statute: AGI must be strictly below the threshold. other: AGI equal to the threshold qualifies. pe_us: - follows: conflicting-source + follows: statute code: - policyengine_us/variables/gov/states/vt/tax/income/credits/cdcc/vt_low_income_cdcc_eligible.py - prs: [] - state: unreviewed - note: The statute-first rule requires a strict below-threshold test; verify form years before changing the inclusive - comparison. + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10300 + state: ruled + note: Under the statute-first rule PE-US applies the strict below-threshold test (#10300). Act 138 struck the income + test from 2022, so 2021 is the only affected year in the model; a 2021 filer at exactly the threshold takes the + 24% nonrefundable credit instead. The 2021 form directs filers whose AGI equals the threshold to treat it as + qualifying, so a return filed as instructed differs from the model at exactly $30,000 or $40,000. - id: us-vt:medical-deduction-without-federal-itemizing program: income-tax years: