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-schedule-c-category-losses-agi.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Deduct a Schedule C loss in one SSTB category from AGI when the same person has Schedule C profit in the other category, and treat the two categories separately in the Wisconsin homestead loss add-back and the Kentucky and Maryland spouse loss allocations.
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ description: Wisconsin adds back the losses from these person-level income sourc
values:
2021-01-01:
# Schedule 4, line 2: net business loss from a sole proprietorship
# (Schedule C). SSTB and non-SSTB income are combined, as loss_ald
# deducts the loss of their total.
- total_self_employment_income
# (Schedule C). The line 11j instructions say to consider each business
# individually, so the SSTB and non-SSTB losses are added back
# separately, as loss_ald deducts them.
- self_employment_income
- sstb_self_employment_income
- rental_income # line 4: net rental real estate and royalty loss
# Form 4835 farm rental loss: rental real estate (71.52(1e)(d)) or net
# farm loss (71.52(1e)(e)).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,9 @@ def test_units_without_dependents_match_all_member_formula(runs, units):
"""Differential check against the all-member formula."""
p = runs["irs"]
filing_status = runs["with"]["filing_status"]
se = _by_person(units, "self_employment_income") + _by_person(
units, "sstb_self_employment_income"
)
person_business = [se] + [_by_person(units, name) for name in BUSINESS_INPUTS[2:]]
# Each Schedule C category's profit and loss on its own, as
# irs_gross_income counts them (#9989).
person_business = [_by_person(units, name) for name in BUSINESS_INPUTS]
income = sum(_unit_sum(runs, np.maximum(x, 0)) for x in person_business)
loss = sum(_unit_sum(runs, np.maximum(-x, 0)) for x in person_business)
limited_business_loss = np.minimum(loss, income + p.ald.loss.max[filing_status])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,10 @@ def _pre_extraction_reference(unit, threshold, capital_cap):
for person, dependent in unit["members"]:
if dependent:
continue
# Each Schedule C category is its own source, as in irs_gross_income.
business_sources = (
person["self_employment_income"] + person["sstb_self_employment_income"],
person["self_employment_income"],
person["sstb_self_employment_income"],
person["farm_operations_income"],
person["rental_income"],
person["farm_rent_income"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,32 @@
sstb_self_employment_income_behavioral_response: 1_000
self_employment_income: 0
sstb_self_employment_income: -9_000

- name: Non-SSTB Schedule C loss offsets SSTB Schedule C profit in AGI
# Two Schedules C: line 31 of (5,000) and 5,000 both go to Schedule 1
# line 3, which is 0, so Form 1040 line 11 AGI is 0.
period: 2024
input:
self_employment_income: -5_000
sstb_self_employment_income: 5_000
output:
adjusted_gross_income: 0

- name: SSTB Schedule C loss offsets non-SSTB Schedule C profit in AGI
period: 2024
input:
self_employment_income: 5_000
sstb_self_employment_income: -5_000
output:
adjusted_gross_income: 0

- name: Offsetting Schedule C results leave AGI equal to wages
# Form 1040 line 1z 50,000 plus Schedule 1 line 3 of 0 gives line 11 AGI
# of 50,000.
period: 2024
input:
employment_income: 50_000
self_employment_income: -5_000
sstb_self_employment_income: 5_000
output:
adjusted_gross_income: 50_000
Original file line number Diff line number Diff line change
Expand Up @@ -271,3 +271,30 @@
ky_agi: [50_000, -13_000]
ky_modified_agi_if_joint: 37_000
ky_modified_agi_if_separate: 50_000

- name: A spouse's non-SSTB Schedule C loss offsets the same spouse's SSTB Schedule C profit
# 2025 Form 740 instructions, page 13, line 9: "Each spouse must claim his
# or her own income and deductions. The total of line 5, Columns A and B,
# must equal the combined federal adjusted gross income." The head's two
# Schedules C (line 31 of (5,000) and 5,000) net to 0 on Schedule 1 line 3,
# so the head's line 5 is 0 and the spouse's is the 40,000 of wages.
period: 2025
input:
people:
head:
age: 45
self_employment_income: -5_000
sstb_self_employment_income: 5_000
spouse:
age: 43
employment_income: 40_000
tax_units:
tax_unit:
members: [head, spouse]
households:
household:
members: [head, spouse]
state_code: KY
output:
adjusted_gross_income: 40_000
ky_federal_agi: [0, 40_000]
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,25 @@
state_code: WI
output:
wi_homestead_disqualified_losses: 0

- name: Case 9, a non-SSTB sole proprietorship loss is not netted against SSTB sole proprietorship income.
period: 2023
absolute_error_margin: 0.01
input:
people:
head:
age: 70
self_employment_income: -5_000
sstb_self_employment_income: 5_000
tax_units:
tax_unit:
members: [head]
households:
household:
members: [head]
state_code: WI
output:
# 2023 Schedule H instructions, line 11j (page 16): consider each business
# individually and do not net a business with a gain against one with a
# loss (Example 1). Schedule 4, line 2 = 5,000.
wi_homestead_disqualified_losses: 5_000
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,6 @@
# Two Schedule C businesses (2023 instructions, page 16, Example 1):
# Schedule 1 line 3 = 5,000 - 5,000 = 0, and Schedule 4 line 2 adds back
# the 5,000 loss without netting. Household income = 0 + 5,000 = 5,000.
# loss_ald deducts the loss of total_self_employment_income (0 here), so
# the add-back follows that total and household income is the same.
# loss_ald deducts each category's loss on its own, so AGI is 0 and the
# add-back is the 5,000 non-SSTB loss.
wi_homestead_income: 5_000
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,12 @@ def formula(tax_unit, period, parameters):
# business amounts flow into gross income and losses are deducted here,
# so allowable business losses are capped at business income plus
# the threshold.
indiv_se_income = max_(0, person("total_self_employment_income", period))
indiv_se_loss = max_(0, -person("total_self_employment_income", period))
# irs_gross_income counts each Schedule C category's profit on its
# own, so each category's loss is deducted on its own here.
non_sstb_se = person("self_employment_income", period)
sstb_se = person("sstb_self_employment_income", period)
indiv_se_income = max_(0, non_sstb_se) + max_(0, sstb_se)
indiv_se_loss = max_(0, -non_sstb_se) + max_(0, -sstb_se)
self_employment_income = tax_unit.sum(not_dependent * indiv_se_income)
self_employment_loss = tax_unit.sum(not_dependent * indiv_se_loss)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ def formula(person, period, parameters):
business_loss = max_(loss - capital_loss, 0)
not_dependent = ~person("is_tax_unit_dependent", period)
owned_business_loss = 0
# Each Schedule C category's loss counts on its own, as in loss_ald.
for source in (
"total_self_employment_income",
"self_employment_income",
"sstb_self_employment_income",
"farm_operations_income",
"rental_income",
"farm_rent_income",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from policyengine_us.model_api import *


# Person-level sources of the business losses in loss_ald.
# Person-level sources of the business losses in loss_ald, with each
# Schedule C category on its own, as loss_ald deducts them.
BUSINESS_LOSS_SOURCES = [
"total_self_employment_income",
"self_employment_income",
"sstb_self_employment_income",
"farm_operations_income",
"rental_income",
"farm_rent_income",
Expand Down
Loading