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:
- Utah refundable EITC contributed reform.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
description: The Utah EITC is refundable for households with children below a certain age when this parameter is in effect.

values:
0000-01-01: false

metadata:
unit: bool
period: year
label: Utah refundable EITC in effect
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
description: The maximum age for a child to qualify the household for the refundable Utah EITC.

values:
0000-01-01: 2

metadata:
unit: year
period: year
label: Utah refundable EITC maximum child age
5 changes: 5 additions & 0 deletions policyengine_us/reforms/reforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@
from .states.mi.surtax import (
create_mi_surtax_reform,
)
from .states.ut import (
create_ut_refundable_eitc_reform,
)
from .additional_tax_bracket import (
create_additional_tax_bracket_reform,
)
Expand Down Expand Up @@ -248,6 +251,7 @@ def create_structural_reforms_from_parameters(parameters, period):
parameters, period
)
mi_surtax = create_mi_surtax_reform(parameters, period)
ut_refundable_eitc = create_ut_refundable_eitc_reform(parameters, period)

american_worker_rebate_act = create_american_worker_rebate_act_reform(
parameters, period
Expand Down Expand Up @@ -315,6 +319,7 @@ def create_structural_reforms_from_parameters(parameters, period):
reconciled_ssn_for_llc_and_aoc,
ctc_additional_bracket,
mi_surtax,
ut_refundable_eitc,
additional_tax_bracket,
american_worker_rebate_act,
ctc_per_child_phase_out,
Expand Down
3 changes: 3 additions & 0 deletions policyengine_us/reforms/states/ut/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .ut_refundable_eitc import (
create_ut_refundable_eitc_reform,
)
118 changes: 118 additions & 0 deletions policyengine_us/reforms/states/ut/ut_refundable_eitc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
from policyengine_us.model_api import *
from policyengine_core.periods import period as period_


def create_ut_refundable_eitc() -> Reform:
class ut_has_qualifying_child_for_refundable_eitc(Variable):
value_type = bool
entity = TaxUnit
label = "Utah tax unit has qualifying child for refundable EITC"
defined_for = StateCode.UT
definition_period = YEAR

def formula(tax_unit, period, parameters):
person = tax_unit.members
p = parameters(period).gov.contrib.states.ut.eitc
age = person("age", period)
is_dependent = person("is_tax_unit_dependent", period)
is_qualifying_child = (age <= p.max_age) & is_dependent
return tax_unit.any(is_qualifying_child)

class ut_refundable_eitc(Variable):
value_type = float
entity = TaxUnit
label = "Utah refundable EITC"
unit = USD
definition_period = YEAR
defined_for = "ut_has_qualifying_child_for_refundable_eitc"

adds = ["ut_eitc"]

class ut_eitc(Variable):
value_type = float
entity = TaxUnit
label = "Utah Earned Income Tax Credit"
unit = USD
documentation = "This credit is a fraction of the federal EITC."
definition_period = YEAR
defined_for = StateCode.UT
reference = "https://le.utah.gov/xcode/Title59/Chapter10/59-10-S1044.html?v=C59-10-S1044_2022050420220504"

def formula(tax_unit, period, parameters):
p = parameters(
period
).gov.states.ut.tax.income.credits.earned_income
federal_eitc = tax_unit("eitc", period)
return p.rate * federal_eitc

class ut_non_refundable_eitc(Variable):
value_type = float
entity = TaxUnit
label = "Utah non-refundable EITC"
unit = USD
definition_period = YEAR
defined_for = StateCode.UT

adds = ["ut_eitc"]
subtracts = ["ut_refundable_eitc"]

class ut_non_refundable_credits(Variable):
value_type = float
entity = TaxUnit
label = "Utah non-refundable tax credits"
unit = USD
definition_period = YEAR
defined_for = StateCode.UT

adds = [
"ut_non_refundable_eitc",
"ut_retirement_credit",
"ut_ss_benefits_credit",
"ut_at_home_parent_credit",
"ut_ctc",
]

class ut_refundable_credits(Variable):
value_type = float
entity = TaxUnit
label = "Utah refundable credits"
unit = USD
definition_period = YEAR
defined_for = StateCode.UT

adds = ["ut_refundable_eitc"]

class reform(Reform):
def apply(self):
self.add_variable(ut_has_qualifying_child_for_refundable_eitc)
self.add_variable(ut_refundable_eitc)
self.add_variable(ut_non_refundable_eitc)
self.update_variable(ut_eitc)
self.update_variable(ut_non_refundable_credits)
self.update_variable(ut_refundable_credits)

return reform


def create_ut_refundable_eitc_reform(parameters, period, bypass: bool = False):
if bypass:
return create_ut_refundable_eitc()

p = parameters.gov.contrib.states.ut.eitc

reform_active = False
current_period = period_(period)

for i in range(5):
if p(current_period).in_effect:
reform_active = True
break
current_period = current_period.offset(1, "year")

if reform_active:
return create_ut_refundable_eitc()
else:
return None


ut_refundable_eitc = create_ut_refundable_eitc_reform(None, None, bypass=True)
214 changes: 214 additions & 0 deletions policyengine_us/tests/policy/contrib/states/ut/ut_refundable_eitc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
- name: Single parent with child under max age - full EITC refundable
period: 2024
reforms: policyengine_us.reforms.states.ut.ut_refundable_eitc.ut_refundable_eitc
input:
gov.contrib.states.ut.eitc.in_effect: true
people:
parent:
age: 30
child:
age: 2
is_tax_unit_dependent: true
tax_units:
tax_unit:
members: [parent, child]
eitc: 5_000
households:
household:
members: [parent, child]
state_code: UT
output:
# Utah EITC = 20% of federal EITC = 0.2 * 5_000 = 1_000
# Since child is age 2 (at max_age threshold), full amount is refundable
ut_eitc: 1_000 # Total EITC
ut_refundable_eitc: 1_000
ut_non_refundable_eitc: 0 # Non-refundable portion is reduced to zero
ut_has_qualifying_child_for_refundable_eitc: true

- name: Single parent with child at age 1
period: 2024
reforms: policyengine_us.reforms.states.ut.ut_refundable_eitc.ut_refundable_eitc
input:
gov.contrib.states.ut.eitc.in_effect: true
people:
parent:
age: 30
child:
age: 1
is_tax_unit_dependent: true
tax_units:
tax_unit:
members: [parent, child]
eitc: 3_000
households:
household:
members: [parent, child]
state_code: UT
output:
# Utah EITC = 20% of federal EITC = 0.2 * 3_000 = 600
ut_eitc: 600
ut_refundable_eitc: 600
ut_non_refundable_eitc: 0
ut_has_qualifying_child_for_refundable_eitc: true

- name: Single parent with child age 3 - not eligible for refundable EITC
period: 2024
reforms: policyengine_us.reforms.states.ut.ut_refundable_eitc.ut_refundable_eitc
input:
gov.contrib.states.ut.eitc.in_effect: true
people:
parent:
age: 30
child:
age: 3
is_tax_unit_dependent: true
tax_units:
tax_unit:
members: [parent, child]
eitc: 4_000
households:
household:
members: [parent, child]
state_code: UT
output:
# Child is too old (max_age is 2)
# Utah EITC = 0.2 * 4_000 = 800
ut_eitc: 800
ut_refundable_eitc: 0
ut_non_refundable_eitc: 800 # Remains fully non-refundable
ut_has_qualifying_child_for_refundable_eitc: false

- name: Single parent with multiple children, one qualifying
period: 2024
reforms: policyengine_us.reforms.states.ut.ut_refundable_eitc.ut_refundable_eitc
input:
gov.contrib.states.ut.eitc.in_effect: true
people:
parent:
age: 35
child1:
age: 1
is_tax_unit_dependent: true
child2:
age: 5
is_tax_unit_dependent: true
tax_units:
tax_unit:
members: [parent, child1, child2]
eitc: 6_000
households:
household:
members: [parent, child1, child2]
state_code: UT
output:
# Has at least one qualifying child, so full EITC is refundable
# Utah EITC = 0.2 * 6_000 = 1_200
ut_eitc: 1_200
ut_refundable_eitc: 1_200
ut_non_refundable_eitc: 0
ut_has_qualifying_child_for_refundable_eitc: true

- name: Childless tax unit - not eligible
period: 2024
reforms: policyengine_us.reforms.states.ut.ut_refundable_eitc.ut_refundable_eitc
input:
gov.contrib.states.ut.eitc.in_effect: true
people:
person:
age: 30
tax_units:
tax_unit:
members: [person]
eitc: 500
households:
household:
members: [person]
state_code: UT
output:
# Utah EITC = 0.2 * 500 = 100 (all non-refundable)
ut_eitc: 100
ut_refundable_eitc: 0
ut_non_refundable_eitc: 100
ut_has_qualifying_child_for_refundable_eitc: false

- name: Married couple with infant (age 0)
period: 2024
reforms: policyengine_us.reforms.states.ut.ut_refundable_eitc.ut_refundable_eitc
input:
gov.contrib.states.ut.eitc.in_effect: true
people:
parent1:
age: 28
parent2:
age: 30
child:
age: 0
is_tax_unit_dependent: true
tax_units:
tax_unit:
members: [parent1, parent2, child]
eitc: 7_000
households:
household:
members: [parent1, parent2, child]
state_code: UT
output:
# Utah EITC = 0.2 * 7_000 = 1_400
ut_eitc: 1_400
ut_refundable_eitc: 1_400
ut_non_refundable_eitc: 0
ut_has_qualifying_child_for_refundable_eitc: true

- name: Tax unit with qualifying child but no federal EITC
period: 2024
reforms: policyengine_us.reforms.states.ut.ut_refundable_eitc.ut_refundable_eitc
input:
gov.contrib.states.ut.eitc.in_effect: true
people:
parent:
age: 30
child:
age: 2
is_tax_unit_dependent: true
tax_units:
tax_unit:
members: [parent, child]
eitc: 0
households:
household:
members: [parent, child]
state_code: UT
output:
# No federal EITC means no Utah EITC
ut_eitc: 0
ut_refundable_eitc: 0
ut_non_refundable_eitc: 0
ut_has_qualifying_child_for_refundable_eitc: true

- name: Custom max_age parameter - child at age 4 qualifies
period: 2024
reforms: policyengine_us.reforms.states.ut.ut_refundable_eitc.ut_refundable_eitc
input:
gov.contrib.states.ut.eitc.in_effect: true
gov.contrib.states.ut.eitc.max_age: 4
people:
parent:
age: 30
child:
age: 4
is_tax_unit_dependent: true
tax_units:
tax_unit:
members: [parent, child]
eitc: 5_000
households:
household:
members: [parent, child]
state_code: UT
output:
# With max_age = 4, child age 4 qualifies
# Utah EITC = 0.2 * 5_000 = 1_000
ut_eitc: 1_000
ut_refundable_eitc: 1_000
ut_non_refundable_eitc: 0
ut_has_qualifying_child_for_refundable_eitc: true