diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..6f9db1d4046 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: minor + changes: + added: + - Add NY A04948 Youth Worker Tax Benefits reform. diff --git a/policyengine_us/parameters/gov/contrib/states/ny/a04948/in_effect.yaml b/policyengine_us/parameters/gov/contrib/states/ny/a04948/in_effect.yaml new file mode 100644 index 00000000000..44e02760aaf --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ny/a04948/in_effect.yaml @@ -0,0 +1,10 @@ +description: The New York Youth Worker Tax Benefits Act (Assembly Bill A04948) applies if this is true. +metadata: + unit: bool + period: year + label: NY A04948 Youth Worker Tax Benefits in effect + reference: + - title: NY Assembly Bill 2025-A4948 + href: https://www.nysenate.gov/legislation/bills/2025/A4948 +values: + 0000-01-01: false diff --git a/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_eitc/match.yaml b/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_eitc/match.yaml new file mode 100644 index 00000000000..b4203e74bb1 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_eitc/match.yaml @@ -0,0 +1,10 @@ +description: New York provides this multiplier of the federal Earned Income Tax Credit for eligible youth workers under the Youth Worker Tax Benefits Act. +metadata: + unit: /1 + period: year + label: NY A04948 youth Earned Income Tax Credit match rate + reference: + - title: NY Assembly Bill 2025-A4948 Section 1 (Section 606(d-2)) + href: https://www.nysenate.gov/legislation/bills/2025/A4948 +values: + 2026-01-01: 1.3 diff --git a/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_eitc/max_age.yaml b/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_eitc/max_age.yaml new file mode 100644 index 00000000000..15a52abaeb7 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_eitc/max_age.yaml @@ -0,0 +1,10 @@ +description: New York sets this maximum age for eligibility under the youth Earned Income Tax Credit. +metadata: + unit: year + period: year + label: NY A04948 youth Earned Income Tax Credit maximum age + reference: + - title: NY Assembly Bill 2025-A4948 Section 1 (Section 606(d-2)) + href: https://www.nysenate.gov/legislation/bills/2025/A4948 +values: + 2026-01-01: 24 diff --git a/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_eitc/min_age.yaml b/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_eitc/min_age.yaml new file mode 100644 index 00000000000..66a1cac26a6 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_eitc/min_age.yaml @@ -0,0 +1,10 @@ +description: New York sets this minimum age for eligibility under the youth Earned Income Tax Credit. +metadata: + unit: year + period: year + label: NY A04948 youth Earned Income Tax Credit minimum age + reference: + - title: NY Assembly Bill 2025-A4948 Section 1 (Section 606(d-2)) + href: https://www.nysenate.gov/legislation/bills/2025/A4948 +values: + 2026-01-01: 17 diff --git a/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_standard_deduction/amount.yaml b/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_standard_deduction/amount.yaml new file mode 100644 index 00000000000..dff6595afd5 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_standard_deduction/amount.yaml @@ -0,0 +1,10 @@ +description: New York provides this amount as the enhanced standard deduction for eligible young adults under the Youth Worker Tax Benefits Act. +metadata: + unit: currency-USD + period: year + label: NY A04948 youth enhanced standard deduction amount + reference: + - title: NY Assembly Bill 2025-A4948 Section 2 (Section 614) + href: https://www.nysenate.gov/legislation/bills/2025/A4948 +values: + 2027-01-01: 10_000 diff --git a/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_standard_deduction/max_age.yaml b/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_standard_deduction/max_age.yaml new file mode 100644 index 00000000000..1a02ccea0d7 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_standard_deduction/max_age.yaml @@ -0,0 +1,10 @@ +description: New York sets this maximum age for eligibility under the youth enhanced standard deduction. +metadata: + unit: year + period: year + label: NY A04948 youth enhanced standard deduction maximum age + reference: + - title: NY Assembly Bill 2025-A4948 Section 2 (Section 614) + href: https://www.nysenate.gov/legislation/bills/2025/A4948 +values: + 2027-01-01: 24 diff --git a/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_standard_deduction/min_age.yaml b/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_standard_deduction/min_age.yaml new file mode 100644 index 00000000000..7ff86aac2aa --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ny/a04948/youth_standard_deduction/min_age.yaml @@ -0,0 +1,10 @@ +description: New York sets this minimum age for eligibility under the youth enhanced standard deduction. +metadata: + unit: year + period: year + label: NY A04948 youth enhanced standard deduction minimum age + reference: + - title: NY Assembly Bill 2025-A4948 Section 2 (Section 614) + href: https://www.nysenate.gov/legislation/bills/2025/A4948 +values: + 2027-01-01: 18 diff --git a/policyengine_us/reforms/reforms.py b/policyengine_us/reforms/reforms.py index e6f0cb4db9d..449fbe7a974 100644 --- a/policyengine_us/reforms/reforms.py +++ b/policyengine_us/reforms/reforms.py @@ -20,6 +20,9 @@ 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.ny.a04948 import ( + create_ny_a04948_youth_worker_tax_benefits_reform, +) from .states.ny.a04038 import create_ny_a04038_enhanced_escc_infants_reform from .states.sc.h3492 import create_sc_h3492_eitc_refundable_reform from .states.ny.s04487 import create_ny_s04487_newborn_credit_reform @@ -181,6 +184,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) + ny_a04948 = create_ny_a04948_youth_worker_tax_benefits_reform( + parameters, period + ) ny_a04038_enhanced_escc_infants = ( create_ny_a04038_enhanced_escc_infants_reform(parameters, period) ) @@ -335,6 +341,7 @@ def create_structural_reforms_from_parameters(parameters, period): capital_gains_tax_increase, halve_joint_eitc_phase_out_rate, ny_wftc, + ny_a04948, ny_a04038_enhanced_escc_infants, sc_h3492_eitc_refundable, ny_s04487_newborn_credit, diff --git a/policyengine_us/reforms/states/ny/a04948/__init__.py b/policyengine_us/reforms/states/ny/a04948/__init__.py new file mode 100644 index 00000000000..72be3e5914c --- /dev/null +++ b/policyengine_us/reforms/states/ny/a04948/__init__.py @@ -0,0 +1,3 @@ +from .ny_a04948_youth_worker_tax_benefits import ( + create_ny_a04948_youth_worker_tax_benefits_reform, +) diff --git a/policyengine_us/reforms/states/ny/a04948/ny_a04948_youth_worker_tax_benefits.py b/policyengine_us/reforms/states/ny/a04948/ny_a04948_youth_worker_tax_benefits.py new file mode 100644 index 00000000000..1101ad843dd --- /dev/null +++ b/policyengine_us/reforms/states/ny/a04948/ny_a04948_youth_worker_tax_benefits.py @@ -0,0 +1,386 @@ +from policyengine_us.model_api import * + + +def create_ny_a04948_youth_worker_tax_benefits() -> Reform: + """ + NY Assembly Bill A04948 - Youth Worker Tax Benefits Act + + Creates three tax benefits for young workers in New York: + 1. Youth EITC: 130% of federal childless EITC for ages 17-24 + 2. Youth Standard Deduction: $10,000 for single filers ages 18-24 + 3. Student Loan Interest Deduction: Federal IRC 221 deduction for NY + + Reference: https://www.nysenate.gov/legislation/bills/2025/A4948 + """ + + class ny_a04948_youth_eitc_eligible(Variable): + value_type = bool + entity = Person + label = "Eligible for NY A04948 youth EITC" + definition_period = YEAR + reference = "https://www.nysenate.gov/legislation/bills/2025/A4948" + defined_for = StateCode.NY + + def formula(person, period, parameters): + p = parameters(period).gov.contrib.states.ny.a04948 + # Reform must be in effect + in_effect = p.in_effect + # Age requirements: 17-24 + age = person("age", period) + age_eligible = (age >= p.youth_eitc.min_age) & ( + age <= p.youth_eitc.max_age + ) + # Cannot be claimed as dependent + not_dependent = ~person("is_tax_unit_dependent", period) + # Cannot be a parent (no qualifying children) + tax_unit = person.tax_unit + has_qualifying_children = tax_unit("eitc_child_count", period) > 0 + is_head_or_spouse = person("is_tax_unit_head_or_spouse", period) + not_parent = ~(is_head_or_spouse & has_qualifying_children) + return in_effect & age_eligible & not_dependent & not_parent + + class ny_a04948_youth_eitc_childless_maximum(Variable): + value_type = float + entity = TaxUnit + label = "NY A04948 youth EITC childless maximum amount" + unit = USD + definition_period = YEAR + reference = "https://www.law.cornell.edu/uscode/text/26/32#a" + + def formula(tax_unit, period, parameters): + # Calculate federal childless EITC maximum (0 children) + eitc = parameters(period).gov.irs.credits.eitc + return eitc.max.calc(0) + + class ny_a04948_youth_eitc_phase_in_rate(Variable): + value_type = float + entity = TaxUnit + label = "NY A04948 youth EITC phase-in rate" + unit = "/1" + definition_period = YEAR + + def formula(tax_unit, period, parameters): + eitc = parameters(period).gov.irs.credits.eitc + return eitc.phase_in_rate.calc(0) + + class ny_a04948_youth_eitc_phased_in(Variable): + value_type = float + entity = TaxUnit + label = "NY A04948 youth EITC phased-in amount" + unit = USD + definition_period = YEAR + + def formula(tax_unit, period, parameters): + maximum = tax_unit( + "ny_a04948_youth_eitc_childless_maximum", period + ) + phase_in_rate = tax_unit( + "ny_a04948_youth_eitc_phase_in_rate", period + ) + earnings = tax_unit("filer_adjusted_earnings", period) + phased_in_amount = earnings * phase_in_rate + return min_(maximum, phased_in_amount) + + class ny_a04948_youth_eitc_phase_out_start(Variable): + value_type = float + entity = TaxUnit + label = "NY A04948 youth EITC phase-out start" + unit = USD + definition_period = YEAR + + def formula(tax_unit, period, parameters): + eitc = parameters(period).gov.irs.credits.eitc + is_joint = tax_unit("tax_unit_is_joint", period) + joint_bonus = eitc.phase_out.joint_bonus.calc(0) + phase_out_start = eitc.phase_out.start.calc(0) + return phase_out_start + is_joint * joint_bonus + + class ny_a04948_youth_eitc_phase_out_rate(Variable): + value_type = float + entity = TaxUnit + label = "NY A04948 youth EITC phase-out rate" + unit = "/1" + definition_period = YEAR + + def formula(tax_unit, period, parameters): + eitc = parameters(period).gov.irs.credits.eitc + return eitc.phase_out.rate.calc(0) + + class ny_a04948_youth_eitc_reduction(Variable): + value_type = float + entity = TaxUnit + label = "NY A04948 youth EITC reduction" + unit = USD + definition_period = YEAR + + def formula(tax_unit, period, parameters): + earnings = tax_unit("filer_adjusted_earnings", period) + agi = tax_unit("adjusted_gross_income", period) + highest_income = max_(earnings, agi) + phase_out_start = tax_unit( + "ny_a04948_youth_eitc_phase_out_start", period + ) + phase_out_rate = tax_unit( + "ny_a04948_youth_eitc_phase_out_rate", period + ) + phase_out_region = max_(0, highest_income - phase_out_start) + return phase_out_rate * phase_out_region + + class ny_a04948_youth_eitc_federal_amount(Variable): + value_type = float + entity = TaxUnit + label = "NY A04948 federal childless EITC amount" + unit = USD + definition_period = YEAR + reference = "https://www.law.cornell.edu/uscode/text/26/32#a" + + def formula(tax_unit, period, parameters): + # Calculate federal childless EITC (as if 0 qualifying children) + maximum = tax_unit( + "ny_a04948_youth_eitc_childless_maximum", period + ) + phased_in = tax_unit("ny_a04948_youth_eitc_phased_in", period) + reduction = tax_unit("ny_a04948_youth_eitc_reduction", period) + limitation = max_(0, maximum - reduction) + return min_(phased_in, limitation) + + class ny_a04948_youth_eitc(Variable): + value_type = float + entity = TaxUnit + label = "NY A04948 youth earned income tax credit" + unit = USD + definition_period = YEAR + reference = ( + "https://www.nysenate.gov/legislation/bills/2025/A4948", + "https://www.nysenate.gov/legislation/laws/TAX/606", + ) + defined_for = StateCode.NY + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.contrib.states.ny.a04948 + # Check if reform is in effect + in_effect = p.in_effect + # Check if any member is eligible for the youth EITC + person = tax_unit.members + eligible = person("ny_a04948_youth_eitc_eligible", period) + any_eligible = tax_unit.any(eligible) + # Calculate 130% of federal childless EITC + federal_childless_eitc = tax_unit( + "ny_a04948_youth_eitc_federal_amount", period + ) + youth_eitc_amount = federal_childless_eitc * p.youth_eitc.match + return where(in_effect & any_eligible, youth_eitc_amount, 0) + + class ny_a04948_youth_standard_deduction_eligible(Variable): + value_type = bool + entity = Person + label = "Eligible for NY A04948 youth enhanced standard deduction" + definition_period = YEAR + reference = ( + "https://www.nysenate.gov/legislation/bills/2025/A4948", + "https://www.nysenate.gov/legislation/laws/TAX/614", + ) + defined_for = StateCode.NY + + def formula(person, period, parameters): + p = parameters(period).gov.contrib.states.ny.a04948 + # Reform must be in effect + in_effect = p.in_effect + # Check if youth standard deduction parameters are defined + # (effective 2027) + youth_std_ded = p.youth_standard_deduction + min_age = youth_std_ded.min_age + max_age = youth_std_ded.max_age + # Age requirements: 18-24 + age = person("age", period) + age_eligible = (age >= min_age) & (age <= max_age) + # Cannot be claimed as dependent + not_dependent = ~person("is_tax_unit_dependent", period) + # Filing status: must be Single + filing_status = person.tax_unit("filing_status", period) + is_single = filing_status == filing_status.possible_values.SINGLE + # Must be the filer + is_filer = person("is_tax_unit_head_or_spouse", period) + return ( + in_effect & age_eligible & not_dependent & is_single & is_filer + ) + + class ny_a04948_youth_standard_deduction(Variable): + value_type = float + entity = TaxUnit + label = "NY A04948 youth enhanced standard deduction" + unit = USD + definition_period = YEAR + reference = ( + "https://www.nysenate.gov/legislation/bills/2025/A4948", + "https://www.nysenate.gov/legislation/laws/TAX/614", + ) + defined_for = StateCode.NY + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.contrib.states.ny.a04948 + # Check if reform is in effect + in_effect = p.in_effect + # Check if filer is eligible + person = tax_unit.members + eligible = person( + "ny_a04948_youth_standard_deduction_eligible", period + ) + filer_eligible = tax_unit.any(eligible) + enhanced_deduction = p.youth_standard_deduction.amount + return where(in_effect & filer_eligible, enhanced_deduction, 0) + + class ny_standard_deduction(Variable): + value_type = float + entity = TaxUnit + label = "NY standard deduction" + unit = USD + definition_period = YEAR + reference = "https://www.nysenate.gov/legislation/laws/TAX/614" + defined_for = StateCode.NY + + def formula(tax_unit, period, parameters): + # Get standard NY standard deduction based on filing status + filing_status = tax_unit("filing_status", period) + p = parameters(period).gov.states.ny.tax.income.deductions + standard = p.standard.amount[filing_status] + # Check for youth enhanced standard deduction + youth_deduction = tax_unit( + "ny_a04948_youth_standard_deduction", period + ) + # Use the greater of standard or youth enhanced deduction + return max_(standard, youth_deduction) + + class ny_a04948_student_loan_interest_deduction(Variable): + value_type = float + entity = TaxUnit + label = "NY A04948 student loan interest deduction" + unit = USD + definition_period = YEAR + reference = ( + "https://www.nysenate.gov/legislation/bills/2025/A4948", + "https://www.nysenate.gov/legislation/laws/TAX/615", + "https://www.law.cornell.edu/uscode/text/26/221", + ) + defined_for = StateCode.NY + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.contrib.states.ny.a04948 + # Check if reform is in effect + in_effect = p.in_effect + # Get student loan interest from all members + person = tax_unit.members + interest = person("student_loan_interest", period) + total_interest = tax_unit.sum(interest) + # Apply federal cap per IRC 221 + p_fed = parameters(period).gov.irs.ald.student_loan_interest + filing_status = tax_unit("filing_status", period) + cap = p_fed.cap[filing_status] + capped_interest = min_(total_interest, cap) + # Cannot be married filing separately + separate = filing_status == filing_status.possible_values.SEPARATE + # Cannot be claimed as dependent + head_is_dependent = tax_unit("head_is_dependent_elsewhere", period) + eligible = ~separate & ~head_is_dependent + # Apply phaseout based on MAGI + agi = tax_unit("adjusted_gross_income", period) + reduction_start = p_fed.reduction.start[filing_status] + income_excess = max_(0, agi - reduction_start) + divisor = p_fed.reduction.divisor[filing_status] + reduction_rate = where(divisor > 0, income_excess / divisor, 0) + reduction_rate = min_(reduction_rate, 1) # Cap at 100% + reduction_amount = capped_interest * reduction_rate + deduction = max_(capped_interest - reduction_amount, 0) + return where(in_effect & eligible, deduction, 0) + + class ny_agi(Variable): + value_type = float + entity = TaxUnit + label = "NY adjusted gross income" + unit = USD + definition_period = YEAR + reference = "https://www.nysenate.gov/legislation/laws/TAX/612" + defined_for = StateCode.NY + + def formula(tax_unit, period, parameters): + # Start with federal AGI + agi = tax_unit("adjusted_gross_income", period) + # Add NY additions + additions = add( + tax_unit, + period, + [ + "ny_agi_additions", + ], + ) + # Subtract NY subtractions + subtractions = add( + tax_unit, + period, + [ + "ny_agi_subtractions", + ], + ) + # Subtract student loan interest deduction (A04948) + student_loan_deduction = tax_unit( + "ny_a04948_student_loan_interest_deduction", period + ) + return agi + additions - subtractions - student_loan_deduction + + class ny_refundable_credits(Variable): + value_type = float + entity = TaxUnit + label = "NY refundable credits" + unit = USD + definition_period = YEAR + defined_for = StateCode.NY + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.ny.tax.income.credits + standard_credits = add(tax_unit, period, p.refundable) + # Add youth EITC from A04948 + youth_eitc = tax_unit("ny_a04948_youth_eitc", period) + return standard_credits + youth_eitc + + class reform(Reform): + def apply(self): + # Youth EITC variables + self.update_variable(ny_a04948_youth_eitc_eligible) + self.update_variable(ny_a04948_youth_eitc_childless_maximum) + self.update_variable(ny_a04948_youth_eitc_phase_in_rate) + self.update_variable(ny_a04948_youth_eitc_phased_in) + self.update_variable(ny_a04948_youth_eitc_phase_out_start) + self.update_variable(ny_a04948_youth_eitc_phase_out_rate) + self.update_variable(ny_a04948_youth_eitc_reduction) + self.update_variable(ny_a04948_youth_eitc_federal_amount) + self.update_variable(ny_a04948_youth_eitc) + # Youth standard deduction variables + self.update_variable(ny_a04948_youth_standard_deduction_eligible) + self.update_variable(ny_a04948_youth_standard_deduction) + self.update_variable(ny_standard_deduction) + # Student loan interest deduction + self.update_variable(ny_a04948_student_loan_interest_deduction) + self.update_variable(ny_agi) + # Update refundable credits to include youth EITC + self.update_variable(ny_refundable_credits) + + return reform + + +def create_ny_a04948_youth_worker_tax_benefits_reform( + parameters, period, bypass: bool = False +): + if bypass: + return create_ny_a04948_youth_worker_tax_benefits() + + p = parameters(period).gov.contrib.states.ny.a04948 + + if p.in_effect: + return create_ny_a04948_youth_worker_tax_benefits() + else: + return None + + +ny_a04948_youth_worker_tax_benefits = ( + create_ny_a04948_youth_worker_tax_benefits_reform(None, None, bypass=True) +) diff --git a/policyengine_us/tests/policy/contrib/states/ny/a04948/ny_a04948_youth_worker_tax_benefits.yaml b/policyengine_us/tests/policy/contrib/states/ny/a04948/ny_a04948_youth_worker_tax_benefits.yaml new file mode 100644 index 00000000000..8e8d689d645 --- /dev/null +++ b/policyengine_us/tests/policy/contrib/states/ny/a04948/ny_a04948_youth_worker_tax_benefits.yaml @@ -0,0 +1,574 @@ +# NY A04948 Youth Worker Tax Benefits Tests +# Tests the interaction of all three reform components: +# 1. Youth EITC (ages 17-24, 130% of federal childless EITC) +# 2. Youth Standard Deduction ($10,000 for ages 18-24 single filers) +# 3. Student Loan Interest Deduction (up to $2,500 per IRC 221) + +# Youth EITC eligibility tests +- name: Youth EITC - age 17 single non-dependent without children is eligible + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 17 + is_tax_unit_head: true + is_tax_unit_dependent: false + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_eitc_eligible: [true] + +- name: Youth EITC - age 20 single non-dependent without children is eligible + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 20 + is_tax_unit_head: true + is_tax_unit_dependent: false + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_eitc_eligible: [true] + +- name: Youth EITC - age 24 single non-dependent without children is eligible + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 24 + is_tax_unit_head: true + is_tax_unit_dependent: false + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_eitc_eligible: [true] + +- name: Youth EITC - age 25 not eligible, too old + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 25 + is_tax_unit_head: true + is_tax_unit_dependent: false + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_eitc_eligible: [false] + +- name: Youth EITC - age 16 not eligible, too young + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 16 + is_tax_unit_head: true + is_tax_unit_dependent: false + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_eitc_eligible: [false] + +- name: Youth EITC - age 20 claimed as dependent not eligible + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 20 + is_tax_unit_head: true + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_eitc_eligible: [false] + +# Youth EITC amount tests +- name: Youth EITC amount - eligible youth with no earned income gets zero + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 20 + is_tax_unit_head: true + is_tax_unit_dependent: false + employment_income: 0 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_eitc: 0 + +- name: Youth EITC amount - eligible youth with $5k earned income in phase-in + period: 2027 + absolute_error_margin: 10 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 20 + is_tax_unit_head: true + is_tax_unit_dependent: false + employment_income: 5_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NY + output: + # Phase-in: $5,000 * 7.65% = $382.50 federal + # Youth credit: $382.50 * 1.3 = $497.25 + ny_a04948_youth_eitc: 497 + +- name: Youth EITC amount - ineligible age 25 gets zero + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 25 + is_tax_unit_head: true + is_tax_unit_dependent: false + employment_income: 15_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_eitc: 0 + +- name: Youth EITC amount - age 17 with $3k earned income + period: 2027 + absolute_error_margin: 10 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 17 + is_tax_unit_head: true + is_tax_unit_dependent: false + employment_income: 3_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NY + output: + # Phase-in: $3,000 * 7.65% = $229.50 federal + # Youth credit: $229.50 * 1.3 = $298.35 + ny_a04948_youth_eitc: 298 + +- name: Youth EITC amount - age 24 with $10k earned income at max + period: 2027 + absolute_error_margin: 20 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 24 + is_tax_unit_head: true + is_tax_unit_dependent: false + employment_income: 10_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: NY + output: + # At maximum federal childless EITC ($10,000 * 7.65% = $765 exceeds max) + # Federal max $677 * 1.3 = $880.10 + ny_a04948_youth_eitc: 880 + +# Youth Standard Deduction eligibility tests +- name: Youth Standard Deduction - age 20 single non-dependent is eligible + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 20 + is_tax_unit_head: true + is_tax_unit_dependent: false + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_standard_deduction_eligible: true + ny_a04948_youth_standard_deduction: 10_000 + ny_standard_deduction: 10_000 + +- name: Youth Standard Deduction - age 17 not eligible, too young + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 17 + is_tax_unit_head: true + is_tax_unit_dependent: false + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_standard_deduction_eligible: false + ny_a04948_youth_standard_deduction: 0 + +- name: Youth Standard Deduction - age 25 not eligible, too old + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 25 + is_tax_unit_head: true + is_tax_unit_dependent: false + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_standard_deduction_eligible: false + ny_a04948_youth_standard_deduction: 0 + +- name: Youth Standard Deduction - married filing jointly not eligible + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 22 + is_tax_unit_head: true + is_tax_unit_dependent: false + person2: + age: 25 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + households: + household: + members: [person1, person2] + state_code: NY + output: + ny_a04948_youth_standard_deduction_eligible: false + ny_a04948_youth_standard_deduction: 0 + +- name: Youth Standard Deduction - head of household not eligible + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 22 + is_tax_unit_head: true + is_tax_unit_dependent: false + tax_units: + tax_unit: + members: [person1] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_standard_deduction_eligible: false + ny_a04948_youth_standard_deduction: 0 + +# Student Loan Interest Deduction tests +- name: Student Loan Interest - NY resident with $2,000 interest + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 28 + is_tax_unit_head: true + is_tax_unit_dependent: false + student_loan_interest: 2_000 + employment_income: 50_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: NY + output: + # Full $2,000 deduction (below cap, below phaseout) + ny_a04948_student_loan_interest_deduction: 2_000 + +- name: Student Loan Interest - $3,000 interest capped at $2,500 + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 28 + is_tax_unit_head: true + is_tax_unit_dependent: false + student_loan_interest: 3_000 + employment_income: 50_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: NY + output: + # Capped at $2,500 maximum + ny_a04948_student_loan_interest_deduction: 2_500 + +- name: Student Loan Interest - no interest + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 28 + is_tax_unit_head: true + is_tax_unit_dependent: false + student_loan_interest: 0 + employment_income: 50_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_student_loan_interest_deduction: 0 + +# Integration tests +- name: Integration - age 20 gets youth EITC and enhanced standard deduction + period: 2027 + absolute_error_margin: 20 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 20 + is_tax_unit_head: true + is_tax_unit_dependent: false + employment_income: 15_000 + student_loan_interest: 1_500 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_eitc_eligible: [true] + ny_a04948_youth_standard_deduction_eligible: true + ny_a04948_youth_standard_deduction: 10_000 + ny_standard_deduction: 10_000 + ny_a04948_student_loan_interest_deduction: 1_500 + # Youth EITC based on $15,000 income in phaseout + # Federal childless max $677 (2027), phase-out start $11,070 + # Phased-in: $15,000 * 7.65% = $1,147.50 + # Phase-out reduction: ($15,000 - $11,070) * 7.65% = $300.645 + # Limitation: $677 - $300.645 = $376.355 + # Federal EITC: min($1,147.50, $376.355) = $376.355 + # Youth EITC: $376.355 * 1.3 = $489.26 + ny_a04948_youth_eitc: 489 + +- name: Integration - age 17 gets youth EITC but NOT standard deduction + period: 2027 + absolute_error_margin: 15 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 17 + is_tax_unit_head: true + is_tax_unit_dependent: false + employment_income: 8_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_eitc_eligible: [true] + ny_a04948_youth_standard_deduction_eligible: false + ny_a04948_youth_standard_deduction: 0 + # Youth EITC: $8,000 * 7.65% = $612.00 federal * 1.3 = $795.60 + ny_a04948_youth_eitc: 796 + +- name: Integration - age 25 gets student loan deduction only + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 25 + is_tax_unit_head: true + is_tax_unit_dependent: false + employment_income: 50_000 + student_loan_interest: 2_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: NY + output: + ny_a04948_youth_eitc_eligible: [false] + ny_a04948_youth_eitc: 0 + ny_a04948_youth_standard_deduction_eligible: false + ny_a04948_youth_standard_deduction: 0 + ny_a04948_student_loan_interest_deduction: 2_000 + +- name: Integration - age 20 parent not eligible for youth EITC + period: 2027 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: true + people: + person1: + age: 20 + is_tax_unit_head: true + is_tax_unit_dependent: false + employment_income: 25_000 + student_loan_interest: 1_000 + person2: + age: 2 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + filing_status: HEAD_OF_HOUSEHOLD + households: + household: + members: [person1, person2] + state_code: NY + output: + ny_a04948_youth_eitc_eligible: [false, false] + ny_a04948_youth_eitc: 0 + ny_a04948_youth_standard_deduction_eligible: false + ny_a04948_youth_standard_deduction: 0 + ny_a04948_student_loan_interest_deduction: 1_000 + +- name: No reform applied before 2026 + period: 2025 + reforms: policyengine_us.reforms.states.ny.a04948.ny_a04948_youth_worker_tax_benefits.ny_a04948_youth_worker_tax_benefits + input: + gov.contrib.states.ny.a04948.in_effect: false + people: + person1: + age: 20 + is_tax_unit_head: true + is_tax_unit_dependent: false + employment_income: 15_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: NY + output: + # Reform not in effect, should be zero + ny_a04948_youth_eitc: 0 + ny_a04948_youth_standard_deduction: 0 + ny_a04948_student_loan_interest_deduction: 0