diff --git a/changelog.d/dc-eitc-itin-relationship-fixes.fixed.md b/changelog.d/dc-eitc-itin-relationship-fixes.fixed.md new file mode 100644 index 00000000000..22af1c534f2 --- /dev/null +++ b/changelog.d/dc-eitc-itin-relationship-fixes.fixed.md @@ -0,0 +1 @@ +Limit the DC EITC ITIN extension to tax years from 2023 (D.C. Code 47-1806.04(f)(1)(D), added by D.C. Law 24-167 section 7012, not D.C. Law 23-149), cite the D-40 Line 27a instructions for sending a DC filer whose qualifying children have no Social Security number or ITIN to the childless schedule, and stop counting a disabled parent or grandparent dependent as an EITC qualifying child under IRC 152(c)(2) in the federal, CA, CO, DC, IL, MN and WA credits. diff --git a/policyengine_us/parameters/gov/states/dc/tax/income/credits/eitc/itin_eligible.yaml b/policyengine_us/parameters/gov/states/dc/tax/income/credits/eitc/itin_eligible.yaml new file mode 100644 index 00000000000..b23b36c78ef --- /dev/null +++ b/policyengine_us/parameters/gov/states/dc/tax/income/credits/eitc/itin_eligible.yaml @@ -0,0 +1,14 @@ +description: The District of Columbia accepts an individual taxpayer identification number for the filer, spouse and qualifying children under its earned income tax credit if this is true. +values: + 2015-01-01: false + # (f)(1)(D)(ii) applies to taxable years beginning after December 31, 2022. + 2023-01-01: true +metadata: + unit: bool + period: year + label: DC EITC ITIN eligibility + reference: + - title: Code of the District of Columbia § 47–1806.04 (f)(1)(D)(ii) + href: https://code.dccouncil.gov/us/dc/council/code/sections/47-1806.04#(f)(1)(D)(ii) + - title: D.C. Law 24-167, Fiscal Year 2023 Budget Support Act of 2022, § 7012 + href: https://code.dccouncil.gov/us/dc/council/laws/24-167 diff --git a/policyengine_us/parameters/gov/states/dc/tax/income/credits/eitc/qualifying_child_tin_required.yaml b/policyengine_us/parameters/gov/states/dc/tax/income/credits/eitc/qualifying_child_tin_required.yaml new file mode 100644 index 00000000000..ee328064c4f --- /dev/null +++ b/policyengine_us/parameters/gov/states/dc/tax/income/credits/eitc/qualifying_child_tin_required.yaml @@ -0,0 +1,45 @@ +description: The District of Columbia treats a filer whose qualifying children all lack a Social Security number or individual taxpayer identification number as a filer without a qualifying child under its earned income tax credit if this is true. +values: + # From 2023 the D-40 Line 27a instructions require each qualifying child to + # have a Social Security number or ITIN and send a filer whose children have + # neither to the childless schedule. No DC source settles earlier years; + # the 2021 and 2022 booklets' qualifying-child rules have no identification + # test. Read alone, D.C. Code 47-1806.04(f)(4) and IRC 32(c)(3)(D) keep such + # a child a qualifying child, which closes the (f)(1)(C) childless + # schedule; setting this to false applies that reading. ARPA section 9622, + # "Taxpayer eligible for childless earned income credit in case of + # qualifying children who fail to meet certain identification + # requirements", struck former IRC 32(c)(1)(F) from 2021, and the 2021 + # booklet's "New for 2021" note repeats it. PolicyEngine applies the + # childless treatment in every year, so a child with neither number never + # counts. + 2015-01-01: true +metadata: + unit: bool + period: year + label: DC EITC qualifying child identification requirement + reference: + - title: Code of the District of Columbia § 47–1806.04 (f)(1)(D)(ii) + href: https://code.dccouncil.gov/us/dc/council/code/sections/47-1806.04#(f)(1)(D)(ii) + - title: Code of the District of Columbia § 47–1806.04 (f)(4) + href: https://code.dccouncil.gov/us/dc/council/code/sections/47-1806.04#(f)(4) + - title: American Rescue Plan Act of 2021, Pub. L. 117-2, § 9622, 135 Stat. 153 + href: https://www.congress.gov/117/plaws/publ2/PLAW-117publ2.pdf#page=151 + - title: 2021 DC Form D-40 Booklet, Page 3, New for 2021, Earned Income Tax Credit + href: https://otr.cfo.dc.gov/sites/default/files/dc/sites/otr/publication/attachments/52926_D-40_12.21.21_Final_Rev011122.pdf#page=3 + - title: 2021 DC Form D-40 Booklet, Page 12, Qualifying Child for EITC Purposes + href: https://otr.cfo.dc.gov/sites/default/files/dc/sites/otr/publication/attachments/52926_D-40_12.21.21_Final_Rev011122.pdf#page=12 + - title: 2022 DC Form D-40 Booklet, Page 11, Taxpayers with a Qualifying Child + href: https://otr.cfo.dc.gov/sites/default/files/dc/sites/otr/publication/attachments/2022_D-40_Booklet_Final_blk_01_23_23_Ordc.pdf#page=11 + - title: 2023 DC Form D-40 Booklet, Page 10, Taxpayers with a Qualifying Child + href: https://otr.cfo.dc.gov/sites/default/files/dc/sites/otr/publication/attachments/2023_D40_Book_Final_012324.pdf#page=10 + - title: 2023 DC Form D-40 Booklet, Page 18, Line 27a + href: https://otr.cfo.dc.gov/sites/default/files/dc/sites/otr/publication/attachments/2023_D40_Book_Final_012324.pdf#page=18 + - title: 2024 DC Form D-40 Booklet, Page 10, Taxpayers with a Qualifying Child + href: https://otr.cfo.dc.gov/sites/default/files/dc/sites/otr/publication/attachments/2024_D40_Booklet_011525.pdf#page=10 + - title: 2024 DC Form D-40 Booklet, Page 18, Line 27a + href: https://otr.cfo.dc.gov/sites/default/files/dc/sites/otr/publication/attachments/2024_D40_Booklet_011525.pdf#page=18 + - title: 2025 DC Form D-40 Booklet, Page 13, Taxpayers with a Qualifying Child + href: https://otr.cfo.dc.gov/sites/default/files/dc/sites/otr/publication/attachments/2025_D40_Book_082026_v1.pdf#page=13 + - title: 2025 DC Form D-40 Booklet, Page 21, Line 27a + href: https://otr.cfo.dc.gov/sites/default/files/dc/sites/otr/publication/attachments/2025_D40_Book_082026_v1.pdf#page=21 diff --git a/policyengine_us/tests/policy/baseline/gov/irs/credits/earned_income/eitc_child_count.yaml b/policyengine_us/tests/policy/baseline/gov/irs/credits/earned_income/eitc_child_count.yaml index eee9530b246..d51c725e8e9 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/credits/earned_income/eitc_child_count.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/credits/earned_income/eitc_child_count.yaml @@ -85,3 +85,65 @@ members: [person1, person2] output: eitc_child_count: 0 + +- name: Case 6, disabled parent dependent fails the relationship test. + period: 2026 + input: + people: + person1: + is_tax_unit_head_or_spouse: true + meets_eitc_identification_requirements: true + person2: + age: 75 + is_permanently_and_totally_disabled: true + is_tax_unit_dependent: true + is_parent_of_filer_or_spouse: true + meets_eitc_identification_requirements: true + tax_units: + tax_unit: + members: [person1, person2] + output: + # IRC 152(c)(2): a parent is a qualifying relative, not a qualifying child. + eitc_child_count: 0 + +- name: Case 7, disabled grandparent dependent fails the relationship test. + period: 2026 + input: + people: + person1: + is_tax_unit_head_or_spouse: true + meets_eitc_identification_requirements: true + person2: + age: 85 + is_permanently_and_totally_disabled: true + is_tax_unit_dependent: true + is_grandparent_of_filer_or_spouse: true + meets_eitc_identification_requirements: true + tax_units: + tax_unit: + members: [person1, person2] + output: + eitc_child_count: 0 + +- name: Case 8, federal EITC uses the childless schedule for a filer supporting a disabled parent. + period: 2023 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 6_000 + parent: + age: 75 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + is_parent_of_filer_or_spouse: true + tax_units: + tax_unit: + members: [head, parent] + filing_status: HEAD_OF_HOUSEHOLD + output: + eitc_child_count: 0 + # Rev. Proc. 2022-38: 7.65% x 6,000 = 459, not the one-child 34% x 6,000. + eitc: 459 diff --git a/policyengine_us/tests/policy/baseline/gov/irs/credits/earned_income/is_eitc_qualifying_child.yaml b/policyengine_us/tests/policy/baseline/gov/irs/credits/earned_income/is_eitc_qualifying_child.yaml new file mode 100644 index 00000000000..3bdd49ebc3c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/irs/credits/earned_income/is_eitc_qualifying_child.yaml @@ -0,0 +1,106 @@ +# IRC 32(c)(3)(A) applies the IRC 152(c) qualifying-child definition: the +# 152(c)(2) relationship test and the 152(c)(3) age test, which 152(c)(3)(B) +# waives for a permanently and totally disabled individual. The identification +# requirement of IRC 32(c)(3)(D) is applied by each credit. + +- name: A dependent child under the age limit is an EITC qualifying child. + period: 2026 + input: + people: + head: + age: 40 + is_tax_unit_head: true + child: + age: 10 + is_tax_unit_dependent: true + output: + is_eitc_qualifying_child: [false, true] + +- name: A permanently and totally disabled adult child is an EITC qualifying child. + period: 2026 + input: + people: + head: + age: 55 + is_tax_unit_head: true + adult_child: + age: 30 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + output: + is_eitc_qualifying_child: [false, true] + +- name: A non-disabled adult dependent is not an EITC qualifying child. + period: 2026 + input: + people: + head: + age: 55 + is_tax_unit_head: true + adult_child: + age: 30 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: false + output: + is_eitc_qualifying_child: [false, false] + +- name: A permanently and totally disabled parent fails the relationship test. + period: 2026 + input: + people: + head: + age: 50 + is_tax_unit_head: true + parent: + age: 75 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + is_parent_of_filer_or_spouse: true + output: + # A parent can be a qualifying relative under IRC 152(d)(2)(C) but never + # a qualifying child under IRC 152(c)(2). + is_eitc_qualifying_child: [false, false] + +- name: A permanently and totally disabled grandparent fails the relationship test. + period: 2026 + input: + people: + head: + age: 50 + is_tax_unit_head: true + grandparent: + age: 85 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + is_grandparent_of_filer_or_spouse: true + output: + is_eitc_qualifying_child: [false, false] + +- name: A disabled non-dependent is not an EITC qualifying child. + period: 2026 + input: + people: + head: + age: 50 + is_tax_unit_head: true + is_permanently_and_totally_disabled: true + output: + is_eitc_qualifying_child: false + +- name: The identification requirement is not part of this test. + period: 2026 + input: + people: + head: + age: 40 + is_tax_unit_head: true + child: + age: 10 + is_tax_unit_dependent: true + ssn_card_type: NONE + output: + is_eitc_qualifying_child: [false, true] diff --git a/policyengine_us/tests/policy/baseline/gov/irs/credits/earned_income/test_eitc_qualifying_child_invariants.py b/policyengine_us/tests/policy/baseline/gov/irs/credits/earned_income/test_eitc_qualifying_child_invariants.py new file mode 100644 index 00000000000..a0612249389 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/irs/credits/earned_income/test_eitc_qualifying_child_invariants.py @@ -0,0 +1,352 @@ +"""Invariants of the EITC qualifying-child test and the DC EITC branches. + +Hypothesis draws earnings, investment income and ages. Each draw becomes one +vectorized simulation holding every combination of dependent, identification +status and state, so each property is checked on every combination for the +drawn incomes. + +EITC qualifying child (IRC 32(c)(3)(A), applying IRC 152(c)): + +1. A dependent flagged as a parent or grandparent of the filer is never an + EITC qualifying child. The IRC 152(c)(3)(B) disability waiver reaches only + the age test, not the IRC 152(c)(2) relationship test. +2. Relationship dominates disability: for a parent or grandparent dependent, + the disability flag changes no EITC-style credit (federal, CA, CO, DC, IL, + MN, WA). +3. Disability monotonicity: making an adult child dependent disabled never + moves a DC unit from the with-child schedule to the childless one. + +DC EITC (D.C. Code 47-1806.04(f)): + +4. Both branches are non-negative, at most one is positive, and dc_eitc + equals the branch selected by dc_eitc_has_qualifying_child, which is also + max(with, without). +5. The with-child branch is zero without a qualifying child, and the + childless branch is zero with one. +6. Before 2023, the with-child branch is the match times the federal credit + allowed (a differential check against the federal eitc variable). +7. Before 2023 an ITIN filer receives no DC EITC, and giving a qualifying + child an ITIN instead of a Social Security number never raises dc_eitc. +8. From 2023, giving a qualifying child an ITIN instead of a Social Security + number leaves dc_eitc unchanged (D.C. Code 47-1806.04(f)(1)(D)(ii)). +9. A qualifying child with an ITIN routes its unit like one with a Social + Security number in every year; before 2023 it is still a qualifying child, + only left out of the IRC 32(b) computation. A qualifying child with + neither number counts for nothing: the unit gets the same routing and the + same dc_eitc as the same filer with no dependent. The D-40 instructions + say so from 2023 (Line 27a), and the model keeps that treatment for + earlier years (qualifying_child_tin_required). +10. From 2023, removing a qualifying child's TIN never raises dc_eitc. Before + 2023 it can, as intended: DC's childless schedule can pay more than the + with-child match on the federal credit allowed. In TY2022 at $6,000 of + earnings, an ITIN child gives 70% x 459 = 321.30 and a child with no + number gives the childless 459. + +With qualifying_child_tin_required switched off, the reading of (f)(4) and +IRC 32(c)(3)(D) alone: + +11. Schedule selection follows qualifying-child status whatever the child's + identification. +12. Before 2023 a qualifying child with no number gives the same dc_eitc as + one with an ITIN, since IRC 32(m) treats the two alike. +13. In every year, removing a qualifying child's TIN never raises dc_eitc. +""" + +import gc +import itertools + +import numpy as np +import pytest +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from policyengine_core.reforms import Reform + +from policyengine_us import CountryTaxBenefitSystem, Simulation + +YEARS = [2021, 2022, 2023, 2025] +ITIN_START = 2023 + +# Dependent kinds: (age, disabled, parent, grandparent). A kind of None has no +# dependent. "child" takes the drawn child age. +KINDS = { + "none": None, + "child": ("draw", False, False, False), + "disabled_adult_child": (30, True, False, False), + "adult_child": (30, False, False, False), + "disabled_parent": (75, True, True, False), + "parent": (75, False, True, False), + "disabled_grandparent": (90, True, False, True), + "grandparent": (90, False, False, True), +} +QUALIFYING_CHILD_KINDS = ["child", "disabled_adult_child"] +ASCENDANT_KINDS = ["disabled_parent", "parent", "disabled_grandparent", "grandparent"] +# (ssn_card_type, has_tin) +IDS = {"ssn": ("CITIZEN", True), "itin": ("NONE", True), "none": ("NONE", False)} +STATES = ["DC", "CA", "CO", "IL", "MN", "WA", "TX"] +CREDITS = [ + "eitc", + "dc_eitc", + "ca_eitc", + "co_eitc", + "il_eitc", + "mn_child_and_working_families_credits", + "wa_working_families_tax_credit", +] + +household_draw = st.fixed_dictionaries( + { + "earnings": st.integers(0, 60_000), + "interest": st.one_of(st.just(0), st.integers(0, 15_000)), + "head_age": st.integers(19, 70), + "child_age": st.integers(0, 18), + } +) + + +def build(draw, rows, system=None): + """One tax unit per row; returns the simulation and row metadata.""" + situation = {"people": {}, "tax_units": {}, "households": {}} + dependent_index = [] + person_count = 0 + for i, (kind, dep_id, filer_id, state) in enumerate(rows): + card, has_tin = IDS[filer_id] + head = f"h{i}" + situation["people"][head] = { + "age": {y: draw["head_age"] for y in YEARS}, + "is_tax_unit_head": {y: True for y in YEARS}, + "employment_income": {y: draw["earnings"] for y in YEARS}, + "taxable_interest_income": {y: draw["interest"] for y in YEARS}, + "ssn_card_type": {y: card for y in YEARS}, + "has_tin": {y: has_tin for y in YEARS}, + } + members = [head] + person_count += 1 + spec = KINDS[kind] + if spec is None: + dependent_index.append(-1) + else: + age, disabled, parent, grandparent = spec + age = draw["child_age"] if age == "draw" else age + dep_card, dep_has_tin = IDS[dep_id] + dependent = f"d{i}" + situation["people"][dependent] = { + "age": {y: age for y in YEARS}, + "is_tax_unit_dependent": {y: True for y in YEARS}, + "is_tax_unit_spouse": {y: False for y in YEARS}, + "is_permanently_and_totally_disabled": {y: disabled for y in YEARS}, + "is_parent_of_filer_or_spouse": {y: parent for y in YEARS}, + "is_grandparent_of_filer_or_spouse": {y: grandparent for y in YEARS}, + "ssn_card_type": {y: dep_card for y in YEARS}, + "has_tin": {y: dep_has_tin for y in YEARS}, + } + members.append(dependent) + dependent_index.append(person_count) + person_count += 1 + situation["tax_units"][f"t{i}"] = {"members": members} + situation["households"][f"hh{i}"] = { + "members": members, + "state_code": {y: state for y in YEARS}, + } + simulation = Simulation(situation=situation, tax_benefit_system=system) + return simulation, np.array(dependent_index) + + +def index_rows(rows): + return {row: i for i, row in enumerate(rows)} + + +DC_ROWS = [ + (kind, dep_id, filer_id, "DC") + for kind, dep_id, filer_id in itertools.product(KINDS, IDS, ["ssn", "itin"]) + if not (kind == "none" and dep_id != "ssn") +] +STATE_ROWS = [ + (kind, dep_id, filer_id, state) + for kind, dep_id, filer_id, state in itertools.product( + ASCENDANT_KINDS + ["adult_child"], ["ssn", "itin"], ["ssn", "itin"], STATES + ) +] + + +@pytest.fixture(scope="module") +def tin_rule_off_system(): + """The tax-benefit system with qualifying_child_tin_required off. + + Built once for this module and only read. It is released when the module + finishes, so the rest of the pytest process does not keep a second full + system resident. + """ + reform = Reform.from_dict( + { + "gov.states.dc.tax.income.credits.eitc.qualifying_child_tin_required": { + "2015-01-01.2100-12-31": False + } + }, + country_id="us", + ) + yield CountryTaxBenefitSystem(reform=reform) + gc.collect() + + +SETTINGS = settings( + max_examples=8, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow], +) + + +@SETTINGS +@given(draw=household_draw) +def test_dc_eitc_invariants(draw): + sim, dependent_index = build(draw, DC_ROWS) + row = index_rows(DC_ROWS) + for year in YEARS: + with_child = sim.calculate("dc_eitc_with_qualifying_child", year) + without = sim.calculate("dc_eitc_without_qualifying_child", year) + dc_eitc = sim.calculate("dc_eitc", year) + has_child = sim.calculate("dc_eitc_has_qualifying_child", year) + federal = sim.calculate("eitc", year) + qualifying = sim.calculate("is_eitc_qualifying_child", year) + match = sim.tax_benefit_system.parameters( + f"{year}-01-01" + ).gov.states.dc.tax.income.credits.eitc.with_children.match + context = f"year {year}, draw {draw}" + + # 1. Ascendants are never qualifying children. + for (kind, *_), i in row.items(): + if kind in ASCENDANT_KINDS: + assert not qualifying[dependent_index[i]], (kind, context) + assert not has_child[i], (kind, context) + # 9. An ITIN child routes like a Social Security number child; a + # qualifying child with neither number leaves the unit where the same + # filer with no dependent would be. + for kind, filer_id in itertools.product( + QUALIFYING_CHILD_KINDS, ["ssn", "itin"] + ): + ssn = row[(kind, "ssn", filer_id, "DC")] + itin = row[(kind, "itin", filer_id, "DC")] + no_tin = row[(kind, "none", filer_id, "DC")] + alone = row[("none", "ssn", filer_id, "DC")] + assert qualifying[dependent_index[no_tin]], (kind, context) + assert has_child[ssn] and has_child[itin], (kind, context) + assert not has_child[no_tin] and not has_child[alone], (kind, context) + assert np.isclose(dc_eitc[no_tin], dc_eitc[alone]), (kind, context) + + # 4 and 5. Branch structure. + assert np.all(with_child >= 0) and np.all(without >= 0), context + assert np.all(with_child * without == 0), context + assert np.all(with_child[~has_child] == 0), context + assert np.all(without[has_child] == 0), context + assert np.allclose(dc_eitc, np.where(has_child, with_child, without)), context + assert np.allclose(dc_eitc, np.maximum(with_child, without)), context + + # 3. Disability never moves a unit off the with-child schedule. + for dep_id, filer_id in itertools.product(IDS, ["ssn", "itin"]): + disabled = row[("disabled_adult_child", dep_id, filer_id, "DC")] + plain = row[("adult_child", dep_id, filer_id, "DC")] + assert has_child[disabled] >= has_child[plain], context + + if year < ITIN_START: + # 6. Differential check against the federal credit. + assert np.allclose(with_child, np.where(has_child, match * federal, 0)), ( + context + ) + # 7. No ITIN path before 2023. + itin_filer = np.array([r[2] == "itin" for r in DC_ROWS]) + assert np.all(dc_eitc[itin_filer] == 0), context + for kind, filer_id in itertools.product( + QUALIFYING_CHILD_KINDS, ["ssn", "itin"] + ): + ssn = row[(kind, "ssn", filer_id, "DC")] + itin = row[(kind, "itin", filer_id, "DC")] + assert dc_eitc[itin] <= dc_eitc[ssn] + 1e-6, (kind, context) + else: + # 8. ITIN invariance from 2023. + for kind, filer_id in itertools.product( + QUALIFYING_CHILD_KINDS, ["ssn", "itin"] + ): + ssn = row[(kind, "ssn", filer_id, "DC")] + itin = row[(kind, "itin", filer_id, "DC")] + assert np.isclose(dc_eitc[itin], dc_eitc[ssn]), (kind, context) + # 10. From 2023, removing a qualifying child's TIN never raises + # the credit. + assert_no_tin_never_raises(dc_eitc, row, context) + + +def assert_no_tin_never_raises(dc_eitc, row, context): + for kind, filer_id in itertools.product(QUALIFYING_CHILD_KINDS, ["ssn", "itin"]): + for dep_id in ["ssn", "itin"]: + with_tin = row[(kind, dep_id, filer_id, "DC")] + no_tin = row[(kind, "none", filer_id, "DC")] + assert dc_eitc[no_tin] <= dc_eitc[with_tin] + 1e-6, ( + kind, + dep_id, + filer_id, + context, + ) + + +@SETTINGS +@given(draw=household_draw) +def test_dc_eitc_without_tin_rule(tin_rule_off_system, draw): + sim, dependent_index = build(draw, DC_ROWS, system=tin_rule_off_system) + row = index_rows(DC_ROWS) + has_dependent = dependent_index >= 0 + for year in YEARS: + dc_eitc = sim.calculate("dc_eitc", year) + has_child = sim.calculate("dc_eitc_has_qualifying_child", year) + qualifying = sim.calculate("is_eitc_qualifying_child", year) + context = f"year {year}, draw {draw}, TIN rule off" + + # 11. Routing follows qualifying-child status alone. + dep_qualifies = np.where( + has_dependent, qualifying[np.maximum(dependent_index, 0)], False + ) + assert np.array_equal(has_child, dep_qualifies), context + + # 12. Before 2023 no number is treated like an ITIN. + if year < ITIN_START: + for kind, filer_id in itertools.product( + QUALIFYING_CHILD_KINDS, ["ssn", "itin"] + ): + itin = row[(kind, "itin", filer_id, "DC")] + no_tin = row[(kind, "none", filer_id, "DC")] + assert np.isclose(dc_eitc[no_tin], dc_eitc[itin]), (kind, context) + + # 13. Removing a qualifying child's TIN never raises the credit. + assert_no_tin_never_raises(dc_eitc, row, context) + + +@SETTINGS +@given(draw=household_draw) +def test_relationship_dominates_disability_across_credits(draw): + sim, dependent_index = build(draw, STATE_ROWS) + row = index_rows(STATE_ROWS) + for year in YEARS: + qualifying = sim.calculate("is_eitc_qualifying_child", year) + child_count = sim.calculate("eitc_child_count", year) + values = {credit: sim.calculate(credit, year) for credit in CREDITS} + context = f"year {year}, draw {draw}" + for (kind, dep_id, filer_id, state), i in row.items(): + if kind in ASCENDANT_KINDS: + # 1. Ascendants never qualify, whatever their disability. + assert not qualifying[dependent_index[i]], (kind, context) + assert child_count[i] == 0, (kind, context) + # 2. For an ascendant, disability changes no credit. + for ascendant in ["parent", "grandparent"]: + for dep_id, filer_id, state in itertools.product( + ["ssn", "itin"], ["ssn", "itin"], STATES + ): + disabled = row[(f"disabled_{ascendant}", dep_id, filer_id, state)] + plain = row[(ascendant, dep_id, filer_id, state)] + for credit, value in values.items(): + assert np.isclose(value[disabled], value[plain]), ( + credit, + ascendant, + dep_id, + filer_id, + state, + context, + ) diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/earned_income/ca_is_qualifying_child_for_caleitc.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/earned_income/ca_is_qualifying_child_for_caleitc.yaml index bd53d5ea72d..cefea311401 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/earned_income/ca_is_qualifying_child_for_caleitc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/earned_income/ca_is_qualifying_child_for_caleitc.yaml @@ -61,3 +61,24 @@ state_code: CA output: ca_is_qualifying_child_for_caleitc: false + +- name: Disabled parent dependent is not a CalEITC qualifying child. + period: 2026 + input: + people: + head: + age: 50 + is_tax_unit_head: true + disabled_parent: + age: 75 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + is_parent_of_filer_or_spouse: true + households: + household: + members: [head, disabled_parent] + state_code: CA + output: + # IRC 152(c)(2), which the RTC 17052 qualifying-child definition follows. + ca_is_qualifying_child_for_caleitc: [false, false] diff --git a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/eitc/co_eitc.yaml b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/eitc/co_eitc.yaml index 061ddff486b..024f0913570 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/eitc/co_eitc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/co/tax/income/credits/eitc/co_eitc.yaml @@ -361,3 +361,39 @@ # child under IRC 152(c)(3)(B), so the CO EITC pays its match on the # 1-child federal-style EITC rather than the childless amount. co_eitc: 1_700 + +- name: Colorado EITC uses the childless schedule for a disabled parent dependent (IRC 152(c)(2)) + period: 2025 + absolute_error_margin: 0.01 + input: + people: + head: + age: 45 + employment_income: 10_000 + is_tax_unit_head: true + has_tin: true + ssn_card_type: CITIZEN + disabled_parent: + age: 75 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + is_parent_of_filer_or_spouse: true + has_tin: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [head, disabled_parent] + filing_status: HEAD_OF_HOUSEHOLD + spm_units: + spm_unit: + members: [head, disabled_parent] + households: + household: + members: [head, disabled_parent] + state_code: CO + output: + # A parent fails the IRC 152(c)(2) relationship test, so the federal + # credit is the childless 7.65% x 10,000 capped at 649; 50% x 649. + eitc_child_count: 0 + co_eitc: 324.5 diff --git a/policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/dc_eitc.yaml b/policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/dc_eitc.yaml index 236fd0dc8cf..f440ab68ecf 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/dc_eitc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/dc_eitc.yaml @@ -74,6 +74,7 @@ disabled_adult: age: 30 is_tax_unit_dependent: true + is_tax_unit_spouse: false is_permanently_and_totally_disabled: true ssn_card_type: NONE has_tin: true @@ -86,11 +87,725 @@ members: [head, disabled_adult] state_code: DC output: - # The federal credit needs a Social Security number, D.C. Law 23-149 - # does not. The childless branch also counts this dependent as a child, + # The federal credit needs a Social Security number; from 2023 D.C. Code + # 47-1806.04(f)(1)(D)(ii), added by D.C. Law 24-167 section 7012, accepts + # an ITIN. The childless branch also counts this dependent as a child, # so before the router matched it the unit got neither credit. eitc_child_count: 0 dc_eitc_without_qualifying_child: 0 dc_eitc_with_qualifying_child: 2_796.5 dc_eitc: 2_796.5 +- name: DC EITC does not count an ITIN child before 2023 (TY2022) + period: 2022 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: CITIZEN + dependent: + age: 30 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: NONE + has_tin: true + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # (f)(1)(D)(ii) applies only to tax years beginning after December 31, + # 2022. Before then IRC 32(c)(3)(D) keeps the ITIN child out of the + # federal credit, which for this filer is the childless amount: + # 560 - 7.65% x (20,000 - 9,160) < 0. The child is still a qualifying + # child, so the (f)(1)(C) childless schedule does not apply. + eitc: 0 + dc_eitc_has_qualifying_child: true + dc_eitc_with_qualifying_child: 0 + dc_eitc_without_qualifying_child: 0 + dc_eitc: 0 + +- name: DC EITC counts an ITIN child from 2023 (TY2023) + period: 2023 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: CITIZEN + dependent: + age: 30 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: NONE + has_tin: true + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # 70% x the one-child federal-like credit of 3,995, as if the ITIN met + # IRC 32(m). + eitc: 0 + dc_eitc_with_qualifying_child: 2_796.5 + dc_eitc_without_qualifying_child: 0 + dc_eitc: 2_796.5 + +- name: DC EITC matches the childless federal credit for a filer with only an ITIN child in TY2021 + period: 2021 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: CITIZEN + dependent: + age: 30 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: NONE + has_tin: true + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # ARPA's 2021 childless credit: 1,502 - 15.3% x (20,000 - 11,610) = + # 218.33 is the federal credit allowed; DC matches 40% of it. + eitc: 218.33 + dc_eitc_with_qualifying_child: 87.33 + dc_eitc_without_qualifying_child: 0 + dc_eitc: 87.33 + +- name: DC EITC matches the childless federal credit for a filer with only an ITIN child in TY2022 at low earnings + period: 2022 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 6_000 + ssn_card_type: CITIZEN + dependent: + age: 30 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: NONE + has_tin: true + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # Federal credit allowed: 7.65% x 6,000 = 459. DC matches 70% of it. + eitc: 459 + dc_eitc_with_qualifying_child: 321.3 + dc_eitc_without_qualifying_child: 0 + dc_eitc: 321.3 + +- name: DC EITC sends a filer whose disabled adult qualifying child has no TIN to the childless schedule (TY2022) + period: 2022 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: CITIZEN + dependent: + age: 30 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: NONE + has_tin: false + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # A qualifying child with neither a Social Security number nor an ITIN + # does not count (qualifying_child_tin_required), unlike the ITIN child + # above. (f)(1)(C): min(7.65% x 20,000, 560) = 560, below the 20,532 + # phase-out start. + eitc: 0 + dc_eitc_has_qualifying_child: false + dc_eitc_with_qualifying_child: 0 + dc_eitc_without_qualifying_child: 560 + dc_eitc: 560 + +- name: DC EITC sends a filer whose minor qualifying child has no TIN to the childless schedule (TY2022) + period: 2022 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: CITIZEN + dependent: + age: 10 + is_tax_unit_dependent: true + ssn_card_type: NONE + has_tin: false + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # Same routing for an ordinary minor child. The federal credit is the + # self-only amount, 560 - 7.65% x (20,000 - 9,160) < 0, but DC's own + # childless schedule pays min(7.65% x 20,000, 560) = 560. + eitc: 0 + dc_eitc_has_qualifying_child: false + dc_eitc_with_qualifying_child: 0 + dc_eitc_without_qualifying_child: 560 + dc_eitc: 560 + +- name: DC EITC sends a filer whose qualifying child has no TIN to the childless schedule in TY2022 at low earnings + period: 2022 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 6_000 + ssn_card_type: CITIZEN + dependent: + age: 30 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: NONE + has_tin: false + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # (f)(1)(C): 7.65% x 6,000 = 459. The ITIN child above instead gets + # 70% of the same 459 federal credit, 321.30. + eitc: 459 + dc_eitc_has_qualifying_child: false + dc_eitc_with_qualifying_child: 0 + dc_eitc_without_qualifying_child: 459 + dc_eitc: 459 + +- name: DC EITC sends a filer whose qualifying child has no TIN to the childless schedule in TY2021 + period: 2021 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: CITIZEN + dependent: + age: 30 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: NONE + has_tin: false + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # (f)(1)(C) on ARPA's 2021 childless phase-in: + # min(15.3% x 20,000, 1,502) - 8.48% x (20,000 - 19,743) = 1,480.21. + # The ITIN child above instead gets 40% of the 218.33 federal credit. + eitc: 218.33 + dc_eitc_has_qualifying_child: false + dc_eitc_with_qualifying_child: 0 + dc_eitc_without_qualifying_child: 1_480.21 + dc_eitc: 1_480.21 + +- name: Without the TIN rule, a filer whose qualifying child has no TIN gets the with-child match on the federal credit in TY2022 + period: 2022 + absolute_error_margin: 0.01 + input: + gov.states.dc.tax.income.credits.eitc.qualifying_child_tin_required: false + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 6_000 + ssn_card_type: CITIZEN + dependent: + age: 30 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: NONE + has_tin: false + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # The reading of (f)(4) and IRC 32(c)(3)(D) alone: the child stays a + # qualifying child, so the filer gets the with-child match on the + # federal credit allowed, as for an ITIN child: 70% x 459 = 321.30. + eitc: 459 + dc_eitc_has_qualifying_child: true + dc_eitc_with_qualifying_child: 321.3 + dc_eitc_without_qualifying_child: 0 + dc_eitc: 321.3 + +- name: Without the TIN rule, a filer whose qualifying child has no TIN gets the with-child match on the federal credit in TY2021 + period: 2021 + absolute_error_margin: 0.01 + input: + gov.states.dc.tax.income.credits.eitc.qualifying_child_tin_required: false + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: CITIZEN + dependent: + age: 30 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: NONE + has_tin: false + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # 40% x the ARPA childless credit allowed, + # 1,502 - 15.3% x (20,000 - 11,610) = 218.33, giving 87.33. + eitc: 218.33 + dc_eitc_has_qualifying_child: true + dc_eitc_with_qualifying_child: 87.33 + dc_eitc_without_qualifying_child: 0 + dc_eitc: 87.33 + +- name: DC EITC sends a filer whose only qualifying child has no SSN or ITIN to the childless schedule from 2023 + period: 2023 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: CITIZEN + dependent: + age: 10 + is_tax_unit_dependent: true + ssn_card_type: NONE + has_tin: false + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # 2023 D-40 instructions, Line 27a (p. 18): "Each qualifying child must + # have a valid social security number (SSN) or individual taxpayer + # identification number (ITIN) issued by the IRS. If you have no children + # who qualify, you must claim the DC EITC without qualifying children." + # (f)(1)(C): 600, below the 21,888 phase-out start. + eitc: 0 + dc_eitc_has_qualifying_child: false + dc_eitc_with_qualifying_child: 0 + dc_eitc_without_qualifying_child: 600 + dc_eitc: 600 + +- name: Without the TIN rule, a filer whose qualifying child has no TIN gets the with-child match on the self-only credit in 2023 + period: 2023 + absolute_error_margin: 0.01 + input: + gov.states.dc.tax.income.credits.eitc.qualifying_child_tin_required: false + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 6_000 + ssn_card_type: CITIZEN + dependent: + age: 10 + is_tax_unit_dependent: true + ssn_card_type: NONE + has_tin: false + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # The child stays a qualifying child but is not counted in the IRC 32(b) + # computation, so the base is the self-only amount, 7.65% x 6,000 = 459, + # and the match is 70% of it. + dc_eitc_has_qualifying_child: true + dc_eitc_with_qualifying_child: 321.3 + dc_eitc_without_qualifying_child: 0 + dc_eitc: 321.3 + +- name: Without the TIN rule, a filer under 25 whose qualifying child has no TIN gets no DC EITC in 2023 + period: 2023 + absolute_error_margin: 0.01 + input: + gov.states.dc.tax.income.credits.eitc.qualifying_child_tin_required: false + people: + head: + age: 22 + is_tax_unit_head: true + employment_income: 6_000 + ssn_card_type: CITIZEN + dependent: + age: 10 + is_tax_unit_dependent: true + ssn_card_type: NONE + has_tin: false + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # With no child in the count, the federal demographic test falls back on + # the childless minimum age of 25, as the federal credit that is the + # pre-2023 base does, so the self-only amount is 0. + eitc: 0 + dc_eitc_has_qualifying_child: true + dc_eitc_with_qualifying_child: 0 + dc_eitc_without_qualifying_child: 0 + dc_eitc: 0 + +- name: DC EITC uses the one-child credit for an ITIN child in TY2023 at low earnings + period: 2023 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 6_000 + ssn_card_type: CITIZEN + dependent: + age: 30 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: NONE + has_tin: true + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # 70% x 34% x 6,000 = 1,428, not 70% of the 459 federal credit allowed. + eitc: 459 + dc_eitc_with_qualifying_child: 1_428 + dc_eitc_without_qualifying_child: 0 + dc_eitc: 1_428 + +- name: DC EITC denies an ITIN filer with a Social Security number child before 2023 + period: 2022 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: NONE + dependent: + age: 10 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: false + ssn_card_type: CITIZEN + has_tin: true + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # The filer has no Social Security number and (f)(1)(D) is not yet in + # force. + eitc_child_count: 1 + eitc: 0 + dc_eitc_with_qualifying_child: 0 + dc_eitc: 0 + +- name: DC EITC allows an ITIN filer with a Social Security number child from 2023 + period: 2023 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: NONE + dependent: + age: 10 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: false + ssn_card_type: CITIZEN + has_tin: true + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # 70% x 3,995. + eitc_child_count: 1 + eitc: 0 + dc_eitc_with_qualifying_child: 2_796.5 + dc_eitc: 2_796.5 + +- name: DC EITC with-child branch for a disabled adult child with a Social Security number + period: 2023 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: CITIZEN + dependent: + age: 30 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: CITIZEN + has_tin: true + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # IRC 152(c)(3)(B) waives the age test for the disabled adult child. + eitc_child_count: 1 + eitc: 3_995 + dc_eitc_with_qualifying_child: 2_796.5 + dc_eitc_without_qualifying_child: 0 + dc_eitc: 2_796.5 + +- name: DC EITC childless amount for a disabled parent dependent + period: 2023 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: CITIZEN + dependent: + age: 75 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: CITIZEN + has_tin: true + is_parent_of_filer_or_spouse: true + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # A parent fails the IRC 152(c)(2) relationship test, so the disabled + # parent is a qualifying relative, not a qualifying child. (f)(1)(C): + # min(7.65% x 20,000, 600) - 8.48% x max(0, 20,000 - 21,888) = 600. + is_eitc_qualifying_child: [false, false] + eitc_child_count: 0 + dc_eitc_has_qualifying_child: false + dc_eitc_with_qualifying_child: 0 + dc_eitc_without_qualifying_child: 600 + dc_eitc: 600 + +- name: DC EITC childless amount for a disabled parent dependent at low earnings + period: 2023 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 6_000 + ssn_card_type: CITIZEN + dependent: + age: 75 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: CITIZEN + has_tin: true + is_parent_of_filer_or_spouse: true + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # 7.65% x 6,000 = 459 under both the federal and DC childless rules. + eitc_child_count: 0 + eitc: 459 + dc_eitc_with_qualifying_child: 0 + dc_eitc_without_qualifying_child: 459 + dc_eitc: 459 + +- name: DC EITC childless amount for a disabled grandparent dependent + period: 2023 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: CITIZEN + dependent: + age: 80 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: CITIZEN + has_tin: true + is_grandparent_of_filer_or_spouse: true + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # A grandparent also fails the IRC 152(c)(2) relationship test. + eitc_child_count: 0 + dc_eitc_with_qualifying_child: 0 + dc_eitc_without_qualifying_child: 600 + dc_eitc: 600 + +- name: DC EITC childless amount for a disabled parent dependent with an ITIN + period: 2023 + absolute_error_margin: 0.01 + input: + people: + head: + age: 50 + is_tax_unit_head: true + employment_income: 20_000 + ssn_card_type: CITIZEN + dependent: + age: 75 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + ssn_card_type: NONE + has_tin: true + is_parent_of_filer_or_spouse: true + tax_units: + tax_unit: + members: [head, dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [head, dependent] + state_code: DC + output: + # Before this fix the ITIN parent routed the unit to the with-child + # branch and received 70% x 3,995 = 2,796.50. + dc_eitc_has_qualifying_child: false + dc_eitc_with_qualifying_child: 0 + dc_eitc_without_qualifying_child: 600 + dc_eitc: 600 diff --git a/policyengine_us/tests/policy/baseline/gov/states/il/tax/income/credits/il_eitc.yaml b/policyengine_us/tests/policy/baseline/gov/states/il/tax/income/credits/il_eitc.yaml index 14c1be44cb2..d43f6df3d5d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/il/tax/income/credits/il_eitc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/il/tax/income/credits/il_eitc.yaml @@ -174,3 +174,38 @@ # child under IRC 152(c)(3)(B), so the IL EIC reflects the 1-child federal # EITC (rather than the childless schedule) times the IL match. il_eitc: 680 + +- name: Illinois EITC uses the childless schedule for a disabled parent dependent (IRC 152(c)(2)) + period: 2025 + absolute_error_margin: 0.01 + input: + people: + head: + age: 45 + employment_income: 10_000 + is_tax_unit_head: true + has_tin: true + ssn_card_type: CITIZEN + disabled_parent: + age: 75 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + is_parent_of_filer_or_spouse: true + has_tin: true + ssn_card_type: CITIZEN + tax_units: + tax_unit: + members: [head, disabled_parent] + filing_status: HEAD_OF_HOUSEHOLD + spm_units: + spm_unit: + members: [head, disabled_parent] + households: + household: + members: [head, disabled_parent] + state_code: IL + output: + # A parent fails the IRC 152(c)(2) relationship test: 20% x the childless + # federal-like credit of 649. + il_eitc: 129.8 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/credits/mn_child_and_working_families_credits.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/credits/mn_child_and_working_families_credits.yaml index 13ac7c22a3e..595b43b987e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/credits/mn_child_and_working_families_credits.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/credits/mn_child_and_working_families_credits.yaml @@ -567,6 +567,37 @@ output: mn_child_and_working_families_credits: 2_129.2 +- name: MN qualifying older child bonus excludes a disabled parent dependent (IRC 152(c)(2)) + # A parent fails the IRC 152(c)(2) relationship test, so the disabled parent + # is not an IRC 32(c) qualifying child and not a qualifying older child. + period: 2025 + input: + people: + person1: + age: 45 + is_full_time_student: false + disabled_parent: + age: 75 + is_tax_unit_dependent: true + is_full_time_student: false + is_permanently_and_totally_disabled: true + is_parent_of_filer_or_spouse: true + tax_units: + tax_unit: + members: [person1, disabled_parent] + ctc_qualifying_children: 0 + mn_wfc_eligible: true + eitc_earned_income: 10_000 + adjusted_gross_income: 10_000 + filing_status: JOINT + households: + household: + members: [person1, disabled_parent] + state_code: MN + output: + # WFC base only: min($10,000, $9,480) * 0.04 = $379.20. + mn_child_and_working_families_credits: 379.2 + # Schedule M1CWFC, line 2 takes earned income from federal EIC Worksheet B: # both spouses combined, a net self-employment loss subtracted, not less than # zero. Line 10 is the greater of AGI (line 1) and line 2. diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_disabled_itin.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_disabled_itin.yaml index b4c2b9c1d9f..54cfe8e7ce4 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_disabled_itin.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_disabled_itin.yaml @@ -271,3 +271,42 @@ eitc_child_count: 0 # The Washington exception requires a valid SSN or ITIN for the child. wa_working_families_tax_credit: 0 + +- name: Disabled ITIN parent dependent does not count as a qualifying child. + period: 2023 + absolute_error_margin: 0.01 + input: + people: + head: + age: 45 + employment_income: 10_000 + is_tax_unit_head: true + has_tin: true + ssn_card_type: OTHER_NON_CITIZEN + disabled_parent: + age: 75 + is_tax_unit_dependent: true + is_tax_unit_spouse: false + is_permanently_and_totally_disabled: true + is_parent_of_filer_or_spouse: true + has_tin: true + ssn_card_type: OTHER_NON_CITIZEN + is_disabled: true + tax_units: + tax_unit: + members: [head, disabled_parent] + filing_status: HEAD_OF_HOUSEHOLD + would_file_taxes_voluntarily: true + takes_up_eitc: true + spm_units: + spm_unit: + members: [head, disabled_parent] + households: + household: + members: [head, disabled_parent] + state_code: WA + output: + # A parent fails the IRC 152(c)(2) relationship test, so the filer gets the + # childless $315 maximum rather than the one-child $625. + eitc_child_count: 0 + wa_working_families_tax_credit: 315 diff --git a/policyengine_us/variables/gov/irs/credits/earned_income/eitc_child_count.py b/policyengine_us/variables/gov/irs/credits/earned_income/eitc_child_count.py index 28120110d0b..b6df0c2be59 100644 --- a/policyengine_us/variables/gov/irs/credits/earned_income/eitc_child_count.py +++ b/policyengine_us/variables/gov/irs/credits/earned_income/eitc_child_count.py @@ -11,18 +11,13 @@ class eitc_child_count(Variable): reference = ( # IRC 32(c)(3)(D)(i) specifies qualifying children need a taxpayer identification number. "https://www.law.cornell.edu/uscode/text/26/32#c_3_D_i", - # IRC 152(c)(3)(B) waives the qualifying-child age test for permanently and totally disabled individuals. - "https://www.law.cornell.edu/uscode/text/26/152#c_3_B", + # IRC 32(c)(3)(A) applies the IRC 152(c) qualifying-child definition. + "https://www.law.cornell.edu/uscode/text/26/32#c_3_A", ) def formula(tax_unit, period, parameters): person = tax_unit.members - is_disabled_dependent = person("is_tax_unit_dependent", period) & person( - "is_permanently_and_totally_disabled", period - ) - is_child = ( - person("is_qualifying_child_dependent", period) | is_disabled_dependent - ) + is_child = person("is_eitc_qualifying_child", period) meets_eitc_identification_requirements = person( "meets_eitc_identification_requirements", period ) diff --git a/policyengine_us/variables/gov/irs/credits/earned_income/is_eitc_qualifying_child.py b/policyengine_us/variables/gov/irs/credits/earned_income/is_eitc_qualifying_child.py new file mode 100644 index 00000000000..47841c8c963 --- /dev/null +++ b/policyengine_us/variables/gov/irs/credits/earned_income/is_eitc_qualifying_child.py @@ -0,0 +1,42 @@ +from policyengine_us.model_api import * + + +class is_eitc_qualifying_child(Variable): + value_type = bool + entity = Person + label = "Is an EITC qualifying child before the identification requirement" + documentation = """ + Whether a tax unit dependent is a qualifying child under IRC 32(c)(3)(A), + which applies the IRC 152(c) qualifying-child definition. The taxpayer + identification number requirement of IRC 32(c)(3)(D) is applied by each + credit, because some states accept an ITIN where the federal credit + requires a Social Security number. + """ + definition_period = YEAR + reference = ( + # IRC 32(c)(3)(A) applies the IRC 152(c) qualifying-child definition. + "https://www.law.cornell.edu/uscode/text/26/32#c_3_A", + # IRC 152(c)(2) is the relationship test. + "https://www.law.cornell.edu/uscode/text/26/152#c_2", + # IRC 152(c)(3)(B) waives the age test for permanently and totally disabled individuals. + "https://www.law.cornell.edu/uscode/text/26/152#c_3_B", + ) + + def formula(person, period, parameters): + # IRC 152(c)(3)(B) treats the age test of 152(c)(3)(A) as met for a + # permanently and totally disabled dependent of any age. + is_disabled_dependent = person("is_tax_unit_dependent", period) & person( + "is_permanently_and_totally_disabled", period + ) + meets_age_test = ( + person("is_qualifying_child_dependent", period) | is_disabled_dependent + ) + # The waiver does not reach the IRC 152(c)(2) relationship test, which + # admits only the taxpayer's children, siblings and their descendants. + # A parent or grandparent fails it and can be a qualifying relative + # (IRC 152(d)(2)(C)-(D)) but not a qualifying child. Other relatives + # outside 152(c)(2) are not recorded, so they are not excluded here. + fails_relationship_test = person( + "is_parent_of_filer_or_spouse", period + ) | person("is_grandparent_of_filer_or_spouse", period) + return meets_age_test & ~fails_relationship_test diff --git a/policyengine_us/variables/gov/states/ca/tax/income/credits/earned_income/ca_is_qualifying_child_for_caleitc.py b/policyengine_us/variables/gov/states/ca/tax/income/credits/earned_income/ca_is_qualifying_child_for_caleitc.py index 6d82511a734..7cb17b9f4b6 100644 --- a/policyengine_us/variables/gov/states/ca/tax/income/credits/earned_income/ca_is_qualifying_child_for_caleitc.py +++ b/policyengine_us/variables/gov/states/ca/tax/income/credits/earned_income/ca_is_qualifying_child_for_caleitc.py @@ -10,16 +10,13 @@ class ca_is_qualifying_child_for_caleitc(Variable): "https://www.ftb.ca.gov/file/personal/credits/EITC-calculator/Help/QualifyingChildren", # RTC 17052 conforms CalEITC to the IRC 32 qualifying-child definition. "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=RTC§ionNum=17052", - # IRC 152(c)(3)(B) waives the qualifying-child age test for permanently and totally disabled individuals. - "https://www.law.cornell.edu/uscode/text/26/152#c_3_B", + # IRC 32(c)(3)(A) applies the IRC 152(c) qualifying-child definition. + "https://www.law.cornell.edu/uscode/text/26/32#c_3_A", ) defined_for = StateCode.CA def formula(person, period, parameters): - # CalEITC uses federal EITC rules regarding qualifying children. - # IRC 152(c)(3)(B) waives the age test for a permanently and totally - # disabled dependent, so such a dependent qualifies at any age. - is_disabled_dependent = person("is_tax_unit_dependent", period) & person( - "is_permanently_and_totally_disabled", period - ) - return person("is_qualifying_child_dependent", period) | is_disabled_dependent + # CalEITC uses federal EITC rules regarding qualifying children, + # including the IRC 152(c)(3)(B) age waiver for a permanently and + # totally disabled dependent and the IRC 152(c)(2) relationship test. + return person("is_eitc_qualifying_child", period) diff --git a/policyengine_us/variables/gov/states/co/tax/income/credits/eitc/co_eitc.py b/policyengine_us/variables/gov/states/co/tax/income/credits/eitc/co_eitc.py index cec12bfd7e6..c941c366164 100644 --- a/policyengine_us/variables/gov/states/co/tax/income/credits/eitc/co_eitc.py +++ b/policyengine_us/variables/gov/states/co/tax/income/credits/eitc/co_eitc.py @@ -14,8 +14,8 @@ class co_eitc(Variable): "https://leg.colorado.gov/sites/default/files/te19_colorado_earned_income_tax_credit.pdf", # C.R.S. 39-22-123.5 pays a percentage of the federal IRC 32 credit. "https://leg.colorado.gov/sites/default/files/images/olls/crs2023-title-39.pdf", - # IRC 152(c)(3)(B) waives the qualifying-child age test for permanently and totally disabled individuals. - "https://www.law.cornell.edu/uscode/text/26/152#c_3_B", + # IRC 32(c)(3)(A) applies the IRC 152(c) qualifying-child definition. + "https://www.law.cornell.edu/uscode/text/26/32#c_3_A", ) defined_for = StateCode.CO @@ -32,14 +32,9 @@ def formula(tax_unit, period, parameters): filer_has_federal_identification = ( tax_unit.sum(is_head_or_spouse & ~federal_identification) == 0 ) - # IRC 152(c)(3)(B) waives the age test for a permanently and totally - # disabled dependent, matching the federal eitc_child_count. - is_disabled_dependent = person("is_tax_unit_dependent", period) & person( - "is_permanently_and_totally_disabled", period - ) - qualifying_child_with_tin = ( - person("is_qualifying_child_dependent", period) | is_disabled_dependent - ) & has_tin + # Same qualifying-child test as the federal eitc_child_count, with an + # ITIN accepted in place of a Social Security number. + qualifying_child_with_tin = person("is_eitc_qualifying_child", period) & has_tin child_count_with_tin = tax_unit.sum(qualifying_child_with_tin) federal_eitc_parameters = parameters(period).gov.irs.credits.eitc student = person("is_full_time_student", period) diff --git a/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc.py b/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc.py index 24aef3ae7a5..853ace34e03 100644 --- a/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc.py +++ b/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc.py @@ -9,24 +9,14 @@ class dc_eitc(Variable): definition_period = YEAR reference = ( "https://code.dccouncil.gov/us/dc/council/code/sections/47-1806.04", # (f) - "https://code.dccouncil.gov/us/dc/council/laws/23-149", # D.C. Law 23-149 ITIN expansion ) defined_for = StateCode.DC def formula(tax_unit, period, parameters): - # D.C. Law 23-149 extends EITC eligibility to filers and qualifying - # children with ITINs. - person = tax_unit.members - # IRC 152(c)(3)(B) waives the age test for a permanently and totally - # disabled dependent, as both branch variables do. - is_disabled_dependent = person("is_tax_unit_dependent", period) & person( - "is_permanently_and_totally_disabled", period - ) - dc_qualifying_child = ( - person("is_qualifying_child_dependent", period) | is_disabled_dependent - ) & person("has_tin", period) + # The with-children and childless schedules are mutually exclusive; + # both branch variables apply the same qualifying-child test. return where( - tax_unit.sum(dc_qualifying_child) > 0, + tax_unit("dc_eitc_has_qualifying_child", period), tax_unit("dc_eitc_with_qualifying_child", period), tax_unit("dc_eitc_without_qualifying_child", period), ) diff --git a/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc_has_qualifying_child.py b/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc_has_qualifying_child.py new file mode 100644 index 00000000000..afac929572d --- /dev/null +++ b/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc_has_qualifying_child.py @@ -0,0 +1,42 @@ +from policyengine_us.model_api import * + + +class dc_eitc_has_qualifying_child(Variable): + value_type = bool + entity = TaxUnit + label = "Has a qualifying child for the DC EITC" + definition_period = YEAR + reference = ( + "https://code.dccouncil.gov/us/dc/council/code/sections/47-1806.04#(f)(1)", + # (f)(4) gives "qualifying child" its IRC 32 meaning. + "https://code.dccouncil.gov/us/dc/council/code/sections/47-1806.04#(f)(4)", + # IRC 32(c)(3)(D) keeps a child without a Social Security number out + # of the credit computation without making it a non-qualifying child. + "https://www.law.cornell.edu/uscode/text/26/32#c_3_D", + # From 2023, Line 27a: "Each qualifying child must have a valid social + # security number (SSN) or individual taxpayer identification number + # (ITIN) issued by the IRS. If you have no children who qualify, you + # must claim the DC EITC without qualifying children." + "https://otr.cfo.dc.gov/sites/default/files/dc/sites/otr/publication/attachments/2023_D40_Book_Final_012324.pdf#page=18", + ) + defined_for = StateCode.DC + + def formula(tax_unit, period, parameters): + # Selects between the with-children schedule of (f)(1)(B)-(B-2) and + # the childless schedule of (f)(1)(C). A qualifying child with an ITIN + # keeps the unit on the with-children schedule in every year; before + # 2023 IRC 32(c)(3)(D) only leaves it out of the credit computation + # (see dc_eitc_with_qualifying_child). A filer whose qualifying + # children have neither a Social Security number nor an ITIN claims + # the childless schedule: Line 27a says so from 2023, and + # qualifying_child_tin_required applies the same treatment to earlier + # years. Setting it to false keeps such a child a qualifying child. + person = tax_unit.members + p = parameters(period).gov.states.dc.tax.income.credits.eitc + meets_identification = where( + p.qualifying_child_tin_required, person("has_tin", period), True + ) + qualifying_child = ( + person("is_eitc_qualifying_child", period) & meets_identification + ) + return tax_unit.any(qualifying_child) diff --git a/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc_with_qualifying_child.py b/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc_with_qualifying_child.py index 141cd99c32b..9c4b3815058 100644 --- a/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc_with_qualifying_child.py +++ b/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc_with_qualifying_child.py @@ -12,34 +12,37 @@ class dc_eitc_with_qualifying_child(Variable): definition_period = YEAR reference = ( "https://code.dccouncil.gov/us/dc/council/code/sections/47-1806.04", # (f) - # IRC 152(c)(3)(B) waives the qualifying-child age test for permanently and totally disabled individuals. - "https://www.law.cornell.edu/uscode/text/26/152#c_3_B", ) - defined_for = StateCode.DC + defined_for = "dc_eitc_has_qualifying_child" def formula(tax_unit, period, parameters): - # D.C. Law 23-149 extends the EITC to ITIN filers and ITIN qualifying - # children, overriding the federal IRC section 32 SSN-only rule. + # D.C. Code 47-1806.04(f)(1)(B)-(B-2) match the federal credit + # allowed under IRC 32. Before 2023 that is the federal credit itself, + # which leaves out a qualifying child without a Social Security + # number (IRC 32(c)(3)(D)) and denies ITIN filers (IRC 32(c)(1)(E)). + federal_eitc = tax_unit("eitc", period) + # From 2023, (f)(1)(D)(ii) computes the credit as if an ITIN met the + # IRC 32(m) Social Security number rule for the filer, spouse and + # qualifying children. person = tax_unit.members has_tin = person("has_tin", period) is_head_or_spouse = person("is_tax_unit_head_or_spouse", period) - # IRC 152(c)(3)(B) waives the age test for a permanently and totally - # disabled dependent, matching the federal eitc_child_count. - is_disabled_dependent = person("is_tax_unit_dependent", period) & person( - "is_permanently_and_totally_disabled", period - ) - qualifying_child = ( - person("is_qualifying_child_dependent", period) | is_disabled_dependent - ) & has_tin - child_count = tax_unit.sum(qualifying_child) + child_count = tax_unit.sum(person("is_eitc_qualifying_child", period) & has_tin) filer_has_tin = tax_unit.sum(is_head_or_spouse & ~has_tin) == 0 - federal_like_eitc = calculate_eitc_like_amount( + # The federal demographic test with these children counted: a unit + # with none in the count qualifies only through the childless age + # rules, as for the federal credit. + demographic_eligible = (child_count > 0) | tax_unit( + "eitc_demographic_eligible", period + ) + itin_eitc = calculate_eitc_like_amount( tax_unit, period, parameters, child_count, - child_count > 0, + demographic_eligible, filer_has_tin, ) - p = parameters(period).gov.states.dc.tax.income.credits - return federal_like_eitc * p.eitc.with_children.match + p = parameters(period).gov.states.dc.tax.income.credits.eitc + federal_like_eitc = where(p.itin_eligible, itin_eitc, federal_eitc) + return federal_like_eitc * p.with_children.match diff --git a/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc_without_qualifying_child.py b/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc_without_qualifying_child.py index 324b243f10f..1eb790af145 100644 --- a/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc_without_qualifying_child.py +++ b/policyengine_us/variables/gov/states/dc/tax/income/credits/eitc/dc_eitc_without_qualifying_child.py @@ -13,34 +13,30 @@ class dc_eitc_without_qualifying_child(Variable): definition_period = YEAR reference = ( "https://code.dccouncil.gov/us/dc/council/code/sections/47-1806.04", # (f) - # IRC 152(c)(3)(B) waives the qualifying-child age test for permanently and totally disabled individuals. - "https://www.law.cornell.edu/uscode/text/26/152#c_3_B", ) defined_for = StateCode.DC def formula(tax_unit, period, parameters): - # D.C. Law 23-149 extends the EITC to ITIN filers, overriding the - # federal IRC section 32 SSN-only identification rule. + # From 2023, D.C. Code 47-1806.04(f)(1)(D)(ii) extends the credit to + # ITIN filers, overriding the IRC 32(m) Social Security number rule. person = tax_unit.members age = person("age", period) has_tin = person("has_tin", period) is_head_or_spouse = person("is_tax_unit_head_or_spouse", period) filer_has_tin = tax_unit.sum(is_head_or_spouse & ~has_tin) == 0 + p = parameters(period).gov.states.dc.tax.income.credits.eitc + filer_meets_identification = where( + p.itin_eligible, + filer_has_tin, + tax_unit("filer_meets_eitc_identification_requirements", period), + ) min_age = parameters.gov.irs.credits.eitc.eligibility.age.min(period) max_age = parameters.gov.irs.credits.eitc.eligibility.age.max(period) age_eligible = is_head_or_spouse & (age >= min_age) & (age <= max_age) - # IRC 152(c)(3)(B) waives the age test for a permanently and totally - # disabled dependent, so such a dependent is a qualifying child and - # routes the unit to the with-children schedule. - is_disabled_dependent = person("is_tax_unit_dependent", period) & person( - "is_permanently_and_totally_disabled", period - ) - qualifying_child = ( - person("is_qualifying_child_dependent", period) | is_disabled_dependent - ) & has_tin - no_qualifying_child = tax_unit.sum(qualifying_child) == 0 + # (f)(1)(C) is limited to an individual without a qualifying child. + no_qualifying_child = ~tax_unit("dc_eitc_has_qualifying_child", period) us_eligible = ( - filer_has_tin + filer_meets_identification & no_qualifying_child & tax_unit.any(age_eligible) & tax_unit("eitc_investment_income_eligible", period) diff --git a/policyengine_us/variables/gov/states/il/tax/income/credits/il_eitc.py b/policyengine_us/variables/gov/states/il/tax/income/credits/il_eitc.py index b51831b58bb..6b35fa1328e 100644 --- a/policyengine_us/variables/gov/states/il/tax/income/credits/il_eitc.py +++ b/policyengine_us/variables/gov/states/il/tax/income/credits/il_eitc.py @@ -14,8 +14,8 @@ class il_eitc(Variable): "https://tax.illinois.gov/programs/eitc.html", # 35 ILCS 5/212 bases the IL EIC on the federal IRC 32 credit. "https://www.ilga.gov/legislation/ilcs/fulltext.asp?DocName=003500050K212", - # IRC 152(c)(3)(B) waives the qualifying-child age test for permanently and totally disabled individuals. - "https://www.law.cornell.edu/uscode/text/26/152#c_3_B", + # IRC 32(c)(3)(A) applies the IRC 152(c) qualifying-child definition. + "https://www.law.cornell.edu/uscode/text/26/32#c_3_A", ) defined_for = StateCode.IL @@ -24,14 +24,9 @@ def formula(tax_unit, period, parameters): age = person("age", period) has_tin = person("has_tin", period) is_head_or_spouse = person("is_tax_unit_head_or_spouse", period) - # IRC 152(c)(3)(B) waives the age test for a permanently and totally - # disabled dependent, matching the federal eitc_child_count. - is_disabled_dependent = person("is_tax_unit_dependent", period) & person( - "is_permanently_and_totally_disabled", period - ) - qualifying_child = ( - person("is_qualifying_child_dependent", period) | is_disabled_dependent - ) & has_tin + # Same qualifying-child test as the federal eitc_child_count, with an + # ITIN accepted in place of a Social Security number. + qualifying_child = person("is_eitc_qualifying_child", period) & has_tin child_count = tax_unit.sum(qualifying_child) filer_has_tin = tax_unit.sum(is_head_or_spouse & ~has_tin) == 0 p = parameters(period).gov.states.il.tax.income.credits.eitc diff --git a/policyengine_us/variables/gov/states/mn/tax/income/credits/mn_child_and_working_families_credits.py b/policyengine_us/variables/gov/states/mn/tax/income/credits/mn_child_and_working_families_credits.py index b0972f570f6..d694b84191a 100644 --- a/policyengine_us/variables/gov/states/mn/tax/income/credits/mn_child_and_working_families_credits.py +++ b/policyengine_us/variables/gov/states/mn/tax/income/credits/mn_child_and_working_families_credits.py @@ -40,15 +40,14 @@ def formula(tax_unit, period, parameters): # an IRC 32(c) qualifying child that attained at least age 18; the # IRC 32(c)(3) definition incorporates IRC 152(c)(3)(B), which waives # the age (and student) test for permanently and totally disabled - # individuals. Schedule M1DQC step 4 routes a disabled dependent aged - # 18 or older directly to the qualifying-older-child row (row 11) - # without the full-time-student test. + # individuals, and the IRC 152(c)(2) relationship test. Schedule M1DQC + # step 4 routes a disabled dependent aged 18 or older directly to the + # qualifying-older-child row (row 11) without the full-time-student + # test. is_disabled_dependent = person("is_tax_unit_dependent", period) & person( "is_permanently_and_totally_disabled", period ) - qualifying_child = ( - person("is_qualifying_child_dependent", period) | is_disabled_dependent - ) + qualifying_child = person("is_eitc_qualifying_child", period) age = person("age", period) full_time_student = person("is_full_time_student", period) qualifying_older_child = ( diff --git a/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.py b/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.py index b54c92851fb..99a2d7de224 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit.py @@ -51,16 +51,11 @@ def formula(tax_unit, period, parameters): person = tax_unit.members has_tin = person("has_tin", period) is_head_or_spouse = person("is_tax_unit_head_or_spouse", period) - # IRC 152(c)(3)(B) (part of the frozen 2022-06-09 federal EITC rules) - # waives the age test for a permanently and totally disabled - # dependent, matching the federal eitc_child_count. - is_disabled_dependent = person("is_tax_unit_dependent", period) & person( - "is_permanently_and_totally_disabled", period - ) - child_count = tax_unit.sum( - (person("is_qualifying_child_dependent", period) | is_disabled_dependent) - & has_tin - ) + # The IRC 152(c) qualifying-child definition, including the + # 152(c)(3)(B) disabled age waiver and the 152(c)(2) relationship test + # (both part of the frozen 2022-06-09 federal EITC rules), matching + # the federal eitc_child_count. + child_count = tax_unit.sum(person("is_eitc_qualifying_child", period) & has_tin) filer_has_tin = tax_unit.sum(is_head_or_spouse & ~has_tin) == 0 federal_identification_eligible = tax_unit( "filer_meets_eitc_identification_requirements", period diff --git a/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_maximum_qualifying_income.py b/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_maximum_qualifying_income.py index 72ec64a6c64..9573440aad6 100644 --- a/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_maximum_qualifying_income.py +++ b/policyengine_us/variables/gov/states/wa/tax/income/credits/wa_working_families_tax_credit_maximum_qualifying_income.py @@ -38,14 +38,10 @@ def formula(tax_unit, period, parameters): eitc = parameters(period).gov.irs.credits.eitc person = tax_unit.members federal_child_count = tax_unit("eitc_child_count", period) - # Apply the IRC 152(c)(3)(B) age waiver to ITIN children too, using - # the same qualifying-child count as the WFTC amount formula. - is_disabled_dependent = person("is_tax_unit_dependent", period) & person( - "is_permanently_and_totally_disabled", period - ) + # Count ITIN children too, using the same qualifying-child test as the + # WFTC amount formula. washington_child_count = tax_unit.sum( - (person("is_qualifying_child_dependent", period) | is_disabled_dependent) - & person("has_tin", period) + person("is_eitc_qualifying_child", period) & person("has_tin", period) ) child_count = max_(federal_child_count, washington_child_count) federal_max_agi = calculate_eitc_max_agi_limit(