From 954466727d4251940ffe4c60c0923b488b1852c5 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 2 Mar 2026 16:52:27 -0500 Subject: [PATCH] Add 529 plan contribution deductions/credits for 7 states Implement 529 plan tax benefits for OK, OR, PA, UT, VA, VT, and WI. SC and WV already had full (uncapped) deductions via investment_in_529_plan. - OK: AGI subtraction, $10K single / $20K joint cap - OR: Refundable tax credit, $180 single / $360 joint (2025) - PA: Deduction, $19K per beneficiary (tied to gift tax exclusion) - UT: Non-refundable credit, 4.55% of contributions up to cap per beneficiary - VA: Subtraction with $4K cap per account (was previously uncapped) - VT: Non-refundable credit, 10% of first $2,500/$5,000 - WI: Subtraction, $5,130 per beneficiary ($2,560 MFS) in 2025 Co-Authored-By: Claude Opus 4.6 --- changelog.d/529-batch-3.added.md | 1 + .../income/agi/subtractions/plan_529/cap.yaml | 23 ++++++++ .../income/agi/subtractions/subtractions.yaml | 1 + .../income/credits/plan_529/max_credit.yaml | 33 +++++++++++ .../or/tax/income/credits/refundable.yaml | 7 +++ .../tax/income/deductions/plan_529/cap.yaml | 18 ++++++ .../ut/tax/income/credits/non_refundable.yaml | 2 + .../ut/tax/income/credits/plan_529/cap.yaml | 40 +++++++++++++ .../ut/tax/income/credits/plan_529/rate.yaml | 15 +++++ .../tax/income/subtractions/plan_529/cap.yaml | 17 ++++++ .../tax/income/subtractions/subtractions.yaml | 2 +- .../vt/tax/income/credits/non_refundable.yaml | 1 + .../vt/tax/income/credits/plan_529/cap.yaml | 25 +++++++++ .../vt/tax/income/credits/plan_529/rate.yaml | 12 ++++ .../tax/income/subtractions/plan_529/cap.yaml | 40 +++++++++++++ .../wi/tax/income/subtractions/sources.yaml | 2 + .../ok/tax/income/ok_529_plan_deduction.yaml | 44 +++++++++++++++ .../or/tax/income/credits/or_529_credit.yaml | 44 +++++++++++++++ .../deductions/pa_529_plan_deduction.yaml | 43 ++++++++++++++ .../income/credits/ut_529_plan_credit.yaml | 53 ++++++++++++++++++ .../subtractions/va_529_plan_deduction.yaml | 43 ++++++++++++++ .../income/credits/vt_529_plan_credit.yaml | 48 ++++++++++++++++ .../subtractions/wi_529_plan_deduction.yaml | 56 +++++++++++++++++++ .../ok/tax/income/ok_529_plan_deduction.py | 23 ++++++++ .../or/tax/income/credits/or_529_credit.py | 21 +++++++ .../deductions/pa_529_plan_deduction.py | 25 +++++++++ .../income/deductions/pa_tax_deductions.py | 3 + .../tax/income/credits/ut_529_plan_credit.py | 27 +++++++++ .../subtractions/va_529_plan_deduction.py | 25 +++++++++ .../tax/income/credits/vt_529_plan_credit.py | 22 ++++++++ .../tax/income/vt_non_refundable_credits.py | 2 + .../subtractions/wi_529_plan_deduction.py | 26 +++++++++ 32 files changed, 743 insertions(+), 1 deletion(-) create mode 100644 changelog.d/529-batch-3.added.md create mode 100644 policyengine_us/parameters/gov/states/ok/tax/income/agi/subtractions/plan_529/cap.yaml create mode 100644 policyengine_us/parameters/gov/states/or/tax/income/credits/plan_529/max_credit.yaml create mode 100644 policyengine_us/parameters/gov/states/pa/tax/income/deductions/plan_529/cap.yaml create mode 100644 policyengine_us/parameters/gov/states/ut/tax/income/credits/plan_529/cap.yaml create mode 100644 policyengine_us/parameters/gov/states/ut/tax/income/credits/plan_529/rate.yaml create mode 100644 policyengine_us/parameters/gov/states/va/tax/income/subtractions/plan_529/cap.yaml create mode 100644 policyengine_us/parameters/gov/states/vt/tax/income/credits/plan_529/cap.yaml create mode 100644 policyengine_us/parameters/gov/states/vt/tax/income/credits/plan_529/rate.yaml create mode 100644 policyengine_us/parameters/gov/states/wi/tax/income/subtractions/plan_529/cap.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ok/tax/income/ok_529_plan_deduction.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/or/tax/income/credits/or_529_credit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/deductions/pa_529_plan_deduction.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/ut_529_plan_credit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/va/tax/income/subtractions/va_529_plan_deduction.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/credits/vt_529_plan_credit.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/subtractions/wi_529_plan_deduction.yaml create mode 100644 policyengine_us/variables/gov/states/ok/tax/income/ok_529_plan_deduction.py create mode 100644 policyengine_us/variables/gov/states/or/tax/income/credits/or_529_credit.py create mode 100644 policyengine_us/variables/gov/states/pa/tax/income/deductions/pa_529_plan_deduction.py create mode 100644 policyengine_us/variables/gov/states/ut/tax/income/credits/ut_529_plan_credit.py create mode 100644 policyengine_us/variables/gov/states/va/tax/income/subtractions/va_529_plan_deduction.py create mode 100644 policyengine_us/variables/gov/states/vt/tax/income/credits/vt_529_plan_credit.py create mode 100644 policyengine_us/variables/gov/states/wi/tax/income/subtractions/wi_529_plan_deduction.py diff --git a/changelog.d/529-batch-3.added.md b/changelog.d/529-batch-3.added.md new file mode 100644 index 00000000000..a5bf6b41381 --- /dev/null +++ b/changelog.d/529-batch-3.added.md @@ -0,0 +1 @@ +Add 529 plan contribution deductions/credits for Oklahoma, Oregon, Pennsylvania, Utah, Virginia, Vermont, and Wisconsin. diff --git a/policyengine_us/parameters/gov/states/ok/tax/income/agi/subtractions/plan_529/cap.yaml b/policyengine_us/parameters/gov/states/ok/tax/income/agi/subtractions/plan_529/cap.yaml new file mode 100644 index 00000000000..d5650f85e6c --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/tax/income/agi/subtractions/plan_529/cap.yaml @@ -0,0 +1,23 @@ +description: Oklahoma caps the 529 plan contributions deduction at this amount. +metadata: + label: Oklahoma 529 plan contribution deduction cap + period: year + unit: currency-USD + breakdown: + - filing_status + reference: + - title: Oklahoma 529 Plan FAQ + href: https://www.oklahoma529.com/resources/faq/ + - title: 2024 Oklahoma Form 511 Instructions + href: https://oklahoma.gov/content/dam/ok/en/tax/documents/forms/individuals/current/511-Pkt.pdf#page=16 + +JOINT: + 2021-01-01: 20_000 +SURVIVING_SPOUSE: + 2021-01-01: 20_000 +SINGLE: + 2021-01-01: 10_000 +HEAD_OF_HOUSEHOLD: + 2021-01-01: 10_000 +SEPARATE: + 2021-01-01: 10_000 diff --git a/policyengine_us/parameters/gov/states/ok/tax/income/agi/subtractions/subtractions.yaml b/policyengine_us/parameters/gov/states/ok/tax/income/agi/subtractions/subtractions.yaml index a28a8d91956..beb97fef8a4 100644 --- a/policyengine_us/parameters/gov/states/ok/tax/income/agi/subtractions/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/ok/tax/income/agi/subtractions/subtractions.yaml @@ -5,6 +5,7 @@ values: - taxable_social_security - ok_pension_subtraction - ok_military_retirement_exclusion + - ok_529_plan_deduction metadata: unit: list diff --git a/policyengine_us/parameters/gov/states/or/tax/income/credits/plan_529/max_credit.yaml b/policyengine_us/parameters/gov/states/or/tax/income/credits/plan_529/max_credit.yaml new file mode 100644 index 00000000000..4162c26640d --- /dev/null +++ b/policyengine_us/parameters/gov/states/or/tax/income/credits/plan_529/max_credit.yaml @@ -0,0 +1,33 @@ +description: Oregon caps the 529 plan contribution tax credit at this amount. +metadata: + label: Oregon 529 plan contribution credit maximum + period: year + unit: currency-USD + breakdown: + - filing_status + reference: + - title: Oregon Department of Revenue - Tax benefits for families + href: https://www.oregon.gov/dor/programs/individuals/pages/credits.aspx + - title: ORS 315.643 + href: https://oregon.public.law/statutes/ors_315.643 + +JOINT: + 2020-01-01: 300 + 2025-01-01: 360 + 2026-01-01: 380 +SURVIVING_SPOUSE: + 2020-01-01: 300 + 2025-01-01: 360 + 2026-01-01: 380 +SINGLE: + 2020-01-01: 150 + 2025-01-01: 180 + 2026-01-01: 190 +HEAD_OF_HOUSEHOLD: + 2020-01-01: 150 + 2025-01-01: 180 + 2026-01-01: 190 +SEPARATE: + 2020-01-01: 150 + 2025-01-01: 180 + 2026-01-01: 190 diff --git a/policyengine_us/parameters/gov/states/or/tax/income/credits/refundable.yaml b/policyengine_us/parameters/gov/states/or/tax/income/credits/refundable.yaml index a1f4302c189..57dcf1d4fbc 100644 --- a/policyengine_us/parameters/gov/states/or/tax/income/credits/refundable.yaml +++ b/policyengine_us/parameters/gov/states/or/tax/income/credits/refundable.yaml @@ -4,15 +4,22 @@ values: - or_eitc - or_kicker - or_working_family_household_and_dependent_care_credit + 2020-01-01: + - or_eitc + - or_kicker + - or_529_credit + - or_working_family_household_and_dependent_care_credit 2023-01-01: - or_eitc - or_kicker - or_ctc + - or_529_credit - or_working_family_household_and_dependent_care_credit # Child Tax Credit legislation ends in 2029. 2029-01-01: - or_eitc - or_kicker + - or_529_credit - or_working_family_household_and_dependent_care_credit metadata: unit: list diff --git a/policyengine_us/parameters/gov/states/pa/tax/income/deductions/plan_529/cap.yaml b/policyengine_us/parameters/gov/states/pa/tax/income/deductions/plan_529/cap.yaml new file mode 100644 index 00000000000..90c273e06e8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/pa/tax/income/deductions/plan_529/cap.yaml @@ -0,0 +1,18 @@ +description: > + Pennsylvania caps the 529 plan contributions deduction per beneficiary + at this amount, which is tied to the federal annual gift tax exclusion. +values: + 2021-01-01: 15_000 + 2022-01-01: 16_000 + 2023-01-01: 17_000 + 2024-01-01: 18_000 + 2025-01-01: 19_000 +metadata: + unit: currency-USD + period: year + label: Pennsylvania 529 plan contribution deduction cap per beneficiary + reference: + - title: PA Revenue - What is the limit on a deduction to a 529 plan? + href: https://revenue-pa.custhelp.com/app/answers/detail/a_id/2208/~/what-is-the-limit-on-a-deduction-to-a-529-plan + - title: PA 529 Plan FAQs + href: https://www.pa529.com/faqs/ diff --git a/policyengine_us/parameters/gov/states/ut/tax/income/credits/non_refundable.yaml b/policyengine_us/parameters/gov/states/ut/tax/income/credits/non_refundable.yaml index c967b951149..cc8084f7419 100644 --- a/policyengine_us/parameters/gov/states/ut/tax/income/credits/non_refundable.yaml +++ b/policyengine_us/parameters/gov/states/ut/tax/income/credits/non_refundable.yaml @@ -33,6 +33,7 @@ values: - ut_retirement_credit - ut_ss_benefits_credit - ut_at_home_parent_credit + - ut_529_plan_credit 2024-01-01: - ut_eitc @@ -41,3 +42,4 @@ values: - ut_at_home_parent_credit - ut_ctc - ut_military_retirement_credit + - ut_529_plan_credit diff --git a/policyengine_us/parameters/gov/states/ut/tax/income/credits/plan_529/cap.yaml b/policyengine_us/parameters/gov/states/ut/tax/income/credits/plan_529/cap.yaml new file mode 100644 index 00000000000..d6cc11b72d6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ut/tax/income/credits/plan_529/cap.yaml @@ -0,0 +1,40 @@ +description: > + Utah caps the 529 plan contribution amount eligible for the state tax + credit at this amount per beneficiary. +metadata: + label: Utah 529 plan contribution credit cap per beneficiary + period: year + unit: currency-USD + breakdown: + - filing_status + reference: + - title: Utah state tax benefits information - my529 + href: https://my529.org/utah-state-tax-benefits-information/ + - title: TC-40A Supplemental Schedule Instructions - my529 + href: https://incometax.utah.gov/credits/my529 + +JOINT: + 2022-01-01: 4_260 + 2023-01-01: 4_580 + 2024-01-01: 4_820 + 2025-01-01: 4_980 +SURVIVING_SPOUSE: + 2022-01-01: 4_260 + 2023-01-01: 4_580 + 2024-01-01: 4_820 + 2025-01-01: 4_980 +SINGLE: + 2022-01-01: 2_130 + 2023-01-01: 2_290 + 2024-01-01: 2_410 + 2025-01-01: 2_490 +HEAD_OF_HOUSEHOLD: + 2022-01-01: 2_130 + 2023-01-01: 2_290 + 2024-01-01: 2_410 + 2025-01-01: 2_490 +SEPARATE: + 2022-01-01: 2_130 + 2023-01-01: 2_290 + 2024-01-01: 2_410 + 2025-01-01: 2_490 diff --git a/policyengine_us/parameters/gov/states/ut/tax/income/credits/plan_529/rate.yaml b/policyengine_us/parameters/gov/states/ut/tax/income/credits/plan_529/rate.yaml new file mode 100644 index 00000000000..d45d8645e11 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ut/tax/income/credits/plan_529/rate.yaml @@ -0,0 +1,15 @@ +description: Utah applies this tax credit rate to eligible 529 plan contributions. +values: + 2022-01-01: 0.0485 + 2023-01-01: 0.0465 + 2024-01-01: 0.0455 + 2025-01-01: 0.045 +metadata: + unit: /1 + period: year + label: Utah 529 plan contribution credit rate + reference: + - title: Utah state tax benefits information - my529 + href: https://my529.org/utah-state-tax-benefits-information/ + - title: TC-40A Supplemental Schedule Instructions - my529 + href: https://incometax.utah.gov/credits/my529 diff --git a/policyengine_us/parameters/gov/states/va/tax/income/subtractions/plan_529/cap.yaml b/policyengine_us/parameters/gov/states/va/tax/income/subtractions/plan_529/cap.yaml new file mode 100644 index 00000000000..e28c0885689 --- /dev/null +++ b/policyengine_us/parameters/gov/states/va/tax/income/subtractions/plan_529/cap.yaml @@ -0,0 +1,17 @@ +description: > + Virginia caps the 529 plan contributions deduction at this amount per + account per year. Taxpayers age 70 and over may deduct the entire + amount contributed. +values: + 2021-01-01: 4_000 +metadata: + unit: currency-USD + period: year + label: Virginia 529 plan contribution deduction cap per account + reference: + - title: Virginia Tax - Deductions + href: https://www.tax.virginia.gov/deductions + - title: Code of Virginia 58.1-322.02 + href: https://law.lis.virginia.gov/vacodefull/title58.1/chapter3/article2/ + - title: 2024 Form 760 Instructions - Subtractions, Certification Number 34 + href: https://www.tax.virginia.gov/sites/default/files/vatax-pdf/2024-760-instructions.pdf#page=24 diff --git a/policyengine_us/parameters/gov/states/va/tax/income/subtractions/subtractions.yaml b/policyengine_us/parameters/gov/states/va/tax/income/subtractions/subtractions.yaml index 87da1b28c23..82f8bf354b4 100644 --- a/policyengine_us/parameters/gov/states/va/tax/income/subtractions/subtractions.yaml +++ b/policyengine_us/parameters/gov/states/va/tax/income/subtractions/subtractions.yaml @@ -9,7 +9,7 @@ values: - unemployment_compensation # Certification Number 37 - va_federal_state_employees_subtraction # Certification Number 39 - va_military_benefit_subtraction # Certification Number 60 - - investment_in_529_plan # Certification Number 34 + - va_529_plan_deduction # Certification Number 34 - va_age_deduction # Certification Number 4 - taxable_social_security # Certification Number 5 diff --git a/policyengine_us/parameters/gov/states/vt/tax/income/credits/non_refundable.yaml b/policyengine_us/parameters/gov/states/vt/tax/income/credits/non_refundable.yaml index f3123e74258..28aef5c93f3 100644 --- a/policyengine_us/parameters/gov/states/vt/tax/income/credits/non_refundable.yaml +++ b/policyengine_us/parameters/gov/states/vt/tax/income/credits/non_refundable.yaml @@ -2,6 +2,7 @@ description: Vermont non-refundable tax credits. values: 2021-01-01: - vt_charitable_contribution_credit + - vt_529_plan_credit metadata: unit: list label: Vermont non-refundable tax credits diff --git a/policyengine_us/parameters/gov/states/vt/tax/income/credits/plan_529/cap.yaml b/policyengine_us/parameters/gov/states/vt/tax/income/credits/plan_529/cap.yaml new file mode 100644 index 00000000000..0c750b53452 --- /dev/null +++ b/policyengine_us/parameters/gov/states/vt/tax/income/credits/plan_529/cap.yaml @@ -0,0 +1,25 @@ +description: > + Vermont caps the 529 plan contribution amount eligible for the state tax + credit at this amount per beneficiary. +metadata: + label: Vermont 529 plan contribution credit cap per beneficiary + period: year + unit: currency-USD + breakdown: + - filing_status + reference: + - title: Vermont Tax Credits and Adjustments for Individuals + href: https://tax.vermont.gov/individuals/personal-income-tax/tax-credits + - title: VT529 Benefits + href: https://vt529.org/benefits + +JOINT: + 2021-01-01: 5_000 +SURVIVING_SPOUSE: + 2021-01-01: 5_000 +SINGLE: + 2021-01-01: 2_500 +HEAD_OF_HOUSEHOLD: + 2021-01-01: 2_500 +SEPARATE: + 2021-01-01: 2_500 diff --git a/policyengine_us/parameters/gov/states/vt/tax/income/credits/plan_529/rate.yaml b/policyengine_us/parameters/gov/states/vt/tax/income/credits/plan_529/rate.yaml new file mode 100644 index 00000000000..08bf9594c6b --- /dev/null +++ b/policyengine_us/parameters/gov/states/vt/tax/income/credits/plan_529/rate.yaml @@ -0,0 +1,12 @@ +description: Vermont applies this credit rate to eligible 529 plan contributions. +values: + 2021-01-01: 0.10 +metadata: + unit: /1 + period: year + label: Vermont 529 plan contribution credit rate + reference: + - title: Vermont Tax Credits and Adjustments for Individuals + href: https://tax.vermont.gov/individuals/personal-income-tax/tax-credits + - title: VT529 Benefits + href: https://vt529.org/benefits diff --git a/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/plan_529/cap.yaml b/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/plan_529/cap.yaml new file mode 100644 index 00000000000..5d4dec8d29c --- /dev/null +++ b/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/plan_529/cap.yaml @@ -0,0 +1,40 @@ +description: > + Wisconsin caps the 529 plan contributions deduction per beneficiary + at this amount. The married filing separately cap is half the regular cap. +metadata: + label: Wisconsin 529 plan contribution deduction cap per beneficiary + period: year + unit: currency-USD + breakdown: + - filing_status + reference: + - title: Edvest 529 Tax Benefits + href: https://www.edvest.com/learn/tax-benefits/ + - title: DFI Wisconsin 529 College Savings Program + href: https://dfi.wi.gov/Pages/EducationalServices/CollegeSavingsCareerPlanning/CollegeSavingsProgram.aspx + +JOINT: + 2021-01-01: 3_560 + 2024-01-01: 5_000 + 2025-01-01: 5_130 + 2026-01-01: 5_280 +SURVIVING_SPOUSE: + 2021-01-01: 3_560 + 2024-01-01: 5_000 + 2025-01-01: 5_130 + 2026-01-01: 5_280 +SINGLE: + 2021-01-01: 3_560 + 2024-01-01: 5_000 + 2025-01-01: 5_130 + 2026-01-01: 5_280 +HEAD_OF_HOUSEHOLD: + 2021-01-01: 3_560 + 2024-01-01: 5_000 + 2025-01-01: 5_130 + 2026-01-01: 5_280 +SEPARATE: + 2021-01-01: 1_780 + 2024-01-01: 2_500 + 2025-01-01: 2_560 + 2026-01-01: 2_640 diff --git a/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/sources.yaml b/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/sources.yaml index 793b1540683..228c2187562 100644 --- a/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/sources.yaml +++ b/policyengine_us/parameters/gov/states/wi/tax/income/subtractions/sources.yaml @@ -6,11 +6,13 @@ values: - wi_capital_gain_loss_subtraction - wi_childcare_expense_subtraction - wi_retirement_income_subtraction + - wi_529_plan_deduction 2022-01-01: - wi_unemployment_compensation_subtraction - tax_unit_taxable_social_security - wi_capital_gain_loss_subtraction - wi_retirement_income_subtraction + - wi_529_plan_deduction metadata: unit: list diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/tax/income/ok_529_plan_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/tax/income/ok_529_plan_deduction.yaml new file mode 100644 index 00000000000..1ee280c7e13 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/tax/income/ok_529_plan_deduction.yaml @@ -0,0 +1,44 @@ +- name: Single filer below cap + period: 2024 + input: + state_code: OK + filing_status: SINGLE + investment_in_529_plan_indv: 5_000 + output: + ok_529_plan_deduction: 5_000 + +- name: Single filer above cap + period: 2024 + input: + state_code: OK + filing_status: SINGLE + investment_in_529_plan_indv: 15_000 + output: + ok_529_plan_deduction: 10_000 + +- name: Joint filer below cap + period: 2024 + input: + state_code: OK + filing_status: JOINT + investment_in_529_plan_indv: 15_000 + output: + ok_529_plan_deduction: 15_000 + +- name: Joint filer above cap + period: 2024 + input: + state_code: OK + filing_status: JOINT + investment_in_529_plan_indv: 25_000 + output: + ok_529_plan_deduction: 20_000 + +- name: Zero contributions + period: 2024 + input: + state_code: OK + filing_status: SINGLE + investment_in_529_plan_indv: 0 + output: + ok_529_plan_deduction: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/or/tax/income/credits/or_529_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/or/tax/income/credits/or_529_credit.yaml new file mode 100644 index 00000000000..98abb66ac04 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/or/tax/income/credits/or_529_credit.yaml @@ -0,0 +1,44 @@ +- name: Single filer contribution below max credit + period: 2025 + input: + state_code: OR + filing_status: SINGLE + investment_in_529_plan_indv: 100 + output: + or_529_credit: 100 + +- name: Single filer contribution above max credit + period: 2025 + input: + state_code: OR + filing_status: SINGLE + investment_in_529_plan_indv: 500 + output: + or_529_credit: 180 + +- name: Joint filer contribution above max credit + period: 2025 + input: + state_code: OR + filing_status: JOINT + investment_in_529_plan_indv: 1_000 + output: + or_529_credit: 360 + +- name: Joint filer contribution below max credit + period: 2025 + input: + state_code: OR + filing_status: JOINT + investment_in_529_plan_indv: 200 + output: + or_529_credit: 200 + +- name: Zero contributions + period: 2025 + input: + state_code: OR + filing_status: SINGLE + investment_in_529_plan_indv: 0 + output: + or_529_credit: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/deductions/pa_529_plan_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/deductions/pa_529_plan_deduction.yaml new file mode 100644 index 00000000000..09197e4b9e4 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/deductions/pa_529_plan_deduction.yaml @@ -0,0 +1,43 @@ +- name: Contribution below cap with one beneficiary + period: 2025 + input: + state_code: PA + investment_in_529_plan_indv: 10_000 + count_529_contribution_beneficiaries: 1 + output: + pa_529_plan_deduction: 10_000 + +- name: Contribution above cap with one beneficiary + period: 2025 + input: + state_code: PA + investment_in_529_plan_indv: 25_000 + count_529_contribution_beneficiaries: 1 + output: + pa_529_plan_deduction: 19_000 + +- name: Two beneficiaries increases the cap + period: 2025 + input: + people: + person1: + investment_in_529_plan_indv: 25_000 + count_529_contribution_beneficiaries: 2 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: PA + output: + pa_529_plan_deduction: 25_000 + +- name: Zero contributions + period: 2025 + input: + state_code: PA + investment_in_529_plan_indv: 0 + count_529_contribution_beneficiaries: 0 + output: + pa_529_plan_deduction: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/ut_529_plan_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/ut_529_plan_credit.yaml new file mode 100644 index 00000000000..e068e213849 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ut/tax/income/credits/ut_529_plan_credit.yaml @@ -0,0 +1,53 @@ +- name: Single filer below cap with one beneficiary + period: 2024 + input: + state_code: UT + filing_status: SINGLE + investment_in_529_plan_indv: 1_000 + count_529_contribution_beneficiaries: 1 + output: + # 1_000 * 0.0455 = 45.50 + ut_529_plan_credit: 45.50 + +- name: Single filer above cap with one beneficiary + period: 2024 + input: + state_code: UT + filing_status: SINGLE + investment_in_529_plan_indv: 5_000 + count_529_contribution_beneficiaries: 1 + output: + # 2_410 * 0.0455 = 109.655 + ut_529_plan_credit: 109.655 + +- name: Joint filer below cap with one beneficiary + period: 2024 + input: + state_code: UT + filing_status: JOINT + investment_in_529_plan_indv: 3_000 + count_529_contribution_beneficiaries: 1 + output: + # 3_000 * 0.0455 = 136.50 + ut_529_plan_credit: 136.50 + +- name: Joint filer above cap with one beneficiary + period: 2024 + input: + state_code: UT + filing_status: JOINT + investment_in_529_plan_indv: 10_000 + count_529_contribution_beneficiaries: 1 + output: + # 4_820 * 0.0455 = 219.31 + ut_529_plan_credit: 219.31 + +- name: Zero contributions + period: 2024 + input: + state_code: UT + filing_status: SINGLE + investment_in_529_plan_indv: 0 + count_529_contribution_beneficiaries: 0 + output: + ut_529_plan_credit: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/subtractions/va_529_plan_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/subtractions/va_529_plan_deduction.yaml new file mode 100644 index 00000000000..15f3a20889f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/subtractions/va_529_plan_deduction.yaml @@ -0,0 +1,43 @@ +- name: Contribution below cap with one beneficiary + period: 2024 + input: + state_code: VA + investment_in_529_plan_indv: 3_000 + count_529_contribution_beneficiaries: 1 + output: + va_529_plan_deduction: 3_000 + +- name: Contribution above cap with one beneficiary + period: 2024 + input: + state_code: VA + investment_in_529_plan_indv: 6_000 + count_529_contribution_beneficiaries: 1 + output: + va_529_plan_deduction: 4_000 + +- name: Two beneficiaries increases the cap + period: 2024 + input: + people: + person1: + investment_in_529_plan_indv: 7_000 + count_529_contribution_beneficiaries: 2 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: VA + output: + va_529_plan_deduction: 7_000 + +- name: Zero contributions + period: 2024 + input: + state_code: VA + investment_in_529_plan_indv: 0 + count_529_contribution_beneficiaries: 0 + output: + va_529_plan_deduction: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/credits/vt_529_plan_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/credits/vt_529_plan_credit.yaml new file mode 100644 index 00000000000..b3ee1421b20 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/vt/tax/income/credits/vt_529_plan_credit.yaml @@ -0,0 +1,48 @@ +- name: Single filer below cap + period: 2024 + input: + state_code: VT + filing_status: SINGLE + investment_in_529_plan_indv: 1_000 + output: + # 1_000 * 0.10 = 100 + vt_529_plan_credit: 100 + +- name: Single filer above cap + period: 2024 + input: + state_code: VT + filing_status: SINGLE + investment_in_529_plan_indv: 5_000 + output: + # 2_500 * 0.10 = 250 + vt_529_plan_credit: 250 + +- name: Joint filer below cap + period: 2024 + input: + state_code: VT + filing_status: JOINT + investment_in_529_plan_indv: 3_000 + output: + # 3_000 * 0.10 = 300 + vt_529_plan_credit: 300 + +- name: Joint filer above cap + period: 2024 + input: + state_code: VT + filing_status: JOINT + investment_in_529_plan_indv: 10_000 + output: + # 5_000 * 0.10 = 500 + vt_529_plan_credit: 500 + +- name: Zero contributions + period: 2024 + input: + state_code: VT + filing_status: SINGLE + investment_in_529_plan_indv: 0 + output: + vt_529_plan_credit: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/subtractions/wi_529_plan_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/subtractions/wi_529_plan_deduction.yaml new file mode 100644 index 00000000000..b25d7de6253 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wi/tax/income/subtractions/wi_529_plan_deduction.yaml @@ -0,0 +1,56 @@ +- name: Single filer below cap with one beneficiary + period: 2025 + input: + state_code: WI + filing_status: SINGLE + investment_in_529_plan_indv: 3_000 + count_529_contribution_beneficiaries: 1 + output: + wi_529_plan_deduction: 3_000 + +- name: Single filer above cap with one beneficiary + period: 2025 + input: + state_code: WI + filing_status: SINGLE + investment_in_529_plan_indv: 8_000 + count_529_contribution_beneficiaries: 1 + output: + wi_529_plan_deduction: 5_130 + +- name: Married filing separately has lower cap + period: 2025 + input: + state_code: WI + filing_status: SEPARATE + investment_in_529_plan_indv: 5_000 + count_529_contribution_beneficiaries: 1 + output: + wi_529_plan_deduction: 2_560 + +- name: Two beneficiaries increases cap + period: 2025 + input: + people: + person1: + investment_in_529_plan_indv: 9_000 + count_529_contribution_beneficiaries: 2 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: WI + output: + wi_529_plan_deduction: 9_000 + +- name: Zero contributions + period: 2025 + input: + state_code: WI + filing_status: SINGLE + investment_in_529_plan_indv: 0 + count_529_contribution_beneficiaries: 0 + output: + wi_529_plan_deduction: 0 diff --git a/policyengine_us/variables/gov/states/ok/tax/income/ok_529_plan_deduction.py b/policyengine_us/variables/gov/states/ok/tax/income/ok_529_plan_deduction.py new file mode 100644 index 00000000000..0c52eb58bc4 --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/tax/income/ok_529_plan_deduction.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class ok_529_plan_deduction(Variable): + value_type = float + entity = TaxUnit + label = "Oklahoma deduction for contributions to 529 plans" + unit = USD + definition_period = YEAR + reference = ( + "https://www.oklahoma529.com/resources/faq/", + "https://oklahoma.gov/content/dam/ok/en/tax/documents/forms/individuals/current/511-Pkt.pdf#page=16", + ) + defined_for = StateCode.OK + + def formula(tax_unit, period, parameters): + p = parameters( + period + ).gov.states.ok.tax.income.agi.subtractions.plan_529 + contributions = tax_unit("investment_in_529_plan", period) + filing_status = tax_unit("filing_status", period) + cap = p.cap[filing_status] + return min_(contributions, cap) diff --git a/policyengine_us/variables/gov/states/or/tax/income/credits/or_529_credit.py b/policyengine_us/variables/gov/states/or/tax/income/credits/or_529_credit.py new file mode 100644 index 00000000000..514540c5d02 --- /dev/null +++ b/policyengine_us/variables/gov/states/or/tax/income/credits/or_529_credit.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class or_529_credit(Variable): + value_type = float + entity = TaxUnit + label = "Oregon 529 plan contribution credit" + unit = USD + definition_period = YEAR + reference = ( + "https://www.oregon.gov/dor/programs/individuals/pages/credits.aspx", + "https://oregon.public.law/statutes/ors_315.643", + ) + defined_for = StateCode.OR + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states["or"].tax.income.credits.plan_529 + contributions = tax_unit("investment_in_529_plan", period) + filing_status = tax_unit("filing_status", period) + max_credit = p.max_credit[filing_status] + return min_(contributions, max_credit) diff --git a/policyengine_us/variables/gov/states/pa/tax/income/deductions/pa_529_plan_deduction.py b/policyengine_us/variables/gov/states/pa/tax/income/deductions/pa_529_plan_deduction.py new file mode 100644 index 00000000000..9861935cd0c --- /dev/null +++ b/policyengine_us/variables/gov/states/pa/tax/income/deductions/pa_529_plan_deduction.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class pa_529_plan_deduction(Variable): + value_type = float + entity = TaxUnit + label = "Pennsylvania deduction for contributions to 529 plans" + unit = USD + definition_period = YEAR + reference = ( + "https://revenue-pa.custhelp.com/app/answers/detail/a_id/2208/~/what-is-the-limit-on-a-deduction-to-a-529-plan", + "https://www.pa529.com/faqs/", + ) + defined_for = StateCode.PA + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.pa.tax.income.deductions.plan_529 + contributions = tax_unit("investment_in_529_plan", period) + beneficiaries = add( + tax_unit, + period, + ["count_529_contribution_beneficiaries"], + ) + cap = p.cap * beneficiaries + return min_(contributions, cap) diff --git a/policyengine_us/variables/gov/states/pa/tax/income/deductions/pa_tax_deductions.py b/policyengine_us/variables/gov/states/pa/tax/income/deductions/pa_tax_deductions.py index ce23ff8aa16..ea70c6ae90d 100644 --- a/policyengine_us/variables/gov/states/pa/tax/income/deductions/pa_tax_deductions.py +++ b/policyengine_us/variables/gov/states/pa/tax/income/deductions/pa_tax_deductions.py @@ -1,6 +1,7 @@ from policyengine_us.model_api import * # PA law does not allow standard deductions, deductions for personal exemptions, itemized deductions or deductions for personal expenses. +# However, PA does allow deductions for 529 plan contributions. class pa_tax_deductions(Variable): @@ -11,3 +12,5 @@ class pa_tax_deductions(Variable): definition_period = YEAR reference = "https://www.revenue.pa.gov/FormsandPublications/FormsforIndividuals/PIT/Documents/2021/2021_pa-40in.pdf#page=20" defined_for = StateCode.PA + + adds = ["pa_529_plan_deduction"] diff --git a/policyengine_us/variables/gov/states/ut/tax/income/credits/ut_529_plan_credit.py b/policyengine_us/variables/gov/states/ut/tax/income/credits/ut_529_plan_credit.py new file mode 100644 index 00000000000..4efc823e869 --- /dev/null +++ b/policyengine_us/variables/gov/states/ut/tax/income/credits/ut_529_plan_credit.py @@ -0,0 +1,27 @@ +from policyengine_us.model_api import * + + +class ut_529_plan_credit(Variable): + value_type = float + entity = TaxUnit + label = "Utah 529 plan contribution tax credit" + unit = USD + definition_period = YEAR + reference = ( + "https://my529.org/utah-state-tax-benefits-information/", + "https://incometax.utah.gov/credits/my529", + ) + defined_for = StateCode.UT + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.ut.tax.income.credits.plan_529 + contributions = tax_unit("investment_in_529_plan", period) + filing_status = tax_unit("filing_status", period) + beneficiaries = add( + tax_unit, + period, + ["count_529_contribution_beneficiaries"], + ) + cap = p.cap[filing_status] * beneficiaries + eligible_contributions = min_(contributions, cap) + return eligible_contributions * p.rate diff --git a/policyengine_us/variables/gov/states/va/tax/income/subtractions/va_529_plan_deduction.py b/policyengine_us/variables/gov/states/va/tax/income/subtractions/va_529_plan_deduction.py new file mode 100644 index 00000000000..269b87198be --- /dev/null +++ b/policyengine_us/variables/gov/states/va/tax/income/subtractions/va_529_plan_deduction.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class va_529_plan_deduction(Variable): + value_type = float + entity = TaxUnit + label = "Virginia deduction for contributions to 529 plans" + unit = USD + definition_period = YEAR + reference = ( + "https://www.tax.virginia.gov/deductions", + "https://law.lis.virginia.gov/vacodefull/title58.1/chapter3/article2/", + ) + defined_for = StateCode.VA + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.va.tax.income.subtractions.plan_529 + contributions = tax_unit("investment_in_529_plan", period) + beneficiaries = add( + tax_unit, + period, + ["count_529_contribution_beneficiaries"], + ) + cap = p.cap * beneficiaries + return min_(contributions, cap) diff --git a/policyengine_us/variables/gov/states/vt/tax/income/credits/vt_529_plan_credit.py b/policyengine_us/variables/gov/states/vt/tax/income/credits/vt_529_plan_credit.py new file mode 100644 index 00000000000..3f932b02441 --- /dev/null +++ b/policyengine_us/variables/gov/states/vt/tax/income/credits/vt_529_plan_credit.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class vt_529_plan_credit(Variable): + value_type = float + entity = TaxUnit + label = "Vermont 529 plan contribution tax credit" + unit = USD + definition_period = YEAR + reference = ( + "https://tax.vermont.gov/individuals/personal-income-tax/tax-credits", + "https://vt529.org/benefits", + ) + defined_for = StateCode.VT + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.vt.tax.income.credits.plan_529 + contributions = tax_unit("investment_in_529_plan", period) + filing_status = tax_unit("filing_status", period) + cap = p.cap[filing_status] + eligible_contributions = min_(contributions, cap) + return eligible_contributions * p.rate diff --git a/policyengine_us/variables/gov/states/vt/tax/income/vt_non_refundable_credits.py b/policyengine_us/variables/gov/states/vt/tax/income/vt_non_refundable_credits.py index 432c87affc2..d6d5ba3eadb 100644 --- a/policyengine_us/variables/gov/states/vt/tax/income/vt_non_refundable_credits.py +++ b/policyengine_us/variables/gov/states/vt/tax/income/vt_non_refundable_credits.py @@ -8,3 +8,5 @@ class vt_non_refundable_credits(Variable): unit = USD definition_period = YEAR defined_for = StateCode.VT + + adds = "gov.states.vt.tax.income.credits.non_refundable" diff --git a/policyengine_us/variables/gov/states/wi/tax/income/subtractions/wi_529_plan_deduction.py b/policyengine_us/variables/gov/states/wi/tax/income/subtractions/wi_529_plan_deduction.py new file mode 100644 index 00000000000..9c5b1e55eb5 --- /dev/null +++ b/policyengine_us/variables/gov/states/wi/tax/income/subtractions/wi_529_plan_deduction.py @@ -0,0 +1,26 @@ +from policyengine_us.model_api import * + + +class wi_529_plan_deduction(Variable): + value_type = float + entity = TaxUnit + label = "Wisconsin deduction for contributions to 529 plans" + unit = USD + definition_period = YEAR + reference = ( + "https://www.edvest.com/learn/tax-benefits/", + "https://dfi.wi.gov/Pages/EducationalServices/CollegeSavingsCareerPlanning/CollegeSavingsProgram.aspx", + ) + defined_for = StateCode.WI + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.wi.tax.income.subtractions.plan_529 + contributions = tax_unit("investment_in_529_plan", period) + filing_status = tax_unit("filing_status", period) + beneficiaries = add( + tax_unit, + period, + ["count_529_contribution_beneficiaries"], + ) + cap = p.cap[filing_status] * beneficiaries + return min_(contributions, cap)