diff --git a/changelog.d/fix-ca-mn-casualty-loss.fixed.md b/changelog.d/fix-ca-mn-casualty-loss.fixed.md new file mode 100644 index 00000000000..50af78741a3 --- /dev/null +++ b/changelog.d/fix-ca-mn-casualty-loss.fixed.md @@ -0,0 +1 @@ +Allow non-disaster personal casualty and theft losses in California and Minnesota itemized deductions (and Minnesota alternative minimum taxable income), which do not follow the federal limit to declared disasters (Cal. Rev. & Tax. Code 17204(b); Minn. Stat. 290.0122, subd. 8): add `ca_casualty_loss_deduction` and `mn_casualty_loss_deduction`, each the loss less $100 and 10% of federal adjusted gross income, in place of the federal deduction. diff --git a/policyengine_us/parameters/gov/irs/deductions/itemized/casualty/per_casualty_reduction.yaml b/policyengine_us/parameters/gov/irs/deductions/itemized/casualty/per_casualty_reduction.yaml new file mode 100644 index 00000000000..b56d5b69462 --- /dev/null +++ b/policyengine_us/parameters/gov/irs/deductions/itemized/casualty/per_casualty_reduction.yaml @@ -0,0 +1,20 @@ +description: The IRS reduces each casualty or theft loss of personal-use property by this amount before applying the income floor. +values: + 2008-01-01: 100 + 2009-01-01: 500 + 2010-01-01: 100 +metadata: + unit: currency-USD + period: year + label: Casualty loss reduction per casualty + reference: + - title: 26 U.S.C. § 165(h)(1) + href: https://www.law.cornell.edu/uscode/text/26/165#h_1 + - title: 2008 Form 4684, line 11 + href: https://www.irs.gov/pub/irs-prior/f4684--2008.pdf#page=1 + - title: 2009 Form 4684, line 11 + href: https://www.irs.gov/pub/irs-prior/f4684--2009.pdf#page=1 + - title: 2022 Form 4684, line 11 + href: https://www.irs.gov/pub/irs-prior/f4684--2022.pdf#page=1 + - title: IRS Publication 547 (2022), $100 Rule + href: https://www.irs.gov/pub/irs-prior/p547--2022.pdf#page=10 diff --git a/policyengine_us/parameters/gov/states/ca/tax/income/deductions/itemized/limit/excluded_deductions.yaml b/policyengine_us/parameters/gov/states/ca/tax/income/deductions/itemized/limit/excluded_deductions.yaml index d3d5fd934b8..f0fc3bc9320 100644 --- a/policyengine_us/parameters/gov/states/ca/tax/income/deductions/itemized/limit/excluded_deductions.yaml +++ b/policyengine_us/parameters/gov/states/ca/tax/income/deductions/itemized/limit/excluded_deductions.yaml @@ -2,7 +2,9 @@ description: Itemized deductions excluded from CA high-AGI limitation. values: 2021-01-01: - medical_expense_deduction - - casualty_loss_deduction + # California's own casualty and theft loss (Schedule CA line 15), which + # replaces the federal one in the pre-limitation total. + - ca_casualty_loss_deduction - non_mortgage_interest metadata: @@ -18,5 +20,12 @@ metadata: href: https://www.ftb.ca.gov/forms/2024/2024-540-ca-instructions.html - title: 2025 Form 540 Schedule CA instructions href: https://www.ftb.ca.gov/forms/2025/2025-540-ca-instructions.html + - title: 2024 Schedule CA (540) instructions, line 29 itemized deductions worksheet, line 2 + href: https://www.ftb.ca.gov/forms/2024/2024-540-booklet.pdf#page=68 - title: Cal. Rev. & Tax. Code § 17077 href: https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=RTC§ionNum=17077 + # R&TC 17077 adopts 26 U.S.C. 68, whose subsection (c)(3) (before P.L. 119-21) + # leaves casualty and theft losses described in 165(c)(2) or (3) out of the + # deductions the limitation reduces. + - title: 26 U.S.C. § 68 (amendment notes for subsection (c)(3)) + href: https://www.law.cornell.edu/uscode/text/26/68 diff --git a/policyengine_us/reforms/states/mn/walz/mn_walz_hf1938.py b/policyengine_us/reforms/states/mn/walz/mn_walz_hf1938.py index 78aed52cd19..0a2f4903d04 100644 --- a/policyengine_us/reforms/states/mn/walz/mn_walz_hf1938.py +++ b/policyengine_us/reforms/states/mn/walz/mn_walz_hf1938.py @@ -112,13 +112,22 @@ def formula(tax_unit, period, parameters): # ... calculate pre-limitation itemized deductions itm_deds_less_salt = tax_unit("itemized_deductions_less_salt", period) capped_property_taxes = tax_unit("capped_property_taxes", period) - mn_itm_deds = itm_deds_less_salt + capped_property_taxes + # Schedule M1SA line 19 takes Minnesota's own casualty and theft + # loss (Schedule M1CAT) in place of the federal one. + federal_casualty_loss = tax_unit("casualty_loss_deduction", period) + mn_casualty_loss = tax_unit("mn_casualty_loss_deduction", period) + mn_itm_deds = ( + itm_deds_less_salt + - federal_casualty_loss + + mn_casualty_loss + + capped_property_taxes + ) # ... calculate itemized deductions offset p = parameters(period).gov.states.mn.tax.income.deductions.itemized exempt_deds = add( tax_unit, period, - ["medical_expense_deduction", "casualty_loss_deduction"], + ["medical_expense_deduction", "mn_casualty_loss_deduction"], ) net_deds = max_(0, mn_itm_deds - exempt_deds) net_deds_offset = p.reduction.alternate.rate * net_deds diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_casualty_loss_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_casualty_loss_deduction.yaml new file mode 100644 index 00000000000..ff9f57920e5 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_casualty_loss_deduction.yaml @@ -0,0 +1,198 @@ +# 2024 Schedule CA (540) instructions, line 15 (Form 540 booklet, PDF p. 66): +# federal law allows the personal casualty and theft loss deduction only for a +# federally declared disaster; "California law does not conform." Filers +# "complete another federal Form 4684 ... using California amounts". +# Cal. Rev. & Tax. Code 17204(b) (as amended by SB 711, 2025): 26 U.S.C. +# 165(h)(5) "shall not apply". +# FTB Publication 1034 (PDF p. 4): "subtract $100 and then 10% of your federal +# adjusted gross income." +# 2024 Form 4684: line 11 enters $100; line 17 enters 10% of adjusted gross +# income from Form 1040 line 11; line 18 is line 16 less line 17, not below 0. +# A joint return is one individual for the $100 rule (165(h)(4)(B)). The model +# records one loss amount per person, not separate casualty events, so a +# return's losses are treated as one casualty. A dependent's loss belongs on +# the dependent's own return, as the dependent's income does. + +- name: Case 1, the $100 reduction applies before the 10 percent floor. + period: 2024 + input: + state_code: CA + employment_income: 100_000 + casualty_loss: 15_000 + output: + # Form 4684: line 12 = 15,000 - 100 = 14,900; line 17 = 10% x 100,000 + # = 10,000; line 18 = 14,900 - 10,000. + ca_casualty_loss_deduction: 4_900 + # California allows the loss though the federal deduction is suspended. + casualty_loss_deduction: 0 + +- name: Case 2, a loss $100 above the floor nets to zero. + period: 2024 + input: + state_code: CA + employment_income: 100_000 + casualty_loss: 10_100 + output: + # (10,100 - 100) - 10% x 100,000 = 10,000 - 10,000 + ca_casualty_loss_deduction: 0 + +- name: Case 3, a loss $101 above the floor leaves $1. + period: 2024 + input: + state_code: CA + employment_income: 100_000 + casualty_loss: 10_101 + output: + # (10,101 - 100) - 10% x 100,000 = 10,001 - 10,000 + ca_casualty_loss_deduction: 1 + +- name: Case 4, a loss of exactly $100 is fully absorbed by the $100 reduction. + period: 2024 + input: + state_code: CA + casualty_loss: 100 + output: + ca_casualty_loss_deduction: 0 + +- name: Case 5, with no income a loss is deductible above the $100. + period: 2024 + input: + state_code: CA + casualty_loss: 101 + output: + # (101 - 100) - 10% x 0 + ca_casualty_loss_deduction: 1 + +- name: Case 6, Publication 547 Example 1 with $80,000 of AGI. + period: 2024 + input: + state_code: CA + employment_income: 80_000 + casualty_loss: 14_800 + output: + # IRS Publication 547 (2017, PDF p. 10), Example 1: loss after + # reimbursement 14,800; subtract $100 = 14,700; subtract 10% of 80,000 AGI + # = 6,700. + ca_casualty_loss_deduction: 6_700 + +- name: Case 7, the floor uses federal AGI, not California AGI. + period: 2024 + input: + state_code: CA + adjusted_gross_income: 100_000 + ca_agi: 60_000 + casualty_loss: 15_000 + output: + # (15,000 - 100) - 10% x 100,000 federal AGI = 4,900. On California AGI it + # would be 14,900 - 6,000 = 8,900. + ca_casualty_loss_deduction: 4_900 + +- name: Case 8, a negative federal AGI gives no floor, not a larger loss. + period: 2024 + input: + state_code: CA + adjusted_gross_income: -20_000 + casualty_loss: 15_000 + output: + # The 10% floor is not allowed below zero: 15,000 - 100. + ca_casualty_loss_deduction: 14_900 + +- name: Case 9, a joint return reduces the spouses' pooled losses by $100 once. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 60_000 + casualty_loss: 10_000 + person2: + age: 40 + employment_income: 40_000 + casualty_loss: 5_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + output: + filing_status: JOINT + # (10,000 + 5,000 - 100) - 10% x 100,000 = 14,900 - 10,000 + ca_casualty_loss_deduction: 4_900 + +- name: Case 10, a dependent's loss is left to the dependent's own return. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 100_000 + casualty_loss: 15_000 + person2: + age: 10 + casualty_loss: 5_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + output: + is_tax_unit_dependent: [false, true] + # The child's 5,000 is not the parent's loss. + # (15,000 - 100) - 10% x 100,000 = 14,900 - 10,000 + ca_casualty_loss_deduction: 4_900 + +- name: Case 11, a loss only the dependent had gives the parent nothing. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 100_000 + person2: + age: 10 + casualty_loss: 15_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: CA + output: + is_tax_unit_dependent: [false, true] + ca_casualty_loss_deduction: 0 + +- name: Case 12, California keeps allowing the loss under its 2025 conformity date. + period: 2026 + input: + state_code: CA + employment_income: 100_000 + casualty_loss: 15_000 + output: + # R&TC 17204(b) turns 165(h)(5) off for taxable years from 2025. + ca_casualty_loss_deduction: 4_900 + casualty_loss_deduction: 0 + +- name: Case 13, the deduction is zero outside California. + period: 2024 + input: + state_code: NY + employment_income: 100_000 + casualty_loss: 15_000 + output: + ca_casualty_loss_deduction: 0 + +- name: Case 14, lifting the federal suspension does not change California's deduction. + period: 2024 + input: + gov.irs.deductions.itemized.casualty.active: true + state_code: CA + employment_income: 100_000 + casualty_loss: 15_000 + output: + # California's deduction does not read the federal switch. + ca_casualty_loss_deduction: 4_900 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions.yaml index 13ce42b7d1c..a6847243c65 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions.yaml @@ -51,3 +51,26 @@ ca_itemized_deductions_pre_limitation: 10_000 output: ca_itemized_deductions: 7_000 # charity subject to limitation + +# 2024 Schedule CA (540) instructions, line 29 worksheet (Form 540 booklet, +# PDF p. 68): line 2 takes medical expenses, investment interest, casualty and +# theft losses and gambling losses out before the 80%/6% limitation. Cal. Rev. +# & Tax. Code 17077 adopts 26 U.S.C. 68, which leaves 165(c)(3) losses out. +- name: California casualty loss is not subject to the high-AGI limitation + absolute_error_margin: 0.01 + period: 2024 + input: + state_code: CA + filing_status: SINGLE + adjusted_gross_income: 244_857 + 50_000 + ca_charitable_deduction: 1_000 + casualty_loss: 40_000 + output: + # Form 4684: (40,000 - 100) - 10% x 294,857 = 39,900 - 29,485.70 + ca_casualty_loss_deduction: 10_414.30 + ca_itemized_deductions_pre_limitation: 11_414.30 + # Worksheet: line 3 = 11,414.30 - 10,414.30 = 1,000; line 4 = 80% x 1,000 + # = 800; line 8 = 6% x 50,000 = 3,000; line 9 = 800. + # 11,414.30 - 800. Were the loss limited too, line 4 would be 9,131.44, + # line 9 would be 3,000 and the result 8,414.30. + ca_itemized_deductions: 10_614.30 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions_pre_limitation.yaml b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions_pre_limitation.yaml index 524500a4c91..eb522ef4498 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions_pre_limitation.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions_pre_limitation.yaml @@ -385,3 +385,31 @@ # Also includes #10032's IRA 219(g) phase-out, since this is a two-cause # CA + IRA cell. state_income_tax_before_refundable_credits: 4441.45 + +# 2024 Schedule CA (540) instructions, line 15 (Form 540 booklet, PDF p. 66): +# "California law does not conform" to the federal limit of personal casualty +# losses to declared disasters; filers complete a second Form 4684 with +# California amounts. +- name: California allows a non-disaster casualty loss the federal return does not. + period: 2024 + input: + state_code: CA + employment_income: 100_000 + casualty_loss: 15_000 + output: + casualty_loss_deduction: 0 + # Form 4684: (15,000 - 100) - 10% x 100,000 = 4,900 + ca_itemized_deductions_pre_limitation: 4_900 + +- name: California counts the casualty loss once when the federal suspension is lifted. + period: 2024 + input: + gov.irs.deductions.itemized.casualty.active: true + state_code: CA + employment_income: 100_000 + casualty_loss: 15_000 + output: + ca_casualty_loss_deduction: 4_900 + # The federal deduction, now positive, is replaced by California's 4,900, + # not added to it. + ca_itemized_deductions_pre_limitation: 4_900 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_amt_taxable_income.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_amt_taxable_income.yaml index 3a65303cfad..4310e3a2c90 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_amt_taxable_income.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_amt_taxable_income.yaml @@ -19,3 +19,29 @@ state_code: MN output: mn_amt_taxable_income: 200_000 - 250 - 3_000 + +# 2024 Schedule M1MT, line 12 (PDF p. 1): "Casualty and theft losses (from line +# 19 of Schedule M1SA)", Minnesota's own amount from Schedule M1CAT. +- name: MN AMT taxable income subtracts the Minnesota casualty loss + period: 2024 + input: + adjusted_gross_income: 200_000 + mn_itemizing: true + casualty_loss: 40_000 + state_code: MN + output: + # The federal deduction is suspended. + casualty_loss_deduction: 0 + # M1CAT: (40,000 - 100) - 10% x 200,000 = 19,900 + mn_casualty_loss_deduction: 19_900 + mn_amt_taxable_income: 200_000 - 19_900 + +- name: MN AMT taxable income leaves the casualty loss out for a non-itemizer + period: 2024 + input: + adjusted_gross_income: 200_000 + mn_itemizing: false + casualty_loss: 40_000 + state_code: MN + output: + mn_amt_taxable_income: 200_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_casualty_loss_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_casualty_loss_deduction.yaml new file mode 100644 index 00000000000..a051c1798fa --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_casualty_loss_deduction.yaml @@ -0,0 +1,181 @@ +# Minn. Stat. 290.0122, subd. 8: losses under 26 U.S.C. 165(c)(3), "including +# the provisions of section 165(h) ... but disregarding paragraph (h)(5)". +# 2024 Schedule M1SA instructions, line 19 (PDF p. 7): a loss is deductible +# only to the extent each loss "is more than $100" and the year's losses +# "reduced by $100" are "more than 10% of the amount on line 1 of Form M1". +# 2024 Schedule M1CAT (PDF p. 1): line 11 "Enter $100"; line 18 "Enter the +# amount from line 1 of Form M1" (federal adjusted gross income); line 19 +# "Multiply line 18 by 10%"; line 20 subtracts line 19 from line 17, not below +# 0, and goes to M1SA line 19. The 2018 M1CAT has the same $100 reduction and +# 10% floor; its line 20 goes to M1SA line 18, and its line 18 takes Schedule +# M1NC line 38 (federal adjustments) from filers of that schedule, which the +# model does not have. These cases are ordinary losses: +# the 2020 Schedule M1SA's net qualified disaster loss (federal Form 4684 line +# 15, $500 and no 10% floor) is not modeled. +# A joint return is one individual for the $100 rule (165(h)(4)(B)). The model +# records one loss amount per person, not separate casualty events, so a +# return's losses are treated as one casualty. A dependent's loss belongs on +# the dependent's own return, as the dependent's income does. + +- name: Case 1, the $100 reduction applies before the 10 percent floor. + period: 2024 + input: + state_code: MN + employment_income: 100_000 + casualty_loss: 15_000 + output: + # M1CAT: line 12 = 15,000 - 100 = 14,900; line 19 = 10% x 100,000 + # = 10,000; line 20 = 14,900 - 10,000. + mn_casualty_loss_deduction: 4_900 + # Minnesota allows the loss though the federal deduction is suspended. + casualty_loss_deduction: 0 + +- name: Case 2, a loss $100 above the floor nets to zero. + period: 2024 + input: + state_code: MN + employment_income: 100_000 + casualty_loss: 10_100 + output: + # (10,100 - 100) - 10% x 100,000 = 10,000 - 10,000 + mn_casualty_loss_deduction: 0 + +- name: Case 3, a loss $101 above the floor leaves $1. + period: 2024 + input: + state_code: MN + employment_income: 100_000 + casualty_loss: 10_101 + output: + # (10,101 - 100) - 10% x 100,000 = 10,001 - 10,000 + mn_casualty_loss_deduction: 1 + +- name: Case 4, a loss of exactly $100 is fully absorbed by the $100 reduction. + period: 2024 + input: + state_code: MN + casualty_loss: 100 + output: + mn_casualty_loss_deduction: 0 + +- name: Case 5, Publication 547 Example 1 with $80,000 of AGI. + period: 2024 + input: + state_code: MN + employment_income: 80_000 + casualty_loss: 14_800 + output: + # IRS Publication 547 (2017, PDF p. 10), Example 1: 14,800 - 100 = 14,700; + # less 10% of 80,000 = 6,700. + mn_casualty_loss_deduction: 6_700 + +- name: Case 6, a negative federal AGI gives no floor, not a larger loss. + period: 2024 + input: + state_code: MN + adjusted_gross_income: -20_000 + casualty_loss: 15_000 + output: + # M1CAT line 18 has no "enter 0" rule; the floor is held at zero so the + # deduction never exceeds the reduced loss: 15,000 - 100. + mn_casualty_loss_deduction: 14_900 + +- name: Case 7, a joint return reduces the spouses' pooled losses by $100 once. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 60_000 + casualty_loss: 10_000 + person2: + age: 40 + employment_income: 40_000 + casualty_loss: 5_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MN + output: + filing_status: JOINT + # (10,000 + 5,000 - 100) - 10% x 100,000 = 14,900 - 10,000 + mn_casualty_loss_deduction: 4_900 + +- name: Case 8, a dependent's loss is left to the dependent's own return. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 100_000 + casualty_loss: 15_000 + person2: + age: 10 + casualty_loss: 5_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MN + output: + is_tax_unit_dependent: [false, true] + # (15,000 - 100) - 10% x 100,000 = 14,900 - 10,000 + mn_casualty_loss_deduction: 4_900 + +- name: Case 9, a loss only the dependent had gives the parent nothing. + period: 2024 + input: + people: + person1: + age: 40 + employment_income: 100_000 + person2: + age: 10 + casualty_loss: 15_000 + tax_units: + tax_unit: + members: [person1, person2] + households: + household: + members: [person1, person2] + state_code: MN + output: + is_tax_unit_dependent: [false, true] + mn_casualty_loss_deduction: 0 + +- name: Case 10, the 2018 Schedule M1CAT already allows a non-disaster loss. + period: 2018 + input: + state_code: MN + employment_income: 50_000 + casualty_loss: 8_000 + output: + # For a filer with no Schedule M1NC: (8,000 - 100) - 10% x 50,000 + # = 7,900 - 5,000 + mn_casualty_loss_deduction: 2_900 + casualty_loss_deduction: 0 + +- name: Case 11, the deduction is zero outside Minnesota. + period: 2024 + input: + state_code: WI + employment_income: 100_000 + casualty_loss: 15_000 + output: + mn_casualty_loss_deduction: 0 + +- name: Case 12, lifting the federal suspension does not change Minnesota's deduction. + period: 2024 + input: + gov.irs.deductions.itemized.casualty.active: true + state_code: MN + employment_income: 100_000 + casualty_loss: 15_000 + output: + # Minnesota's deduction does not read the federal switch. + mn_casualty_loss_deduction: 4_900 diff --git a/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_itemized_deductions.yaml b/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_itemized_deductions.yaml index 632dba542f1..acb1fa03b73 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_itemized_deductions.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/mn/tax/income/mn_itemized_deductions.yaml @@ -39,7 +39,9 @@ adjusted_gross_income: 1_206_050 interest_deduction: 10_000 medical_expense_deduction: 400 - casualty_loss_deduction: 200 + # Minnesota's own casualty loss (Schedule M1SA line 19) is exempt from the + # reduction, as medical expenses are. + mn_casualty_loss_deduction: 200 state_code: MN output: mn_itemized_deductions: (10_000 + 400 + 200) - 0.80 * 10_000 @@ -90,3 +92,60 @@ state_code: MN output: mn_itemized_deductions: 10_000 + +# Schedule M1SA line 19 takes the casualty and theft loss from Schedule M1CAT: +# each casualty less $100, then less 10% of Form M1 line 1 (federal AGI). Minn. +# Stat. 290.0122, subd. 8, disregards the federal limit to declared disasters. +- name: 2024 MN itemized deductions include a non-disaster casualty loss + absolute_error_margin: 0.01 + period: 2024 + input: + filing_status: SINGLE + adjusted_gross_income: 100_000 + interest_deduction: 10_000 + casualty_loss: 15_000 + state_code: MN + output: + # The federal deduction is suspended. + casualty_loss_deduction: 0 + # M1CAT: (15,000 - 100) - 10% x 100,000 = 4,900 + mn_casualty_loss_deduction: 4_900 + # M1SA line 25: 10,000 interest + 4,900 casualty; AGI is under the + # $232,500 reduction threshold. + mn_itemized_deductions: 14_900 + +# M1SA line 26 Worksheet B, step 2, takes lines 4, 13 and 19 out before the +# 80% reduction (Minn. Stat. 290.0122, subd. 2(d)(3)). +- name: 2024 MN casualty loss is exempt from the high-income reduction + absolute_error_margin: 0.01 + period: 2024 + input: + filing_status: SINGLE + adjusted_gross_income: 2_000_000 + interest_deduction: 10_000 + casualty_loss: 250_000 + state_code: MN + output: + # M1CAT: (250,000 - 100) - 10% x 2,000,000 = 49,900 + mn_casualty_loss_deduction: 49_900 + # AGI is over $1,053,750, so the reduction is 80% of the deductions + # other than the casualty loss: 0.8 x 10,000 = 8,000. + # 10,000 + 49,900 - 8,000. Were the loss reduced too, the result would be + # 59,900 - 0.8 x 59,900 = 11,980. + mn_itemized_deductions: 51_900 + +- name: 2024 MN counts the casualty loss once when the federal suspension is lifted + absolute_error_margin: 0.01 + period: 2024 + input: + gov.irs.deductions.itemized.casualty.active: true + filing_status: SINGLE + adjusted_gross_income: 100_000 + interest_deduction: 10_000 + casualty_loss: 15_000 + state_code: MN + output: + mn_casualty_loss_deduction: 4_900 + # The federal deduction, now positive inside itemized_deductions_less_salt, + # is replaced by Minnesota's 4,900, not added to it. + mn_itemized_deductions: 14_900 diff --git a/policyengine_us/tests/policy/contrib/states/mn/walz/mn_walz_hf1938.yaml b/policyengine_us/tests/policy/contrib/states/mn/walz/mn_walz_hf1938.yaml index ba403f7eda6..aacb657d111 100644 --- a/policyengine_us/tests/policy/contrib/states/mn/walz/mn_walz_hf1938.yaml +++ b/policyengine_us/tests/policy/contrib/states/mn/walz/mn_walz_hf1938.yaml @@ -109,3 +109,22 @@ state_code: MN output: mn_itemized_deductions: 10_000 + +- name: Itemized deductions with reform take the Minnesota casualty loss and exempt it from the offset + absolute_error_margin: 0.5 + period: 2023 + reforms: policyengine_us.reforms.states.mn.walz.mn_walz_hf1938.mn_walz_hf1938 + input: + gov.contrib.states.mn.walz.hf1938.repeal: true + filing_status: SINGLE + adjusted_gross_income: 2_000_000 + interest_deduction: 10_000 + casualty_loss: 250_000 + state_code: MN + output: + # Schedule M1CAT: (250,000 - 100) - 10% x 2,000,000 = 49,900 + mn_casualty_loss_deduction: 49_900 + # Offset: the lesser of 80% of the deductions other than the casualty loss + # (0.8 x 10,000 = 8,000) and 3% of AGI over $220,650 (53,380.50). + # 10,000 + 49,900 - 8,000 + mn_itemized_deductions: 51_900 diff --git a/policyengine_us/tests/unit/test_ca_mn_casualty_loss_deduction_properties.py b/policyengine_us/tests/unit/test_ca_mn_casualty_loss_deduction_properties.py new file mode 100644 index 00000000000..96193c6eb9b --- /dev/null +++ b/policyengine_us/tests/unit/test_ca_mn_casualty_loss_deduction_properties.py @@ -0,0 +1,211 @@ +"""Properties of California's and Minnesota's casualty loss deductions. + +Both states allow a personal casualty or theft loss under 26 U.S.C. 165(h) +without the federal limit to declared disasters (Cal. Rev. & Tax. Code +17204(b), Schedule CA (540) line 15; Minn. Stat. 290.0122, subd. 8, Schedule +M1CAT). Each reduces the loss by $100 (Form 4684 line 11; M1CAT line 11) and +allows the rest above 10% of federal adjusted gross income (Form 4684 line 17 +and FTB Publication 1034; M1CAT lines 18-19). A joint return is one individual +for the $100 rule, and a dependent's loss belongs on the dependent's own +return. The model records one loss amount per person and no event count, so a +return's losses are treated as one casualty. + +`ca_casualty_loss_deduction` and `mn_casualty_loss_deduction` are two copies +of that computation for an ordinary loss. The model has no disaster input and +no Minnesota Schedule M1NC, so the properties below do not cover the 2020 +Schedule M1SA's net qualified disaster loss or the 2018 M1CAT's Schedule M1NC +line 38 base. Hypothesis draws batches of tax units (single or joint, +with up to two dependents who have their own losses), places each in +California and in Minnesota, and runs each batch as one vectorized baseline +simulation. For every tax unit and year: + +1. Each copy equals a closed-form reference on the head's and spouse's losses: + max(max(loss - 100, 0) - 10% x max(AGI, 0), 0). Dependents' losses never + enter it, and neither does California AGI. +2. Bounds: 0 <= deduction <= max(loss - 100, 0). +3. Each copy is zero outside its state. +4. Differential: the two copies agree on the same drawn units. +5. The federal `casualty_loss_deduction` is zero in these years, so neither + state follows the federal suspension. + +A deterministic grid adds the boundary inputs ($0, $99, $100, $101, the floor +plus $100) and checks monotonicity: each copy rises with the loss and falls +with AGI, and is zero for a loss of $100 or less. +""" + +import itertools + +import numpy as np +import pytest +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from policyengine_us import Simulation + +REDUCTION = 100 # Form 4684 line 11; Schedule M1CAT line 11 +FLOOR = 0.1 # Form 4684 line 17; Schedule M1CAT line 19 +TOLERANCE = 0.01 +CA_AGI_OFFSET = 7_000 # makes California AGI differ from federal AGI +# 2018 is the first year of the federal suspension; 2026 follows California's +# move to a January 1, 2025 conformity date. +YEARS = [2018, 2026] +STATE_OF = { + "ca_casualty_loss_deduction": "CA", + "mn_casualty_loss_deduction": "MN", +} +STATES = list(STATE_OF.values()) + + +def reference(loss, agi): + reduced = np.maximum(loss - REDUCTION, 0) + return np.maximum(reduced - FLOOR * np.maximum(agi, 0), 0) + + +def every_year(value): + return {year: value for year in YEARS} + + +def build_situation(units): + """Place each unit in each state, with the same federal AGI.""" + people, tax_units, households = {}, {}, {} + rows = [] # (filer loss, AGI, state) for each tax unit, in order + for state in STATES: + for i, unit in enumerate(units): + name = f"{state}{i}" + members = [f"{name}_head"] + people[members[0]] = { + "age": every_year(40), + "casualty_loss": every_year(unit["head_loss"]), + } + filer_loss = unit["head_loss"] + if unit["joint"]: + members.append(f"{name}_spouse") + people[members[-1]] = { + "age": every_year(40), + "casualty_loss": every_year(unit["spouse_loss"]), + } + filer_loss += unit["spouse_loss"] + for d, dependent_loss in enumerate(unit["dependent_losses"]): + members.append(f"{name}_dep{d}") + people[members[-1]] = { + "age": every_year(10), + "is_tax_unit_dependent": every_year(True), + "casualty_loss": every_year(dependent_loss), + } + agi = unit["agi"] + tax_units[name] = { + "members": members, + "adjusted_gross_income": every_year(agi), + # California's floor is on federal AGI (FTB Publication 1034), + # so a different California AGI must not move its copy. + "ca_agi": every_year(agi + CA_AGI_OFFSET), + } + households[name] = {"members": members, "state_code": every_year(state)} + rows.append((filer_loss, agi, state)) + situation = {"people": people, "tax_units": tax_units, "households": households} + loss, agi, state = (np.array(column) for column in zip(*rows)) + return situation, loss.astype(float), agi.astype(float), state + + +def check_reference_and_bounds(sim, loss, agi, state): + for variable, own_state in STATE_OF.items(): + for year in YEARS: + value = sim.calculate(variable, year) + expected = np.where(state == own_state, reference(loss, agi), 0) + np.testing.assert_allclose( + value, expected, atol=TOLERANCE, err_msg=f"{variable} {year}" + ) + assert np.all(value >= 0) + assert np.all(value <= np.maximum(loss - REDUCTION, 0) + TOLERANCE) + + +def check_copies_agree(sim, state): + for year in YEARS: + california = sim.calculate("ca_casualty_loss_deduction", year) + minnesota = sim.calculate("mn_casualty_loss_deduction", year) + # The same drawn units, in the same order, sit in each state. + np.testing.assert_allclose( + california[state == "CA"], minnesota[state == "MN"], atol=TOLERANCE + ) + # Neither state follows the federal suspension. + assert np.all(sim.calculate("casualty_loss_deduction", year) == 0) + + +money = st.one_of( + st.sampled_from([0, 50, 99, 100, 101, 150]), + st.integers(0, 60_000), +).map(float) +agis = st.one_of( + st.sampled_from([0, 1_000, 50_000]), + st.integers(-20_000, 300_000), +).map(float) +tax_unit_strategy = st.fixed_dictionaries( + { + "joint": st.booleans(), + "head_loss": money, + "spouse_loss": money, + "dependent_losses": st.lists(money, max_size=2), + "agi": agis, + } +) +SETTINGS = dict( + max_examples=20, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) + + +@settings(**SETTINGS) +@given(st.lists(tax_unit_strategy, min_size=4, max_size=15)) +def test_copies_match_the_form_4684_reference(units): + situation, loss, agi, state = build_situation(units) + sim = Simulation(situation=situation) + check_reference_and_bounds(sim, loss, agi, state) + check_copies_agree(sim, state) + + +GRID_LOSSES = [0, 50, 99, 100, 101, 150, 5_000, 10_100, 10_101, 30_000] +GRID_AGIS = [-10_000, 0, 1_000, 50_000, 100_000, 300_000] +GRID_DEPENDENT_LOSSES = [0, 20_000] + + +def grid_situation(): + units = [ + { + "joint": False, + "head_loss": float(loss), + "spouse_loss": 0.0, + "dependent_losses": [float(dependent_loss)], + "agi": float(agi), + } + for loss, agi, dependent_loss in itertools.product( + GRID_LOSSES, GRID_AGIS, GRID_DEPENDENT_LOSSES + ) + ] + return build_situation(units) + + +@pytest.fixture(scope="module") +def grid(): + situation, loss, agi, state = grid_situation() + return Simulation(situation=situation), loss, agi, state + + +@pytest.mark.parametrize("variable, year", list(itertools.product(STATE_OF, YEARS))) +def test_grid_monotone_and_boundaries(grid, variable, year): + sim, loss, agi, state = grid + rows = state == STATE_OF[variable] + value = sim.calculate(variable, year)[rows] + np.testing.assert_allclose(value, reference(loss[rows], agi[rows]), atol=TOLERANCE) + shape = (len(GRID_LOSSES), len(GRID_AGIS), len(GRID_DEPENDENT_LOSSES)) + table = value.reshape(shape) + # A dependent's loss never changes the filer's deduction. + np.testing.assert_allclose(table[..., 0], table[..., 1], atol=TOLERANCE) + assert np.all(np.diff(table, axis=0) >= -TOLERANCE), "falls as the loss rises" + assert np.all(np.diff(table, axis=1) <= TOLERANCE), "rises as AGI rises" + # A loss of $100 or less is absorbed by the $100 reduction. + small = np.array(GRID_LOSSES) <= REDUCTION + assert np.all(table[small] == 0) + # Guard against a vacuous pass. + assert table.max() > 0 diff --git a/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_casualty_loss_deduction.py b/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_casualty_loss_deduction.py new file mode 100644 index 00000000000..1e4ef8389cb --- /dev/null +++ b/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_casualty_loss_deduction.py @@ -0,0 +1,56 @@ +from policyengine_us.model_api import * + + +class ca_casualty_loss_deduction(Variable): + value_type = float + entity = TaxUnit + label = "California casualty loss deduction" + unit = USD + definition_period = YEAR + reference = ( + # Cal. Rev. & Tax. Code § 17201: the IRC itemized deductions, + # including 26 U.S.C. 165, apply + "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=RTC§ionNum=17201", + # Cal. Rev. & Tax. Code § 17204(b): 26 U.S.C. 165(h)(5) shall not apply + "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=RTC§ionNum=17204", + # 2024 Schedule CA (540) instructions, line 15 + "https://www.ftb.ca.gov/forms/2024/2024-540-booklet.pdf#page=66", + # 2025 Schedule CA (540) instructions, line 15 + "https://www.ftb.ca.gov/forms/2025/2025-540-ca-instructions.html", + # FTB Publication 1034, How to Calculate a Disaster Loss - Individuals + # (2025 edition; the 2024 edition has the same text on the same page) + "https://www.ftb.ca.gov/forms/misc/1034.pdf#page=4", + "https://web.archive.org/web/20250529011540/https://www.ftb.ca.gov/forms/misc/1034.pdf#page=4", + # 2024 Form 4684, lines 10-18 + "https://www.irs.gov/pub/irs-prior/f4684--2024.pdf#page=1", + ) + defined_for = StateCode.CA + documentation = """ + California adopts 26 U.S.C. 165 (R&TC 17201) but not the federal limit of + personal casualty losses to declared disasters (R&TC 17204(b)). Schedule CA + (540) line 15 has filers complete a second federal Form 4684 with California + amounts, so a non-disaster personal casualty or theft loss stays + deductible: each casualty is reduced by $100, and the rest is deductible + above 10% of federal adjusted gross income. + """ + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.irs.deductions.itemized.casualty + # California never applies the federal suspension: its IRC conformity + # date was January 1, 2015 through 2024, before 26 U.S.C. 165(h)(5) + # was enacted, and R&TC 17204(b) turns (h)(5) off from 2025. + # Only the owner of the property claims the loss. A dependent's loss + # belongs on the dependent's own return, as the dependent's income + # does: adjusted gross income leaves it out. + loss = tax_unit_non_dep_add(tax_unit, period, ["casualty_loss"]) + # Form 4684 line 11 reduces each casualty by $100. California states no + # amount of its own; it takes 165(h)(1) through R&TC 17201. A joint + # return is one individual for the $100 rule. The model records one + # loss amount per person, not separate casualty events, so the + # return's losses are treated as one casualty and the reduction + # applies once. + reduced_loss = max_(loss - p.per_casualty_reduction, 0) + # Form 4684 line 17 and FTB Publication 1034: 10% of federal adjusted + # gross income (Form 540 line 13), not California AGI. + positive_agi = tax_unit("positive_agi", period) + return max_(reduced_loss - positive_agi * p.floor, 0) diff --git a/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions_pre_limitation.py b/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions_pre_limitation.py index 80c39a22960..091b5150824 100644 --- a/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions_pre_limitation.py +++ b/policyengine_us/variables/gov/states/ca/tax/income/deductions/itemized/ca_itemized_deductions_pre_limitation.py @@ -12,12 +12,17 @@ class ca_itemized_deductions_pre_limitation(Variable): "https://www.ftb.ca.gov/forms/2022/2022-540-ca-instructions.html", "https://www.ftb.ca.gov/forms/2025/2025-540-ca-instructions.html", "https://www.ftb.ca.gov/about-ftb/data-reports-plans/summary-of-federal-income-tax-changes/index.html", + # 2024 Schedule CA (540) instructions, line 15 + "https://www.ftb.ca.gov/forms/2024/2024-540-booklet.pdf#page=66", ) defined_for = StateCode.CA def formula(tax_unit, period, parameters): # Exclude the replaced federal amounts before summation, so changes - # to federal charity/misc rules cannot cause cancellation errors. + # to federal charity/misc/casualty rules cannot cause cancellation + # errors. Schedule CA line 15 replaces the federal casualty loss, + # which is limited to declared disasters from 2018, with California's + # own. federal_components = parameters(period).gov.irs.deductions.itemized_deductions deductions = [ variable @@ -28,6 +33,7 @@ def formula(tax_unit, period, parameters): "charitable_deduction", "charitable_deduction_for_non_itemizers", "misc_deduction", + "casualty_loss_deduction", ) ] deductions += [ @@ -35,6 +41,7 @@ def formula(tax_unit, period, parameters): "real_estate_taxes", "ca_charitable_deduction", "ca_misc_deduction", + "ca_casualty_loss_deduction", ] # Federal investment interest is nested in interest_deduction. return add(tax_unit, period, deductions) - add( diff --git a/policyengine_us/variables/gov/states/mn/tax/income/amt/mn_amt_taxable_income.py b/policyengine_us/variables/gov/states/mn/tax/income/amt/mn_amt_taxable_income.py index 50dc8cc7602..83736e79da5 100644 --- a/policyengine_us/variables/gov/states/mn/tax/income/amt/mn_amt_taxable_income.py +++ b/policyengine_us/variables/gov/states/mn/tax/income/amt/mn_amt_taxable_income.py @@ -10,6 +10,8 @@ class mn_amt_taxable_income(Variable): reference = ( "https://www.revenue.state.mn.us/sites/default/files/2023-02/m1mt_21.pdf", "https://www.revenue.state.mn.us/sites/default/files/2023-01/m1mt_22.pdf", + # 2024 Schedule M1MT, line 12 + "https://www.revenue.state.mn.us/sites/default/files/2025-07/m1mt-24.pdf#page=1", ) defined_for = StateCode.MN @@ -19,7 +21,9 @@ def formula(tax_unit, period, parameters): SOME_DEDUCTIONS = [ "charitable_deduction", "medical_expense_deduction", - "casualty_loss_deduction", + # M1MT line 12 takes the casualty and theft loss from Schedule + # M1SA line 19, Minnesota's own amount. + "mn_casualty_loss_deduction", ] some_itm_deds = itemizing * add(tax_unit, period, SOME_DEDUCTIONS) AMT_SUBTRACTIONS = [ diff --git a/policyengine_us/variables/gov/states/mn/tax/income/deductions/mn_casualty_loss_deduction.py b/policyengine_us/variables/gov/states/mn/tax/income/deductions/mn_casualty_loss_deduction.py new file mode 100644 index 00000000000..e8d3b9bfdf1 --- /dev/null +++ b/policyengine_us/variables/gov/states/mn/tax/income/deductions/mn_casualty_loss_deduction.py @@ -0,0 +1,62 @@ +from policyengine_us.model_api import * + + +class mn_casualty_loss_deduction(Variable): + value_type = float + entity = TaxUnit + label = "Minnesota casualty loss deduction" + unit = USD + definition_period = YEAR + reference = ( + # Minn. Stat. § 290.0122, subd. 8: losses under 26 U.S.C. 165(c)(3), + # including 165(h) but disregarding (h)(5) + "https://www.revisor.mn.gov/statutes/cite/290.0122#stat.290.0122.8", + # 2024 Schedule M1SA, line 19, and its instructions + # PDF pages 1, 7 + "https://www.revenue.state.mn.us/sites/default/files/2024-12/m1sa-24.pdf#page=1", + # 2024 Schedule M1CAT, lines 10-20 + "https://www.revenue.state.mn.us/sites/default/files/2024-12/m1cat-24.pdf#page=1", + # 2018 Schedule M1CAT, lines 10-20 + "https://www.revenue.state.mn.us/sites/default/files/2018-11/m1cat_18.pdf#page=1", + # 2020 Schedule M1SA instructions, line 19, qualified disaster loss + # PDF pages 6-7 + "https://www.revenue.state.mn.us/sites/default/files/2023-01/m1sa_20.pdf#page=6", + ) + defined_for = StateCode.MN + documentation = """ + Minnesota allows personal casualty and theft losses under 26 U.S.C. 165(h) + but disregards the federal limit to declared disasters (Minn. Stat. + 290.0122, subd. 8). Schedule M1CAT reduces each casualty by $100 and allows + the rest above 10% of Form M1 line 1 (federal adjusted gross income); the + result goes on Schedule M1SA line 19. Two cases on the forms are not + modeled: for 2018, filers of Schedule M1NC (federal adjustments) use its + line 38 in place of Form M1 line 1; and the 2020 Schedule M1SA takes a + net qualified disaster loss from federal Form 4684 line 15 ($500 per + casualty, no 10% floor), which can be deducted without itemizing. + """ + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.irs.deductions.itemized.casualty + # For 2018 Minnesota computed tax under the Internal Revenue Code as + # amended through December 16, 2016 (Minn. Stat. 290.993), before + # 26 U.S.C. 165(h)(5) existed, and Schedule M1CAT has applied the $100 + # and 10% to an ordinary (not qualified disaster) loss in every year + # since, so the federal suspension never applies. + # Only the owner of the property claims the loss. A dependent's loss + # belongs on the dependent's own return, as the dependent's income + # does: adjusted gross income leaves it out. + loss = tax_unit_non_dep_add(tax_unit, period, ["casualty_loss"]) + # M1CAT line 11: "Enter $100". A joint return is one individual for the + # $100 rule (165(h)(4)(B)). The model records one loss amount per + # person, not separate casualty events, so the return's losses are + # treated as one casualty and the reduction applies once. + reduced_loss = max_(loss - p.per_casualty_reduction, 0) + # M1CAT lines 18-20: subtract 10% of Form M1 line 1 (federal adjusted + # gross income). The 2018 form takes Schedule M1NC line 38 instead + # from filers of that schedule; the model has no Schedule M1NC, so + # 2018 also uses federal adjusted gross income. The form does not say + # to enter 0 for a negative AGI; like Form 4684 and the federal + # deduction, the floor is not allowed to go below zero, so the + # deduction never exceeds the reduced loss. + positive_agi = tax_unit("positive_agi", period) + return max_(reduced_loss - positive_agi * p.floor, 0) diff --git a/policyengine_us/variables/gov/states/mn/tax/income/deductions/mn_itemized_deductions.py b/policyengine_us/variables/gov/states/mn/tax/income/deductions/mn_itemized_deductions.py index bbd8191185d..7fc89edb407 100644 --- a/policyengine_us/variables/gov/states/mn/tax/income/deductions/mn_itemized_deductions.py +++ b/policyengine_us/variables/gov/states/mn/tax/income/deductions/mn_itemized_deductions.py @@ -12,6 +12,11 @@ class mn_itemized_deductions(Variable): "https://www.revenue.state.mn.us/sites/default/files/2023-12/m1_inst_21.pdf", "https://www.revenue.state.mn.us/sites/default/files/2023-12/m1_22.pdf", "https://www.revenue.state.mn.us/sites/default/files/2024-02/m1-inst-22.pdf", + # 2024 Schedule M1SA, line 19, and the line 26 limitation worksheets + # PDF pages 1, 8 + "https://www.revenue.state.mn.us/sites/default/files/2024-12/m1sa-24.pdf#page=1", + # Minn. Stat. § 290.0122, subd. 2(d) and subd. 8 + "https://www.revisor.mn.gov/statutes/cite/290.0122", ) defined_for = StateCode.MN @@ -24,13 +29,26 @@ def formula(tax_unit, period, parameters): # ... calculate pre-limitation itemized deductions itm_deds_less_salt = tax_unit("itemized_deductions_less_salt", period) capped_property_taxes = tax_unit("capped_property_taxes", period) - mn_itm_deds = itm_deds_less_salt + capped_property_taxes + # Schedule M1SA line 19 takes Minnesota's own casualty and theft loss + # (Schedule M1CAT) in place of the federal one, which is limited to + # declared disasters from 2018. + federal_casualty_loss = tax_unit("casualty_loss_deduction", period) + mn_casualty_loss = tax_unit("mn_casualty_loss_deduction", period) + mn_itm_deds = ( + itm_deds_less_salt + - federal_casualty_loss + + mn_casualty_loss + + capped_property_taxes + ) # ... calculate itemized deductions offset p = parameters(period).gov.states.mn.tax.income.deductions.itemized + # Minn. Stat. 290.0122, subd. 2(d), and the M1SA line 26 worksheets + # (step 2: lines 4, 13 and 19) leave medical expenses and casualty + # and theft losses out of the reduction. exempt_deds = add( tax_unit, period, - ["medical_expense_deduction", "casualty_loss_deduction"], + ["medical_expense_deduction", "mn_casualty_loss_deduction"], ) net_deds = max_(0, mn_itm_deds - exempt_deds) filing_status = tax_unit("filing_status", period)