diff --git a/changelog.d/ctc-2021-refundable-split.fixed.md b/changelog.d/ctc-2021-refundable-split.fixed.md new file mode 100644 index 00000000000..1d7fe5f8c27 --- /dev/null +++ b/changelog.d/ctc-2021-refundable-split.fixed.md @@ -0,0 +1,3 @@ +Correct the 2021 child tax credit split after both phaseouts so the credit for other dependents remains nonrefundable, including its effect on solar-credit ordering and Oklahoma conformity. + +Correct the ordinary CTC phaseout threshold for surviving spouses to $200,000 from 2018 onward, while retaining their separate $150,000 ARPA threshold. diff --git a/policyengine_us/parameters/gov/irs/credits/ctc/phase_out/threshold.yaml b/policyengine_us/parameters/gov/irs/credits/ctc/phase_out/threshold.yaml index 44326a91b4d..57434861b63 100644 --- a/policyengine_us/parameters/gov/irs/credits/ctc/phase_out/threshold.yaml +++ b/policyengine_us/parameters/gov/irs/credits/ctc/phase_out/threshold.yaml @@ -13,7 +13,7 @@ HEAD_OF_HOUSEHOLD: 2018-01-01: 200_000 SURVIVING_SPOUSE: 2013-01-01: 75_000 - 2018-01-01: 400_000 + 2018-01-01: 200_000 metadata: propagate_metadata_to_children: true unit: currency-USD @@ -27,6 +27,8 @@ metadata: # TCJA: - title: U.S.C 26 U.S. Code ยง 24(h)(3) href: https://www.law.cornell.edu/uscode/text/26/24#h_3 + - title: 2021 Schedule 8812, line 9 + href: https://www.irs.gov/pub/irs-prior/f1040s8--2021.pdf#page=1 - title: H.R.1 - One Big Beautiful Bill Act href: https://www.congress.gov/bill/119th-congress/house-bill/1/text # OBBB extends TCJA CTC phaseout thresholds. diff --git a/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/ctc.yaml b/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/ctc.yaml index cf952a3fb1f..d7e3e28ea60 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/ctc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/ctc.yaml @@ -6,3 +6,31 @@ ctc_phase_out: 1 output: ctc: 2 + +- name: A surviving spouse phases out the 2021 child credit above 200000. + period: 2021 + input: + people: + parent: + age: 40 + is_tax_unit_head: true + employment_income: 200_001 + child: + age: 5 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [parent, child] + filing_status: SURVIVING_SPOUSE + households: + household: + members: [parent, child] + state_code: TX + output: + ctc_arpa_phase_out_threshold: 150_000 + ctc_arpa_phase_out: 1_600 + ctc_phase_out_threshold: 200_000 + ctc_phase_out: 50 + ctc: 1_950 + refundable_ctc: 1_950 + non_refundable_ctc: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/phase_out/arpa/ctc_arpa_phase_out_cap.yaml b/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/phase_out/arpa/ctc_arpa_phase_out_cap.yaml index 56f4f243246..fab8a2ed4b2 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/phase_out/arpa/ctc_arpa_phase_out_cap.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/phase_out/arpa/ctc_arpa_phase_out_cap.yaml @@ -6,3 +6,21 @@ ctc_arpa_max_addition: 15_000 # e.g. 15 kids * $1,000 extra. output: ctc_arpa_phase_out_cap: 12_500 # 400k - 150k = 250k * 0.05 = 12.5k + +- name: The first ARPA reduction cannot exceed the child credit enhancement. + period: 2021 + input: + filing_status: JOINT + ctc_arpa_max_addition: 1_600 + output: + ctc_arpa_phase_out_cap: 1_600 + +- name: Surviving spouses use the 2500 threshold-difference cap in the Line 5 Worksheet. + period: 2021 + input: + filing_status: SURVIVING_SPOUSE + ctc_arpa_max_addition: 5_000 + output: + ctc_arpa_phase_out_threshold: 150_000 + ctc_phase_out_threshold: 200_000 + ctc_arpa_phase_out_cap: 2_500 diff --git a/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/phase_out/ctc_phase_out_threshold.yaml b/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/phase_out/ctc_phase_out_threshold.yaml index 27ee30edd45..e2fb8bf5d20 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/phase_out/ctc_phase_out_threshold.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/phase_out/ctc_phase_out_threshold.yaml @@ -5,9 +5,40 @@ output: ctc_phase_out_threshold: 200_000 -- name: CTC phases out at $400,000 for singles while TCJA is active. +- name: CTC phases out at $400,000 for joint filers while TCJA is active. period: 2022 input: filing_status: JOINT output: ctc_phase_out_threshold: 400_000 + +# Section 24(h)(3) reserves $400,000 for joint returns. A surviving spouse +# shares joint tax rates under section 1(a), but does not file a joint return. +- name: Before TCJA surviving spouses retain the nonjoint threshold. + period: 2017 + input: + filing_status: [SURVIVING_SPOUSE, JOINT] + output: + ctc_phase_out_threshold: [75_000, 110_000] + +- name: TCJA gives surviving spouses the ordinary nonjoint threshold. + period: 2018 + input: + filing_status: [SURVIVING_SPOUSE, JOINT] + output: + ctc_phase_out_threshold: [200_000, 400_000] + +- name: ARPA does not make surviving spouses joint filers for ordinary phaseout. + period: 2021 + input: + filing_status: [SURVIVING_SPOUSE, JOINT] + output: + ctc_phase_out_threshold: [200_000, 400_000] + ctc_arpa_phase_out_threshold: [150_000, 150_000] + +- name: OBBB retains the nonjoint ordinary threshold for surviving spouses. + period: 2026 + input: + filing_status: [SURVIVING_SPOUSE, JOINT] + output: + ctc_phase_out_threshold: [200_000, 400_000] diff --git a/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/refundable/refundable_ctc.yaml b/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/refundable/refundable_ctc.yaml index 4b6ca135f18..05bb3efe4e2 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/refundable/refundable_ctc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/refundable/refundable_ctc.yaml @@ -206,3 +206,118 @@ section_911_excluded_income: 0 # Without the section 911 bar, the same phase-in gives a $3,400 refund. refundable_ctc: 0 + +# Proposed additions to: +# policyengine_us/tests/policy/baseline/gov/irs/credits/ctc/refundable/refundable_ctc.yaml +# Sources: 2021 IRC 24(i)(1)(B), 24(i)(4)(C)-(D), and Schedule 8812 +# https://www.govinfo.gov/content/pkg/USCODE-2021-title26/pdf/USCODE-2021-title26-subtitleA.pdf#page=57 +# https://www.govinfo.gov/content/pkg/USCODE-2021-title26/pdf/USCODE-2021-title26-subtitleA.pdf#page=58 +# https://www.irs.gov/pub/irs-prior/f1040s8--2021.pdf#page=1 +- name: ARPA phaseout cannot make other-dependent credit refundable in 2021 + period: 2021 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 40 + is_tax_unit_head: true + employment_income: 170_000 + child: + age: 5 + is_tax_unit_dependent: true + other_dependent: + age: 19 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [parent, child, other_dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [parent, child, other_dependent] + state_code: TX + output: + adjusted_gross_income: 170_000 + # min(50 * ceil((170,000 - 112,500) / 1,000), 1,600, 4,375). + ctc_arpa_phase_out: 1_600 + ctc_phase_out: 0 + # Schedule 8812 lines 5 + 7 = (3,600 - 1,600) + 500. + ctc: 2_500 + # Lines 14a = 500; 14b = 2,500 - 500 = 2,000. + refundable_ctc: 2_000 + # Before the section 26(a) tax limit (not binding in this household). + non_refundable_ctc: 500 + ctc_value: 2_500 + +- name: Other-dependent credit remains nonrefundable after the child portion phases out in 2021 + period: 2021 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 40 + is_tax_unit_head: true + employment_income: 240_001 + child: + age: 5 + is_tax_unit_dependent: true + other_dependent: + age: 19 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [parent, child, other_dependent] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [parent, child, other_dependent] + state_code: TX + output: + ctc_arpa_phase_out: 1_600 + # 50 * ceil((240,001 - 200,000) / 1,000) = 2,050. + ctc_phase_out: 2_050 + ctc: 450 + # max(3,600 - 1,600 - 2,050, 0) = 0. + refundable_ctc: 0 + non_refundable_ctc: 450 + ctc_value: 450 + +# This interaction proves the split affects total federal tax, not only labels. +# 2021 IRC 25D(c), Form 5695 lines 6b/14/15 and its Credit Limit Worksheet: +# https://www.govinfo.gov/content/pkg/USCODE-2021-title26/pdf/USCODE-2021-title26-subtitleA.pdf#page=81 +# https://www.irs.gov/pub/irs-prior/f5695--2021.pdf#page=1 +# https://www.irs.gov/pub/irs-prior/i5695--2021.pdf#page=4 +- name: Nonrefundable ODC reduces solar credit capacity before the 2021 child refund + period: 2021 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 40 + is_tax_unit_head: true + employment_income: 170_000 + child: + age: 5 + is_tax_unit_dependent: true + other_dependent: + age: 19 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [parent, child, other_dependent] + filing_status: HEAD_OF_HOUSEHOLD + solar_electric_property_expenditures: 150_000 + households: + household: + members: [parent, child, other_dependent] + state_code: TX + output: + income_tax_before_credits: 28_857 + residential_clean_energy_credit_potential: 39_000 + # 28,857 - 500 ODC; refundable child credit is in a different subpart. + residential_clean_energy_credit_credit_limit: 28_357 + residential_clean_energy_credit: 28_357 + refundable_ctc: 2_000 + non_refundable_ctc: 500 + ctc_value: 2_500 + income_tax: -2_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/ia_integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/ia_integration.yaml index ef0d960dd06..341ffdb7f0f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/ia_integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/ia_integration.yaml @@ -49,11 +49,11 @@ output: # expected ia_income_tax from patched TAXSIM35 2023-05-05 version # federal income tax results used by Iowa income tax: filing_status: JOINT - # federal CTC was fully refundable in 2021, but composition is flawed - non_refundable_ctc: 0 # a negative credit is nonsensical - refundable_ctc: 8_000 # the correct amount in this case is $8000 + # The child-only CTC remaining after both 2021 reductions is refundable. + non_refundable_ctc: 0 + refundable_ctc: 8_000 income_tax_before_refundable_credits: 42_502.80 # - # formula for ia_fedtax_deduction works around the above federal CTC flaw + # Iowa retains its addback of nonrefundable CTC in fully refundable years. additional_medicare_tax: 18.18 # neither this nor SECA tax part of fedtax # Iowa income tax results: ia_net_income: [104_010, 148_010, 0, 0, 0, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/tax/income/credits/ok_federal_ctc.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/tax/income/credits/ok_federal_ctc.yaml index 4f8d7ea0d38..680910cacb6 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ok/tax/income/credits/ok_federal_ctc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/tax/income/credits/ok_federal_ctc.yaml @@ -22,6 +22,42 @@ income_tax_capped_non_refundable_credits: 1_000 ok_federal_ctc: 500 +- name: In 2021 Oklahoma counts the child refund and only usable ODC after ARPA phaseout. + period: 2021 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 40 + is_tax_unit_head: true + employment_income: 90_000 + child: + age: 5 + is_tax_unit_dependent: true + other_dependent: + age: 19 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [parent, child, other_dependent] + filing_status: SINGLE + # Isolate a binding federal tax limit while deriving the CTC split. + income_tax_before_credits: 300 + households: + household: + members: [parent, child, other_dependent] + state_code: OK + output: + ctc_arpa_phase_out: 750 + ctc_phase_out: 0 + ctc: 3_350 + refundable_ctc: 2_850 + non_refundable_ctc: 500 + income_tax_capped_non_refundable_credits: 300 + ctc_value: 3_150 + # Refundable child credit plus 300 of the 500 nonrefundable ODC. + ok_federal_ctc: 3_150 + - name: A credit on Credit Limit Worksheet A, line 2, is applied before the CTC when credits exceed tax. period: 2025 input: diff --git a/policyengine_us/tests/test_ctc_2021_refundable_split.py b/policyengine_us/tests/test_ctc_2021_refundable_split.py new file mode 100644 index 00000000000..14a419e0dc4 --- /dev/null +++ b/policyengine_us/tests/test_ctc_2021_refundable_split.py @@ -0,0 +1,155 @@ +"""Vectorized invariants for the 2021 Schedule 8812 refundable/ODC split. + +The YAML cases cover complete households. This grid checks the partition across +combinations of child credit, other dependent credit, both reductions and the +refundable cap, using one Core simulation for every year. Inputs stop above the +split so these tests exercise its dependency wiring and the pre-liability +``non_refundable_ctc`` definition without building tax-return branches. + +2021 Schedule 8812 lines 12, 14a and 14b, and IRC 24(h)(4), (i)(1)(B), +(i)(4)(D) independently determine the child-only refund and remaining ODC. +Other years retain the existing section 24(d) tax-limit-increase calculation. +""" + +from itertools import product + +import numpy as np +import pytest +from policyengine_core.simulations import SimulationBuilder + +from policyengine_us.system import system + + +OTHER_YEARS = (2018, 2020, 2022, 2025, 2026) +# First-reduction fractions include both ends of the ARPA-increase cap. The +# ordinary reduction extends beyond all child credit and then all ODC. +GRID = np.asarray( + list( + product( + (0, 1), # children under 6 + (0, 1), # children 6 through 17 + (0, 1, 2), # other dependents + (0, 0.5, 1), # share of the ARPA increase removed + (0, 50, 500, 2_000, 4_000, 8_000, 20_000), + ) + ) +) + + +@pytest.fixture(scope="module") +def split_grid(): + # A second copy gives each case a smaller refundable maximum. This guards + # the existing cap contract without making a second, mutable reform tree. + cases = np.concatenate((GRID, GRID)) + young, older, other_dependents, first_share, ordinary = cases.T + children = young + older + count = len(cases) + baseline = np.arange(count) < len(GRID) + simulation = SimulationBuilder().build_default_simulation(system, count) + phase_in = np.resize([0, 300, 1_500, 10_000], count) + liability = np.resize([0, 250, 2_000, 20_000], count) + barred = np.resize([False, False, False, True, False], count) + references = {} + + for year in (2021, *OTHER_YEARS): + p = system.parameters(f"{year}-01-01").gov.irs.credits.ctc + base_per_child = p.amount.base.calc(np.array([5]))[0] + base_children = children * base_per_child + other_credit = other_dependents * p.amount.adult_dependent + if year == 2021: + child_credit = young * 3_600 + older * 3_000 + addition = child_credit - base_children + first = addition * first_share + maximum = np.where(baseline, child_credit, child_credit / 2) + else: + child_credit = base_children + addition = np.zeros(count) + first = np.zeros(count) + maximum = children * min(base_per_child, p.refundable.individual_max) + + inputs = { + "filer_meets_ctc_identification_requirements": np.ones(count, dtype=bool), + "ctc_maximum": base_children + other_credit, + "ctc_arpa_max_addition": addition, + "ctc_arpa_phase_out": first, + "ctc_phase_out": ordinary, + "ctc_refundable_maximum": maximum, + "ctc_phase_in": phase_in, + "ctc_limiting_tax_liability": liability, + "refundable_ctc_barred_by_section_911_exclusion": barred, + } + for name, values in inputs.items(): + simulation.set_input(name, year, values) + references[year] = { + "child": child_credit, + "other": other_credit, + "first": first, + "ordinary": ordinary, + "maximum": maximum, + "total": np.maximum(child_credit + other_credit - first - ordinary, 0), + } + + return simulation, references, baseline, phase_in, liability, barred + + +def test_2021_schedule_8812_partition_before_tax_limit(split_grid): + simulation, references, baseline, _, liability, _ = split_grid + r = references[2021] + total = simulation.calculate("ctc", 2021) + refundable = simulation.calculate("refundable_ctc", 2021) + non_refundable = simulation.calculate("non_refundable_ctc", 2021) + child_after_reductions = np.maximum(r["child"] - r["first"] - r["ordinary"], 0) + + # Schedule 8812 line 14b excludes ODC and applies both reductions. Identity + # alone would miss the old bug: its refundable and non-refundable amounts + # added up correctly while some ODC was incorrectly refundable. + np.testing.assert_allclose(total[baseline], r["total"][baseline]) + np.testing.assert_allclose(refundable[baseline], child_after_reductions[baseline]) + np.testing.assert_allclose( + non_refundable[baseline], np.minimum(r["other"], r["total"])[baseline] + ) + np.testing.assert_allclose(refundable + non_refundable, total) + assert (refundable >= 0).all() + assert (refundable <= child_after_reductions).all() + assert (refundable[r["child"] == 0] == 0).all() + # The stored non-refundable amount is before section 26(a), even where + # the tax unit cannot use all its other-dependent credit. + assert (baseline & (non_refundable > liability)).any() + assert (baseline & (r["first"] > 0) & (r["other"] > 0) & (refundable > 0)).any() + assert ( + baseline & (r["ordinary"] > 0) & (refundable == 0) & (non_refundable > 0) + ).any() + + +def test_2021_preserves_lower_refundable_maximum(split_grid): + simulation, references, baseline, _, _, _ = split_grid + r = references[2021] + expected = np.minimum( + np.maximum(r["maximum"] - r["first"] - r["ordinary"], 0), r["total"] + ) + actual = simulation.calculate("refundable_ctc", 2021) + np.testing.assert_allclose(actual[~baseline], expected[~baseline]) + assert (actual <= r["maximum"]).all() + assert ((~baseline) & (actual > 0) & (actual < r["child"])).any() + + +@pytest.mark.parametrize("year", OTHER_YEARS) +def test_other_years_preserve_partial_refundability(split_grid, year): + simulation, references, _, phase_in, liability, barred = split_grid + r = references[year] + # The legacy section 24(d) calculation refunds the gain in allowed CTC + # when its tax limit increases by the phase-in, subject to its child cap + # and the separate section 911 bar. + increase = np.minimum(r["total"], liability + phase_in) - np.minimum( + r["total"], liability + ) + expected = np.where(barred, 0, np.minimum(r["maximum"], increase)) + total = simulation.calculate("ctc", year) + refundable = simulation.calculate("refundable_ctc", year) + non_refundable = simulation.calculate("non_refundable_ctc", year) + np.testing.assert_allclose(total, r["total"]) + np.testing.assert_allclose(refundable, expected) + np.testing.assert_allclose(refundable + non_refundable, total) + assert (refundable <= r["child"]).all() + assert ((refundable > 0) & (refundable < total)).any() + assert ((total > 0) & (refundable == 0)).any() diff --git a/policyengine_us/variables/gov/irs/credits/ctc/non_refundable_ctc.py b/policyengine_us/variables/gov/irs/credits/ctc/non_refundable_ctc.py index d384b2c4dad..683d9fc8ab5 100644 --- a/policyengine_us/variables/gov/irs/credits/ctc/non_refundable_ctc.py +++ b/policyengine_us/variables/gov/irs/credits/ctc/non_refundable_ctc.py @@ -6,7 +6,15 @@ class non_refundable_ctc(Variable): entity = TaxUnit label = "non-refundable CTC" unit = USD - documentation = "The portion of the Child Tax Credit that is not refundable." + documentation = ( + "The nonrefundable Child Tax Credit entitlement before the section " + "26(a) tax-liability limit. In 2021 this is the credit for other " + "dependents on Schedule 8812 line 14a, before the limit on line 14d." + ) definition_period = YEAR + reference = ( + "https://www.law.cornell.edu/uscode/text/26/26#a", + "https://www.irs.gov/pub/irs-prior/f1040s8--2021.pdf#page=1", + ) adds = ["ctc"] subtracts = ["refundable_ctc"] diff --git a/policyengine_us/variables/gov/irs/credits/ctc/phase_out/arpa/ctc_arpa_max_addition.py b/policyengine_us/variables/gov/irs/credits/ctc/phase_out/arpa/ctc_arpa_max_addition.py index f5f3bb3c7e9..79234777e52 100644 --- a/policyengine_us/variables/gov/irs/credits/ctc/phase_out/arpa/ctc_arpa_max_addition.py +++ b/policyengine_us/variables/gov/irs/credits/ctc/phase_out/arpa/ctc_arpa_max_addition.py @@ -11,7 +11,7 @@ class ctc_arpa_max_addition(Variable): ) definition_period = YEAR # Defined on Line 5 worksheet of 2021 Instructions for Schedule 8812. - reference = "https://www.irs.gov/pub/irs-pdf/i1040s8.pdf#page=4" + reference = "https://www.irs.gov/pub/irs-prior/i1040s8--2021.pdf#page=4" def formula(tax_unit, period, parameters): # Logic sequence follows the form, which is clearer than the IRC. diff --git a/policyengine_us/variables/gov/irs/credits/ctc/phase_out/arpa/ctc_arpa_phase_out_cap.py b/policyengine_us/variables/gov/irs/credits/ctc/phase_out/arpa/ctc_arpa_phase_out_cap.py index 2ffdb47ce97..38a4aa37cee 100644 --- a/policyengine_us/variables/gov/irs/credits/ctc/phase_out/arpa/ctc_arpa_phase_out_cap.py +++ b/policyengine_us/variables/gov/irs/credits/ctc/phase_out/arpa/ctc_arpa_phase_out_cap.py @@ -11,7 +11,7 @@ class ctc_arpa_phase_out_cap(Variable): ) definition_period = YEAR # Defined on Line 5 worksheet of 2021 Instructions for Schedule 8812. - reference = "https://www.irs.gov/pub/irs-pdf/i1040s8.pdf#page=4" + reference = "https://www.irs.gov/pub/irs-prior/i1040s8--2021.pdf#page=4" def formula(tax_unit, period, parameters): # Logic sequence follows the form, which is clearer than the IRC. diff --git a/policyengine_us/variables/gov/irs/credits/ctc/refundable/refundable_ctc.py b/policyengine_us/variables/gov/irs/credits/ctc/refundable/refundable_ctc.py index e2a65576a39..56602e9fa5f 100644 --- a/policyengine_us/variables/gov/irs/credits/ctc/refundable/refundable_ctc.py +++ b/policyengine_us/variables/gov/irs/credits/ctc/refundable/refundable_ctc.py @@ -12,6 +12,10 @@ class refundable_ctc(Variable): "https://www.law.cornell.edu/uscode/text/26/24#d", # No refundable CTC for filers electing a section 911 exclusion. "https://www.law.cornell.edu/uscode/text/26/24#d_3", + # 2021 section 24(h)(4), (i)(1)(B) and (i)(4)(C)-(D), PDF pages 57-58. + "https://www.govinfo.gov/content/pkg/USCODE-2021-title26/pdf/USCODE-2021-title26-subtitleA.pdf#page=57", + "https://www.irs.gov/pub/irs-prior/f1040s8--2021.pdf#page=1", + "https://www.irs.gov/pub/irs-prior/i1040s8--2021.pdf#page=4", ) def formula(tax_unit, period, parameters): @@ -28,7 +32,13 @@ def formula(tax_unit, period, parameters): total_ctc = tax_unit("ctc", period) if ctc.refundable.fully_refundable: - reduction = tax_unit("ctc_phase_out", period) + # Schedule 8812 lines 12 and 14a-14b: refund only the child + # credit after both the first ARPA reduction and ordinary + # phaseout. Section 24(i)(1)(B) excludes the section 24(h)(4) + # credit for other dependents from refundability. + reduction = tax_unit("ctc_arpa_phase_out", period) + tax_unit( + "ctc_phase_out", period + ) reduced_max_amount = max_(0, maximum_amount - reduction) return min_(reduced_max_amount, total_ctc) diff --git a/policyengine_us/variables/gov/states/ia/tax/income/including_married_filing_separately/deductions/ia_fedtax_deduction.py b/policyengine_us/variables/gov/states/ia/tax/income/including_married_filing_separately/deductions/ia_fedtax_deduction.py index 647a9b01594..36d77dca2d5 100644 --- a/policyengine_us/variables/gov/states/ia/tax/income/including_married_filing_separately/deductions/ia_fedtax_deduction.py +++ b/policyengine_us/variables/gov/states/ia/tax/income/including_married_filing_separately/deductions/ia_fedtax_deduction.py @@ -27,7 +27,8 @@ def formula(person, period, parameters): # (line 12) is not added back. With payments equal to the liability, # the deduction is the federal income tax without the added-back taxes. ustax = person.tax_unit("income_tax_before_refundable_credits", period) - # correct ustax amount for flaw in CTC refundable/nonrefundable split + # Retain the existing addback in fully refundable years, including + # any nonrefundable credit for other dependents in 2021. ctc = parameters(period).gov.irs.credits.ctc ctc_fully_refundable = ctc.refundable.fully_refundable if ctc_fully_refundable: