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
4 changes: 4 additions & 0 deletions changelog_entry.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- bump: minor
changes:
added:
- Add SC H.3492 partially refundable EITC reform.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
description: The South Carolina H.3492 Partially Refundable EITC reform applies if this is true.
metadata:
unit: bool
period: year
label: SC H.3492 Partially Refundable EITC in effect
reference:
- title: South Carolina H.3492 (126th Session, 2025-2026)
href: https://www.scstatehouse.gov/sess126_2025-2026/bills/3492.htm
values:
0000-01-01: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
description: If the South Carolina EITC exceeds the taxpayer's state income tax liability, this rate of the excess credit is refunded to the taxpayer.
metadata:
unit: /1
period: year
label: SC H.3492 EITC refundable excess rate
reference:
- title: South Carolina H.3492 (126th Session, 2025-2026)
href: https://www.scstatehouse.gov/sess126_2025-2026/bills/3492.htm
- title: SC Code Section 12-6-3632 (proposed amendment)
href: https://www.scstatehouse.gov/code/t12c006.php
values:
0000-01-01: 0.25
5 changes: 5 additions & 0 deletions policyengine_us/reforms/reforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from .biden.budget_2025 import create_capital_gains_tax_increase_reform
from .eitc import create_halve_joint_eitc_phase_out_rate_reform
from .states.ny.wftc import create_ny_working_families_tax_credit_reform
from .states.sc.h3492 import create_sc_h3492_eitc_refundable_reform
from .harris.lift.middle_class_tax_credit import (
create_middle_class_tax_credit_reform,
)
Expand Down Expand Up @@ -177,6 +178,9 @@ def create_structural_reforms_from_parameters(parameters, period):
create_halve_joint_eitc_phase_out_rate_reform(parameters, period)
)
ny_wftc = create_ny_working_families_tax_credit_reform(parameters, period)
sc_h3492_eitc_refundable = create_sc_h3492_eitc_refundable_reform(
parameters, period
)

middle_class_tax_credit = create_middle_class_tax_credit_reform(
parameters, period
Expand Down Expand Up @@ -320,6 +324,7 @@ def create_structural_reforms_from_parameters(parameters, period):
capital_gains_tax_increase,
halve_joint_eitc_phase_out_rate,
ny_wftc,
sc_h3492_eitc_refundable,
middle_class_tax_credit,
rent_relief_tax_credit,
end_child_poverty_act,
Expand Down
3 changes: 3 additions & 0 deletions policyengine_us/reforms/states/sc/h3492/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .sc_h3492_eitc_refundable import (
create_sc_h3492_eitc_refundable_reform,
)
163 changes: 163 additions & 0 deletions policyengine_us/reforms/states/sc/h3492/sc_h3492_eitc_refundable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
from policyengine_us.model_api import *


def create_sc_h3492_eitc_refundable() -> Reform:
"""
South Carolina H.3492 - Partially Refundable EITC

Amends SC Code Section 12-6-3632 to make a portion of the state EITC
refundable. If the SC EITC (125% of federal) exceeds the taxpayer's
state income tax liability, 25% of the excess is refunded.

Reference: https://www.scstatehouse.gov/sess126_2025-2026/bills/3492.htm
"""

class sc_h3492_total_eitc(Variable):
value_type = float
entity = TaxUnit
label = "SC H.3492 total EITC amount"
unit = USD
definition_period = YEAR
reference = (
"https://www.scstatehouse.gov/sess126_2025-2026/bills/3492.htm",
"https://www.scstatehouse.gov/code/t12c006.php",
)
defined_for = StateCode.SC

def formula(tax_unit, period, parameters):
federal_eitc = tax_unit("eitc", period)
rate = parameters(
period
).gov.states.sc.tax.income.credits.eitc.rate
return np.round(federal_eitc * rate, 1)

class sc_h3492_other_non_refundable_credits(Variable):
value_type = float
entity = TaxUnit
label = "SC non-refundable credits excluding EITC"
unit = USD
definition_period = YEAR
defined_for = StateCode.SC

def formula(tax_unit, period, parameters):
# Sum non-refundable credits excluding EITC
cdcc = tax_unit("sc_cdcc", period)
two_wage = tax_unit("sc_two_wage_earner_credit", period)
return cdcc + two_wage

class sc_h3492_tax_liability_for_eitc(Variable):
value_type = float
entity = TaxUnit
label = "SC tax liability available for EITC"
unit = USD
definition_period = YEAR
defined_for = StateCode.SC

def formula(tax_unit, period, parameters):
# Tax before non-refundable credits minus other credits
tax_before = tax_unit(
"sc_income_tax_before_non_refundable_credits", period
)
other_credits = tax_unit(
"sc_h3492_other_non_refundable_credits", period
)
return max_(0, tax_before - other_credits)

class sc_h3492_eitc_non_refundable(Variable):
value_type = float
entity = TaxUnit
label = "SC H.3492 EITC non-refundable portion"
unit = USD
definition_period = YEAR
reference = (
"https://www.scstatehouse.gov/sess126_2025-2026/bills/3492.htm",
)
defined_for = StateCode.SC

def formula(tax_unit, period, parameters):
total_eitc = tax_unit("sc_h3492_total_eitc", period)
tax_liability = tax_unit("sc_h3492_tax_liability_for_eitc", period)
# Non-refundable portion is limited to tax liability
return min_(total_eitc, tax_liability)

class sc_h3492_eitc_refundable(Variable):
value_type = float
entity = TaxUnit
label = "SC H.3492 EITC refundable portion"
unit = USD
definition_period = YEAR
reference = (
"https://www.scstatehouse.gov/sess126_2025-2026/bills/3492.htm",
)
defined_for = StateCode.SC

def formula(tax_unit, period, parameters):
p = parameters(period).gov.contrib.states.sc.h3492
total_eitc = tax_unit("sc_h3492_total_eitc", period)
non_refundable = tax_unit("sc_h3492_eitc_non_refundable", period)
excess = max_(0, total_eitc - non_refundable)
return excess * p.refundable_excess_rate

class sc_non_refundable_credits(Variable):
value_type = float
entity = TaxUnit
label = "South Carolina non-refundable credits"
unit = USD
definition_period = YEAR
defined_for = StateCode.SC

def formula(tax_unit, period, parameters):
# Other non-refundable credits plus the non-refundable EITC portion
other_credits = tax_unit(
"sc_h3492_other_non_refundable_credits", period
)
eitc_non_refundable = tax_unit(
"sc_h3492_eitc_non_refundable", period
)
return other_credits + eitc_non_refundable

class sc_refundable_credits(Variable):
value_type = float
entity = TaxUnit
label = "South Carolina refundable credits"
unit = USD
definition_period = YEAR
defined_for = StateCode.SC

def formula(tax_unit, period, parameters):
p = parameters(period).gov.states.sc.tax.income.credits
standard_credits = add(tax_unit, period, p.refundable)
# Add refundable EITC portion from H.3492
eitc_refundable = tax_unit("sc_h3492_eitc_refundable", period)
return standard_credits + eitc_refundable

class reform(Reform):
def apply(self):
self.update_variable(sc_h3492_total_eitc)
self.update_variable(sc_h3492_other_non_refundable_credits)
self.update_variable(sc_h3492_tax_liability_for_eitc)
self.update_variable(sc_h3492_eitc_non_refundable)
self.update_variable(sc_h3492_eitc_refundable)
self.update_variable(sc_non_refundable_credits)
self.update_variable(sc_refundable_credits)

return reform


def create_sc_h3492_eitc_refundable_reform(
parameters, period, bypass: bool = False
):
if bypass:
return create_sc_h3492_eitc_refundable()

p = parameters(period).gov.contrib.states.sc.h3492

if p.in_effect:
return create_sc_h3492_eitc_refundable()
else:
return None


sc_h3492_eitc_refundable = create_sc_h3492_eitc_refundable_reform(
None, None, bypass=True
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# SC H.3492 - Partially Refundable EITC Tests
# If SC EITC exceeds state income tax liability, 25% of excess is refunded
# SC EITC = 125% of federal EITC

- name: Credit fully used against tax liability - no refund
period: 2025
reforms: policyengine_us.reforms.states.sc.h3492.sc_h3492_eitc_refundable.sc_h3492_eitc_refundable
input:
gov.contrib.states.sc.h3492.in_effect: true
people:
person:
age: 30
tax_units:
tax_unit:
members: [person]
eitc: 1_000
sc_income_tax_before_non_refundable_credits: 2_000
households:
household:
members: [person]
state_code: SC
output:
# SC EITC = 125% of $1,000 = $1,250
# Tax liability ($2,000) exceeds credit ($1,250)
# Non-refundable: $1,250 (full amount)
# Refundable: $0 (no excess)
sc_h3492_total_eitc: 1_250
sc_h3492_eitc_non_refundable: 1_250
sc_h3492_eitc_refundable: 0

- name: Credit partially exceeds tax liability - partial refund
period: 2025
reforms: policyengine_us.reforms.states.sc.h3492.sc_h3492_eitc_refundable.sc_h3492_eitc_refundable
input:
gov.contrib.states.sc.h3492.in_effect: true
people:
person:
age: 30
tax_units:
tax_unit:
members: [person]
eitc: 4_000
sc_income_tax_before_non_refundable_credits: 3_000
households:
household:
members: [person]
state_code: SC
output:
# SC EITC = 125% of $4,000 = $5,000
# Tax liability: $3,000
# Non-refundable: $3,000 (limited to tax liability)
# Excess: $5,000 - $3,000 = $2,000
# Refundable: 25% of $2,000 = $500
sc_h3492_total_eitc: 5_000
sc_h3492_eitc_non_refundable: 3_000
sc_h3492_eitc_refundable: 500

- name: Zero tax liability - maximum refund
period: 2025
reforms: policyengine_us.reforms.states.sc.h3492.sc_h3492_eitc_refundable.sc_h3492_eitc_refundable
input:
gov.contrib.states.sc.h3492.in_effect: true
people:
person:
age: 30
tax_units:
tax_unit:
members: [person]
eitc: 4_000
sc_income_tax_before_non_refundable_credits: 0
households:
household:
members: [person]
state_code: SC
output:
# SC EITC = 125% of $4,000 = $5,000
# Tax liability: $0
# Non-refundable: $0 (no tax to offset)
# Excess: $5,000 - $0 = $5,000
# Refundable: 25% of $5,000 = $1,250
sc_h3492_total_eitc: 5_000
sc_h3492_eitc_non_refundable: 0
sc_h3492_eitc_refundable: 1_250

- name: With other non-refundable credits - EITC limited by remaining liability
period: 2025
reforms: policyengine_us.reforms.states.sc.h3492.sc_h3492_eitc_refundable.sc_h3492_eitc_refundable
input:
gov.contrib.states.sc.h3492.in_effect: true
people:
person:
age: 30
tax_units:
tax_unit:
members: [person]
eitc: 4_000
sc_income_tax_before_non_refundable_credits: 5_000
sc_cdcc: 1_000
sc_two_wage_earner_credit: 500
households:
household:
members: [person]
state_code: SC
output:
# SC EITC = 125% of $4,000 = $5,000
# Tax before credits: $5,000
# Other credits: $1,000 + $500 = $1,500
# Tax liability for EITC: $5,000 - $1,500 = $3,500
# Non-refundable: min($5,000, $3,500) = $3,500
# Excess: $5,000 - $3,500 = $1,500
# Refundable: 25% of $1,500 = $375
sc_h3492_total_eitc: 5_000
sc_h3492_other_non_refundable_credits: 1_500
sc_h3492_tax_liability_for_eitc: 3_500
sc_h3492_eitc_non_refundable: 3_500
sc_h3492_eitc_refundable: 375

- name: No federal EITC - no state credit
period: 2025
reforms: policyengine_us.reforms.states.sc.h3492.sc_h3492_eitc_refundable.sc_h3492_eitc_refundable
input:
gov.contrib.states.sc.h3492.in_effect: true
people:
person:
age: 30
tax_units:
tax_unit:
members: [person]
eitc: 0
sc_income_tax_before_non_refundable_credits: 3_000
households:
household:
members: [person]
state_code: SC
output:
# No federal EITC means no SC EITC
sc_h3492_total_eitc: 0
sc_h3492_eitc_non_refundable: 0
sc_h3492_eitc_refundable: 0

- name: Small credit fully absorbed by tax
period: 2025
reforms: policyengine_us.reforms.states.sc.h3492.sc_h3492_eitc_refundable.sc_h3492_eitc_refundable
input:
gov.contrib.states.sc.h3492.in_effect: true
people:
person:
age: 30
tax_units:
tax_unit:
members: [person]
eitc: 400
sc_income_tax_before_non_refundable_credits: 1_000
households:
household:
members: [person]
state_code: SC
output:
# SC EITC = 125% of $400 = $500
# Tax liability: $1,000
# Non-refundable: $500 (full amount)
# Refundable: $0 (no excess)
sc_h3492_total_eitc: 500
sc_h3492_eitc_non_refundable: 500
sc_h3492_eitc_refundable: 0