From 52ffe10226cd26b3ff24e48ce7f9bc555924dd07 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 6 Oct 2026 07:08:30 -0400 Subject: [PATCH 1/6] Align Montana separate-filing allocations and the elderly credit with the forms - Federal income tax deduction (through 2023): attribute federal tax to the spouse who earned the income and cap each spouse at $5,000, instead of prorating the jointly capped amount by Montana AGI (2022 Form 2 instructions, Itemized Deductions Schedule, line 4). - Child and dependent care expense deduction (through 2023): phase out on the couple's combined Montana AGI and split the result equally only for spouses filing separately on the same form; a single filer and a joint return take the whole deduction (Form 2441-M lines 3-7). - Elderly homeowner/renter credit: count federal AGI without regard to losses (MCA 15-30-2337(9)(a); Form 2EC line 9). Co-Authored-By: Claude Opus 5.5 --- ...ix-mt-separate-filing-allocations.fixed.md | 1 + .../deductions/itemized/misc_deductions.yaml | 7 +- ...mt_elderly_homeowner_or_renter_credit.yaml | 31 ++++ ..._renter_credit_gross_household_income.yaml | 47 ++++++ ...hild_dependent_care_expense_deduction.yaml | 134 ++++++++++++++---- ...duction_for_federal_itemization_indiv.yaml | 27 ++-- ...uctions_for_federal_itemization_joint.yaml | 6 +- ...mt_federal_income_tax_deduction_indiv.yaml | 103 ++++++++++++-- .../mt_itemized_deductions_joint.yaml | 6 +- ...or_renter_credit_gross_household_income.py | 16 ++- ..._child_dependent_care_expense_deduction.py | 44 +++--- ...are_expense_deduction_eligible_expenses.py | 34 +++++ ..._dependent_care_expense_deduction_joint.py | 30 ++++ ...deduction_for_federal_itemization_indiv.py | 26 ++-- ...eductions_for_federal_itemization_indiv.py | 1 + ...eductions_for_federal_itemization_joint.py | 1 + .../mt_federal_income_tax_deduction_indiv.py | 31 ++-- .../mt_federal_income_tax_deduction_share.py | 33 +++++ .../general/mt_itemized_deductions_indiv.py | 1 + .../general/mt_itemized_deductions_joint.py | 1 + 20 files changed, 472 insertions(+), 108 deletions(-) create mode 100644 changelog.d/fix-mt-separate-filing-allocations.fixed.md create mode 100644 policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction_eligible_expenses.py create mode 100644 policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction_joint.py create mode 100644 policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_tax/mt_federal_income_tax_deduction_share.py diff --git a/changelog.d/fix-mt-separate-filing-allocations.fixed.md b/changelog.d/fix-mt-separate-filing-allocations.fixed.md new file mode 100644 index 00000000000..c7d3be16f20 --- /dev/null +++ b/changelog.d/fix-mt-separate-filing-allocations.fixed.md @@ -0,0 +1 @@ +Montana's federal income tax deduction for spouses filing separately on the same form now attributes federal tax to the spouse who earned the income and caps each spouse at 5,000; the child and dependent care expense deduction phases out on the couple's combined Montana AGI and is halved only for spouses filing separately on the same form; and the elderly homeowner/renter credit counts income without regard to losses. diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/misc_deductions.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/misc_deductions.yaml index 1eeb0351b1a..c4744269768 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/misc_deductions.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/misc_deductions.yaml @@ -1,8 +1,11 @@ description: Montana counts these sources as miscellaneous deductions. +# The child and dependent care expense deduction is also a miscellaneous +# deduction (Form 2 Itemized Deductions Schedule, line 14). It is added +# separately because its income limit uses the return's own Montana AGI, which +# differs between a joint return and separate columns (Form 2441-M line 3). values: 2021-01-01: - - mt_child_dependent_care_expense_deduction - - casualty_loss_deduction + - casualty_loss_deduction 2024-01-01: [] metadata: diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.yaml index 9e4f2540b71..154bf57d561 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.yaml @@ -223,3 +223,34 @@ # Same household, larger exclusion ($12,600) leaves a smaller expected # contribution, so the credit is higher: $539.67. mt_elderly_homeowner_or_renter_credit: 539.67 + +- name: 2023 Form 2EC worked case, a capital loss does not reduce gross household income + period: 2023 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 20_000 + long_term_capital_gains: -3_000 + social_security_retirement: 10_000 + real_estate_taxes: 2_000 + mt_refundable_credits_before_renter_credit: 0 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # Line 1 federal AGI 17_000 (Social Security untaxed: 17_000 + 5_000 is + # under the 25_000 base); line 5 untaxed Social Security 10_000; line 9 + # losses 3_000; line 10 gross household income 30_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: 30_000 + # Line 12 = 30_000 - 12_600 = 17_400; line 13 multiplier 0.05; + # line 14 = 870. + mt_elderly_homeowner_or_renter_credit_net_household_income: 870 + # Line 18 = 2_000; line 19 = 1_130; line 20 = min(1_130, 1_150); + # line 21 = 100% (under 35_000); line 22 = 1_130. + mt_elderly_homeowner_or_renter_credit: 1_130 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml index cee870a82af..f7d12a544dc 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml @@ -37,3 +37,50 @@ # § 15-30-2337(9)(a)(viii) requires all SS to be counted, even the # portion excluded from federal AGI. mt_elderly_homeowner_or_renter_credit_gross_household_income: 30_000 + +- name: A capital loss deducted in federal AGI is added back + period: 2023 + input: + people: + person1: + age: 70 + taxable_pension_income: 20_000 + long_term_capital_gains: -3_000 + mt_refundable_credits_before_renter_credit: 0 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_name: MT + output: + # § 15-30-2337(9)(a): federal AGI "without regard to loss". 2023 Form 2EC: + # line 1 federal AGI 20_000 - 3_000 = 17_000; line 9 adds back the 3_000 + # capital loss; line 10 = 20_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: 20_000 + +- name: A business loss deducted in federal AGI is added back once for the return + period: 2024 + input: + people: + person1: + age: 70 + taxable_pension_income: 20_000 + mt_refundable_credits_before_renter_credit: 0 + person2: + age: 68 + self_employment_income: -5_000 + mt_refundable_credits_before_renter_credit: 0 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # Federal AGI 20_000 - 5_000 = 15_000; the 5_000 loss is added back, so + # gross household income is 20_000 (Form 2EC line 18). Net household + # income: (20_000 - 12_600) * 0.035 = 259, allocated to the head. + mt_elderly_homeowner_or_renter_credit_net_household_income: [259, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.yaml index df49679c68b..b7ce4721911 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.yaml @@ -19,8 +19,8 @@ state_code: MT output: # One qualifying individual caps expenses at 2_400. - # Head receives half: 2_400 * 0.5 = 1_200. - mt_child_dependent_care_expense_deduction: [1_200, 0] + # A single filer enters the full line 7 amount: 2_400. + mt_child_dependent_care_expense_deduction: [2_400, 0] - name: Care expense greater than maximum amount with moderate AGI and 1 child period: 2021 @@ -43,8 +43,8 @@ state_code: MT output: # 2_400 - 0.5 * (20_000 - 18_000) = 1_400. - # Head receives half: 1_400 * 0.5 = 700. - mt_child_dependent_care_expense_deduction: [700, 0] + # A single filer enters the full line 7 amount: 1_400. + mt_child_dependent_care_expense_deduction: [1_400, 0] - name: Care expense greater than maximum amount with high AGI and 1 child period: 2021 @@ -92,8 +92,8 @@ state_code: MT output: # Two qualifying individuals cap expenses at 3_600. - # Head receives half: 3_600 * 0.5 = 1_800. - mt_child_dependent_care_expense_deduction: [1_800, 0, 0] + # A single filer enters the full line 7 amount: 3_600. + mt_child_dependent_care_expense_deduction: [3_600, 0, 0] - name: Care expense greater than maximum amount with moderate AGI and 2 children period: 2021 @@ -119,8 +119,8 @@ state_code: MT output: # 3_600 - 0.5 * (22_000 - 18_000) = 1_600. - # Head receives half: 1_600 * 0.5 = 800. - mt_child_dependent_care_expense_deduction: [800, 0, 0] + # A single filer enters the full line 7 amount: 1_600. + mt_child_dependent_care_expense_deduction: [1_600, 0, 0] - name: Care expense greater than maximum amount with high AGI and 2 children period: 2021 @@ -174,8 +174,8 @@ state_code: MT output: # Three qualifying individuals cap expenses at 4_800. - # Head receives half: 4_800 * 0.5 = 2_400. - mt_child_dependent_care_expense_deduction: [2_400, 0, 0, 0] + # A single filer enters the full line 7 amount: 4_800. + mt_child_dependent_care_expense_deduction: [4_800, 0, 0, 0] - name: Care expense greater than maximum amount with moderate AGI and 3 children period: 2021 @@ -204,8 +204,8 @@ state_code: MT output: # 4_800 - 0.5 * (24_000 - 18_000) = 1_800. - # Head receives half: 1_800 * 0.5 = 900. - mt_child_dependent_care_expense_deduction: [900, 0, 0, 0] + # A single filer enters the full line 7 amount: 1_800. + mt_child_dependent_care_expense_deduction: [1_800, 0, 0, 0] - name: Care expense greater than maximum amount with high AGI and 3 children period: 2021 @@ -255,8 +255,8 @@ members: [person1, person2] state_code: MT output: - # Head receives half: 2_000 * 0.5 = 1_000. - mt_child_dependent_care_expense_deduction: [1_000, 0] + # A single filer enters the full line 7 amount: 2_000. + mt_child_dependent_care_expense_deduction: [2_000, 0] - name: Care expense less than maximum amount with high AGI and 1 child period: 2021 @@ -303,8 +303,8 @@ members: [person1, person2, person3] state_code: MT output: - # Head receives half: 3_000 * 0.5 = 1_500. - mt_child_dependent_care_expense_deduction: [1_500, 0, 0] + # A single filer enters the full line 7 amount: 3_000. + mt_child_dependent_care_expense_deduction: [3_000, 0, 0] - name: Care expense less than maximum amount with high AGI and 2 children period: 2021 @@ -357,8 +357,8 @@ members: [person1, person2, person3, person4] state_code: MT output: - # Head receives half: 4_000 * 0.5 = 2_000. - mt_child_dependent_care_expense_deduction: [2_000, 0, 0, 0] + # A single filer enters the full line 7 amount: 4_000. + mt_child_dependent_care_expense_deduction: [4_000, 0, 0, 0] - name: Care expense less than maximum amount with high AGI and 3 children period: 2021 @@ -441,8 +441,8 @@ state_code: MT output: # One qualifying individual caps expenses at 2_400 (Form 2441-M line 2). - # Head receives half: 2_400 * 0.5 = 1_200. - mt_child_dependent_care_expense_deduction: [1_200, 0] + # A single filer enters the full line 7 amount: 2_400. + mt_child_dependent_care_expense_deduction: [2_400, 0] - name: Case 18, capable disabled adult care expenses are excluded. period: 2021 @@ -470,8 +470,8 @@ state_code: MT output: # Only the child qualifies, so 2_000 of adult care expenses are excluded. - # Head receives half of the 1_000 childcare expense deduction. - mt_child_dependent_care_expense_deduction: [500, 0, 0] + # A single filer enters the full 1_000 childcare expense deduction. + mt_child_dependent_care_expense_deduction: [1_000, 0, 0] - name: Case 19, a child and an incapacitated adult dependent both count toward the tier. period: 2021 @@ -500,8 +500,8 @@ output: # Two qualifying individuals cap expenses at 3_600 (Form 2441-M line 2). # Childcare 3_000 + adult care 1_000 = 4_000, capped at 3_600. - # Head receives half: 3_600 * 0.5 = 1_800. - mt_child_dependent_care_expense_deduction: [1_800, 0, 0] + # A single filer enters the full line 7 amount: 3_600. + mt_child_dependent_care_expense_deduction: [3_600, 0, 0] - name: Case 20, adult care expenses cannot exceed the one-qualifying-individual tier cap. period: 2021 @@ -525,8 +525,8 @@ state_code: MT output: # One qualifying individual caps expenses at 2_400 (Form 2441-M line 2). - # Head receives half: 2_400 * 0.5 = 1_200. - mt_child_dependent_care_expense_deduction: [1_200, 0] + # A single filer enters the full line 7 amount: 2_400. + mt_child_dependent_care_expense_deduction: [2_400, 0] - name: Case 21, incapacitated spouse care expenses qualify. period: 2021 @@ -606,8 +606,8 @@ output: # One qualifying individual caps expenses at 2_400 (Form 2441-M line 2). # Childcare 1_500 + care expenses 1_000 = 2_500, capped at 2_400. - # Head receives half: 2_400 * 0.5 = 1_200. - mt_child_dependent_care_expense_deduction: [1_200, 0] + # A single filer enters the full line 7 amount: 2_400. + mt_child_dependent_care_expense_deduction: [2_400, 0] - name: Case 24, combined childcare and adult care expenses are capped by the three-qualifying-individual tier. period: 2021 @@ -643,3 +643,81 @@ # Childcare 4_000 + adult care 2_000 = 6_000, capped at 4_800. # The deduction is divided equally between spouses: 4_800 * 0.5 = 2_400. mt_child_dependent_care_expense_deduction: [2_400, 2_400, 0, 0] + +- name: Case 25, the phase-out uses the couple's combined Montana AGI, then each column gets half + period: 2022 + absolute_error_margin: 0.01 + input: + people: + person1: + is_tax_unit_head: true + mt_agi_indiv: 20_000 + person2: + is_tax_unit_spouse: true + mt_agi_indiv: 0 + person3: + age: 5 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2, person3] + tax_unit_childcare_expenses: 3_000 + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + # Form 2441-M (2022): line 2 = min(3_000, 2_400) = 2_400; line 3 adds + # columns A and B of Form 2 line 14 = 20_000 + 0 = 20_000; line 5 = 2_000; + # line 6 = 1_000; line 7 = 1_400. Filing separately on the same form, each + # spouse enters one-half of line 7 (700). Applying the phase-out to each + # spouse's own AGI would give 700 and 1_200. + mt_child_dependent_care_expense_deduction_eligible_expenses: 2_400 + mt_child_dependent_care_expense_deduction: [700, 700, 0] + +- name: Case 26, a joint return uses the return's Montana AGI and claims the whole deduction + period: 2022 + absolute_error_margin: 0.01 + input: + people: + person1: + is_tax_unit_head: true + person2: + is_tax_unit_spouse: true + person3: + age: 5 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2, person3] + tax_unit_childcare_expenses: 3_000 + mt_agi_joint: 20_000 + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + # Form 2441-M lines 2-7 with line 3 = 20_000: 2_400 - 0.5 * 2_000 = 1_400, + # entered in full on the joint return. + mt_child_dependent_care_expense_deduction_joint: 1_400 + +- name: Case 27, the joint deduction is repealed beginning in 2024 + period: 2024 + input: + people: + person1: + is_tax_unit_head: true + person2: + age: 5 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + tax_unit_childcare_expenses: 3_000 + mt_agi_joint: 10_000 + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_child_dependent_care_expense_deduction_joint: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_federal_income_tax_deduction_for_federal_itemization_indiv.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_federal_income_tax_deduction_for_federal_itemization_indiv.yaml index e0fed58cbeb..941a60e6c1b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_federal_income_tax_deduction_for_federal_itemization_indiv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_federal_income_tax_deduction_for_federal_itemization_indiv.yaml @@ -1,39 +1,46 @@ -- name: Deductions split evenly +# 2022 Form 2 instructions, Itemized Deductions Schedule, line 4 (PDF p. 33): +# withholding is reported by the spouse who earned the income, and each +# spouse filing separately is limited to 5,000. + +- name: Each spouse deducts their own withholding estimate period: 2021 input: people: person1: - mt_agi_indiv: 500 + mt_withheld_income_tax: 3_000 + adjusted_gross_income_person: 50_000 person2: - mt_agi_indiv: 500 + mt_withheld_income_tax: 1_000 + adjusted_gross_income_person: 50_000 tax_units: tax_unit: members: [person1, person2] - mt_federal_income_tax_deduction_for_federal_itemization: 3_000 state_filing_status_if_married_filing_separately_on_same_return: SEPARATE households: household: members: [person1, person2] state_code: MT output: - mt_federal_income_tax_deduction_for_federal_itemization_indiv: [1_500, 1_500] + # Prorating the couple's 4_000 by Montana AGI would give 2_000 / 2_000. + mt_federal_income_tax_deduction_for_federal_itemization_indiv: [3_000, 1_000] -- name: Deductions capped at max amount individually +- name: Each spouse is capped at 5,000 on their own amount period: 2021 input: people: person1: - mt_agi_indiv: 100 + mt_withheld_income_tax: 7_000 + adjusted_gross_income_person: 60_000 person2: - mt_agi_indiv: 900 + mt_withheld_income_tax: 1_000 + adjusted_gross_income_person: 40_000 tax_units: tax_unit: members: [person1, person2] - mt_federal_income_tax_deduction_for_federal_itemization: 10_000 state_filing_status_if_married_filing_separately_on_same_return: SEPARATE households: household: members: [person1, person2] state_code: MT output: - mt_federal_income_tax_deduction_for_federal_itemization_indiv: [1_000, 5_000] + mt_federal_income_tax_deduction_for_federal_itemization_indiv: [5_000, 1_000] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml index 8a1114f4ef5..41a8d808975 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml @@ -7,7 +7,7 @@ mt_salt_deduction: 5_000 mt_medical_expense_deduction_joint: 1_000 casualty_loss_deduction: 400 - mt_child_dependent_care_expense_deduction: 123 + mt_child_dependent_care_expense_deduction_joint: 123 mt_federal_income_tax_deduction_for_federal_itemization: 2_000 state_code: MT output: @@ -22,7 +22,7 @@ mt_salt_deduction: 10_000 mt_medical_expense_deduction_joint: 3_000 casualty_loss_deduction: 0 - mt_child_dependent_care_expense_deduction: 0 + mt_child_dependent_care_expense_deduction_joint: 0 mt_federal_income_tax_deduction_for_federal_itemization: 2_000 state_code: MT output: @@ -37,7 +37,7 @@ mt_salt_deduction: 1_035 mt_medical_expense_deduction_joint: 3_000 casualty_loss_deduction: 745 - mt_child_dependent_care_expense_deduction: 1_004 + mt_child_dependent_care_expense_deduction_joint: 1_004 mt_federal_income_tax_deduction_for_federal_itemization: 2_000 state_code: MT output: diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_federal_income_tax_deduction_indiv.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_federal_income_tax_deduction_indiv.yaml index 4b0d588ce5e..c7604752c4d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_federal_income_tax_deduction_indiv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_federal_income_tax_deduction_indiv.yaml @@ -1,39 +1,120 @@ -- name: Deductions split evenly +# 2022 Form 2 instructions, Itemized Deductions Schedule, line 4 (PDF p. 33): +# "If you are married filing separately with your spouse, the federal income +# tax withheld should be reported by the spouse who earned the income." and +# "If your filing status is Married Filing Separately, you are each limited to +# the $5,000 federal tax deduction and you cannot arbitrarily allocate this +# deduction between spouses." + +- name: Federal income tax is attributed by each spouse's share of federal AGI period: 2021 + absolute_error_margin: 0.01 input: people: person1: - mt_agi_indiv: 500 + adjusted_gross_income_person: 60_000 person2: - mt_agi_indiv: 500 + adjusted_gross_income_person: 40_000 tax_units: tax_unit: members: [person1, person2] - mt_federal_income_tax_deduction_unit: 3_000 + income_tax_before_refundable_credits: 3_000 state_filing_status_if_married_filing_separately_on_same_return: SEPARATE households: household: members: [person1, person2] state_code: MT output: - mt_federal_income_tax_deduction_indiv: [1_500, 1_500] + mt_federal_income_tax_deduction_share: [0.6, 0.4] + mt_federal_income_tax_deduction_indiv: [1_800, 1_200] -- name: Deductions capped at max amount individually - period: 2021 +- name: Each spouse's own federal tax is capped at 5,000, not a share of the joint cap + period: 2022 + absolute_error_margin: 0.01 + input: + people: + person1: + adjusted_gross_income_person: 80_000 + person2: + adjusted_gross_income_person: 20_000 + tax_units: + tax_unit: + members: [person1, person2] + income_tax_before_refundable_credits: 30_000 + state_filing_status_if_married_filing_separately_on_same_return: SEPARATE + households: + household: + members: [person1, person2] + state_code: MT + output: + # Federal tax attributed 24_000 / 6_000; each spouse is limited to 5_000. + # Capping the couple at 10_000 first and then splitting 80% / 20% would + # give 5_000 / 2_000. + mt_federal_income_tax_deduction_indiv: [5_000, 5_000] + +- name: Montana-only subtractions do not shift federal tax between spouses + period: 2022 + absolute_error_margin: 0.01 + input: + people: + person1: + adjusted_gross_income_person: 50_000 + person2: + adjusted_gross_income_person: 50_000 + mt_subtractions: 20_000 + tax_units: + tax_unit: + members: [person1, person2] + income_tax_before_refundable_credits: 6_000 + state_filing_status_if_married_filing_separately_on_same_return: SEPARATE + households: + household: + members: [person1, person2] + state_code: MT + output: + # The federal tax was paid on 50_000 of federal income each. Prorating by + # Montana AGI (50_000 / 30_000) would give 3_750 / 2_250. + mt_federal_income_tax_deduction_indiv: [3_000, 3_000] + +- name: A dependent's income does not draw a share of the parents' federal tax + period: 2022 + absolute_error_margin: 0.01 + input: + people: + person1: + adjusted_gross_income_person: 40_000 + person2: + adjusted_gross_income_person: 0 + person3: + is_tax_unit_dependent: true + adjusted_gross_income_person: 0 + tax_units: + tax_unit: + members: [person1, person2, person3] + income_tax_before_refundable_credits: 2_000 + state_filing_status_if_married_filing_separately_on_same_return: SEPARATE + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + mt_federal_income_tax_deduction_indiv: [2_000, 0, 0] + +- name: The deduction is repealed from 2024 + period: 2024 input: people: person1: - mt_agi_indiv: 100 + adjusted_gross_income_person: 60_000 person2: - mt_agi_indiv: 900 + adjusted_gross_income_person: 40_000 tax_units: tax_unit: members: [person1, person2] - mt_federal_income_tax_deduction_unit: 10_000 + income_tax_before_refundable_credits: 3_000 state_filing_status_if_married_filing_separately_on_same_return: SEPARATE households: household: members: [person1, person2] state_code: MT output: - mt_federal_income_tax_deduction_indiv: [1_000, 5_000] + mt_federal_income_tax_deduction_indiv: [0, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml index 6b25795e07a..329641eafa3 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml @@ -7,7 +7,7 @@ mt_salt_deduction: 5_000 mt_medical_expense_deduction_joint: 1_000 casualty_loss_deduction: 400 - mt_child_dependent_care_expense_deduction: 123 + mt_child_dependent_care_expense_deduction_joint: 123 mt_federal_income_tax_deduction_unit: 2_000 state_code: MT output: @@ -22,7 +22,7 @@ mt_salt_deduction: 10_000 mt_medical_expense_deduction_joint: 3_000 casualty_loss_deduction: 0 - mt_child_dependent_care_expense_deduction: 0 + mt_child_dependent_care_expense_deduction_joint: 0 mt_federal_income_tax_deduction_unit: 2_000 state_code: MT output: @@ -37,7 +37,7 @@ mt_salt_deduction: 1_035 mt_medical_expense_deduction_joint: 3_000 casualty_loss_deduction: 745 - mt_child_dependent_care_expense_deduction: 1_004 + mt_child_dependent_care_expense_deduction_joint: 1_004 mt_federal_income_tax_deduction_unit: 2_000 state_code: MT output: diff --git a/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.py b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.py index e4a6976f246..4f18254eed0 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.py @@ -8,7 +8,12 @@ class mt_elderly_homeowner_or_renter_credit_gross_household_income(Variable): unit = USD definition_period = YEAR defined_for = StateCode.MT - reference = "https://law.justia.com/codes/montana/2022/title-15/chapter-30/part-23/section-15-30-2337/" + reference = ( + "https://law.justia.com/codes/montana/2022/title-15/chapter-30/part-23/section-15-30-2337/", + "https://mca.legmt.gov/bills/mca/title_0150/chapter_0300/part_0230/section_0370/0150-0300-0230-0370.html", + # 2023 Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 9 + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=52", + ) def formula(person, period, parameters): p = parameters( @@ -20,4 +25,11 @@ def formula(person, period, parameters): social_security = person("social_security", period) taxable_social_security = person("taxable_social_security", period) untaxed_social_security = max_(social_security - taxable_social_security, 0) - return sources + untaxed_social_security + # Income is federal AGI "without regard to loss" (§ 15-30-2337(9)(a)), + # so the business and capital losses deducted in computing federal + # AGI are added back (2023 Form 2EC line 9: "The gross household + # income cannot be reduced by any losses."). The return's losses are + # added once, to the head. + head = person("is_tax_unit_head", period) + losses = head * person.tax_unit("loss_ald", period) + return sources + untaxed_social_security + losses diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.py index 2efb5ad2407..a7ee18fe4f8 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.py @@ -7,9 +7,16 @@ class mt_child_dependent_care_expense_deduction(Variable): label = "Montana child dependent care expense deduction" unit = USD definition_period = YEAR + documentation = ( + "The deduction in each filer's column: an unmarried filer's return, or " + "each spouse's column when spouses file separately on the same form. " + "A joint return uses mt_child_dependent_care_expense_deduction_joint." + ) reference = ( "https://mca.legmt.gov/bills/2019/mca/title_0150/chapter_0300/part_0210/section_0310/0150-0300-0210-0310.html", "https://web.archive.org/web/20230914140156/https://mtrevenue.gov/wp-content/uploads/dlm_uploads/2022/12/2441-M_2022.pdf#page=1", + # 2022 Form 2 instructions, Itemized Deductions Schedule, line 14 + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=35", ) defined_for = StateCode.MT @@ -19,26 +26,21 @@ def formula(person, period, parameters): ).gov.states.mt.tax.income.deductions.child_dependent_care_expense if not p.in_effect: return 0 - tax_unit = person.tax_unit - members = tax_unit.members - qualifying_individual = members( - "mt_child_dependent_care_expense_deduction_qualifying_individual", - period, - ) - # Form 2441-M line 1 - qualifying_individuals = tax_unit.sum(qualifying_individual) - qualifying_care_expenses = tax_unit.sum( - members("care_expenses", period) * qualifying_individual + # Form 2441-M line 2 + eligible_expenses = person.tax_unit( + "mt_child_dependent_care_expense_deduction_eligible_expenses", period ) - childcare_expenses = tax_unit("tax_unit_childcare_expenses", period) - total_expenses = childcare_expenses + qualifying_care_expenses - # Form 2441-M line 2: the lesser of actual dependent care expenses - # or the cap based on the number of qualifying individuals. - capped_expenses = min_(total_expenses, p.cap.calc(qualifying_individuals)) - # Line 3 - agi = person("mt_agi_indiv", period) - # Line 6 - reduction = p.phase_out.calc(agi) - # The deduction has to be allocated equally between spouses + # Line 3: add the Montana adjusted gross income in columns A and B, + # that is, the couple's combined income, not each spouse's own. head_or_spouse = person("is_tax_unit_head_or_spouse", period) - return head_or_spouse * (max_(0, capped_expenses - reduction) * 0.5) + combined_agi = person.tax_unit.sum( + head_or_spouse * person("mt_agi_indiv", period) + ) + # Lines 4-7 + deduction = max_(eligible_expenses - p.phase_out.calc(combined_agi), 0) + # Spouses filing separately on the same form each enter one-half of + # line 7 in their column; an unmarried filer enters all of it. + married = person.tax_unit("tax_unit_married", period) + head = person("is_tax_unit_head", period) + share = where(married, head_or_spouse * 0.5, head * 1.0) + return deduction * share diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction_eligible_expenses.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction_eligible_expenses.py new file mode 100644 index 00000000000..642214c3e55 --- /dev/null +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction_eligible_expenses.py @@ -0,0 +1,34 @@ +from policyengine_us.model_api import * + + +class mt_child_dependent_care_expense_deduction_eligible_expenses(Variable): + value_type = float + entity = TaxUnit + label = "Montana child and dependent care expenses eligible for the deduction" + unit = USD + definition_period = YEAR + reference = ( + "https://mca.legmt.gov/bills/2019/mca/title_0150/chapter_0300/part_0210/section_0310/0150-0300-0210-0310.html", + "https://web.archive.org/web/20230914140156/https://mtrevenue.gov/wp-content/uploads/dlm_uploads/2022/12/2441-M_2022.pdf#page=1", + ) + defined_for = StateCode.MT + + def formula(tax_unit, period, parameters): + p = parameters( + period + ).gov.states.mt.tax.income.deductions.child_dependent_care_expense + person = tax_unit.members + qualifying_individual = person( + "mt_child_dependent_care_expense_deduction_qualifying_individual", + period, + ) + # Form 2441-M line 1 + qualifying_individuals = tax_unit.sum(qualifying_individual) + qualifying_care_expenses = tax_unit.sum( + person("care_expenses", period) * qualifying_individual + ) + childcare_expenses = tax_unit("tax_unit_childcare_expenses", period) + total_expenses = childcare_expenses + qualifying_care_expenses + # Form 2441-M line 2: the lesser of actual dependent care expenses + # or the cap based on the number of qualifying individuals. + return min_(total_expenses, p.cap.calc(qualifying_individuals)) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction_joint.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction_joint.py new file mode 100644 index 00000000000..ae9a5f6eb02 --- /dev/null +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction_joint.py @@ -0,0 +1,30 @@ +from policyengine_us.model_api import * + + +class mt_child_dependent_care_expense_deduction_joint(Variable): + value_type = float + entity = TaxUnit + label = "Montana child dependent care expense deduction on a joint return" + unit = USD + definition_period = YEAR + reference = ( + "https://mca.legmt.gov/bills/2019/mca/title_0150/chapter_0300/part_0210/section_0310/0150-0300-0210-0310.html", + "https://web.archive.org/web/20230914140156/https://mtrevenue.gov/wp-content/uploads/dlm_uploads/2022/12/2441-M_2022.pdf#page=1", + # 2022 Form 2 instructions, Itemized Deductions Schedule, line 14 + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=35", + ) + defined_for = StateCode.MT + + def formula(tax_unit, period, parameters): + p = parameters( + period + ).gov.states.mt.tax.income.deductions.child_dependent_care_expense + if not p.in_effect: + return 0 + # Form 2441-M line 2 + eligible_expenses = tax_unit( + "mt_child_dependent_care_expense_deduction_eligible_expenses", period + ) + # Line 3: the return's Montana adjusted gross income; lines 4-7. + agi = tax_unit("mt_agi_joint", period) + return max_(eligible_expenses - p.phase_out.calc(agi), 0) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_federal_income_tax_deduction_for_federal_itemization_indiv.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_federal_income_tax_deduction_for_federal_itemization_indiv.py index 94951d1ad9c..967ce5bdfb5 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_federal_income_tax_deduction_for_federal_itemization_indiv.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_federal_income_tax_deduction_for_federal_itemization_indiv.py @@ -7,28 +7,24 @@ class mt_federal_income_tax_deduction_for_federal_itemization_indiv(Variable): definition_period = YEAR label = "Montana federal income tax deduction when married couples are filing separately" reference = ( - "https://law.justia.com/codes/montana/2021/title-15/chapter-30/part-21/section-15-30-2131/" + "https://law.justia.com/codes/montana/2021/title-15/chapter-30/part-21/section-15-30-2131/", # MT Code § 15-30-2131 (2021) (1)(b) + # 2022 Form 2 instructions, Itemized Deductions Schedule, line 4 + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=33", ) unit = USD defined_for = "mt_married_filing_separately_on_same_return_eligible" def formula(person, period, parameters): - unit_deds = person.tax_unit( - "mt_federal_income_tax_deduction_for_federal_itemization", period - ) - person_agi = person("mt_agi_indiv", period) - total_agi = person.tax_unit.sum(person_agi) - - prorate = np.zeros_like(total_agi) - mask = total_agi > 0 - prorate[mask] = person_agi[mask] / total_agi[mask] + p = parameters( + period + ).gov.states.mt.tax.income.deductions.itemized.federal_income_tax + # The withholding estimate is computed on each person's own income, so + # each spouse deducts their own amount, up to their own cap. + head_or_spouse = person("is_tax_unit_head_or_spouse", period) + withheld_income_tax = head_or_spouse * person("mt_withheld_income_tax", period) filing_status = person.tax_unit( "state_filing_status_if_married_filing_separately_on_same_return", period, ) - p = parameters( - period - ).gov.states.mt.tax.income.deductions.itemized.federal_income_tax - cap = p.cap[filing_status] - return min_(unit_deds * prorate, cap) + return min_(withheld_income_tax, p.cap[filing_status]) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.py index 5d1cb0c5153..0d5e7d0e577 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.py @@ -29,6 +29,7 @@ def formula(person, period, parameters): period, [ "mt_misc_deductions", + "mt_child_dependent_care_expense_deduction", "mt_medical_expense_deduction_indiv", "mt_salt_deduction", "mt_federal_income_tax_deduction_for_federal_itemization_indiv", diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.py index 3469bb0b4b3..ed3371fd0ab 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.py @@ -24,6 +24,7 @@ def formula(person, period, parameters): period, [ "mt_misc_deductions", + "mt_child_dependent_care_expense_deduction_joint", "mt_medical_expense_deduction_joint", "mt_salt_deduction", "mt_federal_income_tax_deduction_for_federal_itemization", diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_tax/mt_federal_income_tax_deduction_indiv.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_tax/mt_federal_income_tax_deduction_indiv.py index 792174d9142..f84c008f403 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_tax/mt_federal_income_tax_deduction_indiv.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_tax/mt_federal_income_tax_deduction_indiv.py @@ -7,26 +7,31 @@ class mt_federal_income_tax_deduction_indiv(Variable): definition_period = YEAR label = "Montana federal income tax deduction when married couples are filing separately" reference = ( - "https://law.justia.com/codes/montana/2021/title-15/chapter-30/part-21/section-15-30-2131/" + "https://law.justia.com/codes/montana/2021/title-15/chapter-30/part-21/section-15-30-2131/", # MT Code § 15-30-2131 (2021) (1)(b) + # 2022 Form 2 instructions, Itemized Deductions Schedule, line 4 + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=33", ) unit = USD defined_for = "mt_married_filing_separately_on_same_return_eligible" def formula(person, period, parameters): - unit_deds = person.tax_unit("mt_federal_income_tax_deduction_unit", period) - person_agi = person("mt_agi_indiv", period) - total_agi = person.tax_unit.sum(person_agi) - - prorate = np.zeros_like(total_agi) - mask = total_agi > 0 - prorate[mask] = person_agi[mask] / total_agi[mask] + p = parameters( + period + ).gov.states.mt.tax.income.deductions.itemized.federal_income_tax + if not p.applies: + return 0 + # Federal income tax is reported by the spouse who earned the income + # it was paid on, and each spouse is held to their own cap; the + # deduction cannot be arbitrarily allocated. Without each spouse's + # federal withholding, attribute the couple's federal income tax by + # each spouse's share of federal adjusted gross income, then cap it. + federal_income_tax = max_( + person.tax_unit("income_tax_before_refundable_credits", period), 0 + ) + share = person("mt_federal_income_tax_deduction_share", period) filing_status = person.tax_unit( "state_filing_status_if_married_filing_separately_on_same_return", period, ) - p = parameters( - period - ).gov.states.mt.tax.income.deductions.itemized.federal_income_tax - cap = p.cap[filing_status] - return min_(unit_deds * prorate, cap) + return min_(federal_income_tax * share, p.cap[filing_status]) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_tax/mt_federal_income_tax_deduction_share.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_tax/mt_federal_income_tax_deduction_share.py new file mode 100644 index 00000000000..2c6dfd8556b --- /dev/null +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_tax/mt_federal_income_tax_deduction_share.py @@ -0,0 +1,33 @@ +from policyengine_us.model_api import * + + +class mt_federal_income_tax_deduction_share(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "Share of the couple's federal income tax attributed to each spouse for the Montana deduction" + reference = ( + # 2022 Form 2 instructions, Itemized Deductions Schedule, line 4a: + # "If you are married filing separately with your spouse, the federal + # income tax withheld should be reported by the spouse who earned the + # income." + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=33", + ) + unit = "/1" + defined_for = "mt_married_filing_separately_on_same_return_eligible" + + def formula(person, period, parameters): + # Each filer's share of the federal income the tax was paid on, + # counting only positive federal adjusted gross income. A dependent's + # income is on the dependent's own return. With no positive income, + # the tax is attributed to the head. + head_or_spouse = person("is_tax_unit_head_or_spouse", period) + income = head_or_spouse * max_( + person("adjusted_gross_income_person", period), 0 + ) + total_income = person.tax_unit.sum(income) + share = np.zeros_like(total_income) + mask = total_income > 0 + share[mask] = income[mask] / total_income[mask] + head = person("is_tax_unit_head", period) + return where(total_income > 0, share, head) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_indiv.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_indiv.py index 7b31319e265..ff75bc2277f 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_indiv.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_indiv.py @@ -31,6 +31,7 @@ def formula(person, period, parameters): period, [ "mt_misc_deductions", + "mt_child_dependent_care_expense_deduction", "mt_medical_expense_deduction_indiv", "mt_salt_deduction", "mt_federal_income_tax_deduction_indiv", diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_joint.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_joint.py index a3328b0290d..1a13c3a97de 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_joint.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_joint.py @@ -24,6 +24,7 @@ def formula(person, period, parameters): period, [ "mt_misc_deductions", + "mt_child_dependent_care_expense_deduction_joint", "mt_medical_expense_deduction_joint", "mt_salt_deduction", "mt_federal_income_tax_deduction_unit", From 304d880bb6e205730d6dd25b00db4cb89f8551ca Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 6 Oct 2026 07:34:58 -0400 Subject: [PATCH 2/6] Update the 2021 Montana rebate case for per-spouse federal tax deductions Each spouse filing separately on the same form deducts their own federal income tax up to $5,000, so both spouses itemize and Montana tax is 6,295.56. Co-Authored-By: Claude Opus 5.5 --- .../baseline/gov/states/mt/tax/income/integration.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/integration.yaml index 1427235ceaa..687a3ecabbf 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/integration.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/integration.yaml @@ -564,9 +564,12 @@ output: # $2,500 per-return cap split $1,250 per spouse (was double-counted to $5,000) mt_income_tax_rebate: [1_250, 1_250] - # Files separately: 5,099.51 - 1,250 + 3,719.51 - 1,250 = 6,319.02 + # Each spouse deducts their own federal income tax up to $5,000 (2021 + # federal tax 21,175 attributed 90/160 and 70/160), so both itemize 5,000 + # over the 4,830 standard deduction. Taxable income 82,420 and 62,420. + # Files separately: 5,087.78 - 1,250 + 3,707.78 - 1,250 = 6,295.56 # (old double-count subtracted $2,500 per column, understating tax by $2,500) - mt_income_tax: 6_319.02 + mt_income_tax: 6_295.56 - name: MT property tax rebate is not a Form 2 credit and is not tripled (issue 9347) absolute_error_margin: 0.01 From 6eefe271dc9ea5e5bd119221eb70b6e176801e8e Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 6 Oct 2026 08:30:36 -0400 Subject: [PATCH 3/6] Address review: no care deduction on a separate form; name the 2023 schedule - A married person filing on a separate form (federal filing status SEPARATE) cannot take the child and dependent care expense deduction: "married couples shall file a joint return or file separately on the same form" (MCA 15-30-2131(1)(c)(vi)(A)); 2022 instructions, line 14. - The 2023 credit schedule was the Elderly Homeowner/Renter Credit Schedule; it became Schedule 2EC in 2024. Co-Authored-By: Claude Opus 5.5 --- ...mt_elderly_homeowner_or_renter_credit.yaml | 2 +- ..._renter_credit_gross_household_income.yaml | 5 ++-- ...hild_dependent_care_expense_deduction.yaml | 28 +++++++++++++++++++ ...or_renter_credit_gross_household_income.py | 7 +++-- ..._child_dependent_care_expense_deduction.py | 7 ++++- ..._dependent_care_expense_deduction_joint.py | 7 ++++- 6 files changed, 48 insertions(+), 8 deletions(-) diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.yaml index 154bf57d561..8cfb8bc8538 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.yaml @@ -224,7 +224,7 @@ # contribution, so the credit is higher: $539.67. mt_elderly_homeowner_or_renter_credit: 539.67 -- name: 2023 Form 2EC worked case, a capital loss does not reduce gross household income +- name: 2023 Elderly Homeowner/Renter Credit Schedule worked case, a capital loss does not reduce gross household income period: 2023 absolute_error_margin: 0.01 input: diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml index f7d12a544dc..38e02773559 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.yaml @@ -55,7 +55,8 @@ members: [person1] state_name: MT output: - # § 15-30-2337(9)(a): federal AGI "without regard to loss". 2023 Form 2EC: + # § 15-30-2337(9)(a): federal AGI "without regard to loss". 2023 Elderly + # Homeowner/Renter Credit Schedule: # line 1 federal AGI 20_000 - 3_000 = 17_000; line 9 adds back the 3_000 # capital loss; line 10 = 20_000. mt_elderly_homeowner_or_renter_credit_gross_household_income: 20_000 @@ -81,6 +82,6 @@ state_name: MT output: # Federal AGI 20_000 - 5_000 = 15_000; the 5_000 loss is added back, so - # gross household income is 20_000 (Form 2EC line 18). Net household + # gross household income is 20_000 (2024 Schedule 2EC line 18). Net household # income: (20_000 - 12_600) * 0.035 = 259, allocated to the head. mt_elderly_homeowner_or_renter_credit_net_household_income: [259, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.yaml index b7ce4721911..4cdfcd2395d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.yaml @@ -721,3 +721,31 @@ state_code: MT output: mt_child_dependent_care_expense_deduction_joint: 0 + +- name: Case 28, a married person filing on a separate form cannot take the deduction + period: 2022 + input: + people: + person1: + is_tax_unit_head: true + mt_agi_indiv: 15_000 + person2: + age: 5 + is_tax_unit_dependent: true + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SEPARATE + tax_unit_childcare_expenses: 2_000 + mt_agi_joint: 15_000 + households: + household: + members: [person1, person2] + state_code: MT + output: + # MCA 15-30-2131(1)(c)(vi)(A): "married couples shall file a joint return + # or file separately on the same form". 2022 instructions, line 14: "If + # you are married and filing separately on separate forms, or your spouse + # is not filing, you cannot qualify for this deduction." + mt_child_dependent_care_expense_deduction: [0, 0] + mt_child_dependent_care_expense_deduction_joint: 0 diff --git a/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.py b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.py index 4f18254eed0..21c77cdc399 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_gross_household_income.py @@ -12,6 +12,7 @@ class mt_elderly_homeowner_or_renter_credit_gross_household_income(Variable): "https://law.justia.com/codes/montana/2022/title-15/chapter-30/part-23/section-15-30-2337/", "https://mca.legmt.gov/bills/mca/title_0150/chapter_0300/part_0230/section_0370/0150-0300-0230-0370.html", # 2023 Form 2 instructions, Elderly Homeowner/Renter Credit Schedule, line 9 + # (renamed Schedule 2EC from 2024) "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=52", ) @@ -27,9 +28,9 @@ def formula(person, period, parameters): untaxed_social_security = max_(social_security - taxable_social_security, 0) # Income is federal AGI "without regard to loss" (§ 15-30-2337(9)(a)), # so the business and capital losses deducted in computing federal - # AGI are added back (2023 Form 2EC line 9: "The gross household - # income cannot be reduced by any losses."). The return's losses are - # added once, to the head. + # AGI are added back (2023 Elderly Homeowner/Renter Credit Schedule, + # line 9: "The gross household income cannot be reduced by any + # losses."). The return's losses are added once, to the head. head = person("is_tax_unit_head", period) losses = head * person.tax_unit("loss_ald", period) return sources + untaxed_social_security + losses diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.py index a7ee18fe4f8..229fe2db8e6 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction.py @@ -43,4 +43,9 @@ def formula(person, period, parameters): married = person.tax_unit("tax_unit_married", period) head = person("is_tax_unit_head", period) share = where(married, head_or_spouse * 0.5, head * 1.0) - return deduction * share + # Married couples must file a joint return or file separately on the + # same form (MCA 15-30-2131(1)(c)(vi)(A)); a spouse filing on a + # separate form cannot take the deduction. + filing_status = person.tax_unit("filing_status", period) + separate_form = filing_status == filing_status.possible_values.SEPARATE + return deduction * share * ~separate_form diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction_joint.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction_joint.py index ae9a5f6eb02..967ce181cb0 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction_joint.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/cdcc/mt_child_dependent_care_expense_deduction_joint.py @@ -27,4 +27,9 @@ def formula(tax_unit, period, parameters): ) # Line 3: the return's Montana adjusted gross income; lines 4-7. agi = tax_unit("mt_agi_joint", period) - return max_(eligible_expenses - p.phase_out.calc(agi), 0) + deduction = max_(eligible_expenses - p.phase_out.calc(agi), 0) + # A married person filing on a separate form cannot take the deduction + # (MCA 15-30-2131(1)(c)(vi)(A)). + filing_status = tax_unit("filing_status", period) + separate_form = filing_status == filing_status.possible_values.SEPARATE + return deduction * ~separate_form From 95d94db81e660b0fdb7fd8d11a63883435e2b218 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 6 Oct 2026 08:31:26 -0400 Subject: [PATCH 4/6] Count a Montana casualty loss once per joint return and per owning spouse mt_misc_deductions is a Person variable whose `adds` list included the TaxUnit casualty_loss_deduction. policyengine-core evaluates `adds` with calculate(..., map_to=person), which projects a tax-unit value onto every member, so the joint path (summing over the tax unit) counted a couple's casualty loss once per member, and each spouse filing separately got the full amount. Replace it with two Montana variables following the 2021-2023 Form 2 instructions, Itemized Deductions Schedule line 15: complete federal Form 4684 using Montana AGI in place of federal AGI; spouses filing separately each complete their own Form 4684 (and a deduction attributable to one spouse is claimed by that spouse). - mt_casualty_loss_deduction_joint (TaxUnit): the unit's loss above 10% of mt_agi_joint, counted once. - mt_casualty_loss_deduction_indiv (Person): each spouse's own loss above 10% of their own mt_agi_indiv; dependents' losses go to the head, as mt_agi_indiv does with dependents' income. - casualty_loss/applies ends the line in 2024, when Montana discontinued its Itemized Deductions Schedule (2024 instructions, p. 8). With the child care deduction moved out of the misc list (stacked on fix-mt-separate-filing-allocations), the list held only the casualty loss, so the list parameter and mt_misc_deductions are removed. Co-Authored-By: Claude Opus 5.5 --- ...x-mt-casualty-loss-misc-deduction.fixed.md | 1 + .../itemized/casualty_loss/applies.yaml | 20 +++ .../deductions/itemized/misc_deductions.yaml | 25 ---- .../mt_casualty_loss_deduction_indiv.yaml | 107 ++++++++++++++ .../mt_casualty_loss_deduction_joint.yaml | 133 ++++++++++++++++++ ...uctions_for_federal_itemization_indiv.yaml | 44 +++++- ...uctions_for_federal_itemization_joint.yaml | 72 +++++++++- .../mt_itemized_deductions_indiv.yaml | 44 +++++- .../mt_itemized_deductions_joint.yaml | 72 +++++++++- .../mt_casualty_loss_deduction_indiv.py | 38 +++++ .../mt_casualty_loss_deduction_joint.py | 26 ++++ ...eductions_for_federal_itemization_indiv.py | 2 +- ...eductions_for_federal_itemization_joint.py | 2 +- .../general/mt_itemized_deductions_indiv.py | 2 +- .../general/mt_itemized_deductions_joint.py | 2 +- .../itemized/general/mt_misc_deductions.py | 17 --- 16 files changed, 535 insertions(+), 72 deletions(-) create mode 100644 changelog.d/fix-mt-casualty-loss-misc-deduction.fixed.md create mode 100644 policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/casualty_loss/applies.yaml delete mode 100644 policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/misc_deductions.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.yaml create mode 100644 policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.py create mode 100644 policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.py delete mode 100644 policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_misc_deductions.py diff --git a/changelog.d/fix-mt-casualty-loss-misc-deduction.fixed.md b/changelog.d/fix-mt-casualty-loss-misc-deduction.fixed.md new file mode 100644 index 00000000000..63e5c33d9ac --- /dev/null +++ b/changelog.d/fix-mt-casualty-loss-misc-deduction.fixed.md @@ -0,0 +1 @@ +Count a Montana casualty and theft loss once on a joint return, and only in the column of the spouse who had it when spouses file separately, with the 10% floor on Montana AGI (2021-2023 Form 2 Itemized Deductions Schedule, line 15). diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/casualty_loss/applies.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/casualty_loss/applies.yaml new file mode 100644 index 00000000000..cd9a5c74f67 --- /dev/null +++ b/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/casualty_loss/applies.yaml @@ -0,0 +1,20 @@ +description: Montana allows a casualty and theft loss deduction on its Itemized Deductions Schedule, if this is true. +metadata: + label: Montana casualty and theft loss deduction applies + period: year + unit: bool + reference: + - title: 2021 Montana Form 2 Instructions, Itemized Deductions Schedule, line 15 + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2021_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=34 + - title: 2022 Montana Form 2 Instructions, Itemized Deductions Schedule, line 15 + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=35 + - title: 2023 Montana Form 2 Instructions, Itemized Deductions Schedule, line 15 + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=39 + # From 2024, Montana taxable income starts from federal taxable income and + # the Itemized Deductions Schedule is discontinued (SB 399). + - title: 2024 Montana Form 2 Instructions, Discontinued Worksheets and Schedules + href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2024_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=8 + +values: + 2021-01-01: true + 2024-01-01: false diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/misc_deductions.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/misc_deductions.yaml deleted file mode 100644 index c4744269768..00000000000 --- a/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/misc_deductions.yaml +++ /dev/null @@ -1,25 +0,0 @@ -description: Montana counts these sources as miscellaneous deductions. -# The child and dependent care expense deduction is also a miscellaneous -# deduction (Form 2 Itemized Deductions Schedule, line 14). It is added -# separately because its income limit uses the return's own Montana AGI, which -# differs between a joint return and separate columns (Form 2441-M line 3). -values: - 2021-01-01: - - casualty_loss_deduction - 2024-01-01: [] - -metadata: - unit: list - label: Montana miscellaneous deductions - period: year - reference: - - title: Montana Individual Income Tax Return (Form 2) 2024 - href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2024_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=8 - - title: Montana Individual Income Tax Return (Form 2) 2022 - href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2/2022_Montana_Individual_Income_Tax_Return_Form_2.pdf#page=7 - - title: Montana Individual Income Tax Return (Form 2) 2021 - href: https://revenue.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2/2021_Montana_Individual_Income_Tax_Return_Form_2.pdf#page=7 - - title: Montana Tax From Instructions 2021 - href: https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=35 - - title: MT Code § 15-30-2131 (2022) (1)(a)&(c) - href: https://law.justia.com/codes/montana/2022/title-15/chapter-30/part-21/section-15-30-2131/ diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.yaml new file mode 100644 index 00000000000..45789157040 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.yaml @@ -0,0 +1,107 @@ +# 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 (PDF pp. 35-36): +# "To determine your casualty and/or theft loss, use your Montana Adjusted +# Gross Income in place of the Federal Adjusted Gross Income. If you and your +# spouse are filing separately, you each should complete a separate federal +# Form 4684 to determine the amount of your separate casualty and/or theft +# loss." +# 2022 Form 2 instructions, Filing Separately When Married (PDF p. 11): +# "Deductions that are attributable to only one spouse must be claimed by that +# spouse." +# Form 4684 allows the loss above 10% of adjusted gross income. The federal +# suspension of losses outside federally declared disasters is modeled by +# gov.irs.deductions.itemized.casualty.active, which these tests switch on. + +- name: Only the spouse who had the loss deducts it, above 10% of their own Montana AGI + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + casualty_loss: 30_000 + mt_agi_indiv: 60_000 + person2: + age: 40 + mt_agi_indiv: 40_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MT + output: + # 30,000 - 10% x 60,000; the spouse has no loss. + mt_casualty_loss_deduction_indiv: [24_000, 0] + +- name: Each spouse's loss is floored at 10% of that spouse's Montana AGI + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + casualty_loss: 30_000 + mt_agi_indiv: 60_000 + person2: + age: 40 + casualty_loss: 5_000 + mt_agi_indiv: 40_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MT + output: + # 30,000 - 6,000 and 5,000 - 4,000. + mt_casualty_loss_deduction_indiv: [24_000, 1_000] + +- name: A dependent's loss goes to the head, with the dependent's income + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + mt_agi_indiv: 60_000 + person2: + age: 40 + mt_agi_indiv: 40_000 + person3: + age: 10 + is_tax_unit_dependent: true + casualty_loss: 10_000 + mt_agi_indiv: 0 + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + # 10,000 - 10% x 60,000, in the head's column. + mt_casualty_loss_deduction_indiv: [4_000, 0, 0] + +- name: Losses outside federally declared disasters are suspended + period: 2022 + input: + people: + person1: + age: 40 + casualty_loss: 30_000 + mt_agi_indiv: 60_000 + person2: + age: 40 + mt_agi_indiv: 40_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_casualty_loss_deduction_indiv: [0, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.yaml new file mode 100644 index 00000000000..2a70d9efad0 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.yaml @@ -0,0 +1,133 @@ +# 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 (PDF pp. 35-36): +# "You may deduct a casualty and theft loss from a federally declared disaster +# (other than net qualified disaster losses). If you have a casualty and/or +# theft loss, complete federal Form 4684 to figure the amount of the Montana +# loss that you can enter on this line. To determine your casualty and/or theft +# loss, use your Montana Adjusted Gross Income in place of the Federal Adjusted +# Gross Income." and "Deductions for all other casualty and theft losses are +# suspended until tax years beginning after December 31, 2025." +# Form 4684 allows the loss above 10% of adjusted gross income. The federal +# suspension is modeled by gov.irs.deductions.itemized.casualty.active, which +# these tests switch on to exercise a deductible loss. + +- name: A joint return deducts the couple's loss once, above 10% of Montana AGI + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + casualty_loss: 30_000 + person2: + age: 40 + tax_units: + tax_unit: + members: [person1, person2] + mt_agi_joint: 100_000 + households: + household: + members: [person1, person2] + state_code: MT + output: + # 30,000 - 10% x 100,000 + mt_casualty_loss_deduction_joint: 20_000 + +- name: Both spouses' losses go on the joint return's one Form 4684 + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + casualty_loss: 30_000 + person2: + age: 40 + casualty_loss: 5_000 + tax_units: + tax_unit: + members: [person1, person2] + mt_agi_joint: 100_000 + households: + household: + members: [person1, person2] + state_code: MT + output: + # 35,000 - 10% x 100,000 + mt_casualty_loss_deduction_joint: 25_000 + +- name: The 10% floor uses Montana AGI, not federal AGI + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + employment_income: 100_000 + casualty_loss: 30_000 + tax_units: + tax_unit: + members: [person1] + mt_agi_joint: 80_000 + households: + household: + members: [person1] + state_code: MT + output: + # 30,000 - 10% x 80,000. The federal floor would give 30,000 - 10,000. + mt_casualty_loss_deduction_joint: 22_000 + +- name: A loss at or below 10% of Montana AGI is not deductible + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + casualty_loss: 8_000 + tax_units: + tax_unit: + members: [person1] + mt_agi_joint: 100_000 + households: + household: + members: [person1] + state_code: MT + output: + mt_casualty_loss_deduction_joint: 0 + +- name: Losses outside federally declared disasters are suspended + period: 2022 + input: + people: + person1: + age: 40 + casualty_loss: 30_000 + tax_units: + tax_unit: + members: [person1] + mt_agi_joint: 100_000 + households: + household: + members: [person1] + state_code: MT + output: + mt_casualty_loss_deduction_joint: 0 + +- name: Montana discontinued its Itemized Deductions Schedule in 2024 + period: 2024 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + casualty_loss: 30_000 + tax_units: + tax_unit: + members: [person1] + mt_agi_joint: 100_000 + households: + household: + members: [person1] + state_code: MT + output: + mt_casualty_loss_deduction_joint: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.yaml index 4435e64a801..0c0eebb22af 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.yaml @@ -5,7 +5,7 @@ investment_interest_expense: 265 mt_salt_deduction: 5_000 mt_medical_expense_deduction_indiv: 1_000 - casualty_loss_deduction: 400 + mt_casualty_loss_deduction_indiv: 400 mt_child_dependent_care_expense_deduction: 123 mt_federal_income_tax_deduction_for_federal_itemization_indiv: 2_000 state_code: MT @@ -19,7 +19,7 @@ investment_interest_expense: 1_234 mt_salt_deduction: 10_000 mt_medical_expense_deduction_indiv: 3_000 - casualty_loss_deduction: 0 + mt_casualty_loss_deduction_indiv: 0 mt_child_dependent_care_expense_deduction: 0 mt_federal_income_tax_deduction_for_federal_itemization_indiv: 2_000 state_code: MT @@ -33,7 +33,7 @@ mortgage_interest: 34 mt_salt_deduction: 1_035 mt_medical_expense_deduction_indiv: 3_000 - casualty_loss_deduction: 745 + mt_casualty_loss_deduction_indiv: 745 mt_child_dependent_care_expense_deduction: 1_004 mt_federal_income_tax_deduction_for_federal_itemization_indiv: 2_000 state_code: MT @@ -47,20 +47,20 @@ people: person1: is_tax_unit_head_or_spouse: true - mt_misc_deductions: 100 + mt_casualty_loss_deduction_indiv: 100 mt_medical_expense_deduction_indiv: 200 mt_salt_deduction: 300 mt_federal_income_tax_deduction_for_federal_itemization_indiv: 400 person2: is_tax_unit_head_or_spouse: true - mt_misc_deductions: 100 + mt_casualty_loss_deduction_indiv: 100 mt_medical_expense_deduction_indiv: 200 mt_salt_deduction: 300 mt_federal_income_tax_deduction_for_federal_itemization_indiv: 100 person3: is_tax_unit_head_or_spouse: false is_tax_unit_dependent: true - mt_misc_deductions: 100 + mt_casualty_loss_deduction_indiv: 100 mt_medical_expense_deduction_indiv: 12 mt_salt_deduction: 200 mt_federal_income_tax_deduction_for_federal_itemization_indiv: 100 @@ -74,3 +74,35 @@ state_code: MT output: mt_itemized_deductions_for_federal_itemization_indiv: [1_000, 700, 0] + +# 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 (PDF pp. 35-36): +# complete federal Form 4684 using Montana AGI in place of federal AGI; spouses +# filing separately each complete their own Form 4684. The casualty loss is a +# tax unit amount, so it must not be repeated for each member. + +- name: Only the spouse who had the casualty loss deducts it when filing separately + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + employment_income: 60_000 + casualty_loss: 30_000 + mt_salt_deduction: 0 + mt_federal_income_tax_deduction_for_federal_itemization_indiv: 0 + person2: + age: 40 + employment_income: 40_000 + mt_salt_deduction: 0 + mt_federal_income_tax_deduction_for_federal_itemization_indiv: 0 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MT + output: + # 30,000 - 10% x 60,000 Montana AGI in the head's column; none for the spouse. + mt_itemized_deductions_for_federal_itemization_indiv: [24_000, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml index 41a8d808975..616477e630d 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml @@ -6,7 +6,7 @@ investment_interest_expense: 265 mt_salt_deduction: 5_000 mt_medical_expense_deduction_joint: 1_000 - casualty_loss_deduction: 400 + mt_casualty_loss_deduction_joint: 400 mt_child_dependent_care_expense_deduction_joint: 123 mt_federal_income_tax_deduction_for_federal_itemization: 2_000 state_code: MT @@ -21,7 +21,7 @@ mortgage_interest: 1_234 mt_salt_deduction: 10_000 mt_medical_expense_deduction_joint: 3_000 - casualty_loss_deduction: 0 + mt_casualty_loss_deduction_joint: 0 mt_child_dependent_care_expense_deduction_joint: 0 mt_federal_income_tax_deduction_for_federal_itemization: 2_000 state_code: MT @@ -36,7 +36,7 @@ mortgage_interest: 34 mt_salt_deduction: 1_035 mt_medical_expense_deduction_joint: 3_000 - casualty_loss_deduction: 745 + mt_casualty_loss_deduction_joint: 745 mt_child_dependent_care_expense_deduction_joint: 1_004 mt_federal_income_tax_deduction_for_federal_itemization: 2_000 state_code: MT @@ -50,18 +50,15 @@ people: person1: is_tax_unit_head: true - mt_misc_deductions: 100 mt_medical_expense_deduction_joint: 200 mt_salt_deduction: 300 investment_interest_expense: 100 person2: is_tax_unit_head: false - mt_misc_deductions: 100 mt_medical_expense_deduction_joint: 200 mt_salt_deduction: 300 person3: is_tax_unit_head: false - mt_misc_deductions: 100 mt_medical_expense_deduction_joint: 12 mt_salt_deduction: 200 households: @@ -72,5 +69,66 @@ tax_unit: members: [person1, person2, person3] mt_federal_income_tax_deduction_for_federal_itemization: 600 + mt_casualty_loss_deduction_joint: 100 output: - mt_itemized_deductions_for_federal_itemization_joint: [2_212, 0, 0] + mt_itemized_deductions_for_federal_itemization_joint: [2_012, 0, 0] + +# 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 (PDF pp. 35-36): +# complete federal Form 4684 using Montana AGI in place of federal AGI; spouses +# filing separately each complete their own Form 4684. The casualty loss is a +# tax unit amount, so it must not be repeated for each member. + +- name: A couple's casualty loss counts once on a joint return + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + employment_income: 60_000 + casualty_loss: 30_000 + mt_salt_deduction: 0 + person2: + age: 40 + employment_income: 40_000 + mt_salt_deduction: 0 + tax_units: + tax_unit: + members: [person1, person2] + mt_federal_income_tax_deduction_for_federal_itemization: 0 + households: + household: + members: [person1, person2] + state_code: MT + output: + # 30,000 - 10% x 100,000 Montana AGI, counted once. + mt_itemized_deductions_for_federal_itemization_joint: [20_000, 0] + +- name: A dependent in the tax unit does not repeat the joint casualty loss + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + employment_income: 60_000 + casualty_loss: 30_000 + mt_salt_deduction: 0 + person2: + age: 40 + employment_income: 40_000 + mt_salt_deduction: 0 + person3: + age: 10 + is_tax_unit_dependent: true + mt_salt_deduction: 0 + tax_units: + tax_unit: + members: [person1, person2, person3] + mt_federal_income_tax_deduction_for_federal_itemization: 0 + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + mt_itemized_deductions_for_federal_itemization_joint: [20_000, 0, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_indiv.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_indiv.yaml index 2bc390f8ad3..8f5d35063f0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_indiv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_indiv.yaml @@ -5,7 +5,7 @@ investment_interest_expense: 265 mt_salt_deduction: 5_000 mt_medical_expense_deduction_indiv: 1_000 - casualty_loss_deduction: 400 + mt_casualty_loss_deduction_indiv: 400 mt_child_dependent_care_expense_deduction: 123 mt_federal_income_tax_deduction_indiv: 2_000 state_code: MT @@ -19,7 +19,7 @@ investment_interest_expense: 1_234 mt_salt_deduction: 10_000 mt_medical_expense_deduction_indiv: 3_000 - casualty_loss_deduction: 0 + mt_casualty_loss_deduction_indiv: 0 mt_child_dependent_care_expense_deduction: 0 mt_federal_income_tax_deduction_indiv: 2_000 state_code: MT @@ -33,7 +33,7 @@ mortgage_interest: 34 mt_salt_deduction: 1_035 mt_medical_expense_deduction_indiv: 3_000 - casualty_loss_deduction: 745 + mt_casualty_loss_deduction_indiv: 745 mt_child_dependent_care_expense_deduction: 1_004 mt_federal_income_tax_deduction_indiv: 2_000 state_code: MT @@ -47,20 +47,20 @@ people: person1: is_tax_unit_head_or_spouse: true - mt_misc_deductions: 100 + mt_casualty_loss_deduction_indiv: 100 mt_medical_expense_deduction_indiv: 200 mt_salt_deduction: 300 mt_federal_income_tax_deduction_indiv: 400 person2: is_tax_unit_head_or_spouse: true - mt_misc_deductions: 100 + mt_casualty_loss_deduction_indiv: 100 mt_medical_expense_deduction_indiv: 200 mt_salt_deduction: 300 mt_federal_income_tax_deduction_indiv: 100 person3: is_tax_unit_head_or_spouse: false is_tax_unit_dependent: true - mt_misc_deductions: 100 + mt_casualty_loss_deduction_indiv: 100 mt_medical_expense_deduction_indiv: 12 mt_salt_deduction: 200 mt_federal_income_tax_deduction_indiv: 100 @@ -74,3 +74,35 @@ state_code: MT output: mt_itemized_deductions_indiv: [1_000, 700, 0] + +# 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 (PDF pp. 35-36): +# complete federal Form 4684 using Montana AGI in place of federal AGI; spouses +# filing separately each complete their own Form 4684. The casualty loss is a +# tax unit amount, so it must not be repeated for each member. + +- name: Only the spouse who had the casualty loss deducts it when filing separately + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + employment_income: 60_000 + casualty_loss: 30_000 + mt_salt_deduction: 0 + mt_federal_income_tax_deduction_indiv: 0 + person2: + age: 40 + employment_income: 40_000 + mt_salt_deduction: 0 + mt_federal_income_tax_deduction_indiv: 0 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MT + output: + # 30,000 - 10% x 60,000 Montana AGI in the head's column; none for the spouse. + mt_itemized_deductions_indiv: [24_000, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml index 329641eafa3..a9daeb667a3 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml @@ -6,7 +6,7 @@ investment_interest_expense: 265 mt_salt_deduction: 5_000 mt_medical_expense_deduction_joint: 1_000 - casualty_loss_deduction: 400 + mt_casualty_loss_deduction_joint: 400 mt_child_dependent_care_expense_deduction_joint: 123 mt_federal_income_tax_deduction_unit: 2_000 state_code: MT @@ -21,7 +21,7 @@ mortgage_interest: 1_234 mt_salt_deduction: 10_000 mt_medical_expense_deduction_joint: 3_000 - casualty_loss_deduction: 0 + mt_casualty_loss_deduction_joint: 0 mt_child_dependent_care_expense_deduction_joint: 0 mt_federal_income_tax_deduction_unit: 2_000 state_code: MT @@ -36,7 +36,7 @@ mortgage_interest: 34 mt_salt_deduction: 1_035 mt_medical_expense_deduction_joint: 3_000 - casualty_loss_deduction: 745 + mt_casualty_loss_deduction_joint: 745 mt_child_dependent_care_expense_deduction_joint: 1_004 mt_federal_income_tax_deduction_unit: 2_000 state_code: MT @@ -50,18 +50,15 @@ people: person1: is_tax_unit_head: true - mt_misc_deductions: 100 mt_medical_expense_deduction_joint: 200 mt_salt_deduction: 300 investment_interest_expense: 100 person2: is_tax_unit_head: false - mt_misc_deductions: 100 mt_medical_expense_deduction_joint: 200 mt_salt_deduction: 300 person3: is_tax_unit_head: false - mt_misc_deductions: 100 mt_medical_expense_deduction_joint: 12 mt_salt_deduction: 200 households: @@ -72,5 +69,66 @@ tax_unit: members: [person1, person2, person3] mt_federal_income_tax_deduction_unit: 600 + mt_casualty_loss_deduction_joint: 100 output: - mt_itemized_deductions_joint: [2_212, 0, 0] + mt_itemized_deductions_joint: [2_012, 0, 0] + +# 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 (PDF pp. 35-36): +# complete federal Form 4684 using Montana AGI in place of federal AGI; spouses +# filing separately each complete their own Form 4684. The casualty loss is a +# tax unit amount, so it must not be repeated for each member. + +- name: A couple's casualty loss counts once on a joint return + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + employment_income: 60_000 + casualty_loss: 30_000 + mt_salt_deduction: 0 + person2: + age: 40 + employment_income: 40_000 + mt_salt_deduction: 0 + tax_units: + tax_unit: + members: [person1, person2] + mt_federal_income_tax_deduction_unit: 0 + households: + household: + members: [person1, person2] + state_code: MT + output: + # 30,000 - 10% x 100,000 Montana AGI, counted once. + mt_itemized_deductions_joint: [20_000, 0] + +- name: A dependent in the tax unit does not repeat the joint casualty loss + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + employment_income: 60_000 + casualty_loss: 30_000 + mt_salt_deduction: 0 + person2: + age: 40 + employment_income: 40_000 + mt_salt_deduction: 0 + person3: + age: 10 + is_tax_unit_dependent: true + mt_salt_deduction: 0 + tax_units: + tax_unit: + members: [person1, person2, person3] + mt_federal_income_tax_deduction_unit: 0 + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + mt_itemized_deductions_joint: [20_000, 0, 0] diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.py new file mode 100644 index 00000000000..4ee3a76c5a3 --- /dev/null +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.py @@ -0,0 +1,38 @@ +from policyengine_us.model_api import * + + +class mt_casualty_loss_deduction_indiv(Variable): + value_type = float + entity = Person + label = ( + "Montana casualty and theft loss deduction when married couples file separately" + ) + unit = USD + definition_period = YEAR + reference = ( + # 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=35", + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=36", + # 2022 Form 2 instructions, allocation of deductions when filing separately + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=11", + ) + defined_for = "mt_married_filing_separately_on_same_return_eligible" + + def formula(person, period, parameters): + p = parameters(period).gov.states.mt.tax.income.deductions.itemized + if not p.casualty_loss.applies: + return 0 + # Spouses filing separately each complete a separate federal Form 4684 + # for their own loss, using their own Montana adjusted gross income in + # place of federal adjusted gross income. A deduction attributable to + # only one spouse must be claimed by that spouse. + p_casualty = parameters(period).gov.irs.deductions.itemized.casualty + own_loss = person("casualty_loss", period) + # Dependents' losses go to the head, as mt_agi_indiv does with + # dependents' income. + is_dependent = person("is_tax_unit_dependent", period) + is_head = person("is_tax_unit_head", period) + dependents_loss = person.tax_unit.sum(is_dependent * own_loss) + loss = ~is_dependent * own_loss + is_head * dependents_loss + agi = person("mt_agi_indiv", period) + return p_casualty.active * max_(loss - agi * p_casualty.floor, 0) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.py new file mode 100644 index 00000000000..972f03bcede --- /dev/null +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.py @@ -0,0 +1,26 @@ +from policyengine_us.model_api import * + + +class mt_casualty_loss_deduction_joint(Variable): + value_type = float + entity = TaxUnit + label = "Montana casualty and theft loss deduction on a joint return" + unit = USD + definition_period = YEAR + reference = ( + # 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=35", + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=36", + ) + defined_for = StateCode.MT + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.mt.tax.income.deductions.itemized + if not p.casualty_loss.applies: + return 0 + # The return completes one federal Form 4684, using its Montana + # adjusted gross income in place of federal adjusted gross income. + p_casualty = parameters(period).gov.irs.deductions.itemized.casualty + loss = add(tax_unit, period, ["casualty_loss"]) + agi = tax_unit("mt_agi_joint", period) + return p_casualty.active * max_(loss - agi * p_casualty.floor, 0) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.py index 0d5e7d0e577..a47e94c3ea8 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.py @@ -28,7 +28,7 @@ def formula(person, period, parameters): person, period, [ - "mt_misc_deductions", + "mt_casualty_loss_deduction_indiv", "mt_child_dependent_care_expense_deduction", "mt_medical_expense_deduction_indiv", "mt_salt_deduction", diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.py index ed3371fd0ab..5e159b7d606 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.py @@ -23,7 +23,7 @@ def formula(person, period, parameters): person.tax_unit, period, [ - "mt_misc_deductions", + "mt_casualty_loss_deduction_joint", "mt_child_dependent_care_expense_deduction_joint", "mt_medical_expense_deduction_joint", "mt_salt_deduction", diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_indiv.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_indiv.py index ff75bc2277f..808615ac88f 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_indiv.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_indiv.py @@ -30,7 +30,7 @@ def formula(person, period, parameters): person, period, [ - "mt_misc_deductions", + "mt_casualty_loss_deduction_indiv", "mt_child_dependent_care_expense_deduction", "mt_medical_expense_deduction_indiv", "mt_salt_deduction", diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_joint.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_joint.py index 1a13c3a97de..5648c843633 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_joint.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_itemized_deductions_joint.py @@ -23,7 +23,7 @@ def formula(person, period, parameters): person.tax_unit, period, [ - "mt_misc_deductions", + "mt_casualty_loss_deduction_joint", "mt_child_dependent_care_expense_deduction_joint", "mt_medical_expense_deduction_joint", "mt_salt_deduction", diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_misc_deductions.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_misc_deductions.py deleted file mode 100644 index 354dc6ca059..00000000000 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_misc_deductions.py +++ /dev/null @@ -1,17 +0,0 @@ -from policyengine_us.model_api import * - - -class mt_misc_deductions(Variable): - value_type = float - entity = Person - label = "Montana miscellaneous deductions" - unit = USD - definition_period = YEAR - reference = ( - "https://revenuefiles.mt.gov/files/Forms/Montana-Individual-Income-Tax-Return-Form-2/2022_Montana_Individual_Income_Tax_Return_Form_2.pdf#page=7", - "https://law.justia.com/codes/montana/2022/title-15/chapter-30/part-21/section-15-30-2131/", - # Montana Code Annotated MT Code § 15-30-2131 (2022) (1)(a)&(c) - ) - defined_for = StateCode.MT - - adds = "gov.states.mt.tax.income.deductions.itemized.misc_deductions" From 9220847cfe2a0c939f749ebea75c2a2d44ff3af7 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 6 Oct 2026 08:48:03 -0400 Subject: [PATCH 5/6] Apply the Form 4684 $100 reduction and add Montana casualty loss properties Montana's line 15 has filers complete federal Form 4684, whose line 11 reduces each casualty by $100 before the 10%-of-AGI floor (line 17). IRS Publication 547: a joint return is one individual for the $100 rule; spouses filing separately each reduce their own loss by $100. Add the federal amount as gov.irs.deductions.itemized.casualty.per_casualty_reduction (26 U.S.C. 165(h)(1)) and apply it once per joint return and once per spouse's column. The model has one loss amount per person, so each return's (or column's) losses are treated as one casualty, as the Arkansas casualty deduction already does. Add grid property tests: both variants match a closed-form Form 4684 reference; the joint return counts the unit's loss once whatever the number of members; separate filers deduct only their own loss; the deduction is non-negative, bounded, monotone; single-filer variants agree; and it ends in 2024. Co-Authored-By: Claude Opus 5.5 --- ...x-mt-casualty-loss-misc-deduction.fixed.md | 2 +- .../casualty/per_casualty_reduction.yaml | 15 ++ .../mt_casualty_loss_deduction_indiv.yaml | 24 ++- .../mt_casualty_loss_deduction_joint.yaml | 63 +++++- ...uctions_for_federal_itemization_indiv.yaml | 5 +- ...uctions_for_federal_itemization_joint.yaml | 6 +- .../mt_itemized_deductions_indiv.yaml | 5 +- .../mt_itemized_deductions_joint.yaml | 6 +- ...t_mt_casualty_loss_deduction_properties.py | 191 ++++++++++++++++++ .../mt_casualty_loss_deduction_indiv.py | 8 +- .../mt_casualty_loss_deduction_joint.py | 10 +- 11 files changed, 302 insertions(+), 33 deletions(-) create mode 100644 policyengine_us/parameters/gov/irs/deductions/itemized/casualty/per_casualty_reduction.yaml create mode 100644 policyengine_us/tests/unit/test_mt_casualty_loss_deduction_properties.py diff --git a/changelog.d/fix-mt-casualty-loss-misc-deduction.fixed.md b/changelog.d/fix-mt-casualty-loss-misc-deduction.fixed.md index 63e5c33d9ac..c88a9dbce78 100644 --- a/changelog.d/fix-mt-casualty-loss-misc-deduction.fixed.md +++ b/changelog.d/fix-mt-casualty-loss-misc-deduction.fixed.md @@ -1 +1 @@ -Count a Montana casualty and theft loss once on a joint return, and only in the column of the spouse who had it when spouses file separately, with the 10% floor on Montana AGI (2021-2023 Form 2 Itemized Deductions Schedule, line 15). +Count a Montana casualty and theft loss once on a joint return, and only in the column of the spouse who had it when spouses file separately, figured as on federal Form 4684 ($100 reduction, then the 10% floor on Montana AGI) per the 2021-2023 Form 2 Itemized Deductions Schedule, line 15. diff --git a/policyengine_us/parameters/gov/irs/deductions/itemized/casualty/per_casualty_reduction.yaml b/policyengine_us/parameters/gov/irs/deductions/itemized/casualty/per_casualty_reduction.yaml new file mode 100644 index 00000000000..8ba4c1b3038 --- /dev/null +++ b/policyengine_us/parameters/gov/irs/deductions/itemized/casualty/per_casualty_reduction.yaml @@ -0,0 +1,15 @@ +description: The IRS reduces each casualty or theft loss of personal-use property by this amount before applying the income floor. +values: + 2009-01-01: 500 + 2010-01-01: 100 +metadata: + unit: currency-USD + period: year + label: Casualty loss reduction per casualty + reference: + - title: 26 U.S.C. § 165(h)(1) + href: https://www.law.cornell.edu/uscode/text/26/165#h_1 + - title: 2022 Form 4684, line 11 + href: https://www.irs.gov/pub/irs-prior/f4684--2022.pdf#page=1 + - title: IRS Publication 547 (2022), $100 Rule + href: https://www.irs.gov/pub/irs-prior/p547--2022.pdf#page=10 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.yaml index 45789157040..fc4a5df8698 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.yaml @@ -7,9 +7,14 @@ # 2022 Form 2 instructions, Filing Separately When Married (PDF p. 11): # "Deductions that are attributable to only one spouse must be claimed by that # spouse." -# Form 4684 allows the loss above 10% of adjusted gross income. The federal -# suspension of losses outside federally declared disasters is modeled by -# gov.irs.deductions.itemized.casualty.active, which these tests switch on. +# Form 4684 reduces each casualty by $100 (2022 Form 4684 line 11) and allows the +# rest above 10% of adjusted gross income (line 17). IRS Publication 547 (2022, +# PDF p. 10): "If you and your spouse have a casualty or theft loss and you file +# separate returns, each of you must reduce your loss by $100." and "If one +# spouse owns the property, only that spouse can claim a loss deduction on a +# separate return." The federal suspension of losses outside federally declared +# disasters is modeled by gov.irs.deductions.itemized.casualty.active, which +# these tests switch on. - name: Only the spouse who had the loss deducts it, above 10% of their own Montana AGI period: 2022 @@ -31,8 +36,8 @@ members: [person1, person2] state_code: MT output: - # 30,000 - 10% x 60,000; the spouse has no loss. - mt_casualty_loss_deduction_indiv: [24_000, 0] + # (30,000 - 100) - 10% x 60,000; the spouse has no loss. + mt_casualty_loss_deduction_indiv: [23_900, 0] - name: Each spouse's loss is floored at 10% of that spouse's Montana AGI period: 2022 @@ -55,8 +60,9 @@ members: [person1, person2] state_code: MT output: - # 30,000 - 6,000 and 5,000 - 4,000. - mt_casualty_loss_deduction_indiv: [24_000, 1_000] + # (30,000 - 100) - 6,000 and (5,000 - 100) - 4,000: each spouse reduces + # their own loss by $100. + mt_casualty_loss_deduction_indiv: [23_900, 900] - name: A dependent's loss goes to the head, with the dependent's income period: 2022 @@ -82,8 +88,8 @@ members: [person1, person2, person3] state_code: MT output: - # 10,000 - 10% x 60,000, in the head's column. - mt_casualty_loss_deduction_indiv: [4_000, 0, 0] + # (10,000 - 100) - 10% x 60,000, in the head's column. + mt_casualty_loss_deduction_indiv: [3_900, 0, 0] - name: Losses outside federally declared disasters are suspended period: 2022 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.yaml index 2a70d9efad0..4b04030c638 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.yaml @@ -6,9 +6,12 @@ # loss, use your Montana Adjusted Gross Income in place of the Federal Adjusted # Gross Income." and "Deductions for all other casualty and theft losses are # suspended until tax years beginning after December 31, 2025." -# Form 4684 allows the loss above 10% of adjusted gross income. The federal -# suspension is modeled by gov.irs.deductions.itemized.casualty.active, which -# these tests switch on to exercise a deductible loss. +# Form 4684 reduces each casualty by $100 (2022 Form 4684 line 11) and allows the +# rest above 10% of adjusted gross income (line 17). IRS Publication 547 (2022, +# PDF p. 10): "If you and your spouse file a joint return, you are treated as one +# individual in applying the $100 rule." The federal suspension is modeled by +# gov.irs.deductions.itemized.casualty.active, which these tests switch on to +# exercise a deductible loss. - name: A joint return deducts the couple's loss once, above 10% of Montana AGI period: 2022 @@ -29,8 +32,8 @@ members: [person1, person2] state_code: MT output: - # 30,000 - 10% x 100,000 - mt_casualty_loss_deduction_joint: 20_000 + # (30,000 - 100) - 10% x 100,000 + mt_casualty_loss_deduction_joint: 19_900 - name: Both spouses' losses go on the joint return's one Form 4684 period: 2022 @@ -52,8 +55,8 @@ members: [person1, person2] state_code: MT output: - # 35,000 - 10% x 100,000 - mt_casualty_loss_deduction_joint: 25_000 + # (35,000 - 100) - 10% x 100,000; the joint return reduces by $100 once. + mt_casualty_loss_deduction_joint: 24_900 - name: The 10% floor uses Montana AGI, not federal AGI period: 2022 @@ -73,17 +76,17 @@ members: [person1] state_code: MT output: - # 30,000 - 10% x 80,000. The federal floor would give 30,000 - 10,000. - mt_casualty_loss_deduction_joint: 22_000 + # (30,000 - 100) - 10% x 80,000. A federal AGI floor would give 19,900. + mt_casualty_loss_deduction_joint: 21_900 -- name: A loss at or below 10% of Montana AGI is not deductible +- name: A loss whose excess over $100 equals 10% of Montana AGI is not deductible period: 2022 input: gov.irs.deductions.itemized.casualty.active: true people: person1: age: 40 - casualty_loss: 8_000 + casualty_loss: 10_100 tax_units: tax_unit: members: [person1] @@ -95,6 +98,44 @@ output: mt_casualty_loss_deduction_joint: 0 +- name: One dollar above the floor is deductible + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + casualty_loss: 10_101 + tax_units: + tax_unit: + members: [person1] + mt_agi_joint: 100_000 + households: + household: + members: [person1] + state_code: MT + output: + mt_casualty_loss_deduction_joint: 1 + +- name: A loss under $100 is not deductible even with no Montana AGI + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + casualty_loss: 80 + tax_units: + tax_unit: + members: [person1] + mt_agi_joint: 0 + households: + household: + members: [person1] + state_code: MT + output: + mt_casualty_loss_deduction_joint: 0 + - name: Losses outside federally declared disasters are suspended period: 2022 input: diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.yaml index 0c0eebb22af..89ffbe37823 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.yaml @@ -104,5 +104,6 @@ members: [person1, person2] state_code: MT output: - # 30,000 - 10% x 60,000 Montana AGI in the head's column; none for the spouse. - mt_itemized_deductions_for_federal_itemization_indiv: [24_000, 0] + # (30,000 - 100) - 10% x 60,000 Montana AGI in the head's column; none for + # the spouse. + mt_itemized_deductions_for_federal_itemization_indiv: [23_900, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml index 616477e630d..ef35f6d8213 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml @@ -101,8 +101,8 @@ members: [person1, person2] state_code: MT output: - # 30,000 - 10% x 100,000 Montana AGI, counted once. - mt_itemized_deductions_for_federal_itemization_joint: [20_000, 0] + # (30,000 - 100) - 10% x 100,000 Montana AGI, counted once. + mt_itemized_deductions_for_federal_itemization_joint: [19_900, 0] - name: A dependent in the tax unit does not repeat the joint casualty loss period: 2022 @@ -131,4 +131,4 @@ members: [person1, person2, person3] state_code: MT output: - mt_itemized_deductions_for_federal_itemization_joint: [20_000, 0, 0] + mt_itemized_deductions_for_federal_itemization_joint: [19_900, 0, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_indiv.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_indiv.yaml index 8f5d35063f0..e4dc6286dad 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_indiv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_indiv.yaml @@ -104,5 +104,6 @@ members: [person1, person2] state_code: MT output: - # 30,000 - 10% x 60,000 Montana AGI in the head's column; none for the spouse. - mt_itemized_deductions_indiv: [24_000, 0] + # (30,000 - 100) - 10% x 60,000 Montana AGI in the head's column; none for + # the spouse. + mt_itemized_deductions_indiv: [23_900, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml index a9daeb667a3..0630694465f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml @@ -101,8 +101,8 @@ members: [person1, person2] state_code: MT output: - # 30,000 - 10% x 100,000 Montana AGI, counted once. - mt_itemized_deductions_joint: [20_000, 0] + # (30,000 - 100) - 10% x 100,000 Montana AGI, counted once. + mt_itemized_deductions_joint: [19_900, 0] - name: A dependent in the tax unit does not repeat the joint casualty loss period: 2022 @@ -131,4 +131,4 @@ members: [person1, person2, person3] state_code: MT output: - mt_itemized_deductions_joint: [20_000, 0, 0] + mt_itemized_deductions_joint: [19_900, 0, 0] diff --git a/policyengine_us/tests/unit/test_mt_casualty_loss_deduction_properties.py b/policyengine_us/tests/unit/test_mt_casualty_loss_deduction_properties.py new file mode 100644 index 00000000000..1c676c9c780 --- /dev/null +++ b/policyengine_us/tests/unit/test_mt_casualty_loss_deduction_properties.py @@ -0,0 +1,191 @@ +"""Properties of the Montana casualty and theft loss deduction (2021-2023). + +The 2021-2023 Form 2 instructions (Itemized Deductions Schedule, line 15) say +to complete federal Form 4684 with Montana AGI in place of federal AGI, and +that spouses filing separately each complete their own Form 4684. Each test +evaluates every point of an input grid in one vectorized simulation, so the +properties hold for all grid inputs rather than for a few examples: + +- both variants match a closed-form reference of Form 4684 lines 11-12 and + 17-18: the loss less $100, above 10% of Montana AGI; +- a joint return counts the unit's loss once, however many members the tax + unit has, and Montana's joint itemized deductions add it once; +- filing separately, each spouse deducts only their own loss (dependents' + losses go to the head), floored at their own Montana AGI; +- the deductions are non-negative, never exceed the loss less $100, rise with + the loss and fall with Montana AGI; +- for a single filer the joint and separate variants agree; +- the deduction ends in 2024, when Montana discontinued its Itemized + Deductions Schedule. + +The federal suspension of losses outside federally declared disasters is +modeled by gov.irs.deductions.itemized.casualty.active; a reform switches it +on so the properties are not vacuous. +""" + +import itertools + +import numpy as np +import pytest +from policyengine_core.reforms import Reform + +from policyengine_us import Simulation + +REDUCTION = 100 # Form 4684 line 11 +FLOOR = 0.1 # Form 4684 line 17 + +HEAD_LOSSES = [0, 80, 100, 101, 5_000, 30_000] +SPOUSE_LOSSES = [0, 100, 5_000] +HEAD_AGIS = [0, 40_000, 300_000] +SPOUSE_AGIS = [0, 60_000] +# (number of dependents, the first dependent's loss) +DEPENDENTS = [(0, 0), (1, 0), (1, 2_000), (2, 0)] +COUPLE_GRID = list( + itertools.product(HEAD_LOSSES, SPOUSE_LOSSES, HEAD_AGIS, SPOUSE_AGIS, DEPENDENTS) +) +SINGLE_GRID = list(itertools.product(HEAD_LOSSES, HEAD_AGIS)) +YEARS = [2021, 2022, 2023, 2024] + +ACTIVE = Reform.from_dict( + {"gov.irs.deductions.itemized.casualty.active": {"2010-01-01.2100-12-31": True}}, + country_id="us", +) + + +def reference(loss, agi): + return np.maximum(np.maximum(loss - REDUCTION, 0) - FLOOR * agi, 0) + + +def every_year(value): + return {year: value for year in YEARS} + + +@pytest.fixture(scope="module") +def grid(): + """One simulation holding every couple and single-filer grid point.""" + people, tax_units, households = {}, {}, {} + roles = [] # (unit index, role) for each person, in order + for i, (l1, l2, a1, a2, (n_deps, dep_loss)) in enumerate(COUPLE_GRID): + members = [f"c{i}_head", f"c{i}_spouse"] + people[members[0]] = { + "age": every_year(40), + "casualty_loss": every_year(l1), + "mt_agi_indiv": every_year(a1), + } + people[members[1]] = { + "age": every_year(40), + "casualty_loss": every_year(l2), + "mt_agi_indiv": every_year(a2), + } + roles += [(i, "head"), (i, "spouse")] + for d in range(n_deps): + name = f"c{i}_dep{d}" + people[name] = { + "age": every_year(10), + "is_tax_unit_dependent": every_year(True), + "casualty_loss": every_year(dep_loss if d == 0 else 0), + "mt_agi_indiv": every_year(0), + } + members.append(name) + roles.append((i, "dependent")) + tax_units[f"c{i}"] = {"members": members, "mt_agi_joint": every_year(a1 + a2)} + households[f"c{i}"] = {"members": members, "state_code": every_year("MT")} + for j, (loss, agi) in enumerate(SINGLE_GRID): + name = f"s{j}" + people[name] = { + "age": every_year(40), + "casualty_loss": every_year(loss), + "mt_agi_indiv": every_year(agi), + } + roles.append((len(COUPLE_GRID) + j, "single")) + tax_units[name] = {"members": [name], "mt_agi_joint": every_year(agi)} + households[name] = {"members": [name], "state_code": every_year("MT")} + # Zero the other itemized deductions so the aggregators show the casualty + # loss alone; the grid has no medical, care, charitable or interest items. + for person in people.values(): + person["mt_salt_deduction"] = every_year(0) + person["mt_federal_income_tax_deduction_indiv"] = every_year(0) + for unit in tax_units.values(): + unit["mt_federal_income_tax_deduction_unit"] = every_year(0) + sim = Simulation( + situation={"people": people, "tax_units": tax_units, "households": households}, + reform=ACTIVE, + ) + unit = np.array([r[0] for r in roles]) + role = np.array([r[1] for r in roles]) + return sim, unit, role + + +def couple_arrays(): + columns = np.array( + [(l1, l2, a1, a2, n, d) for l1, l2, a1, a2, (n, d) in COUPLE_GRID], + dtype=float, + ).T + return columns # head loss, spouse loss, head AGI, spouse AGI, deps, dep loss + + +@pytest.mark.parametrize("year", [2021, 2022, 2023]) +def test_joint_return_counts_the_unit_loss_once(grid, year): + sim, unit, role = grid + l1, l2, a1, a2, _, dep_loss = couple_arrays() + n = len(COUPLE_GRID) + joint = sim.calculate("mt_casualty_loss_deduction_joint", year)[:n] + np.testing.assert_allclose(joint, reference(l1 + l2 + dep_loss, a1 + a2)) + # Montana's joint itemized deductions add it once, at the head, however + # many members the tax unit has. + itemized = sim.calculate("mt_itemized_deductions_joint", year) + per_unit = np.bincount(unit, weights=itemized)[:n] + np.testing.assert_allclose(per_unit, joint) + assert np.all(itemized[(role != "head") & (role != "single")] == 0) + assert np.all(joint >= 0) + assert np.all(joint <= np.maximum(l1 + l2 + dep_loss - REDUCTION, 0)) + # Guard against a vacuous pass. + assert joint.max() > 0 + + +@pytest.mark.parametrize("year", [2021, 2022, 2023]) +def test_separate_filers_deduct_only_their_own_loss(grid, year): + sim, unit, role = grid + l1, l2, a1, a2, _, dep_loss = couple_arrays() + indiv = sim.calculate("mt_casualty_loss_deduction_indiv", year) + itemized = sim.calculate("mt_itemized_deductions_indiv", year) + head = indiv[role == "head"] + spouse = indiv[role == "spouse"] + # Each spouse's own Form 4684, on their own Montana AGI; a dependent's + # loss is in the head's column. + np.testing.assert_allclose(head, reference(l1 + dep_loss, a1)) + np.testing.assert_allclose(spouse, reference(l2, a2)) + assert np.all(indiv[role == "dependent"] == 0) + # A spouse without a loss deducts nothing, whatever the other spouse lost. + assert np.all(spouse[l2 == 0] == 0) + assert np.all(head[l1 + dep_loss == 0] == 0) + # The separate itemized deductions carry each spouse's own amount. + np.testing.assert_allclose(itemized[role == "head"], head) + np.testing.assert_allclose(itemized[role == "spouse"], spouse) + assert np.all(itemized[role == "dependent"] == 0) + assert np.all(indiv >= 0) + assert head.max() > 0 and spouse.max() > 0 + + +@pytest.mark.parametrize("year", [2021, 2022, 2023]) +def test_single_filer_variants_agree_and_are_monotone(grid, year): + sim, unit, role = grid + single = role == "single" + single_units = unit[single] + loss = np.array([g[0] for g in SINGLE_GRID], dtype=float) + agi = np.array([g[1] for g in SINGLE_GRID], dtype=float) + indiv = sim.calculate("mt_casualty_loss_deduction_indiv", year)[single] + joint = sim.calculate("mt_casualty_loss_deduction_joint", year)[single_units] + np.testing.assert_allclose(joint, reference(loss, agi)) + np.testing.assert_allclose(indiv, joint) + table = joint.reshape(len(HEAD_LOSSES), len(HEAD_AGIS)) + assert np.all(np.diff(table, axis=0) >= 0), "falls as the loss rises" + assert np.all(np.diff(table, axis=1) <= 0), "rises as Montana AGI rises" + + +def test_deduction_ends_with_the_2024_schedule(grid): + sim, _, _ = grid + assert np.all(sim.calculate("mt_casualty_loss_deduction_joint", 2024) == 0) + assert np.all(sim.calculate("mt_casualty_loss_deduction_indiv", 2024) == 0) + # The same inputs are deductible in 2023. + assert sim.calculate("mt_casualty_loss_deduction_joint", 2023).max() > 0 diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.py index 4ee3a76c5a3..f35a75e6a8f 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.py @@ -15,6 +15,9 @@ class mt_casualty_loss_deduction_indiv(Variable): "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=36", # 2022 Form 2 instructions, allocation of deductions when filing separately "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=11", + # 2022 Form 4684, lines 10-12 and 17; IRS Publication 547, $100 Rule + "https://www.irs.gov/pub/irs-prior/f4684--2022.pdf#page=1", + "https://www.irs.gov/pub/irs-prior/p547--2022.pdf#page=10", ) defined_for = "mt_married_filing_separately_on_same_return_eligible" @@ -34,5 +37,8 @@ def formula(person, period, parameters): is_head = person("is_tax_unit_head", period) dependents_loss = person.tax_unit.sum(is_dependent * own_loss) loss = ~is_dependent * own_loss + is_head * dependents_loss + # Spouses filing separately each reduce their own loss by $100 + # (Form 4684 line 11), treating each column's losses as one casualty. + reduced_loss = max_(loss - p_casualty.per_casualty_reduction, 0) agi = person("mt_agi_indiv", period) - return p_casualty.active * max_(loss - agi * p_casualty.floor, 0) + return p_casualty.active * max_(reduced_loss - agi * p_casualty.floor, 0) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.py index 972f03bcede..63a9693ba18 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.py @@ -11,6 +11,9 @@ class mt_casualty_loss_deduction_joint(Variable): # 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=35", "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=36", + # 2022 Form 4684, lines 10-12 and 17; IRS Publication 547, $100 Rule + "https://www.irs.gov/pub/irs-prior/f4684--2022.pdf#page=1", + "https://www.irs.gov/pub/irs-prior/p547--2022.pdf#page=10", ) defined_for = StateCode.MT @@ -21,6 +24,11 @@ def formula(tax_unit, period, parameters): # The return completes one federal Form 4684, using its Montana # adjusted gross income in place of federal adjusted gross income. p_casualty = parameters(period).gov.irs.deductions.itemized.casualty + # A joint return is one individual for the $100 rule. The model records + # one loss amount per person, not separate casualty events, so the + # return's losses are treated as one casualty and the $100 reduction + # (Form 4684 line 11) applies once. loss = add(tax_unit, period, ["casualty_loss"]) + reduced_loss = max_(loss - p_casualty.per_casualty_reduction, 0) agi = tax_unit("mt_agi_joint", period) - return p_casualty.active * max_(loss - agi * p_casualty.floor, 0) + return p_casualty.active * max_(reduced_loss - agi * p_casualty.floor, 0) From e352ed05bba085eb2502ef60bb96505e3322acde Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 6 Oct 2026 09:24:29 -0400 Subject: [PATCH 6/6] Leave dependents' casualty losses to their own returns; address review From the adversarial review of #9888 (law, code and test lenses, all approving): - A dependent's casualty loss belongs on the dependent's own return, as the dependent's income does (adjusted_gross_income_person, and so Montana AGI, leaves it out; Pub. 547: only the owner claims the loss). The joint path now sums non-dependents' losses (tax_unit_non_dep_add) and the separate path counts only the head's or spouse's own loss, instead of moving dependents' losses into the head's column while their income stayed out of it. - Say what the suspension flag models: PE has no input distinguishing federally declared disaster losses, so, like the federal deduction, no personal casualty loss is deductible from 2018 unless gov.irs.deductions.itemized.casualty.active is on. - Cite former MCA 15-30-2131(1)(a) (MCA 2021), which allowed the items of IRC 161 (including 165 losses), on the parameter and variables. - Describe the Form 4684 computation per lines 10-18 rather than as one form per return, and fix the separate-path test headers. - Add the 2008 $100 value to per_casualty_reduction (2008 and 2009 Form 4684 line 11), so it is defined before 2009. - Tests: natural-input dependent cases on both paths, and a 2024 case with filing status 2a allowed that exercises the separate path's applies gate (it fails if the gate is removed). Co-Authored-By: Claude Opus 5.5 --- .../casualty/per_casualty_reduction.yaml | 5 ++ .../itemized/casualty_loss/applies.yaml | 2 + .../mt_casualty_loss_deduction_indiv.yaml | 51 +++++++++++++++---- .../mt_casualty_loss_deduction_joint.yaml | 41 +++++++++++++-- ...uctions_for_federal_itemization_indiv.yaml | 5 +- ...uctions_for_federal_itemization_joint.yaml | 4 +- .../mt_itemized_deductions_indiv.yaml | 5 +- .../mt_itemized_deductions_joint.yaml | 4 +- ...t_mt_casualty_loss_deduction_properties.py | 29 ++++++----- .../mt_casualty_loss_deduction_indiv.py | 18 ++++--- .../mt_casualty_loss_deduction_joint.py | 16 ++++-- 11 files changed, 133 insertions(+), 47 deletions(-) diff --git a/policyengine_us/parameters/gov/irs/deductions/itemized/casualty/per_casualty_reduction.yaml b/policyengine_us/parameters/gov/irs/deductions/itemized/casualty/per_casualty_reduction.yaml index 8ba4c1b3038..b56d5b69462 100644 --- a/policyengine_us/parameters/gov/irs/deductions/itemized/casualty/per_casualty_reduction.yaml +++ b/policyengine_us/parameters/gov/irs/deductions/itemized/casualty/per_casualty_reduction.yaml @@ -1,5 +1,6 @@ description: The IRS reduces each casualty or theft loss of personal-use property by this amount before applying the income floor. values: + 2008-01-01: 100 2009-01-01: 500 2010-01-01: 100 metadata: @@ -9,6 +10,10 @@ metadata: reference: - title: 26 U.S.C. § 165(h)(1) href: https://www.law.cornell.edu/uscode/text/26/165#h_1 + - title: 2008 Form 4684, line 11 + href: https://www.irs.gov/pub/irs-prior/f4684--2008.pdf#page=1 + - title: 2009 Form 4684, line 11 + href: https://www.irs.gov/pub/irs-prior/f4684--2009.pdf#page=1 - title: 2022 Form 4684, line 11 href: https://www.irs.gov/pub/irs-prior/f4684--2022.pdf#page=1 - title: IRS Publication 547 (2022), $100 Rule diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/casualty_loss/applies.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/casualty_loss/applies.yaml index cd9a5c74f67..6c6d2c05de1 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/casualty_loss/applies.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/deductions/itemized/casualty_loss/applies.yaml @@ -4,6 +4,8 @@ metadata: period: year unit: bool reference: + - title: MCA § 15-30-2131(1)(a) (2021), itemized deductions by reference to 26 U.S.C. 161 and 211 (repealed effective 2024) + href: https://mca.legmt.gov/bills/2022/mca/title_0150/chapter_0300/part_0210/section_0310/0150-0300-0210-0310.html - title: 2021 Montana Form 2 Instructions, Itemized Deductions Schedule, line 15 href: https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2021_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=34 - title: 2022 Montana Form 2 Instructions, Itemized Deductions Schedule, line 15 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.yaml index fc4a5df8698..06f6e05ad30 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.yaml @@ -12,9 +12,10 @@ # PDF p. 10): "If you and your spouse have a casualty or theft loss and you file # separate returns, each of you must reduce your loss by $100." and "If one # spouse owns the property, only that spouse can claim a loss deduction on a -# separate return." The federal suspension of losses outside federally declared -# disasters is modeled by gov.irs.deductions.itemized.casualty.active, which -# these tests switch on. +# separate return." The model has no input that distinguishes federally declared +# disaster losses; like the federal deduction, it allows no personal casualty +# loss from 2018 unless gov.irs.deductions.itemized.casualty.active is switched +# on, as these tests do. - name: Only the spouse who had the loss deducts it, above 10% of their own Montana AGI period: 2022 @@ -64,22 +65,23 @@ # their own loss by $100. mt_casualty_loss_deduction_indiv: [23_900, 900] -- name: A dependent's loss goes to the head, with the dependent's income +- name: A dependent's loss stays off the parents' columns, like the dependent's income period: 2022 input: gov.irs.deductions.itemized.casualty.active: true people: person1: age: 40 - mt_agi_indiv: 60_000 + employment_income: 60_000 + casualty_loss: 30_000 person2: age: 40 - mt_agi_indiv: 40_000 + employment_income: 40_000 person3: - age: 10 + age: 17 is_tax_unit_dependent: true + employment_income: 5_000 casualty_loss: 10_000 - mt_agi_indiv: 0 tax_units: tax_unit: members: [person1, person2, person3] @@ -88,10 +90,37 @@ members: [person1, person2, person3] state_code: MT output: - # (10,000 - 100) - 10% x 60,000, in the head's column. - mt_casualty_loss_deduction_indiv: [3_900, 0, 0] + # The dependent's wages are not in the head's Montana AGI (60,000), and the + # dependent's loss belongs on the dependent's own return: + # (30,000 - 100) - 10% x 60,000 for the head. + mt_casualty_loss_deduction_indiv: [23_900, 0, 0] + +- name: Spouses filing separately on one form in 2024 have no Montana casualty line + period: 2024 + input: + # Allowing filing status 2a in 2024 (as a reform would) reaches the + # separate path; the discontinued schedule still gives no deduction. + gov.states.mt.tax.income.married_filing_separately_on_same_return_allowed: true + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + casualty_loss: 30_000 + mt_agi_indiv: 60_000 + person2: + age: 40 + mt_agi_indiv: 40_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MT + output: + mt_casualty_loss_deduction_indiv: [0, 0] -- name: Losses outside federally declared disasters are suspended +- name: No loss is deductible while the federal casualty deduction is suspended period: 2022 input: people: diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.yaml index 4b04030c638..261add5e5c5 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.yaml @@ -9,9 +9,10 @@ # Form 4684 reduces each casualty by $100 (2022 Form 4684 line 11) and allows the # rest above 10% of adjusted gross income (line 17). IRS Publication 547 (2022, # PDF p. 10): "If you and your spouse file a joint return, you are treated as one -# individual in applying the $100 rule." The federal suspension is modeled by -# gov.irs.deductions.itemized.casualty.active, which these tests switch on to -# exercise a deductible loss. +# individual in applying the $100 rule." The model has no input that +# distinguishes federally declared disaster losses; like the federal deduction, +# it allows no personal casualty loss from 2018 unless +# gov.irs.deductions.itemized.casualty.active is switched on, as these tests do. - name: A joint return deducts the couple's loss once, above 10% of Montana AGI period: 2022 @@ -35,7 +36,7 @@ # (30,000 - 100) - 10% x 100,000 mt_casualty_loss_deduction_joint: 19_900 -- name: Both spouses' losses go on the joint return's one Form 4684 +- name: Both spouses' losses are pooled on a joint return period: 2022 input: gov.irs.deductions.itemized.casualty.active: true @@ -58,6 +59,36 @@ # (35,000 - 100) - 10% x 100,000; the joint return reduces by $100 once. mt_casualty_loss_deduction_joint: 24_900 +- name: A dependent's loss is left to the dependent's own return + period: 2022 + input: + gov.irs.deductions.itemized.casualty.active: true + people: + person1: + age: 40 + employment_income: 60_000 + casualty_loss: 30_000 + person2: + age: 40 + employment_income: 40_000 + person3: + age: 17 + is_tax_unit_dependent: true + employment_income: 5_000 + casualty_loss: 10_000 + tax_units: + tax_unit: + members: [person1, person2, person3] + households: + household: + members: [person1, person2, person3] + state_code: MT + output: + # Montana AGI is the spouses' 100,000 (the dependent's wages are on the + # dependent's own return), and so is the dependent's loss: + # (30,000 - 100) - 10% x 100,000. + mt_casualty_loss_deduction_joint: 19_900 + - name: The 10% floor uses Montana AGI, not federal AGI period: 2022 input: @@ -136,7 +167,7 @@ output: mt_casualty_loss_deduction_joint: 0 -- name: Losses outside federally declared disasters are suspended +- name: No loss is deductible while the federal casualty deduction is suspended period: 2022 input: people: diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.yaml index 89ffbe37823..c7a4ffc9f8b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_indiv.yaml @@ -77,8 +77,9 @@ # 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 (PDF pp. 35-36): # complete federal Form 4684 using Montana AGI in place of federal AGI; spouses -# filing separately each complete their own Form 4684. The casualty loss is a -# tax unit amount, so it must not be repeated for each member. +# filing separately each complete their own Form 4684. Each spouse deducts only +# their own loss, on their own Montana AGI; the tax unit's loss must not be +# given to every member. - name: Only the spouse who had the casualty loss deducts it when filing separately period: 2022 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml index ef35f6d8213..af31671a593 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/federal_itemization/mt_itemized_deductions_for_federal_itemization_joint.yaml @@ -75,8 +75,8 @@ # 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 (PDF pp. 35-36): # complete federal Form 4684 using Montana AGI in place of federal AGI; spouses -# filing separately each complete their own Form 4684. The casualty loss is a -# tax unit amount, so it must not be repeated for each member. +# filing separately each complete their own Form 4684. A joint return pools the +# tax unit's losses, so they must be counted once, not once per member. - name: A couple's casualty loss counts once on a joint return period: 2022 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_indiv.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_indiv.yaml index e4dc6286dad..d41523a13f9 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_indiv.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_indiv.yaml @@ -77,8 +77,9 @@ # 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 (PDF pp. 35-36): # complete federal Form 4684 using Montana AGI in place of federal AGI; spouses -# filing separately each complete their own Form 4684. The casualty loss is a -# tax unit amount, so it must not be repeated for each member. +# filing separately each complete their own Form 4684. Each spouse deducts only +# their own loss, on their own Montana AGI; the tax unit's loss must not be +# given to every member. - name: Only the spouse who had the casualty loss deducts it when filing separately period: 2022 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml index 0630694465f..dbab8e1a2a5 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/deductions/itemized/mt_itemized_deductions_joint.yaml @@ -75,8 +75,8 @@ # 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 (PDF pp. 35-36): # complete federal Form 4684 using Montana AGI in place of federal AGI; spouses -# filing separately each complete their own Form 4684. The casualty loss is a -# tax unit amount, so it must not be repeated for each member. +# filing separately each complete their own Form 4684. A joint return pools the +# tax unit's losses, so they must be counted once, not once per member. - name: A couple's casualty loss counts once on a joint return period: 2022 diff --git a/policyengine_us/tests/unit/test_mt_casualty_loss_deduction_properties.py b/policyengine_us/tests/unit/test_mt_casualty_loss_deduction_properties.py index 1c676c9c780..bb78c499d1f 100644 --- a/policyengine_us/tests/unit/test_mt_casualty_loss_deduction_properties.py +++ b/policyengine_us/tests/unit/test_mt_casualty_loss_deduction_properties.py @@ -8,18 +8,20 @@ - both variants match a closed-form reference of Form 4684 lines 11-12 and 17-18: the loss less $100, above 10% of Montana AGI; -- a joint return counts the unit's loss once, however many members the tax - unit has, and Montana's joint itemized deductions add it once; -- filing separately, each spouse deducts only their own loss (dependents' - losses go to the head), floored at their own Montana AGI; +- a joint return counts the spouses' losses once, however many members the + tax unit has, and Montana's joint itemized deductions add it once; +- filing separately, each spouse deducts only their own loss, floored at their + own Montana AGI; +- a dependent's loss is left to the dependent's own return on both paths; - the deductions are non-negative, never exceed the loss less $100, rise with the loss and fall with Montana AGI; - for a single filer the joint and separate variants agree; - the deduction ends in 2024, when Montana discontinued its Itemized Deductions Schedule. -The federal suspension of losses outside federally declared disasters is -modeled by gov.irs.deductions.itemized.casualty.active; a reform switches it +The model has no input that distinguishes federally declared disaster losses, +so, like the federal deduction, it allows no personal casualty loss from 2018 +unless gov.irs.deductions.itemized.casualty.active is on; a reform switches it on so the properties are not vacuous. """ @@ -127,10 +129,11 @@ def couple_arrays(): @pytest.mark.parametrize("year", [2021, 2022, 2023]) def test_joint_return_counts_the_unit_loss_once(grid, year): sim, unit, role = grid - l1, l2, a1, a2, _, dep_loss = couple_arrays() + l1, l2, a1, a2, _, _ = couple_arrays() n = len(COUPLE_GRID) joint = sim.calculate("mt_casualty_loss_deduction_joint", year)[:n] - np.testing.assert_allclose(joint, reference(l1 + l2 + dep_loss, a1 + a2)) + # A dependent's loss is left to the dependent's own return. + np.testing.assert_allclose(joint, reference(l1 + l2, a1 + a2)) # Montana's joint itemized deductions add it once, at the head, however # many members the tax unit has. itemized = sim.calculate("mt_itemized_deductions_joint", year) @@ -138,7 +141,7 @@ def test_joint_return_counts_the_unit_loss_once(grid, year): np.testing.assert_allclose(per_unit, joint) assert np.all(itemized[(role != "head") & (role != "single")] == 0) assert np.all(joint >= 0) - assert np.all(joint <= np.maximum(l1 + l2 + dep_loss - REDUCTION, 0)) + assert np.all(joint <= np.maximum(l1 + l2 - REDUCTION, 0)) # Guard against a vacuous pass. assert joint.max() > 0 @@ -146,19 +149,19 @@ def test_joint_return_counts_the_unit_loss_once(grid, year): @pytest.mark.parametrize("year", [2021, 2022, 2023]) def test_separate_filers_deduct_only_their_own_loss(grid, year): sim, unit, role = grid - l1, l2, a1, a2, _, dep_loss = couple_arrays() + l1, l2, a1, a2, _, _ = couple_arrays() indiv = sim.calculate("mt_casualty_loss_deduction_indiv", year) itemized = sim.calculate("mt_itemized_deductions_indiv", year) head = indiv[role == "head"] spouse = indiv[role == "spouse"] # Each spouse's own Form 4684, on their own Montana AGI; a dependent's - # loss is in the head's column. - np.testing.assert_allclose(head, reference(l1 + dep_loss, a1)) + # loss is in neither column. + np.testing.assert_allclose(head, reference(l1, a1)) np.testing.assert_allclose(spouse, reference(l2, a2)) assert np.all(indiv[role == "dependent"] == 0) # A spouse without a loss deducts nothing, whatever the other spouse lost. assert np.all(spouse[l2 == 0] == 0) - assert np.all(head[l1 + dep_loss == 0] == 0) + assert np.all(head[l1 == 0] == 0) # The separate itemized deductions carry each spouse's own amount. np.testing.assert_allclose(itemized[role == "head"], head) np.testing.assert_allclose(itemized[role == "spouse"], spouse) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.py index f35a75e6a8f..fa9b40ac705 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_indiv.py @@ -10,6 +10,8 @@ class mt_casualty_loss_deduction_indiv(Variable): unit = USD definition_period = YEAR reference = ( + # MCA § 15-30-2131(1)(a) (2021) + "https://mca.legmt.gov/bills/2022/mca/title_0150/chapter_0300/part_0210/section_0310/0150-0300-0210-0310.html", # 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=35", "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=36", @@ -29,14 +31,16 @@ def formula(person, period, parameters): # for their own loss, using their own Montana adjusted gross income in # place of federal adjusted gross income. A deduction attributable to # only one spouse must be claimed by that spouse. + # Montana allows only federally declared disaster losses (line 15). The + # model has no input that distinguishes them, so, like the federal + # deduction, no personal casualty loss is deductible while + # gov.irs.deductions.itemized.casualty.active is false (from 2018). p_casualty = parameters(period).gov.irs.deductions.itemized.casualty - own_loss = person("casualty_loss", period) - # Dependents' losses go to the head, as mt_agi_indiv does with - # dependents' income. - is_dependent = person("is_tax_unit_dependent", period) - is_head = person("is_tax_unit_head", period) - dependents_loss = person.tax_unit.sum(is_dependent * own_loss) - loss = ~is_dependent * own_loss + is_head * dependents_loss + # Only the owner of the property claims the loss. A dependent's loss + # belongs on the dependent's own return, as the dependent's income does: + # adjusted_gross_income_person, and so Montana AGI, leaves it out. + head_or_spouse = person("is_tax_unit_head_or_spouse", period) + loss = head_or_spouse * person("casualty_loss", period) # Spouses filing separately each reduce their own loss by $100 # (Form 4684 line 11), treating each column's losses as one casualty. reduced_loss = max_(loss - p_casualty.per_casualty_reduction, 0) diff --git a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.py b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.py index 63a9693ba18..ef6dcd421e1 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/casualty_loss/mt_casualty_loss_deduction_joint.py @@ -8,6 +8,8 @@ class mt_casualty_loss_deduction_joint(Variable): unit = USD definition_period = YEAR reference = ( + # MCA § 15-30-2131(1)(a) (2021) + "https://mca.legmt.gov/bills/2022/mca/title_0150/chapter_0300/part_0210/section_0310/0150-0300-0210-0310.html", # 2022 Form 2 instructions, Itemized Deductions Schedule, line 15 "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=35", "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2-Instructions/2022_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=36", @@ -21,14 +23,22 @@ def formula(tax_unit, period, parameters): p = parameters(period).gov.states.mt.tax.income.deductions.itemized if not p.casualty_loss.applies: return 0 - # The return completes one federal Form 4684, using its Montana - # adjusted gross income in place of federal adjusted gross income. + # The return figures its loss as on federal Form 4684 (lines 10-18), + # using its Montana adjusted gross income in place of federal adjusted + # gross income. + # Montana allows only federally declared disaster losses (line 15). The + # model has no input that distinguishes them, so, like the federal + # deduction, no personal casualty loss is deductible while + # gov.irs.deductions.itemized.casualty.active is false (from 2018). p_casualty = parameters(period).gov.irs.deductions.itemized.casualty # A joint return is one individual for the $100 rule. The model records # one loss amount per person, not separate casualty events, so the # return's losses are treated as one casualty and the $100 reduction # (Form 4684 line 11) applies once. - loss = add(tax_unit, period, ["casualty_loss"]) + # Only the owner of the property claims the loss. A dependent's loss + # belongs on the dependent's own return, as the dependent's income does: + # adjusted_gross_income_person, and so Montana AGI, leaves it out. + loss = tax_unit_non_dep_add(tax_unit, period, ["casualty_loss"]) reduced_loss = max_(loss - p_casualty.per_casualty_reduction, 0) agi = tax_unit("mt_agi_joint", period) return p_casualty.active * max_(reduced_loss - agi * p_casualty.floor, 0)