diff --git a/changelog.d/claimable-filer-ny.fixed.md b/changelog.d/claimable-filer-ny.fixed.md new file mode 100644 index 00000000000..c35ffc3af7f --- /dev/null +++ b/changelog.d/claimable-filer-ny.fixed.md @@ -0,0 +1 @@ +Apply New York's rules for a filer who can be claimed as a dependent: no New York State or New York City household credit, school tax credit, real property tax credit, dependent exemptions (also under the dependent exemption and working families tax credit reforms), dependents' college tuition, under-4 New York City child care expenses, New York City income tax elimination credit or 2026 child and dependent care credit when the return's filers do not qualify (Tax Law 606, 616 and 1310), no own college tuition or 2023 inflation refund for a filer who is claimed, and the New York City school tax fixed amount at the individual rate when only one spouse qualifies; the 2026 child and dependent care credit now bars a claimable spouse under either head/spouse label. diff --git a/policyengine_us/reforms/states/ny/dependent_exemption/ny_dependent_exemption_reform.py b/policyengine_us/reforms/states/ny/dependent_exemption/ny_dependent_exemption_reform.py index 3b3b26af188..007179a0a07 100644 --- a/policyengine_us/reforms/states/ny/dependent_exemption/ny_dependent_exemption_reform.py +++ b/policyengine_us/reforms/states/ny/dependent_exemption/ny_dependent_exemption_reform.py @@ -24,7 +24,13 @@ def formula(tax_unit, period, parameters): eligible = is_child_dependent & (age < p.age_limit.threshold) else: eligible = is_child_dependent - count = tax_unit.sum(eligible) + # As in the baseline, a return on which a filer (or, if joint, + # either spouse) can be claimed as a dependent has no dependents + # (Tax Law 616(a), IRC 152(b)(1)). + dependent_filer = tax_unit( + "head_or_spouse_is_dependent_elsewhere_without_filing_exception", period + ) + count = where(dependent_filer, 0, tax_unit.sum(eligible)) return count * p.amount class reform(Reform): diff --git a/policyengine_us/reforms/states/ny/wftc/ny_working_families_tax_credit.py b/policyengine_us/reforms/states/ny/wftc/ny_working_families_tax_credit.py index f5bc382a691..a9fe23a6548 100644 --- a/policyengine_us/reforms/states/ny/wftc/ny_working_families_tax_credit.py +++ b/policyengine_us/reforms/states/ny/wftc/ny_working_families_tax_credit.py @@ -468,7 +468,17 @@ class ny_exemptions(Variable): defined_for = StateCode.NY def formula(tax_unit, period, parameters): - count_dependents = add(tax_unit, period, ["ny_exemptions_dependent"]) + # As in the baseline, a return on which a filer (or, if joint, + # either spouse) can be claimed as a dependent has no dependents + # (Tax Law 616(a), IRC 152(b)(1)). + dependent_filer = tax_unit( + "head_or_spouse_is_dependent_elsewhere_without_filing_exception", period + ) + count_dependents = where( + dependent_filer, + 0, + add(tax_unit, period, ["ny_exemptions_dependent"]), + ) dependent_exemption = parameters( period ).gov.states.ny.tax.income.exemptions.dependent diff --git a/policyengine_us/tests/core/test_claimable_filer_ny_invariants.py b/policyengine_us/tests/core/test_claimable_filer_ny_invariants.py new file mode 100644 index 00000000000..176ef8684d8 --- /dev/null +++ b/policyengine_us/tests/core/test_claimable_filer_ny_invariants.py @@ -0,0 +1,106 @@ +"""New York rules for a filer who can be claimed as a dependent. + +The household credit, real property tax credit, dependent exemptions, college +tuition, 2023 inflation refund and 2026 child and dependent care credit apply +Tax Law 606 and 616's dependent tests. + +For couples with either, both or neither spouse claimed: + +1. Swap invariance: each output is the same under either head/spouse + labelling (Hypothesis batches, the seeded population and the crafted + tuition cases). +2. Monotonicity: marking another filer as claimed never raises an output + (seeded population and crafted cases only). + +The crafted cases give both spouses and a dependent student tuition, which the +generated population never has. The New York City credits need a New York City +household and, like the contributed reforms, are covered by YAML cases only. +""" + +import pytest +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from policyengine_us.tests.core.test_claimable_filer_federal_invariants import ( + check_monotone, + check_swap, +) +from policyengine_us.tests.core.test_dependent_elsewhere_head_spouse_swap_invariance import ( + CLAIM_PATTERNS, + _crafted_cases, + _seeded_couples, + adults, + dependents, +) + +STATES = ["NY"] +YEARS = [2023, 2025, 2026] +OUTPUTS = [ + "ny_household_credit_potential", + "ny_real_property_tax_credit", + "ny_exemptions", + "ny_allowable_college_tuition_expenses", + "ny_inflation_refund_credit", + "ny_cdcc", +] + + +def _tuition_cases(): + # Both spouses and a dependent student with tuition, with and without a + # young child and childcare expenses. + first = { + "age": 45, + "employment_income": 20_000.0, + "qualified_tuition_expenses": 6_000.0, + } + second = { + "age": 44, + "employment_income": 12_000.0, + "qualified_tuition_expenses": 3_000.0, + } + student = { + "age": 19, + "is_full_time_student": True, + "qualified_tuition_expenses": 8_000.0, + } + child = {"age": 3, "pre_subsidy_childcare_expenses": 4_000.0} + return [ + { + "state": "NY", + "adults": [first, second], + "dependents": others, + "claimed": claimed, + } + for others in ([], [student], [student, child]) + for claimed in [(True, False), (False, True), (True, True)] + ] + + +@st.composite +def couples(draw): + return { + "state": draw(st.sampled_from(STATES)), + "adults": [draw(adults()), draw(adults())], + "dependents": draw(st.lists(dependents(), max_size=2)), + "claimed": draw(st.sampled_from(CLAIM_PATTERNS)), + } + + +@settings( + max_examples=2, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) +@given(st.sampled_from(YEARS), st.lists(couples(), min_size=6, max_size=12)) +def test_ny_claimable_filer_rules_are_label_free(year, units): + check_swap(units, year, OUTPUTS) + + +@pytest.mark.parametrize("year", YEARS) +def test_ny_claimable_filer_rules_seeded_population(year): + units = ( + _seeded_couples(STATES, per_state=3) + _crafted_cases(STATES) + _tuition_cases() + ) + check_swap(units, year, OUTPUTS) + check_monotone(units, year, OUTPUTS) diff --git a/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/cdcc/nyc_cdcc_age_restricted_expenses.yaml b/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/cdcc/nyc_cdcc_age_restricted_expenses.yaml index 57e9fadf95c..694631b3168 100644 --- a/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/cdcc/nyc_cdcc_age_restricted_expenses.yaml +++ b/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/cdcc/nyc_cdcc_age_restricted_expenses.yaml @@ -27,3 +27,85 @@ in_nyc: true output: nyc_cdcc_age_restricted_expenses: 0 + + +- name: 2025 joint return with one claimable spouse has no NYC child care dependent (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 22 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 22 + is_tax_unit_head: false + is_tax_unit_spouse: true + child: + age: 3 + pre_subsidy_childcare_expenses: 1000 + tax_units: + tax_unit: + members: [person_a, person_b, child] + filing_status: JOINT + households: + household: + members: [person_a, person_b, child] + state_code: NY + in_nyc: true + output: + # NYC Admin Code 11-1706(e)(1): children "who are dependents of the + # taxpayer"; IRC 152(b)(1). + nyc_cdcc_age_restricted_expenses: 0 + +- name: 2025 joint return with one claimable spouse has no NYC child care dependent (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 22 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 22 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + child: + age: 3 + pre_subsidy_childcare_expenses: 1000 + tax_units: + tax_unit: + members: [person_b, person_a, child] + filing_status: JOINT + households: + household: + members: [person_b, person_a, child] + state_code: NY + in_nyc: true + output: + nyc_cdcc_age_restricted_expenses: 0 + +- name: 2025 joint return with neither spouse claimable counts the child under 4 + period: 2025 + input: + people: + person_a: + age: 22 + person_b: + age: 22 + child: + age: 3 + pre_subsidy_childcare_expenses: 1000 + tax_units: + tax_unit: + members: [person_a, person_b, child] + filing_status: JOINT + households: + household: + members: [person_a, person_b, child] + state_code: NY + in_nyc: true + output: + nyc_cdcc_age_restricted_expenses: 1_000 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 407d8445de0..43eeabb49b8 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 @@ -233,3 +233,119 @@ tax_unit_size: 4 output: nyc_household_credit: 0 + + +- name: 2025 single filer who can be claimed as a dependent gets no NYC household credit + period: 2025 + input: + people: + filer: + age: 22 + employment_income: 10000 + claimed_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [filer] + households: + household: + members: [filer] + state_code: NY + in_nyc: true + output: + # Tax Law 1310(d); IT-201 line 48. + nyc_household_credit: 0 + +- name: 2025 single filer who cannot be claimed gets the NYC household credit + period: 2025 + input: + people: + filer: + age: 22 + employment_income: 10000 + tax_units: + tax_unit: + members: [filer] + households: + household: + members: [filer] + state_code: NY + in_nyc: true + output: + nyc_household_credit: 15 + +- name: 2025 joint return with one claimable spouse gets no NYC household credit (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 5000 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 22 + employment_income: 5000 + is_tax_unit_head: false + is_tax_unit_spouse: 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 joint return with one claimable spouse gets no NYC household credit (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 22 + employment_income: 5000 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 22 + employment_income: 5000 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_b, person_a] + filing_status: JOINT + households: + household: + members: [person_b, person_a] + state_code: NY + in_nyc: true + output: + nyc_household_credit: 0 + +- name: 2025 joint return with neither spouse claimable gets the NYC household credit + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 5000 + person_b: + age: 22 + employment_income: 5000 + 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: + # $30 x 2. + nyc_household_credit: 60 diff --git a/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/income_tax_elimination/nyc_income_tax_elimination_credit_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/income_tax_elimination/nyc_income_tax_elimination_credit_eligible.yaml index 1b0849ee668..99717a573f6 100644 --- a/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/income_tax_elimination/nyc_income_tax_elimination_credit_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/income_tax_elimination/nyc_income_tax_elimination_credit_eligible.yaml @@ -205,3 +205,113 @@ output: # Line 3: -5,000 <= 31,503 -> 0; line C -> No -> continue. nyc_income_tax_elimination_credit_eligible: true + +# Line A asks for a dependent under IRC 151(c). A return on which a filer (or, +# if joint, either spouse) can be claimed has no dependents (IRC 152(b)(1)). +- name: Case 15, a joint return with one claimable spouse has no dependent and is ineligible (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 30 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 30 + is_tax_unit_head: false + is_tax_unit_spouse: true + person_c: + age: 3 + tax_units: + tax_unit: + members: [person_a, person_b, person_c] + filing_status: JOINT + adjusted_gross_income: 1000 + eitc_relevant_investment_income: 0 + households: + household: + members: [person_a, person_b, person_c] + state_code: NY + in_nyc: true + output: + nyc_income_tax_elimination_credit_eligible: false + +- name: Case 15, a joint return with one claimable spouse has no dependent and is ineligible (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 30 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 30 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + person_c: + age: 3 + tax_units: + tax_unit: + members: [person_b, person_a, person_c] + filing_status: JOINT + adjusted_gross_income: 1000 + eitc_relevant_investment_income: 0 + households: + household: + members: [person_b, person_a, person_c] + state_code: NY + in_nyc: true + output: + nyc_income_tax_elimination_credit_eligible: false + +- name: Case 16, the same joint return with nobody claimable is eligible + period: 2025 + input: + people: + person_a: + age: 30 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 30 + is_tax_unit_head: false + is_tax_unit_spouse: true + person_c: + age: 3 + tax_units: + tax_unit: + members: [person_a, person_b, person_c] + filing_status: JOINT + adjusted_gross_income: 1000 + eitc_relevant_investment_income: 0 + households: + household: + members: [person_a, person_b, person_c] + state_code: NY + in_nyc: true + output: + nyc_income_tax_elimination_credit_eligible: true + +- name: Case 17, a claimable single filer with a child is ineligible + period: 2025 + input: + people: + person_a: + age: 19 + claimed_as_dependent_on_another_return: true + person_c: + age: 3 + tax_units: + tax_unit: + members: [person_a, person_c] + adjusted_gross_income: 1000 + eitc_relevant_investment_income: 0 + households: + household: + members: [person_a, person_c] + state_code: NY + in_nyc: true + output: + nyc_income_tax_elimination_credit_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_fixed_amount.yaml b/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_fixed_amount.yaml index 033c38bb536..b3a3384b9ee 100644 --- a/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_fixed_amount.yaml +++ b/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_fixed_amount.yaml @@ -27,3 +27,125 @@ filing_status: SINGLE output: nyc_school_tax_credit_fixed_amount: 0 + + +- name: 2025 single filer who can be claimed as a dependent gets no school tax credit + period: 2025 + input: + people: + filer: + age: 22 + employment_income: 13100 + claimed_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [filer] + households: + household: + members: [filer] + state_code: NY + in_nyc: true + output: + # IT-201 line 69. + nyc_school_tax_credit_fixed_amount: 0 + +- name: 2025 joint return with one claimable spouse gets the eligible spouse's amount (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 13025 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 22 + employment_income: 13025 + is_tax_unit_head: false + is_tax_unit_spouse: 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: + # Form NYC-210: "credit amount of the eligible spouse". + nyc_school_tax_credit_fixed_amount: 63 + +- name: 2025 joint return with one claimable spouse gets the eligible spouse's amount (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 22 + employment_income: 13025 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 22 + employment_income: 13025 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_b, person_a] + filing_status: JOINT + households: + household: + members: [person_b, person_a] + state_code: NY + in_nyc: true + output: + nyc_school_tax_credit_fixed_amount: 63 + +- name: 2025 joint return with both spouses claimable gets no school tax credit + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 13025 + claimed_as_dependent_on_another_return: true + person_b: + age: 22 + employment_income: 13025 + 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_school_tax_credit_fixed_amount: 0 + +- name: 2025 joint return with neither spouse claimable gets the joint amount + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 13025 + person_b: + age: 22 + employment_income: 13025 + 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_school_tax_credit_fixed_amount: 125 diff --git a/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_rate_reduction_amount_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_rate_reduction_amount_eligible.yaml index 1e624e5e6f7..ab89c0674dd 100644 --- a/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_rate_reduction_amount_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_rate_reduction_amount_eligible.yaml @@ -83,3 +83,83 @@ nyc_taxable_income: 0 output: nyc_school_tax_credit_rate_reduction_amount_eligible: false + +- name: 2025 joint return with one claimable spouse stays eligible for the rate reduction amount (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 13025 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 22 + employment_income: 13025 + is_tax_unit_head: false + is_tax_unit_spouse: 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: + # IT-201 line 69a bars a filer who can be claimed; the other spouse + # still qualifies. + nyc_school_tax_credit_rate_reduction_amount_eligible: true + +- name: 2025 joint return with one claimable spouse stays eligible for the rate reduction amount (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 22 + employment_income: 13025 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 22 + employment_income: 13025 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_b, person_a] + filing_status: JOINT + households: + household: + members: [person_b, person_a] + state_code: NY + in_nyc: true + output: + nyc_school_tax_credit_rate_reduction_amount_eligible: true + +- name: 2025 joint return with both spouses claimable is not eligible for the rate reduction amount + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 13025 + claimed_as_dependent_on_another_return: true + person_b: + age: 22 + employment_income: 13025 + 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_school_tax_credit_rate_reduction_amount_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_cdcc_2026.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_cdcc_2026.yaml index 6adacc0a1c5..0966549b75e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_cdcc_2026.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_cdcc_2026.yaml @@ -121,8 +121,126 @@ period: 2026 input: state_code: NY - head_is_dependent_elsewhere: true + head_or_spouse_is_dependent_elsewhere: true ny_agi: 20_000 ny_cdcc_qualifying_expenses: 3_000 output: ny_cdcc: 0 + +# Tax Law 606(c-2)(2)(A): the credit is for a taxpayer who is not a dependent +# of another taxpayer; a joint return is one taxpayer, so either spouse who can +# be claimed bars it. IRC 152(b)(1) also leaves such a return no qualifying child. +- name: Case 10, a joint return with one claimable spouse gets no 2026 credit (the claimable spouse is the head) + period: 2026 + input: + people: + person_a: + age: 30 + employment_income: 20000 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 30 + employment_income: 20000 + is_tax_unit_head: false + is_tax_unit_spouse: true + person_c: + age: 1 + tax_units: + tax_unit: + members: [person_a, person_b, person_c] + filing_status: JOINT + tax_unit_childcare_expenses: 3000 + ny_agi: 40000 + households: + household: + members: [person_a, person_b, person_c] + state_code: NY + output: + ny_cdcc_qualifying_expenses: 0 + ny_cdcc: 0 + +- name: Case 10, a joint return with one claimable spouse gets no 2026 credit (the claimable spouse is the spouse) + period: 2026 + input: + people: + person_b: + age: 30 + employment_income: 20000 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 30 + employment_income: 20000 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + person_c: + age: 1 + tax_units: + tax_unit: + members: [person_b, person_a, person_c] + filing_status: JOINT + tax_unit_childcare_expenses: 3000 + ny_agi: 40000 + households: + household: + members: [person_b, person_a, person_c] + state_code: NY + output: + ny_cdcc_qualifying_expenses: 0 + ny_cdcc: 0 + +- name: Case 11, the same joint return with nobody claimable gets the credit + period: 2026 + input: + people: + person_a: + age: 30 + employment_income: 20000 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 30 + employment_income: 20000 + is_tax_unit_head: false + is_tax_unit_spouse: true + person_c: + age: 1 + tax_units: + tax_unit: + members: [person_a, person_b, person_c] + filing_status: JOINT + tax_unit_childcare_expenses: 3000 + ny_agi: 40000 + households: + household: + members: [person_a, person_b, person_c] + state_code: NY + output: + # 3,000 x (0.55 - 0.0000025 x (40,000 - 15,000)) = 3,000 x 0.4875 + ny_cdcc_qualifying_expenses: 3000 + ny_cdcc: 1462.5 + +- name: Case 12, a single filer who can be claimed gets no 2026 credit + period: 2026 + input: + people: + person_a: + age: 19 + employment_income: 20000 + claimed_as_dependent_on_another_return: true + person_c: + age: 1 + tax_units: + tax_unit: + members: [person_a, person_c] + tax_unit_childcare_expenses: 3000 + ny_agi: 20000 + households: + household: + members: [person_a, person_c] + state_code: NY + output: + ny_cdcc: 0 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 690a1d23798..75ecd16039e 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 @@ -88,3 +88,116 @@ state_fips: 36 output: ny_household_credit: 100 + + +- name: 2025 single filer who can be claimed as a dependent gets no household credit + period: 2025 + input: + people: + filer: + age: 22 + employment_income: 10000 + claimed_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [filer] + households: + household: + members: [filer] + state_code: NY + output: + # Tax Law 606(b)(3)(B); IT-201 line 40: "If you marked the Yes box at item C + # ... you do not qualify". + ny_household_credit_potential: 0 + +- name: 2025 single filer who cannot be claimed gets the household credit + period: 2025 + input: + people: + filer: + age: 22 + employment_income: 10000 + tax_units: + tax_unit: + members: [filer] + households: + household: + members: [filer] + state_code: NY + output: + ny_household_credit_potential: 45 + +- name: 2025 joint return with one claimable spouse gets no household credit (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 5000 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 22 + employment_income: 5000 + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + households: + household: + 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 + +- name: 2025 joint return with one claimable spouse gets no household credit (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 22 + employment_income: 5000 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 22 + employment_income: 5000 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_b, person_a] + filing_status: JOINT + households: + household: + members: [person_b, person_a] + state_code: NY + output: + ny_household_credit_potential: 0 + +- name: 2025 joint return with neither spouse claimable gets the household credit + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 5000 + person_b: + age: 22 + employment_income: 5000 + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + households: + household: + members: [person_a, person_b] + state_code: NY + output: + # $60 + $15 x (2 - 1). + ny_household_credit_potential: 75 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_inflation_refund_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_inflation_refund_credit.yaml index 9858d1b695f..b1ac4ffcdcb 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_inflation_refund_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_inflation_refund_credit.yaml @@ -137,3 +137,113 @@ filing_status: SINGLE output: ny_inflation_refund_credit: 200 + + +- name: 2023 single filer claimed as a dependent gets no inflation refund + period: 2023 + input: + people: + filer: + age: 22 + claimed_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [filer] + ny_agi: 10000 + households: + household: + members: [filer] + state_code: NY + output: + # Tax Law 606(qqq): recipients "must not have been claimed as a dependent". + ny_inflation_refund_credit: 0 + +- name: 2023 joint return with one spouse claimed gets no inflation refund (the claimable spouse is the head) + period: 2023 + input: + people: + person_a: + age: 22 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 22 + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + ny_agi: 10000 + households: + household: + members: [person_a, person_b] + state_code: NY + output: + # The rule covers "taxpayers filing joint returns". + ny_inflation_refund_credit: 0 + +- name: 2023 joint return with one spouse claimed gets no inflation refund (the claimable spouse is the spouse) + period: 2023 + input: + people: + person_b: + age: 22 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 22 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_b, person_a] + filing_status: JOINT + ny_agi: 10000 + households: + household: + members: [person_b, person_a] + state_code: NY + output: + ny_inflation_refund_credit: 0 + +- name: 2023 joint return with neither spouse claimed gets the inflation refund + period: 2023 + input: + people: + person_a: + age: 22 + person_b: + age: 22 + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + ny_agi: 10000 + households: + household: + members: [person_a, person_b] + state_code: NY + output: + ny_inflation_refund_credit: 400 + +- name: 2023 single filer who could be claimed but was not claimed gets the inflation refund + period: 2023 + input: + people: + filer: + age: 22 + claimable_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [filer] + ny_agi: 10000 + households: + household: + members: [filer] + state_code: NY + output: + # Tax Law 606(qqq) turns on having been claimed, not on being claimable. + ny_inflation_refund_credit: 200 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_real_property_tax_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_real_property_tax_credit.yaml index 4e87bf18870..01fce52cf2b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_real_property_tax_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/credits/ny_real_property_tax_credit.yaml @@ -589,3 +589,231 @@ state_code: NY output: ny_real_property_tax_credit: 0 + +- name: 2025 single filer who can be claimed as a dependent gets no real property tax credit + period: 2025 + input: + people: + filer: + age: 22 + employment_income: 2000 + real_estate_taxes: 500 + claimed_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [filer] + households: + household: + members: [filer] + state_code: NY + output: + # Tax Law 606(e)(7)(E); IT-214: "You could not be claimed as a dependent". + ny_real_property_tax_credit: 0 + +- name: 2025 joint return with one claimable spouse keeps the real property tax credit (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 1000 + real_estate_taxes: 500 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 22 + employment_income: 1000 + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + households: + household: + members: [person_a, person_b] + state_code: NY + output: + # Tax Law 606(e)(6)(C) covers "a qualified taxpayer and their spouse"; + # non-elderly Table B at FAGI $2,000. + ny_real_property_tax_credit: 75 + +- name: 2025 joint return with one claimable spouse keeps the real property tax credit (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 22 + employment_income: 1000 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 22 + employment_income: 1000 + real_estate_taxes: 500 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_b, person_a] + filing_status: JOINT + households: + household: + members: [person_b, person_a] + state_code: NY + output: + ny_real_property_tax_credit: 75 + +- name: 2025 joint return with both spouses claimable gets no real property tax credit + period: 2025 + input: + people: + person_a: + age: 22 + employment_income: 1000 + real_estate_taxes: 500 + claimed_as_dependent_on_another_return: true + person_b: + age: 22 + employment_income: 1000 + 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: + ny_real_property_tax_credit: 0 + +# Tax Law 606(e)(3): the elderly amounts need a qualified taxpayer, spouse or IRC +# 152 dependent aged 65 or older. A return on which a filer can be claimed has no +# dependents (IRC 152(b)(1)), so a dependent's age does not reach the elderly +# table: non-elderly Table B at FAGI $2,000 gives $75, the elderly table $375. +- name: 2025 aged dependent of a joint return with one claimable spouse does not reach the elderly table (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 40 + employment_income: 1000 + real_estate_taxes: 500 + claimable_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 40 + employment_income: 1000 + is_tax_unit_head: false + is_tax_unit_spouse: true + relative: + age: 66 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_a, person_b, relative] + filing_status: JOINT + households: + household: + members: [person_a, person_b, relative] + state_code: NY + output: + ny_real_property_tax_credit: 75 + +- name: 2025 aged dependent of a joint return with one claimable spouse does not reach the elderly table (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 40 + employment_income: 1000 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 40 + employment_income: 1000 + real_estate_taxes: 500 + claimable_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + relative: + age: 66 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_b, person_a, relative] + filing_status: JOINT + households: + household: + members: [person_b, person_a, relative] + state_code: NY + output: + ny_real_property_tax_credit: 75 + +- name: 2025 aged dependent of a joint return whose claimable spouse is within the filing exception reaches the elderly table + period: 2025 + input: + people: + person_a: + age: 40 + employment_income: 1000 + real_estate_taxes: 500 + claimable_as_dependent_on_another_return: true + dependent_claimant_filing_exception: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 40 + employment_income: 1000 + is_tax_unit_head: false + is_tax_unit_spouse: true + relative: + age: 66 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_a, person_b, relative] + filing_status: JOINT + households: + household: + members: [person_a, person_b, relative] + state_code: NY + output: + ny_real_property_tax_credit: 375 + +- name: 2025 aged dependent of a joint return with neither spouse claimable reaches the elderly table + period: 2025 + input: + people: + person_a: + age: 40 + employment_income: 1000 + real_estate_taxes: 500 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 40 + employment_income: 1000 + is_tax_unit_head: false + is_tax_unit_spouse: true + relative: + age: 66 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_a, person_b, relative] + filing_status: JOINT + households: + household: + members: [person_a, person_b, relative] + state_code: NY + output: + ny_real_property_tax_credit: 375 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/ny_allowable_college_tuition_expenses.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/ny_allowable_college_tuition_expenses.yaml index a1fe33acce8..223f28d30e5 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/ny_allowable_college_tuition_expenses.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/ny_allowable_college_tuition_expenses.yaml @@ -6,3 +6,207 @@ qualified_tuition_expenses: 12_000 output: ny_allowable_college_tuition_expenses: 10_000 + +- name: 2025 single student claimed as a dependent elsewhere has no allowable tuition + period: 2025 + input: + people: + student: + age: 20 + qualified_tuition_expenses: 6000 + claimed_as_dependent_on_another_return: true + tax_units: + tax_unit: + members: [student] + households: + household: + members: [student] + state_code: NY + output: + # Tax Law 606(t)(2)(D); IT-272: "only the person who claims the student as a + # dependent". + ny_allowable_college_tuition_expenses: 0 + +- name: 2025 joint return keeps the tuition of the spouse who is not claimed (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 20 + qualified_tuition_expenses: 6000 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 20 + qualified_tuition_expenses: 6000 + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + households: + household: + members: [person_a, person_b] + state_code: NY + output: + ny_allowable_college_tuition_expenses: 6_000 + +- name: 2025 joint return keeps the tuition of the spouse who is not claimed (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 20 + qualified_tuition_expenses: 6000 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 20 + qualified_tuition_expenses: 6000 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person_b, person_a] + filing_status: JOINT + households: + household: + members: [person_b, person_a] + state_code: NY + output: + ny_allowable_college_tuition_expenses: 6_000 + +- name: 2025 joint return with neither spouse claimed counts both students + period: 2025 + input: + people: + person_a: + age: 20 + qualified_tuition_expenses: 6000 + person_b: + age: 20 + qualified_tuition_expenses: 6000 + tax_units: + tax_unit: + members: [person_a, person_b] + filing_status: JOINT + households: + household: + members: [person_a, person_b] + state_code: NY + output: + ny_allowable_college_tuition_expenses: 12_000 + +# Tax Law 606(t): the tuition of a dependent counts only for a dependent for whom +# an exemption is allowed under section 616, and a return on which a filer can be +# claimed has none (IRC 152(b)(1)). +- name: 2025 dependent student's tuition does not count on a joint return with one claimable spouse (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 45 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 45 + is_tax_unit_head: false + is_tax_unit_spouse: true + student: + age: 19 + qualified_tuition_expenses: 6000 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_a, person_b, student] + filing_status: JOINT + households: + household: + members: [person_a, person_b, student] + state_code: NY + output: + ny_allowable_college_tuition_expenses: 0 + +- name: 2025 dependent student's tuition does not count on a joint return with one claimable spouse (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 45 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 45 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + student: + age: 19 + qualified_tuition_expenses: 6000 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_b, person_a, student] + filing_status: JOINT + households: + household: + members: [person_b, person_a, student] + state_code: NY + output: + ny_allowable_college_tuition_expenses: 0 + +- name: 2025 dependent student's tuition counts on a joint return with neither spouse claimable + period: 2025 + input: + people: + person_a: + age: 45 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 45 + is_tax_unit_head: false + is_tax_unit_spouse: true + student: + age: 19 + qualified_tuition_expenses: 6000 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_a, person_b, student] + filing_status: JOINT + households: + household: + members: [person_a, person_b, student] + state_code: NY + output: + ny_allowable_college_tuition_expenses: 6000 + +# Tax Law 606(t)(2)(D) bars a student who is claimed on another return; a student +# who can be claimed but is not keeps their own tuition. +- name: 2025 single student who can be claimed but is not claimed keeps their tuition + period: 2025 + input: + people: + student: + age: 20 + qualified_tuition_expenses: 6000 + claimable_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [student] + households: + household: + members: [student] + state_code: NY + output: + ny_allowable_college_tuition_expenses: 6000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/taxable_income/ny_exemptions.yaml b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/taxable_income/ny_exemptions.yaml index e5e06495934..7804d736c52 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/taxable_income/ny_exemptions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ny/tax/income/taxable_income/ny_exemptions.yaml @@ -6,3 +6,137 @@ tax_unit_child_dependents: 2 output: ny_exemptions: 2_000 + +- name: 2025 joint return with one claimable spouse has no dependent exemptions (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 22 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 22 + is_tax_unit_head: false + is_tax_unit_spouse: true + child: + age: 3 + tax_units: + tax_unit: + members: [person_a, person_b, child] + filing_status: JOINT + households: + household: + members: [person_a, person_b, child] + state_code: NY + output: + # Tax Law 616(a) needs a dependent deduction under IRC 151(c); IRC 152(b)(1). + ny_exemptions: 0 + +- name: 2025 joint return with one claimable spouse has no dependent exemptions (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 22 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 22 + claimed_as_dependent_on_another_return: true + is_tax_unit_head: false + is_tax_unit_spouse: true + child: + age: 3 + tax_units: + tax_unit: + members: [person_b, person_a, child] + filing_status: JOINT + households: + household: + members: [person_b, person_a, child] + state_code: NY + output: + ny_exemptions: 0 + +- name: 2025 joint return with neither spouse claimable has a dependent exemption + period: 2025 + input: + people: + person_a: + age: 22 + person_b: + age: 22 + child: + age: 3 + tax_units: + tax_unit: + members: [person_a, person_b, child] + filing_status: JOINT + households: + household: + members: [person_a, person_b, child] + state_code: NY + output: + ny_exemptions: 1_000 + +# Publication 501, Dependent Taxpayer Test: a filer whose would-be claimant is not +# required to file and files no return or only for a refund can claim dependents. +- name: 2025 joint return whose claimable spouse is within the filing exception keeps the dependent exemption (the claimable spouse is the head) + period: 2025 + input: + people: + person_a: + age: 30 + claimable_as_dependent_on_another_return: true + dependent_claimant_filing_exception: true + is_tax_unit_head: true + is_tax_unit_spouse: false + person_b: + age: 30 + is_tax_unit_head: false + is_tax_unit_spouse: true + child: + age: 5 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_a, person_b, child] + filing_status: JOINT + households: + household: + members: [person_a, person_b, child] + state_code: NY + output: + ny_exemptions: 1000 + +- name: 2025 joint return whose claimable spouse is within the filing exception keeps the dependent exemption (the claimable spouse is the spouse) + period: 2025 + input: + people: + person_b: + age: 30 + is_tax_unit_head: true + is_tax_unit_spouse: false + person_a: + age: 30 + claimable_as_dependent_on_another_return: true + dependent_claimant_filing_exception: true + is_tax_unit_head: false + is_tax_unit_spouse: true + child: + age: 5 + is_tax_unit_head: false + is_tax_unit_spouse: false + tax_units: + tax_unit: + members: [person_b, person_a, child] + filing_status: JOINT + households: + household: + members: [person_b, person_a, child] + state_code: NY + output: + ny_exemptions: 1000 diff --git a/policyengine_us/tests/policy/contrib/states/ny/dependent_exemption_reform_test.yaml b/policyengine_us/tests/policy/contrib/states/ny/dependent_exemption_reform_test.yaml index 65344a7d085..4ffc86b56c4 100644 --- a/policyengine_us/tests/policy/contrib/states/ny/dependent_exemption_reform_test.yaml +++ b/policyengine_us/tests/policy/contrib/states/ny/dependent_exemption_reform_test.yaml @@ -71,3 +71,43 @@ households: {household: {members: [parent, child1], state_name: NY}} # Dependent one year under the limit (12 < 13) receives the exemption. output: {ny_exemptions: 1_000} + +# As in the baseline, a return on which a filer (or, if joint, either spouse) can +# be claimed as a dependent has no dependents (Tax Law 616(a), IRC 152(b)(1)). +- name: NY dependent exemption reform - no exemption for the child of a filer who can be claimed as a dependent + period: 2025 + reforms: policyengine_us.reforms.states.ny.dependent_exemption.ny_dependent_exemption_reform.ny_dependent_exemption_reform + input: + gov.contrib.states.ny.dependent_exemption.in_effect: true + people: + parent: {age: 40, employment_income: 60_000, claimed_as_dependent_on_another_return: true} + child1: {age: 5, is_tax_unit_dependent: true} + tax_units: {tax_unit: {members: [parent, child1], filing_status: SINGLE}} + households: {household: {members: [parent, child1], state_name: NY}} + output: {ny_exemptions: 0} + +- name: NY dependent exemption reform - no exemption on a joint return with one claimable spouse (the claimable spouse is the head) + period: 2025 + reforms: policyengine_us.reforms.states.ny.dependent_exemption.ny_dependent_exemption_reform.ny_dependent_exemption_reform + input: + gov.contrib.states.ny.dependent_exemption.in_effect: true + people: + person_a: {age: 40, claimed_as_dependent_on_another_return: true, is_tax_unit_head: true, is_tax_unit_spouse: false} + person_b: {age: 40, employment_income: 60_000, is_tax_unit_head: false, is_tax_unit_spouse: true} + child1: {age: 5, is_tax_unit_dependent: true} + tax_units: {tax_unit: {members: [person_a, person_b, child1], filing_status: JOINT}} + households: {household: {members: [person_a, person_b, child1], state_name: NY}} + output: {ny_exemptions: 0} + +- name: NY dependent exemption reform - no exemption on a joint return with one claimable spouse (the claimable spouse is the spouse) + period: 2025 + reforms: policyengine_us.reforms.states.ny.dependent_exemption.ny_dependent_exemption_reform.ny_dependent_exemption_reform + input: + gov.contrib.states.ny.dependent_exemption.in_effect: true + people: + person_b: {age: 40, employment_income: 60_000, is_tax_unit_head: true, is_tax_unit_spouse: false} + person_a: {age: 40, claimed_as_dependent_on_another_return: true, is_tax_unit_head: false, is_tax_unit_spouse: true} + child1: {age: 5, is_tax_unit_dependent: true} + tax_units: {tax_unit: {members: [person_b, person_a, child1], filing_status: JOINT}} + households: {household: {members: [person_b, person_a, child1], state_name: NY}} + output: {ny_exemptions: 0} diff --git a/policyengine_us/tests/policy/contrib/states/ny/ny_working_families_tax_credit.yaml b/policyengine_us/tests/policy/contrib/states/ny/ny_working_families_tax_credit.yaml index 092224494a7..ea750e30421 100644 --- a/policyengine_us/tests/policy/contrib/states/ny/ny_working_families_tax_credit.yaml +++ b/policyengine_us/tests/policy/contrib/states/ny/ny_working_families_tax_credit.yaml @@ -256,7 +256,6 @@ eitc_maximum: 7_152 ny_eitc: 1_006.46 - - name: 2025 test with two dependents, one older child and one younger period: 2025 absolute_error_margin: 1 @@ -318,3 +317,30 @@ state_code: NY output: ny_exemptions: 1_000 + +# As in the baseline, a return on which a filer can be claimed as a dependent has +# no dependents (Tax Law 616(a), IRC 152(b)(1)). +- name: Claimable single person, one older child - reform keeps no dependent exemption + period: 2025 + reforms: policyengine_us.reforms.states.ny.wftc.ny_working_families_tax_credit.ny_working_families_tax_credit + input: + gov.contrib.states.ny.wftc.in_effect: true + people: + person1: + age: 40 + is_tax_unit_dependent: false + employment_income: 20_000 + claimed_as_dependent_on_another_return: true + person2: + age: 18 + is_tax_unit_dependent: true + is_full_time_student: true + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: NY + output: + ny_exemptions: 0 diff --git a/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/cdcc/nyc_cdcc_age_restricted_expenses.py b/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/cdcc/nyc_cdcc_age_restricted_expenses.py index 9a48c41d9a0..1b5c828fbed 100644 --- a/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/cdcc/nyc_cdcc_age_restricted_expenses.py +++ b/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/cdcc/nyc_cdcc_age_restricted_expenses.py @@ -18,7 +18,15 @@ def formula(tax_unit, period, parameters): children = tax_unit("tax_unit_children", period) person = tax_unit.members - qualifying_child = person("age", period) < p.child_age_restriction + # NYC Admin Code 11-1706(e)(1) counts children "who are dependents of + # the taxpayer"; a return on which the filer (or, if joint, either + # spouse) can be claimed as a dependent has none (IRC 152(b)(1)). + dependent_filer = person.tax_unit( + "head_or_spouse_is_dependent_elsewhere_without_filing_exception", period + ) + qualifying_child = ( + person("age", period) < p.child_age_restriction + ) & ~dependent_filer qualifying_children = tax_unit.sum(qualifying_child) tax_unit_childcare_expenses = tax_unit("tax_unit_childcare_expenses", period) # avoid divide-by-zero warnings by not using where() function 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 88488232d3f..c919d1626d0 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 @@ -25,7 +25,11 @@ def formula(tax_unit, period, parameters): filing_statuses = filing_status.possible_values - return select( + # 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". + dependent_filer = tax_unit("head_or_spouse_is_dependent_elsewhere", period) + amount = select( [ filing_status == filing_statuses.SINGLE, filing_status == filing_statuses.SEPARATE, @@ -41,3 +45,4 @@ def formula(tax_unit, period, parameters): # amount per person, varying with AGI. default=p.other_per_dependent.calc(federal_agi, right=True) * tax_unit_size, ) + return where(dependent_filer, 0, amount) diff --git a/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/income_tax_elimination/nyc_income_tax_elimination_credit_eligible.py b/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/income_tax_elimination/nyc_income_tax_elimination_credit_eligible.py index 303f45b5c8c..ba473a6818c 100644 --- a/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/income_tax_elimination/nyc_income_tax_elimination_credit_eligible.py +++ b/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/income_tax_elimination/nyc_income_tax_elimination_credit_eligible.py @@ -19,7 +19,12 @@ def formula(tax_unit, period, parameters): ).gov.local.ny.nyc.tax.income.credits.income_tax_elimination # § 1310(h)(1)(A); Form IT-270 line A: the taxpayer is entitled to a # dependent deduction under IRC § 151(c). - has_dependent = tax_unit("tax_unit_dependents", period) > 0 + # A return on which the filer (or, if joint, either spouse) can be + # claimed as a dependent has no dependents (IRC 152(b)(1)). + dependent_filer = tax_unit( + "head_or_spouse_is_dependent_elsewhere_without_filing_exception", period + ) + has_dependent = (tax_unit("tax_unit_dependents", period) > 0) & ~dependent_filer # § 1310(h)(1)(B) and (h)(2); line C: federal adjusted gross income # (§ 1310(h)(3)(B)) is no more than the phase-out width above the # threshold. diff --git a/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_fixed_amount.py b/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_fixed_amount.py index 0c8756fb811..7c1c5626dcb 100644 --- a/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_fixed_amount.py +++ b/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_fixed_amount.py @@ -16,4 +16,9 @@ def formula(tax_unit, period, parameters): # Then get the School Tax Credit fixed amount part of the parameter tree. p = parameters(period).gov.local.ny.nyc.tax.income.credits.school.fixed - return p.amount[filing_status] + # A joint return on which a spouse can be claimed as a dependent, so + # that only the other spouse qualifies, gets that spouse's individual + # amount (Form NYC-210 instructions). + joint = filing_status == filing_status.possible_values.JOINT + dependent_filer = tax_unit("head_or_spouse_is_dependent_elsewhere", period) + return where(joint & dependent_filer, p.amount.SINGLE, p.amount[filing_status]) diff --git a/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_fixed_amount_eligible.py b/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_fixed_amount_eligible.py index 21ab9f304f7..e3b6e57a841 100644 --- a/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_fixed_amount_eligible.py +++ b/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_fixed_amount_eligible.py @@ -23,4 +23,10 @@ def formula(tax_unit, period, parameters): # Get income that counts towards the NYC School Tax Credit. nyc_stc_income = tax_unit("nyc_school_credit_income", period) - return nyc_stc_income <= p.income_limit + # A filer who can be claimed as a dependent does not qualify (IT-201 + # line 69). Form NYC-210 asks about each spouse and allows "the credit + # amount of the eligible spouse" when only one qualifies. + independent_filers = tax_unit( + "head_spouse_count_not_dependent_elsewhere", period + ) + return (nyc_stc_income <= p.income_limit) & (independent_filers > 0) diff --git a/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_rate_reduction_amount_eligible.py b/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_rate_reduction_amount_eligible.py index 1ef266385a5..1ad86eaa409 100644 --- a/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_rate_reduction_amount_eligible.py +++ b/policyengine_us/variables/gov/local/ny/nyc/tax/income/credits/school/nyc_school_tax_credit_rate_reduction_amount_eligible.py @@ -25,4 +25,9 @@ def formula(tax_unit, period, parameters): # it not applicable above their top bracket. nyc_taxable_income = tax_unit("nyc_taxable_income", period) taxable_income_eligible = nyc_taxable_income <= p.taxable_income_limit - return income_eligible & taxable_income_eligible + # A filer who can be claimed as a dependent does not qualify (IT-201 + # line 69a); a spouse who cannot be claimed still does. + independent_filers = tax_unit( + "head_spouse_count_not_dependent_elsewhere", period + ) + return income_eligible & taxable_income_eligible & (independent_filers > 0) diff --git a/policyengine_us/variables/gov/states/ny/tax/income/credits/cdcc/ny_cdcc.py b/policyengine_us/variables/gov/states/ny/tax/income/credits/cdcc/ny_cdcc.py index b3275122379..0e9d5c0026b 100644 --- a/policyengine_us/variables/gov/states/ny/tax/income/credits/cdcc/ny_cdcc.py +++ b/policyengine_us/variables/gov/states/ny/tax/income/credits/cdcc/ny_cdcc.py @@ -20,13 +20,15 @@ def formula(tax_unit, period, parameters): # 2026-01-01: qualifying expenses times the applicable percentage, # less $20 per whole $1,000 of New York AGI above $750,000. # (c-2)(2)(A) excludes a taxpayer who is another's dependent and, - # through IRC 21(e)(4), a married taxpayer filing separately. + # through IRC 21(e)(4), a married taxpayer filing separately. A + # joint return is one taxpayer, so either spouse being a dependent + # bars it. expenses = tax_unit("ny_cdcc_qualifying_expenses", period) rate = tax_unit("ny_cdcc_applicable_percentage", period) excess = max_(tax_unit("ny_agi", period) - p.reduction.threshold, 0) reduction = p.reduction.amount * np.floor(excess / p.reduction.increment) eligible = tax_unit("cdcc_filing_status_eligible", period) & ~tax_unit( - "head_is_dependent_elsewhere", period + "head_or_spouse_is_dependent_elsewhere", period ) return eligible * max_(expenses * rate - reduction, 0) # Tax Law 606(c), for taxable years beginning before 2026. 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 80b50900fd9..b71524d37c8 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 @@ -42,4 +42,10 @@ def formula(tax_unit, period, parameters): total_amount_if_not_single / where(separate, 2, 1) ) non_single_amount = amount_if_not_single * ~single - return single_amount + non_single_amount + # 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. + dependent_filer = tax_unit("head_or_spouse_is_dependent_elsewhere", period) + return where(dependent_filer, 0, single_amount + non_single_amount) diff --git a/policyengine_us/variables/gov/states/ny/tax/income/credits/ny_inflation_refund_credit.py b/policyengine_us/variables/gov/states/ny/tax/income/credits/ny_inflation_refund_credit.py index aee8a484a65..1eac9e6bb77 100644 --- a/policyengine_us/variables/gov/states/ny/tax/income/credits/ny_inflation_refund_credit.py +++ b/policyengine_us/variables/gov/states/ny/tax/income/credits/ny_inflation_refund_credit.py @@ -20,8 +20,16 @@ def formula_2023(tax_unit, period, parameters): agi = tax_unit("ny_agi", period) filing_status = tax_unit("filing_status", period) filing_statuses = filing_status.possible_values + # Tax Law 606(qqq): recipients, including "taxpayers filing joint + # returns", "must not have been claimed as a dependent". This turns on + # an actual claim, so it reads the claimed input rather than a + # claimability helper. + person = tax_unit.members + filer = person("is_tax_unit_head_or_spouse", period) + claimed = person("claimed_as_dependent_on_another_return", period) + dependent_filer = tax_unit.any(filer & claimed) - return select( + amount = select( [ filing_status == filing_statuses.SINGLE, filing_status == filing_statuses.JOINT, @@ -37,6 +45,7 @@ def formula_2023(tax_unit, period, parameters): p.surviving_spouse.calc(agi, right=True), ], ) + return where(dependent_filer, 0, amount) def formula_2024(tax_unit, period, parameters): return 0 diff --git a/policyengine_us/variables/gov/states/ny/tax/income/credits/ny_real_property_tax_credit.py b/policyengine_us/variables/gov/states/ny/tax/income/credits/ny_real_property_tax_credit.py index cc546f1a7a6..ed140e803bf 100644 --- a/policyengine_us/variables/gov/states/ny/tax/income/credits/ny_real_property_tax_credit.py +++ b/policyengine_us/variables/gov/states/ny/tax/income/credits/ny_real_property_tax_credit.py @@ -14,11 +14,18 @@ def formula(tax_unit, period, parameters): rptc = parameters(period).gov.states.ny.tax.income.credits.real_property_tax # Age-based eligibility. The elderly tier (IT-214 line 7) applies if the - # filer, spouse, or a claimed dependent is 65 or older. + # filer, spouse, or a claimed dependent is 65 or older. A return on + # which a filer can be claimed as a dependent (outside the claimant + # filing exception) has no dependents (IRC 152(b)(1)), so a + # dependent's age does not count there. person = tax_unit.members age = person("age", period) aged = age >= rptc.elderly_age - meets_age_condition = tax_unit.any(aged) + filer = person("is_tax_unit_head_or_spouse", period) + no_dependents = person.tax_unit( + "head_or_spouse_is_dependent_elsewhere_without_filing_exception", period + ) + meets_age_condition = tax_unit.any(aged & (filer | ~no_dependents)) # Real-estate-based phase-in. real_estate_tax = add(tax_unit, period, ["real_estate_taxes"]) @@ -68,7 +75,16 @@ def formula(tax_unit, period, parameters): # IT-214 income limit ("$18,000 or less"). meets_income_condition = income <= rptc.max_agi - eligible = meets_value_conditions & meets_income_condition + # Tax Law 606(e)(7)(E) excludes an individual whom another taxpayer can + # claim as a dependent ("You could not be claimed as a dependent", + # IT-214), while 606(e)(6)(C) covers "a qualified taxpayer and their + # spouse", so one qualified spouse keeps the credit. + independent_filers = tax_unit( + "head_spouse_count_not_dependent_elsewhere", period + ) + eligible = ( + meets_value_conditions & meets_income_condition & (independent_filers > 0) + ) # From 2025 (Part RR of Chapter 59 of the Laws of 2025) the credit is a # flat amount looked up by federal AGI bracket, allowed only when the diff --git a/policyengine_us/variables/gov/states/ny/tax/income/ny_allowable_college_tuition_expenses.py b/policyengine_us/variables/gov/states/ny/tax/income/ny_allowable_college_tuition_expenses.py index 96fbacd1935..b71b575b111 100644 --- a/policyengine_us/variables/gov/states/ny/tax/income/ny_allowable_college_tuition_expenses.py +++ b/policyengine_us/variables/gov/states/ny/tax/income/ny_allowable_college_tuition_expenses.py @@ -13,5 +13,17 @@ class ny_allowable_college_tuition_expenses(Variable): def formula(tax_unit, period, parameters): p = parameters(period).gov.states.ny.tax.income.college_tuition person = tax_unit.members + # Tax Law 606(t)(2)(D): an individual claimed as a dependent on + # another New York return cannot claim their own tuition ("only the + # person who claims the student as a dependent", IT-272), and a return + # on which a filer can be claimed has no dependents (IRC 152(b)(1)). + # The model has no input for which return claims the person, so an + # actual claim is taken to be on a New York return. + claimed = person("claimed_as_dependent_on_another_return", period) + dependent = person("is_tax_unit_dependent", period) + dependent_filer = person.tax_unit( + "head_or_spouse_is_dependent_elsewhere_without_filing_exception", period + ) + allowed = ~claimed & ~(dependent & dependent_filer) capped = min_(person("qualified_tuition_expenses", period), p.cap) - return tax_unit.sum(capped) + return tax_unit.sum(capped * allowed) diff --git a/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/ny_exemptions.py b/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/ny_exemptions.py index 1684312b883..ad8b14f1f01 100644 --- a/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/ny_exemptions.py +++ b/policyengine_us/variables/gov/states/ny/tax/income/taxable_income/ny_exemptions.py @@ -11,7 +11,16 @@ class ny_exemptions(Variable): defined_for = StateCode.NY def formula(tax_unit, period, parameters): - count_dependents = tax_unit("tax_unit_child_dependents", period) + # Tax Law 616(a) gives the exemption for each dependent for whom the + # taxpayer is entitled to a deduction under IRC 151(c); a return on + # which the filer (or, if joint, either spouse) can be claimed as a + # dependent has none (IRC 152(b)(1)). + dependent_filer = tax_unit( + "head_or_spouse_is_dependent_elsewhere_without_filing_exception", period + ) + count_dependents = where( + dependent_filer, 0, tax_unit("tax_unit_child_dependents", period) + ) dependent_exemption = parameters( period ).gov.states.ny.tax.income.exemptions.dependent