diff --git a/changelog.d/ca-eitc-earned-income-netting.fixed.md b/changelog.d/ca-eitc-earned-income-netting.fixed.md new file mode 100644 index 00000000000..f58cb1e0657 --- /dev/null +++ b/changelog.d/ca-eitc-earned-income-netting.fixed.md @@ -0,0 +1 @@ +Use FTB 3514 line 19 for CalEITC, YCTC and FYTC earned income: net a spouse's self-employment loss against the other spouse's wages, and include farm income and partnership self-employment earnings. diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/earned_income/ca_eitc_earned_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/earned_income/ca_eitc_earned_income.yaml new file mode 100644 index 00000000000..b4084d14bb0 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/earned_income/ca_eitc_earned_income.yaml @@ -0,0 +1,135 @@ +- name: A spouse's self-employment loss offsets the other spouse's wages (FTB 3514 line 19) + period: 2023 + # Line 19 = 9,975.50 - 6,000 = 3,975.50, the midpoint of the 2023 EITC + # Table row 3,951-4,000, which lists $259 with no qualifying children. + absolute_error_margin: 1 + input: + people: + head: + age: 30 + employment_income: 9_975.5 + spouse: + age: 30 + self_employment_income: -6_000 + tax_units: + tax_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: CA + output: + ca_eitc_earned_income: 3_975.5 + ca_eitc: 259 + +- name: No CalEITC when the net of wages and self-employment loss is zero or less + period: 2023 + # Worksheet Part I line 1: "If the amount is zero or less, stop here." + input: + people: + head: + age: 30 + employment_income: 10_000 + spouse: + age: 30 + self_employment_income: -12_000 + tax_units: + tax_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: CA + output: + ca_eitc_earned_income: 0 + ca_eitc: 0 + +- name: YCTC phase-out uses the netted line 19 earned income + period: 2023 + # Line 23 = line 19 = 30,000 - 10,000 = 20,000, below the $25,775 + # threshold, so the full 2023 YCTC of $1,117 applies. + input: + people: + head: + age: 30 + employment_income: 30_000 + spouse: + age: 30 + self_employment_income: -10_000 + child: + age: 3 + tax_units: + tax_unit: + members: [head, spouse, child] + households: + household: + members: [head, spouse, child] + state_code: CA + output: + ca_eitc_earned_income: 20_000 + ca_yctc: 1_117 + +- name: Farm income counts in line 19, less the deductible part of SE tax + period: 2023 + # Worksheet 3 line 2 (Schedule 1 line 6) = 20,000. Schedule SE net earnings + # = 20,000 x 0.9235 = 18,470; SE tax = 18,470 x 15.3% = 2,825.91; line 4 + # (Schedule 1 line 15) = 2,825.91 / 2 = 1,412.955. Line 18 = line 19 + # = 20,000 - 1,412.955 = 18,587.045. + absolute_error_margin: 0.01 + input: + people: + head: + age: 30 + farm_operations_income: 20_000 + tax_units: + tax_unit: + members: [head] + households: + household: + members: [head] + state_code: CA + output: + ca_eitc_earned_income: 18_587.045 + +- name: A spouse's farm loss offsets the other spouse's wages (FTB 3514 line 19) + period: 2023 + # Line 16 = 20,000. Worksheet 3 line 2 = -10,000; a loss has no SE tax, so + # line 4 = 0 and line 18 = -10,000. Line 19 = 20,000 - 10,000 = 10,000. + input: + people: + head: + age: 30 + employment_income: 20_000 + spouse: + age: 30 + farm_operations_income: -10_000 + tax_units: + tax_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: CA + output: + ca_eitc_earned_income: 10_000 + +- name: Partnership self-employment earnings count in line 19 + period: 2023 + # Worksheet 3 line 3 (K-1 box 14, code A) = 20,000. Line 4 = 1,412.955 as in + # the farm case above. Line 19 = 20,000 - 1,412.955 = 18,587.045. + absolute_error_margin: 0.01 + input: + people: + head: + age: 30 + partnership_income: 20_000 + partnership_self_employment_net_earnings: 20_000 + tax_units: + tax_unit: + members: [head] + households: + household: + members: [head] + state_code: CA + output: + ca_eitc_earned_income: 18_587.045 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/earned_income/ca_eitc_integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/earned_income/ca_eitc_integration.yaml index fcf35c87761..ff6fb759d93 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/earned_income/ca_eitc_integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/earned_income/ca_eitc_integration.yaml @@ -5,7 +5,7 @@ input: state_code: CA eitc_child_count: 3 - earned_income: 8_000 + employment_income: 8_000 # AGI equals earned income so the worksheet's earned-income/AGI credit # comparison isolates the table value. adjusted_gross_income: 8_000 @@ -19,7 +19,7 @@ input: state_code: CA eitc_child_count: 1 - earned_income: 6_400 + employment_income: 6_400 adjusted_gross_income: 6_400 output: ca_eitc: 1_843 @@ -31,7 +31,7 @@ input: state_code: CA eitc_child_count: 0 - earned_income: 9_951 + employment_income: 9_951 adjusted_gross_income: 9_951 output: #ca_eitc_second_phase_out_start: 8_201 # First bracket. diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/foster_youth/ca_foster_youth_tax_credit_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/foster_youth/ca_foster_youth_tax_credit_person.yaml index 1f420a8b3cd..1d72764c0fe 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/foster_youth/ca_foster_youth_tax_credit_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/foster_youth/ca_foster_youth_tax_credit_person.yaml @@ -4,7 +4,7 @@ age: 20 ca_foster_youth_tax_credit_eligible_person: true ca_eitc_eligible: true - tax_unit_earned_income: 20_000 + ca_eitc_earned_income: 20_000 output: ca_foster_youth_tax_credit_person: 1_083 @@ -14,7 +14,7 @@ age: 26 ca_foster_youth_tax_credit_eligible_person: true ca_eitc_eligible: true - tax_unit_earned_income: 20_000 + ca_eitc_earned_income: 20_000 output: ca_foster_youth_tax_credit_person: 0 @@ -24,7 +24,7 @@ age: 25 ca_foster_youth_tax_credit_eligible_person: true ca_eitc_eligible: true - tax_unit_earned_income: 30_000 + ca_eitc_earned_income: 30_000 output: #1083-5000*0.2166 = 0 ca_foster_youth_tax_credit_person: 0 @@ -35,7 +35,7 @@ age: 25 ca_foster_youth_tax_credit_eligible_person: true ca_eitc_eligible: true - tax_unit_earned_income: 29_000 + ca_eitc_earned_income: 29_000 output: #1083-4000*0.2166 = 216.6 ca_foster_youth_tax_credit_person: 216.6 @@ -46,6 +46,6 @@ age: 23 ca_foster_youth_tax_credit_eligible_person: false ca_eitc_eligible: true - tax_unit_earned_income: 20_000 + ca_eitc_earned_income: 20_000 output: ca_foster_youth_tax_credit_person: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/young_child/ca_yctc.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/young_child/ca_yctc.yaml index c26330a541e..781ac3bfad0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/young_child/ca_yctc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/credits/young_child/ca_yctc.yaml @@ -9,7 +9,7 @@ tax_units: tax_unit: members: [parent, child] - filer_adjusted_earnings: 25_000 + ca_eitc_earned_income: 25_000 ca_eitc: 1 households: household: @@ -29,7 +29,7 @@ tax_units: tax_unit: members: [parent, child] - filer_adjusted_earnings: 25_100 + ca_eitc_earned_income: 25_100 ca_eitc: 1 households: household: @@ -49,7 +49,7 @@ tax_units: tax_unit: members: [parent, child] - filer_adjusted_earnings: 25_100 + ca_eitc_earned_income: 25_100 ca_eitc: 1 households: household: @@ -90,7 +90,7 @@ tax_units: tax_unit: members: [parent, child] - filer_adjusted_earnings: 30_000 + ca_eitc_earned_income: 30_000 ca_eitc: 1 households: household: @@ -113,7 +113,7 @@ tax_units: tax_unit: members: [parent, child1, child2] - filer_adjusted_earnings: 25_100 + ca_eitc_earned_income: 25_100 ca_eitc: 1 households: household: diff --git a/policyengine_us/variables/gov/states/ca/tax/income/credits/earned_income/ca_eitc.py b/policyengine_us/variables/gov/states/ca/tax/income/credits/earned_income/ca_eitc.py index 06b6fea2c2c..2adfd73c25d 100644 --- a/policyengine_us/variables/gov/states/ca/tax/income/credits/earned_income/ca_eitc.py +++ b/policyengine_us/variables/gov/states/ca/tax/income/credits/earned_income/ca_eitc.py @@ -60,7 +60,7 @@ def credit_for(income): amount_after_first_phase_out, ) - earned_income = tax_unit("filer_adjusted_earnings", period) + earned_income = tax_unit("ca_eitc_earned_income", period) agi = tax_unit("adjusted_gross_income", period) # The California Earned Income Tax Credit Worksheet (FTB 3514 # instructions) figures the credit on California earned income (line 2) diff --git a/policyengine_us/variables/gov/states/ca/tax/income/credits/earned_income/ca_eitc_earned_income.py b/policyengine_us/variables/gov/states/ca/tax/income/credits/earned_income/ca_eitc_earned_income.py new file mode 100644 index 00000000000..385bb883fdb --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/tax/income/credits/earned_income/ca_eitc_earned_income.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class ca_eitc_earned_income(Variable): + value_type = float + entity = TaxUnit + label = "California earned income for the CalEITC, YCTC and FYTC" + unit = USD + definition_period = YEAR + reference = ( + "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=RTC§ionNum=17052", # (c)(4) + "https://www.ftb.ca.gov/forms/2023/2023-3514-instructions.html", # Lines 13-19, Worksheet 3 + "https://www.ftb.ca.gov/forms/2025/2025-3514-booklet.html", + ) + defined_for = StateCode.CA + + def formula(tax_unit, period, parameters): + # FTB 3514 line 19 adds wages (line 16), nontaxable combat pay (line 17) + # and business income or (loss) (line 18) for the whole return. + # Worksheet 3 adds Schedule C income (Schedule 1 line 3), farm income + # (Schedule 1 line 6) and partnership self-employment earnings (K-1 + # box 14, code A), and subtracts the deductible part of SE tax + # (Schedule 1 line 15). A loss of one spouse therefore offsets the + # other spouse's wages before the result is floored at zero. R&TC + # 17052(c)(4) applies IRC 32(c)(2)(A), which the federal EITC earned + # income computes from these same sources. + return tax_unit("eitc_earned_income", period) diff --git a/policyengine_us/variables/gov/states/ca/tax/income/credits/foster_youth/ca_foster_youth_tax_credit_person.py b/policyengine_us/variables/gov/states/ca/tax/income/credits/foster_youth/ca_foster_youth_tax_credit_person.py index 98e20aa6adc..864d623530b 100644 --- a/policyengine_us/variables/gov/states/ca/tax/income/credits/foster_youth/ca_foster_youth_tax_credit_person.py +++ b/policyengine_us/variables/gov/states/ca/tax/income/credits/foster_youth/ca_foster_youth_tax_credit_person.py @@ -14,7 +14,8 @@ def formula(person, period, parameters): p = parameters(period).gov.states.ca.tax.income.credits.foster_youth age = person("age", period) base_credit = p.amount.calc(age) - earned_income = person.tax_unit("tax_unit_earned_income", period) + # FTB 3514 line 34: FYTC earned income is the CalEITC line 19 amount. + earned_income = person.tax_unit("ca_eitc_earned_income", period) excess_earned_income = max_(earned_income - p.phase_out.start, 0) reduction_increments = excess_earned_income / p.phase_out.increment reduction_amount = max_(0, reduction_increments * p.phase_out.amount) diff --git a/policyengine_us/variables/gov/states/ca/tax/income/credits/young_child/ca_yctc.py b/policyengine_us/variables/gov/states/ca/tax/income/credits/young_child/ca_yctc.py index d7501fd6104..73292651c1c 100644 --- a/policyengine_us/variables/gov/states/ca/tax/income/credits/young_child/ca_yctc.py +++ b/policyengine_us/variables/gov/states/ca/tax/income/credits/young_child/ca_yctc.py @@ -51,7 +51,8 @@ def formula(tax_unit, period, parameters): eligible = has_eligible_child & (gets_caleitc | is_loss_eligible) # phase out credit amount - eitc_earnings = tax_unit("filer_adjusted_earnings", period) + # FTB 3514 line 23: YCTC earned income is the CalEITC line 19 amount. + eitc_earnings = tax_unit("ca_eitc_earned_income", period) excess_earnings = max_(0, eitc_earnings - p.phase_out.start) increments = excess_earnings / p.phase_out.increment reduction = increments * p.phase_out.amount