Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/fix-9814-dependent-income-ar-ms-nj-ia.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Leave tax unit dependents' income out of Arkansas, Mississippi and New Jersey adjusted gross income and Iowa net income; dependents report it on their own state returns. Mississippi now limits only the head's and spouse's own capital loss, so a dependent's capital gains no longer change the filers' Mississippi adjusted gross income.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ values:
- self_employment_income
- sstb_self_employment_income
- partnership_s_corp_income
- loss_limited_net_capital_gains_person
# Line 40: the filers' own capital gains and losses, with a net loss
# limited as on the federal return (26 USC 1211(b)). A dependent's
# gains and losses are on the dependent's own return.
- filer_loss_limited_net_capital_gains_person
- rental_income
# Line 41: rental real estates, royalties, partnerships, S corporations,
# trusts, etc. (income or loss from federal Schedule E)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,6 @@ def test_nj_excludes_each_dependents_deduction_only_from_their_own_premiums(
simulation = _nj_simulation(members, reference_system)
paid = np.array([sum(person["premiums"] for person in unit) for unit in members])
other = np.array([sum(person["other"] for person in unit) for unit in members])
deductions = np.array(
[sum(person["deduction"] for person in unit) for unit in members]
)
person_exclusions = [
[min(person["deduction"], person["premiums"]) for person in unit]
for unit in members
Expand All @@ -307,7 +304,10 @@ def test_nj_excludes_each_dependents_deduction_only_from_their_own_premiums(
)
excluded = np.array([sum(exclusions) for exclusions in person_exclusions])
nj_deduction = simulation.calculate("nj_medical_expense_deduction", PERIOD)
actual_exclusion = paid + other + deductions - nj_deduction
# The dependents' separate SE deductions are on their own returns, with
# their income (nj_agi leaves both out), so the parent's deduction does
# not add them.
actual_exclusion = paid + other - nj_deduction

# C.54A:3-3(c)(3) excludes only amounts separately deducted. Each person's
# exclusion is bounded before summation, so no ALD can consume a different
Expand All @@ -316,7 +316,7 @@ def test_nj_excludes_each_dependents_deduction_only_from_their_own_premiums(
assert (actual_exclusion >= 0).all()
assert (actual_exclusion <= excluded).all()
np.testing.assert_array_equal(actual_exclusion, excluded)
np.testing.assert_array_equal(nj_deduction, paid + other + deductions - excluded)
np.testing.assert_array_equal(nj_deduction, paid + other - excluded)


# Flat strategies keep generation small while varying independent caller
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@
On main these depended on the label:
- Arkansas, Delaware, Iowa, Mississippi and Montana put the dependents' income
the model counts on the head's column before taxing each column separately.
It now goes on the column of the spouse with the greater income of their
own, and an exact tie splits it (move_dependent_amounts_to_filer).
In Delaware and Montana it now goes on the column of the spouse with the
greater income of their own, and an exact tie splits it
(move_dependent_amounts_to_filer). Arkansas, Iowa and Mississippi now leave
a dependent's income off the filers' columns altogether, since it belongs
on the dependent's own return (PolicyEngine/policyengine-us#9814).
- Delaware's combined separate return routed the EITC and the dependent care
credit by label on equal incomes and split the dependent personal credits
with a heuristic. They are now chosen together to minimise tax.
Expand Down Expand Up @@ -45,10 +48,11 @@
is finite and the same to the cent.
2. The per-person columns (`ar_agi_indiv`, `de_agi_indiv`, `ia_net_income`,
`ms_agi`, `mt_agi_indiv`) are the same for each person, to the cent.
3. Differential: in Arkansas, Delaware, Iowa and Mississippi those columns
equal an independent numpy allocation of each person's own amount, which
conserves the tax unit's total. Montana's own amounts are not
reconstructed, so it is checked by 1 and 2 only.
3. Differential: in Delaware the column equals an independent numpy
allocation of each person's own amount, which conserves the tax unit's
total. In Arkansas, Iowa and Mississippi it equals each filer's own amount,
and zero for a dependent. Montana's own amounts are not reconstructed, so
it is checked by 1 and 2 only.
"""

import numpy as np
Expand All @@ -71,6 +75,9 @@
"state_income_tax_before_refundable_credits",
]
COLUMNS = ["ar_agi_indiv", "de_agi_indiv", "ia_net_income", "ms_agi", "mt_agi_indiv"]
# Columns that move the dependents' amounts to a filer's column; the others
# leave a dependent's amount off the filers' return.
MOVES_DEPENDENT_AMOUNTS = ["de_agi_indiv"]


def money(high):
Expand Down Expand Up @@ -475,11 +482,9 @@ def calc(name):
return calc("ia_gross_income") - calc("ia_income_adjustments")
if column == "ms_agi":
p = sim.tax_benefit_system.parameters(year).gov.states.ms.tax.income
net = sum(calc(source) for source in p.income_sources) - calc(
return sum(calc(source) for source in p.income_sources) - calc(
"ms_agi_adjustments"
)
dependent = calc("is_tax_unit_dependent").astype(bool)
return np.where(dependent, np.maximum(net, 0), net)
raise ValueError(column)


Expand Down Expand Up @@ -547,7 +552,10 @@ def _check(units, year):
# 3. Differential against the numpy allocation, where the column
# applies (its state, and its years for Iowa).
own = _own_amounts(sim, year, column)
reference = _reference_allocation(own, unit, head, spouse, dependent)
if column in MOVES_DEPENDENT_AMOUNTS:
reference = _reference_allocation(own, unit, head, spouse, dependent)
else:
reference = np.where(dependent, 0.0, own)
in_state = states[unit // 2] == column[:2].upper()
np.testing.assert_allclose(
values[in_state],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
output:
ar_agi_indiv: [900, 1_800]

- name: Dependent AGI goes to the spouse with the greater AGI, AGI capped at 0
- name: A dependent's AGI stays off the filers' columns, and a negative column is floored at 0
period: 2022
input:
people:
Expand All @@ -43,7 +43,9 @@
members: [person1, person2, person3]
state_code: AR
output:
ar_agi_indiv: [1_200, 0, 0]
# The dependent's 300 goes on the dependent's own return (Ark. Code
# 26-51-801(a)-(b)). The spouse's 100 - 200 is floored at 0.
ar_agi_indiv: [900, 0, 0]

- name: Single filer with 401(k) distributions included in gross income and exempted
period: 2024
Expand All @@ -65,7 +67,7 @@
ar_capped_retirement_or_disability_benefits_exemption_person: 6_000
ar_agi_indiv: 50_000

- name: Dependent AGI goes to the spouse with the greater AGI when that spouse is not the head
- name: A dependent's AGI stays off the filers' columns when the head and spouse labels are exchanged
period: 2022
input:
people:
Expand Down Expand Up @@ -96,9 +98,9 @@
state_code: AR
output:
# The same couple as above with the head and spouse labels exchanged.
ar_agi_indiv: [1_200, 0, 0]
ar_agi_indiv: [900, 0, 0]

- name: Spouses with equal AGI split the dependent AGI equally
- name: Spouses with equal AGI keep their own AGI; the dependent's is on the dependent's own return
period: 2022
input:
people:
Expand Down Expand Up @@ -128,7 +130,7 @@
members: [person1, person2, person3]
state_code: AR
output:
ar_agi_indiv: [1_150, 1_150, 0]
ar_agi_indiv: [1_000, 1_000, 0]

- name: Only taxable disability benefits enter Arkansas gross income on line 18.
period: 2024
Expand All @@ -152,3 +154,53 @@
# The 3,000 is under the 6,000 cap and exempt in full.
ar_capped_retirement_or_disability_benefits_exemption_person: 3_000
ar_agi_indiv: 30_000

- name: A dependent child's interest stays off the parent's Arkansas AGI
period: 2025
input:
people:
parent:
age: 40
employment_income: 40_000
child:
age: 16
taxable_interest_income: 8_000
tax_units:
tax_unit:
members: [parent, child]
households:
household:
members: [parent, child]
state_code: AR
output:
# The child files their own AR1000F if their gross income is over the
# filing minimum (Ark. Code 26-51-801(a)); the parent's columns hold only
# the parent's 40,000 of wages, as with no child income.
ar_gross_income_indiv: [40_000, 8_000]
ar_agi_indiv: [40_000, 0]
ar_agi_joint: [40_000, 0]

- name: A dependent child's wages stay off the parent's Arkansas AGI and tax
period: 2025
absolute_error_margin: 0.01
input:
people:
parent:
age: 40
employment_income: 40_000
child:
age: 16
employment_income: 5_000
tax_units:
tax_unit:
members: [parent, child]
households:
household:
members: [parent, child]
state_code: AR
output:
ar_agi_indiv: [40_000, 0]
ar_agi_joint: [40_000, 0]
# The same tax as the parent with a child who has no income (issue
# #9814 reproduction): 957.
ar_income_tax: 957
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
output:
ar_agi_joint: [900, 1_800]

- name: Dependent AGI gets attributed to the head; spouse net income is not floored on a joint return
- name: A dependent's AGI stays off the filers' return; spouse net income is not floored on a joint return
period: 2022
input:
people:
Expand All @@ -43,11 +43,11 @@
members: [person1, person2, person3]
state_code: AR
output:
# Head: 900 + dependent's 300 (dependent income floored at 0, then
# attributed to the head). Spouse: 100 - 200 = -100. On a joint return all
# Head: 900. The dependent's 300 goes on the dependent's own return (Ark.
# Code 26-51-801(a)-(b)). Spouse: 100 - 200 = -100. On a joint return all
# income goes in Column A, so the spouse's amount offsets the head's; the
# tax unit total is floored at 0 only when used as a tax base.
ar_agi_joint: [1_200, -100, 0]
ar_agi_joint: [900, -100, 0]

- name: A spouse's business loss offsets the other spouse's income on a joint return
period: 2024
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
ar_gross_income_joint: 60_000
ar_gross_income_indiv: 60_000

- name: A dependent's gambling winnings go to the head's Arkansas AGI
- name: A dependent's gambling winnings stay off the head's Arkansas AGI
period: 2025
input:
people:
Expand All @@ -61,7 +61,8 @@
state_code: AR
output:
ar_gross_income_joint: [50_000, 1_000]
ar_agi_joint: [51_000, 0]
# The child's winnings go on the child's own Arkansas return.
ar_agi_joint: [50_000, 0]

- name: 2015 itemizer with losses below winnings is taxed on net winnings
period: 2015
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- name: IA net income unit test 1
- name: Dependents' gross income stays off the head's Iowa net income
absolute_error_margin: 0.01
period: 2021
input:
Expand All @@ -24,9 +24,11 @@
members: [person1, person2, person3]
state_code: IA
output:
ia_net_income: [9_400, 0, 0]
# 10,000 - 2,000. The dependents' 800 and 600 go on their own Iowa
# returns if they must file (Iowa Code 422.13(1)(a)).
ia_net_income: [8_000, 0, 0]

- name: Spouses with equal net income split the dependent net income equally
- name: Spouses keep their own net income; the dependent's is on the dependent's own return
absolute_error_margin: 0.01
period: 2022
input:
Expand All @@ -52,10 +54,9 @@
members: [person1, person2, person3]
state_code: IA
output:
# The spouses' net incomes are equal, so they split the dependent's.
ia_net_income: [8_300, 8_300, 0]
ia_net_income: [8_000, 8_000, 0]

- name: Dependent net income goes to the spouse with the greater net income, here not the head
- name: A dependent's net income stays off both spouses' columns
absolute_error_margin: 0.01
period: 2021
input:
Expand Down Expand Up @@ -87,9 +88,9 @@
members: [person1, person2, person3]
state_code: IA
output:
ia_net_income: [8_000, 30_600, 0]
ia_net_income: [8_000, 30_000, 0]

- name: Dependent net income stays with the same spouse when the head and spouse labels are exchanged
- name: A dependent's net income stays off both spouses' columns when the head and spouse labels are exchanged
absolute_error_margin: 0.01
period: 2021
input:
Expand Down Expand Up @@ -121,7 +122,7 @@
members: [person1, person2, person3]
state_code: IA
output:
ia_net_income: [8_000, 30_600, 0]
ia_net_income: [8_000, 30_000, 0]

- name: 2022 single filer with wages and traditional IRA distribution
period: 2022
Expand Down Expand Up @@ -167,4 +168,49 @@
ia_pension_exclusion: 10_000
ia_net_income: 50_000

- name: A dependent child's interest stays off the parent's Iowa net income and 2022 tax
period: 2022
absolute_error_margin: 0.01
input:
people:
parent:
age: 40
employment_income: 40_000
child:
age: 16
taxable_interest_income: 8_000
tax_units:
tax_unit:
members: [parent, child]
households:
household:
members: [parent, child]
state_code: IA
output:
# Iowa net income starts from federal AGI (Iowa Code 422.7), which leaves
# out the child's interest; the child files their own IA 1040 with net
# income of 5,000 or more (Iowa Code 422.13(1)(a)).
ia_net_income: [40_000, 0]
# The same tax as with no child income (issue #9814 reproduction).
ia_income_tax: 1_332.05

- name: A dependent child's wages stay off the parent's Iowa net income
period: 2025
input:
people:
parent:
age: 40
employment_income: 40_000
child:
age: 16
employment_income: 5_000
tax_units:
tax_unit:
members: [parent, child]
households:
household:
members: [parent, child]
state_code: IA
output:
ia_net_income: [40_000, 0]
state_agi: 40_000
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
# The return claims 1,500, shared 1:2.
ms_health_savings_account_adjustment: [500, 1_000]

- name: A dependent's income is not reduced by the filer's deduction, nor by the dependent's own account
- name: A dependent's income and own account stay off the filers' Mississippi AGI
period: 2025
input:
people:
Expand Down Expand Up @@ -148,9 +148,9 @@
# account is left out.
ms_health_savings_account_adjustment: [1_500, 1_500, 0]
ms_agi_adjustments: [1_500, 1_500, 0]
# The child's 5,000 reaches the Mississippi AGI of the spouse with the
# greater income in full: 40,000 - 1,500 + 5,000.
ms_agi: [43_500, 28_500, 0]
# The child's 5,000 goes on the child's own return: 40,000 - 1,500 and
# 30,000 - 1,500.
ms_agi: [38_500, 28_500, 0]

- name: A married person filing a separate federal return takes their own deduction
period: 2025
Expand Down
Loading
Loading