From 52ffe10226cd26b3ff24e48ce7f9bc555924dd07 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 6 Oct 2026 07:08:30 -0400 Subject: [PATCH 1/5] 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/5] 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/5] 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 940e69f031f2c07e7855fcfff4a5e617167f7f12 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 6 Oct 2026 08:33:59 -0400 Subject: [PATCH 4/5] Count household members' income in the Montana elderly credit MCA 15-30-2337(4) defines gross household income as "all income received by all individuals of a household while they are members of the household". The 2023 Elderly Homeowner/Renter Credit Schedule combines the returns of "ALL members of the household" (lines 1-7 and 9) and has non-filing members report their wages on line 8; the 2024 and 2025 Schedule 2EC put "Income received by other members of your household" on line 17. The model summed each person's federal AGI over the tax unit. A tax unit dependent's federal AGI is zero (their income is on their own return), so a dependent's wages and other income were left out, and household members who file their own returns were never counted. - Add dependent_gross_income to the gross income sources. It counts a dependent's gross income items, gains but not losses, and the taxable part of their Social Security; the formula now subtracts that part before adding the untaxed remainder, so the benefits count once. - Sum gross household income over the household instead of the tax unit in the net household income and the credit. Co-Authored-By: Claude Opus 5.5 --- ...x-mt-ehrc-household-member-income.fixed.md | 1 + .../gross_income_sources.yaml | 9 ++ ...mt_elderly_homeowner_or_renter_credit.yaml | 145 ++++++++++++++++++ ..._renter_credit_gross_household_income.yaml | 75 +++++++++ ...or_renter_credit_net_household_income.yaml | 26 ++++ .../mt_elderly_homeowner_or_renter_credit.py | 15 +- ...or_renter_credit_gross_household_income.py | 15 +- ...r_or_renter_credit_net_household_income.py | 11 +- 8 files changed, 288 insertions(+), 9 deletions(-) create mode 100644 changelog.d/fix-mt-ehrc-household-member-income.fixed.md diff --git a/changelog.d/fix-mt-ehrc-household-member-income.fixed.md b/changelog.d/fix-mt-ehrc-household-member-income.fixed.md new file mode 100644 index 00000000000..0b6584283d6 --- /dev/null +++ b/changelog.d/fix-mt-ehrc-household-member-income.fixed.md @@ -0,0 +1 @@ +Count household members' income in the Montana elderly homeowner/renter credit: a tax unit dependent's gross income, and the income of household members who file their own returns. diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml index c949e5c54fe..298ed1755e8 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml @@ -10,11 +10,20 @@ metadata: href: https://law.justia.com/codes/montana/2022/title-15/chapter-30/part-23/section-15-30-2337/ - title: 2024 Montana Individual Income Tax Return 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=46 + - title: 2023 Montana Form 2 Instructions, Elderly Homeowner/Renter Credit Schedule, lines 1 and 8 (income of each member of the household) + 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=51 + - title: 2024 Montana Form 2 Instructions, Schedule 2EC, line 17 (income received by other members of your household) + 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=48 values: 2009-01-01: - adjusted_gross_income_person # Federal AGI baseline; covers taxable # pensions, IRA, wages, interest, dividends, etc. + # A tax unit dependent's income is on their own return, so + # adjusted_gross_income_person is zero for them; count their gross income + # directly. It includes gains but not losses, and only the taxable part + # of their Social Security (the rest is added in the variable formula). + - dependent_gross_income - tax_exempt_interest_income # § 15-30-2337(9)(a)(vii) # AGI already includes taxable IRA distributions via # taxable_retirement_distributions; only the tax-exempt portion 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 8cfb8bc8538..6f2d13342d2 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 @@ -254,3 +254,148 @@ # 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 + +- name: 2024 Schedule 2EC worked case, a dependent's wages count toward gross household income + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 20_000 + real_estate_taxes: 2_000 + person2: + age: 16 + employment_income: 10_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # Line 5 pensions 20_000; line 17 other household members' income + # 10_000 (the dependent's wages); line 18 gross household income 30_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [20_000, 10_000] + # Line 19 12_600; line 20 = 30_000 - 12_600 = 17_400; line 21 = 0.05; + # line 22 = 870. + mt_elderly_homeowner_or_renter_credit_net_household_income: [870, 0] + # Line 23 = 2_000; line 26 = 2_000; line 27 = 2_000 - 870 = 1_130; + # line 28 = min(1_130, 1_150) = 1_130; line 29 = 100% (line 18 is under + # 35_000); line 30 = 1_130. Without the dependent's wages, gross + # household income would be 20_000 and the credit the 1_150 cap. + mt_elderly_homeowner_or_renter_credit: [1_130, 0] + +- name: 2024 Schedule 2EC worked case, a household member filing their own return counts + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 20_000 + real_estate_taxes: 2_000 + person2: + age: 45 + taxable_interest_income: 10_000 + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # The claimant's adult daughter lives in the household and files her + # own return. § 15-30-2337(7)(a): a household is "an association of + # persons who live in the same dwelling"; the 2024 instructions: "You do + # not need to be related to be in the same household." Line 5 = 20_000; + # line 17 = 10_000 (her interest); line 18 = 30_000; line 22 = 870; + # line 27 = 2_000 - 870 = 1_130; line 30 = 1_130. Her tax unit has no + # one aged 62 or older, so it claims nothing. + mt_elderly_homeowner_or_renter_credit_net_household_income: [870, 0] + mt_elderly_homeowner_or_renter_credit: [1_130, 0] + +- name: 2024 Schedule 2EC worked case, a dependent's wages move the credit into the 40 percent band + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 20_000 + real_estate_taxes: 2_000 + person2: + age: 17 + employment_income: 16_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # Line 18 = 20_000 + 16_000 = 36_000; line 20 = 23_400; line 22 = + # 23_400 x 0.05 = 1_170; line 27 = 2_000 - 1_170 = 830; line 28 = 830; + # line 29 = 40% (36_000 is in the 35_000 to 37_500 band); + # line 30 = 830 x 0.4 = 332. + mt_elderly_homeowner_or_renter_credit_net_household_income: [1_170, 0] + mt_elderly_homeowner_or_renter_credit: [332, 0] + +- name: 2024 Schedule 2EC, a dependent's wages bring gross household income to 45,000 + period: 2024 + input: + people: + person1: + age: 70 + taxable_pension_income: 20_000 + real_estate_taxes: 2_000 + person2: + age: 17 + employment_income: 25_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # Line 18 = 45_000. The claimant must have gross household income "less + # than $45,000"; line 29 = 0% at 45_000 and above. + mt_elderly_homeowner_or_renter_credit: [0, 0] + +- name: 2023 Elderly Homeowner/Renter Credit Schedule worked case, a non-filing dependent's wages count + period: 2023 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + taxable_pension_income: 20_000 + real_estate_taxes: 2_000 + person2: + age: 16 + employment_income: 10_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # Line 1 federal AGI 20_000 (the head's return). The dependent's 10_000 + # of wages is under the 13_850 filing threshold for dependents; the + # 2023 instructions say members of the household not filing a Form 2 or + # federal Form 1040 "must report all wages" on line 8. Line 10 = 30_000; + # line 12 = 17_400; line 13 = 0.05; line 14 = 870; line 15 = 2_000; + # line 18 = 2_000; line 19 = 1_130; line 20 = 1_130; line 21 = 100%; + # line 22 = 1_130. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [20_000, 10_000] + mt_elderly_homeowner_or_renter_credit_net_household_income: [870, 0] + mt_elderly_homeowner_or_renter_credit: [1_130, 0] 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 38e02773559..88dbe3c9d4e 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 @@ -85,3 +85,78 @@ # 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] + +- name: A dependent's wages count in gross household income + period: 2024 + input: + people: + person1: + age: 70 + taxable_pension_income: 20_000 + person2: + age: 16 + employment_income: 10_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # § 15-30-2337(4): "all income received by all individuals of a + # household". The dependent's wages are on their own return, not in the + # head's federal AGI. 2024 Schedule 2EC: line 5 pensions 20_000 (head); + # line 17 income of other household members 10_000 (dependent's wages); + # line 18 gross household income 30_000. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [20_000, 10_000] + +- name: A dependent's Social Security counts once, in full + period: 2024 + input: + people: + person1: + age: 70 + person2: + age: 17 + employment_income: 25_000 + social_security_survivors: 10_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # On the dependent's own return, provisional income is + # 25_000 + 10_000 / 2 = 30_000, so 50% x (30_000 - 25_000) = 2_500 of the + # benefits is taxable (IRC 86) and is part of dependent_gross_income. + dependent_taxable_social_security: [0, 2_500] + # § 15-30-2337(9)(a)(viii) counts all Social Security, and 2024 + # Schedule 2EC line 6 takes "the total taxable and nontaxable" benefits: + # wages 25_000 + Social Security 10_000 = 35_000, not 37_500. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [0, 35_000] + +- name: A dependent's capital loss does not reduce gross household income + period: 2024 + input: + people: + person1: + age: 70 + person2: + age: 16 + employment_income: 10_000 + long_term_capital_gains: -3_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_name: MT + output: + # § 15-30-2337(9)(a): income "without regard to loss". 2024 Schedule 2EC + # line 7: "do not include any capital losses". Wages 10_000 count; the + # 3_000 loss does not reduce them. + mt_elderly_homeowner_or_renter_credit_gross_household_income: [0, 10_000] diff --git a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_net_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_net_household_income.yaml index dcc4e975a04..052498f9036 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_net_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_net_household_income.yaml @@ -40,3 +40,29 @@ output: # (48,000 - 6,300) x 0.05 with the 2021 exclusion of $6,300. mt_elderly_homeowner_or_renter_credit_net_household_income: [2_085, 0] + +- name: Gross household income includes members outside the claimant's tax unit + period: 2024 + input: + people: + person1: + mt_elderly_homeowner_or_renter_credit_gross_household_income: 20_000 + mt_elderly_homeowner_or_renter_credit_eligible: true + person2: + mt_elderly_homeowner_or_renter_credit_gross_household_income: 10_000 + mt_elderly_homeowner_or_renter_credit_eligible: false + tax_units: + tax_unit1: + members: [person1] + tax_unit2: + members: [person2] + households: + household: + members: [person1, person2] + state_code: MT + output: + # 2024 Schedule 2EC line 18 = 20_000 + 10_000 (line 17, the other member) + # = 30_000; line 20 = 30_000 - 12_600 = 17_400; line 21 = 0.05; + # line 22 = 870, on the claimant's row. person2's tax unit has no + # claimant, so 0. + mt_elderly_homeowner_or_renter_credit_net_household_income: [870, 0] diff --git a/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.py b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.py index d233f4ad92c..f2cbf8e8162 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit.py @@ -8,16 +8,23 @@ class mt_elderly_homeowner_or_renter_credit(Variable): unit = USD definition_period = YEAR defined_for = "mt_elderly_homeowner_or_renter_credit_eligible" + reference = ( + "https://mca.legmt.gov/bills/mca/title_0150/chapter_0300/part_0230/section_0370/0150-0300-0230-0370.html", + # 2024 Form 2, Schedule 2EC + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2/2024_Montana_Individual_Income_Tax_Return_Form_2.pdf#page=10", + ) def formula(person, period, parameters): p = parameters( period ).gov.states.mt.tax.income.credits.elderly_homeowner_or_renter - # § 15-30-2337(4) defines gross household income at the household - # (tax-unit) level, so the multiplier phase-out must be applied to - # the aggregated amount rather than each person's share. + # § 15-30-2337(4) defines gross household income as "all income + # received by all individuals of a household", including members + # outside the claimant's return (2024 Schedule 2EC line 17), so the + # multiplier phase-out applies to the household's total income rather + # than each person's share. gross_household_income = add( - person.tax_unit, + person.household, period, ["mt_elderly_homeowner_or_renter_credit_gross_household_income"], ) 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 21c77cdc399..d2db70646cc 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 @@ -14,6 +14,9 @@ class mt_elderly_homeowner_or_renter_credit_gross_household_income(Variable): # 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", + # 2024 Schedule 2EC, line 17: income received by other members of + # the household + "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=48", ) def formula(person, period, parameters): @@ -21,10 +24,16 @@ def formula(person, period, parameters): period ).gov.states.mt.tax.income.credits.elderly_homeowner_or_renter sources = add(person, period, p.gross_income_sources) - # AGI only captures the taxable portion of Social Security; add the - # untaxed portion so all SS is counted per § 15-30-2337(9)(a)(viii). + # The sources count only the taxable portion of Social Security: a + # filer's in federal AGI, a dependent's in their own gross income. + # Add the untaxed portion so all SS is counted per + # § 15-30-2337(9)(a)(viii). social_security = person("social_security", period) - taxable_social_security = person("taxable_social_security", period) + taxable_social_security = add( + person, + period, + ["taxable_social_security", "dependent_taxable_social_security"], + ) 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 diff --git a/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_net_household_income.py b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_net_household_income.py index 4c996aded7b..a46ccf6f5c6 100644 --- a/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_net_household_income.py +++ b/policyengine_us/variables/gov/states/mt/tax/income/credits/mt_elderly_homeowner_or_renter/mt_elderly_homeowner_or_renter_credit_net_household_income.py @@ -8,6 +8,11 @@ class mt_elderly_homeowner_or_renter_credit_net_household_income(Variable): unit = USD definition_period = YEAR defined_for = "mt_elderly_homeowner_or_renter_credit_eligible" + reference = ( + "https://mca.legmt.gov/bills/mca/title_0150/chapter_0300/part_0230/section_0370/0150-0300-0230-0370.html", + # 2024 Form 2, Schedule 2EC + "https://revenue.mt.gov/files/forms/Montana-Individual-Income-Tax-Return-Form-2/2024_Montana_Individual_Income_Tax_Return_Form_2.pdf#page=10", + ) def formula(person, period, parameters): p = parameters( @@ -16,10 +21,12 @@ def formula(person, period, parameters): # Only one claim is allowed per household # married taxpayer who are living apart may qualify for only one credit per year standard_exclusion = p.net_household_income.standard_exclusion - # Allocate the income to the head + # Gross household income counts every member of the household, + # including those outside the claimant's return (§ 15-30-2337(4); + # 2024 Schedule 2EC line 17). Allocate it to the head. head = person("is_tax_unit_head", period) gross_household_income = add( - person.tax_unit, + person.household, period, ["mt_elderly_homeowner_or_renter_credit_gross_household_income"], ) From 54d30751e0a16e81675a43dd884138b94dbcfcbc Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 6 Oct 2026 08:45:21 -0400 Subject: [PATCH 5/5] Count a dependent's income only for tax unit dependents; add property tests dependent_gross_income counts anyone who is not the head or spouse, while irs_gross_income counts anyone who is not a dependent. A person with neither role (a minor alone in a tax unit whose dependent flag is input as false) was counted by both. Count dependent_gross_income in the formula for tax unit dependents only, so the two paths split people exactly. The property tests check, for random claimants and household members, that gross household income is the Schedule 2EC total whether the other member is a dependent or files their own return, that the credit is the same either way, stays within its bounds, and never rises with income. Co-Authored-By: Claude Opus 5.5 --- .../gross_income_sources.yaml | 9 - ...est_mt_elderly_credit_household_members.py | 241 ++++++++++++++++++ ...or_renter_credit_gross_household_income.py | 19 +- 3 files changed, 256 insertions(+), 13 deletions(-) create mode 100644 policyengine_us/tests/test_mt_elderly_credit_household_members.py diff --git a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml index 298ed1755e8..c949e5c54fe 100644 --- a/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml +++ b/policyengine_us/parameters/gov/states/mt/tax/income/credits/elderly_homeowner_or_renter/gross_income_sources.yaml @@ -10,20 +10,11 @@ metadata: href: https://law.justia.com/codes/montana/2022/title-15/chapter-30/part-23/section-15-30-2337/ - title: 2024 Montana Individual Income Tax Return 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=46 - - title: 2023 Montana Form 2 Instructions, Elderly Homeowner/Renter Credit Schedule, lines 1 and 8 (income of each member of the household) - 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=51 - - title: 2024 Montana Form 2 Instructions, Schedule 2EC, line 17 (income received by other members of your household) - 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=48 values: 2009-01-01: - adjusted_gross_income_person # Federal AGI baseline; covers taxable # pensions, IRA, wages, interest, dividends, etc. - # A tax unit dependent's income is on their own return, so - # adjusted_gross_income_person is zero for them; count their gross income - # directly. It includes gains but not losses, and only the taxable part - # of their Social Security (the rest is added in the variable formula). - - dependent_gross_income - tax_exempt_interest_income # § 15-30-2337(9)(a)(vii) # AGI already includes taxable IRA distributions via # taxable_retirement_distributions; only the tax-exempt portion diff --git a/policyengine_us/tests/test_mt_elderly_credit_household_members.py b/policyengine_us/tests/test_mt_elderly_credit_household_members.py new file mode 100644 index 00000000000..d1c1fff15ef --- /dev/null +++ b/policyengine_us/tests/test_mt_elderly_credit_household_members.py @@ -0,0 +1,241 @@ +"""Property tests: household members' income in the Montana elderly +homeowner/renter credit. + +MCA 15-30-2337(4) defines gross household income as "all income received by +all individuals of a household while they are members of the household", and +(9)(a) counts federal adjusted gross income "without regard to loss" plus +nontaxable income, including all Social Security. The 2024 Schedule 2EC lists +the claimant's income by category (line 7: "do not include any capital +losses"; line 6: "the total taxable and nontaxable Social Security benefits") +and puts the income of "other members of your household" on line 17. + +The model reaches the same quantity by two paths. A member who is the +claimant's tax unit dependent is counted through dependent_gross_income and +dependent_taxable_social_security; a member who files their own return is +counted through federal AGI, the loss add-back and taxable_social_security. +For a claimant aged 62 or older (taxable pension, Social Security, property +tax, rent) and one other adult in the household (taxable interest, a +long-term capital gain or loss, Social Security): + +1. The household's gross household income is the claimant's pension and + Social Security plus the other member's interest, positive capital gain + and Social Security, whichever path counts the other member. +2. So the claimant's credit is the same in both arrangements, and the other + member's own tax unit, with no one aged 62 or older, claims nothing. +3. The credit is between zero and the cap, and zero when gross household + income is $45,000 or more (line 29). +4. More interest for the other member never raises the credit: gross + household income rises, so net household income (line 22) cannot fall + and the credit multiplier (line 29) cannot rise. + +No one has earned income, so no refundable credit enters line 8. The model +computes in single precision, so comparisons allow one cent or eight float32 +spacings at the household's total income, whichever is larger. +""" + +import numpy as np +import pytest + +from policyengine_us import Simulation + +YEAR = 2024 +CAP = 1_150 +INCOME_LIMIT = 45_000 +TOLERANCE = 0.01 + + +def build_situation(cases): + """Three Montana households per case: (A) the other member is the + claimant's dependent, (B) the other member files their own return and + (C) as A with the other member's extra interest added.""" + people, tax_units, marital_units, spm_units, families, households = ( + {}, + {}, + {}, + {}, + {}, + {}, + ) + for i, c in enumerate(cases): + for arrangement in "ABC": + key = f"{arrangement}{i}" + claimant, member = f"claimant_{key}", f"member_{key}" + interest = c["interest"] + ( + c["extra_interest"] if arrangement == "C" else 0 + ) + people[claimant] = { + "age": {YEAR: c["claimant_age"]}, + "taxable_pension_income": {YEAR: c["pension"]}, + "social_security_retirement": {YEAR: c["claimant_ss"]}, + "real_estate_taxes": {YEAR: c["property_tax"]}, + "rent": {YEAR: c["rent"]}, + } + people[member] = { + "age": {YEAR: c["member_age"]}, + "taxable_interest_income": {YEAR: interest}, + "long_term_capital_gains": {YEAR: c["capital_gain"]}, + "social_security_survivors": {YEAR: c["member_ss"]}, + } + if arrangement == "B": + tax_units[f"tax_unit_{key}"] = {"members": [claimant]} + tax_units[f"tax_unit_{key}_member"] = {"members": [member]} + else: + tax_units[f"tax_unit_{key}"] = {"members": [claimant, member]} + # Set for everyone: an input for some people gives the others + # its default (false), not its formula. Without it the model + # takes an adult in the claimant's tax unit to be the spouse. + people[claimant]["is_tax_unit_dependent"] = {YEAR: False} + people[member]["is_tax_unit_dependent"] = {YEAR: arrangement != "B"} + marital_units[f"marital_unit_{key}"] = {"members": [claimant]} + marital_units[f"marital_unit_{key}_member"] = {"members": [member]} + spm_units[f"spm_unit_{key}"] = {"members": [claimant, member]} + families[f"family_{key}"] = {"members": [claimant, member]} + households[f"household_{key}"] = { + "members": [claimant, member], + "state_code": {YEAR: "MT"}, + } + return { + "people": people, + "tax_units": tax_units, + "marital_units": marital_units, + "spm_units": spm_units, + "families": families, + "households": households, + } + + +def calculate(cases): + """Household totals of gross household income and the credit, and the + other member's credit, as arrays indexed [arrangement, case].""" + simulation = Simulation(situation=build_situation(cases)) + gross_household_income = np.asarray( + simulation.calculate( + "mt_elderly_homeowner_or_renter_credit_gross_household_income", + YEAR, + map_to="household", + ) + ) + credit = np.asarray( + simulation.calculate( + "mt_elderly_homeowner_or_renter_credit", YEAR, map_to="household" + ) + ) + person_credit = np.asarray( + simulation.calculate("mt_elderly_homeowner_or_renter_credit", YEAR) + ) + dependent = np.asarray(simulation.calculate("is_tax_unit_dependent", YEAR)) + # Households and people are in situation order: A0, B0, C0, A1, ...; + # the member follows the claimant. + n = len(cases) + return { + "gross_household_income": gross_household_income.reshape(n, 3).T, + "credit": credit.reshape(n, 3).T, + "member_credit": person_credit[1::2].reshape(n, 3).T, + "member_is_dependent": dependent[1::2].reshape(n, 3).T, + } + + +def expected_gross_household_income(c, extra_interest=0): + """2024 Schedule 2EC line 18: lines 5 and 6 for the claimant, and line + 17 for the other member's interest, gains and Social Security.""" + claimant = c["pension"] + c["claimant_ss"] + member = c["interest"] + extra_interest + max(0, c["capital_gain"]) + return claimant + member + c["member_ss"] + + +def tolerance(amount): + return max(TOLERANCE, 8 * float(np.spacing(np.float32(abs(amount))))) + + +def assert_properties(cases): + result = calculate(cases) + a, b, c_ = 0, 1, 2 + # The other member is a dependent in A and C and their own filer in B. + assert result["member_is_dependent"].tolist() == [ + [True] * len(cases), + [False] * len(cases), + [True] * len(cases), + ] + for i, c in enumerate(cases): + expected = expected_gross_household_income(c) + tol = tolerance(expected + c["extra_interest"]) + ghi = result["gross_household_income"] + credit = result["credit"] + # 1. Both paths give the Schedule 2EC total. + assert ghi[a, i] == pytest.approx(expected, abs=tol), c + assert ghi[b, i] == pytest.approx(expected, abs=tol), c + assert ghi[c_, i] == pytest.approx(expected + c["extra_interest"], abs=tol), c + # 2. The claimant's credit does not depend on the arrangement, and + # the other member claims nothing. + assert credit[a, i] == pytest.approx(credit[b, i], abs=tol), c + assert np.all(result["member_credit"][:, i] == 0), c + for arrangement in (a, b, c_): + # 3. Bounds and the income limit. + assert -tol <= credit[arrangement, i] <= CAP + tol, c + if ghi[arrangement, i] >= INCOME_LIMIT + tol: + assert credit[arrangement, i] == 0, c + # 4. More income never raises the credit. + assert credit[c_, i] <= credit[a, i] + tol, c + + +def test_worked_example(): + """2024 Schedule 2EC: line 5 pension 20,000; line 17 the other member's + interest 10,000; line 18 = 30,000; line 22 = (30,000 - 12,600) x 0.05 = + 870; line 27 = 2,000 - 870 = 1,130; line 30 = 1,130 in both + arrangements. With 5,000 more interest, line 18 = 35,000; line 22 = + 1,120; line 28 = 880; line 29 = 40%; line 30 = 352.""" + case = { + "claimant_age": 70, + "pension": 20_000, + "claimant_ss": 0, + "property_tax": 2_000, + "rent": 0, + "member_age": 40, + "interest": 10_000, + "capital_gain": 0, + "member_ss": 0, + "extra_interest": 5_000, + } + result = calculate([case]) + assert result["gross_household_income"][:, 0] == pytest.approx( + [30_000, 30_000, 35_000], abs=TOLERANCE + ) + assert result["credit"][:, 0] == pytest.approx([1_130, 1_130, 352], abs=TOLERANCE) + assert_properties([case]) + + +try: + import hypothesis + import hypothesis.strategies as st +except ImportError: # pragma: no cover + hypothesis = None + +if hypothesis is not None: + # Each example builds a Simulation; on a loaded runner input generation + # can trip the too_slow health check, which says nothing about the model. + SLOW = [hypothesis.HealthCheck.too_slow] + + def amount(high): + return st.one_of(st.just(0), st.integers(min_value=1, max_value=high)) + + @st.composite + def case(draw): + return { + "claimant_age": draw(st.integers(min_value=62, max_value=90)), + "pension": draw(amount(40_000)), + "claimant_ss": draw(amount(30_000)), + "property_tax": draw(st.integers(min_value=0, max_value=4_000)), + "rent": draw(amount(12_000)), + "member_age": draw(st.integers(min_value=15, max_value=61)), + "interest": draw(amount(40_000)), + "capital_gain": draw( + st.one_of(st.just(0), st.integers(min_value=-20_000, max_value=40_000)) + ), + "member_ss": draw(amount(20_000)), + "extra_interest": draw(st.integers(min_value=1, max_value=20_000)), + } + + @hypothesis.settings(max_examples=15, deadline=None, suppress_health_check=SLOW) + @hypothesis.given(st.lists(case(), min_size=1, max_size=8)) + def test_properties(cases): + assert_properties(cases) 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 d2db70646cc..735e9a7bafc 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 @@ -14,6 +14,9 @@ class mt_elderly_homeowner_or_renter_credit_gross_household_income(Variable): # 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", + # 2023 instructions, lines 1 and 8: the returns of each member of + # the household, and the wages of members who do not file + "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=51", # 2024 Schedule 2EC, line 17: income received by other members of # the household "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=48", @@ -24,9 +27,17 @@ def formula(person, period, parameters): period ).gov.states.mt.tax.income.credits.elderly_homeowner_or_renter sources = add(person, period, p.gross_income_sources) - # The sources count only the taxable portion of Social Security: a - # filer's in federal AGI, a dependent's in their own gross income. - # Add the untaxed portion so all SS is counted per + # Gross household income counts every member of the household + # (§ 15-30-2337(4)). A tax unit dependent's income is on their own + # return, not in adjusted_gross_income_person (irs_gross_income + # leaves dependents out), so count their gross income directly: + # gains but not losses, and the taxable part of their Social + # Security. + is_dependent = person("is_tax_unit_dependent", period) + dependent_income = is_dependent * person("dependent_gross_income", period) + # The income above counts only the taxable portion of Social + # Security: a filer's in federal AGI, a dependent's in their own + # gross income. Add the untaxed portion so all SS is counted per # § 15-30-2337(9)(a)(viii). social_security = person("social_security", period) taxable_social_security = add( @@ -42,4 +53,4 @@ def formula(person, period, parameters): # 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 + return sources + dependent_income + untaxed_social_security + losses