From bdcd44ff7bdd646dddd8744d9095f8197d0d403d Mon Sep 17 00:00:00 2001 From: PavelMakarchuk Date: Wed, 8 Jul 2026 15:39:08 -0400 Subject: [PATCH] Cap MT 2021 income tax rebate at liability per MCA 15-30-2191(2)(b) The variable returned the flat filing-status amount (1,250/2,500) for every MT filer in every year >= 2021, ignoring the statutory cap (lesser of the amount or the taxpayer's income tax liability) and the rebate's 2021-only scope. Montana income tax results are unchanged - the credit application already floored the applied amount - but the variable's reported value was wrong for low-liability filers and for 2022+ (it produced phantom amounts in the TAXSIM-comparison srebate work). Cap at the smaller of the joint and separate-column pre-credit bases (the filing election itself is post-credit and would create a computation cycle), zero-scope the amounts from 2022, and replace the period-2023 no-income unit tests that encoded the uncapped values. Fixes #8958. Co-Authored-By: Claude Opus 4.8 --- ...t-income-tax-rebate-liability-cap.fixed.md | 1 + .../mt/tax/income/credits/rebate/amount.yaml | 7 +- .../credits/rebate/mt_income_tax_rebate.yaml | 99 ++++++++++++++++--- .../credits/rebate/mt_income_tax_rebate.py | 20 +++- 4 files changed, 112 insertions(+), 15 deletions(-) create mode 100644 changelog.d/mt-income-tax-rebate-liability-cap.fixed.md diff --git a/changelog.d/mt-income-tax-rebate-liability-cap.fixed.md b/changelog.d/mt-income-tax-rebate-liability-cap.fixed.md new file mode 100644 index 00000000000..27e423f3929 --- /dev/null +++ b/changelog.d/mt-income-tax-rebate-liability-cap.fixed.md @@ -0,0 +1 @@ +Cap the Montana 2021 income tax rebate at the taxpayer's pre-credit liability per MCA 15-30-2191(2)(b) and zero the amounts from 2022, fixing the variable's reported value; Montana income tax results are unchanged because the credit application already floored the applied amount. diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/credits/rebate/amount.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/credits/rebate/amount.yaml index 323de1b3ef6..21df70439f9 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/credits/rebate/amount.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/credits/rebate/amount.yaml @@ -11,11 +11,16 @@ metadata: SINGLE: 2021-01-01: 1_250 + 2022-01-01: 0 HEAD_OF_HOUSEHOLD: 2021-01-01: 1_250 + 2022-01-01: 0 JOINT: 2021-01-01: 2_500 + 2022-01-01: 0 SURVIVING_SPOUSE: 2021-01-01: 2_500 + 2022-01-01: 0 SEPARATE: - 2021-01-01: 1_250 + 2021-01-01: 1_250 + 2022-01-01: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/rebate/mt_income_tax_rebate.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/rebate/mt_income_tax_rebate.yaml index f8b22b4ca3f..ca636239855 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/rebate/mt_income_tax_rebate.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/rebate/mt_income_tax_rebate.yaml @@ -1,23 +1,98 @@ -- name: Single filer - period: 2023 +- name: Single filer with liability above the rebate amount + period: 2021 input: - filing_status: SINGLE - state_code: MT + people: + person1: + age: 45 + employment_income: 50_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: MT output: mt_income_tax_rebate: 1_250 -- name: Joint filers - period: 2023 +- name: Joint filers with liability above the rebate amount + period: 2021 input: - filing_status: JOINT - state_code: MT + people: + person1: + age: 45 + employment_income: 60_000 + person2: + age: 45 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MT output: mt_income_tax_rebate: 2_500 -- name: Not in Montana - period: 2023 +- name: Rebate is capped at the income tax liability (MCA 15-30-2191(2)(b)) + absolute_error_margin: 1 + period: 2021 input: - filing_status: JOINT - state_code: AR + people: + person1: + age: 45 + employment_income: 20_000 + person2: + age: 45 + marital_units: + marital_unit: + members: [person1, person2] + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MT + output: + # Lesser of $2,500 or the pre-credit liability, not the flat amount. + # (Montana's credit application already floors the applied credit, so + # this fixes the variable's reported value, not the tax outcome.) + mt_income_tax_rebate: 252.40 + +- name: No rebate outside Montana + period: 2021 + input: + people: + person1: + age: 45 + employment_income: 50_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: AR + output: + mt_income_tax_rebate: 0 + +- name: No rebate in 2022 + period: 2022 + input: + people: + person1: + age: 45 + employment_income: 50_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: MT output: mt_income_tax_rebate: 0 diff --git a/policyengine_us/variables/gov/states/mt/tax/income/credits/rebate/mt_income_tax_rebate.py b/policyengine_us/variables/gov/states/mt/tax/income/credits/rebate/mt_income_tax_rebate.py index 031e5cd790f..33351f4caac 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/credits/rebate/mt_income_tax_rebate.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/credits/rebate/mt_income_tax_rebate.py @@ -10,8 +10,24 @@ class mt_income_tax_rebate(Variable): reference = "https://archive.legmt.gov/bills/mca/title_0150/chapter_0300/part_0210/section_0910/0150-0300-0210-0910.html" defined_for = StateCode.MT - # The rebate is based on 2021 income tax liability, but provided in 2023 + # The rebate is based on 2021 income tax liability, but provided in 2023. + # MCA 15-30-2191(2)(b): the rebate is the LESSER of the filing-status + # amount or the taxpayer's income tax liability, so it can not drive the + # liability negative. Montana elects the lower of the joint and + # separate-column computations, but that election + # (mt_files_separately) depends on post-credit liability and would + # create a computation cycle here, so cap at the smaller of the two + # pre-credit bases — never larger than the elected one. def formula(tax_unit, period, parameters): p = parameters(period).gov.states.mt.tax.income.credits.rebate filing_status = tax_unit("filing_status", period) - return p.amount[filing_status] + liability_indiv = add( + tax_unit, + period, + ["mt_income_tax_before_non_refundable_credits_indiv"], + ) + liability_joint = tax_unit( + "mt_income_tax_before_non_refundable_credits_joint", period + ) + liability = min_(liability_indiv, liability_joint) + return min_(p.amount[filing_status], max_(liability, 0))