diff --git a/changelog.d/al-misc-deduction-own-floor.fixed.md b/changelog.d/al-misc-deduction-own-floor.fixed.md new file mode 100644 index 00000000000..501169035c9 --- /dev/null +++ b/changelog.d/al-misc-deduction-own-floor.fixed.md @@ -0,0 +1 @@ +Compute Alabama's miscellaneous itemized deduction from its own list of expenses (unreimbursed employee business expenses and tax preparation fees) above 2% of Alabama AGI in every modeled year, counting only the head's and spouse's expenses, instead of applying a second floor to the federal deduction, which is zero from 2018. diff --git a/policyengine_us/parameters/gov/states/al/tax/income/deductions/itemized/misc_sources.yaml b/policyengine_us/parameters/gov/states/al/tax/income/deductions/itemized/misc_sources.yaml new file mode 100644 index 00000000000..b334c572882 --- /dev/null +++ b/policyengine_us/parameters/gov/states/al/tax/income/deductions/itemized/misc_sources.yaml @@ -0,0 +1,22 @@ +description: Alabama counts these expenses toward the miscellaneous itemized deduction, which applies only above a percentage of Alabama adjusted gross income. +values: + 2017-01-01: + # Section (a)(1): unreimbursed employee business expenses. + - unreimbursed_business_employee_expenses + # Section (a)(14): expenses in connection with the determination, collection, or refund of any tax (26 U.S.C. 212(3)). + - tax_preparation_fees +metadata: + unit: list + period: year + label: Alabama miscellaneous itemized deduction sources + reference: + - title: Code of Alabama Section 40-18-15(a)(1), (14), (23) (2017 edition) + href: https://law.justia.com/codes/alabama/2017/title-40/chapter-18/article-1/section-40-18-15/ + - title: "Act 2026-604, Section 1, amending Code of Alabama Section 40-18-15 #page 2,6-8" + href: https://alison.legislature.state.al.us/files/pdf/SearchableInstruments/2026RS/HB527-enr.pdf#page=2 + - title: "2017 Alabama Form 40 instructions, Schedule A lines 20-24 #page 20-21" + href: https://www.revenue.alabama.gov/wp-content/uploads/2021/10/17f40bk.pdf#page=20 + - title: "2024 Alabama Form 40 instructions, Schedule A lines 20-24 #page 20-21" + href: https://www.revenue.alabama.gov/wp-content/uploads/2025/01/24f40bk.pdf#page=20 + - title: 2025 Alabama Form 40 instructions, Schedule A lines 20-24 + href: https://www.revenue.alabama.gov/wp-content/uploads/2026/01/25f40bk.pdf#page=21 diff --git a/policyengine_us/parameters/gov/states/al/tax/income/deductions/itemized/work_related_expense_rate.yaml b/policyengine_us/parameters/gov/states/al/tax/income/deductions/itemized/work_related_expense_rate.yaml index e8cbbbd7ac7..4fd35adee44 100644 --- a/policyengine_us/parameters/gov/states/al/tax/income/deductions/itemized/work_related_expense_rate.yaml +++ b/policyengine_us/parameters/gov/states/al/tax/income/deductions/itemized/work_related_expense_rate.yaml @@ -1,14 +1,18 @@ -description: Alabama deducts work-related expense over this percentage of adjusted gross income. +description: Alabama allows the total of the subdivision (1) unreimbursed employee business expenses and the subdivision (14) expenses only above this percentage of adjusted gross income. values: - 2021-01-01: 0.02 + 2017-01-01: 0.02 metadata: - label: Alabama work-related expense deduction rate + label: Alabama miscellaneous itemized deduction floor rate period: year unit: /1 reference: - - title: Code of Alabama Section 40-18-15, (a) (3) (h) (23) - href: https://law.justia.com/codes/alabama/2022/title-40/chapter-18/article-1/section-40-18-15/ + - title: Code of Alabama Section 40-18-15(a)(23) (2017 edition) + href: https://law.justia.com/codes/alabama/2017/title-40/chapter-18/article-1/section-40-18-15/ + - title: Code of Alabama Section 40-18-15(a)(23) (2021 edition) + href: https://law.justia.com/codes/alabama/2021/title-40/chapter-18/article-1/section-40-18-15/ + - title: "Act 2026-604, Section 1, amending Code of Alabama Section 40-18-15 #page 7-8" + href: https://alison.legislature.state.al.us/files/pdf/SearchableInstruments/2026RS/HB527-enr.pdf#page=7 - title: 2021 Schedule A (Form 1040) href: https://www.revenue.alabama.gov/ultraviewer/viewer/basic_viewer/index.html?form=2022/06/21f40schabdc_blk.pdf#page=1 - title: 2022 Schedule A (Form 1040) @@ -17,3 +21,9 @@ metadata: href: https://www.revenue.alabama.gov/ultraviewer/viewer/basic_viewer/index.html?form=2024/01/23f40schabdc_blk.pdf#page=1 - title: 2024 Schedule A (Form 1040) href: https://www.revenue.alabama.gov/ultraviewer/viewer/basic_viewer/index.html?form=2025/01/24f40schabdc_blk.pdf#page=20 + - title: "2017 Alabama Form 40 instructions, Schedule A lines 20-24 #page 20-21" + href: https://www.revenue.alabama.gov/wp-content/uploads/2021/10/17f40bk.pdf#page=20 + - title: "2024 Alabama Form 40 instructions, Schedule A lines 20-24 #page 20-21" + href: https://www.revenue.alabama.gov/wp-content/uploads/2025/01/24f40bk.pdf#page=20 + - title: 2025 Alabama Form 40 instructions, Schedule A lines 20-24 + href: https://www.revenue.alabama.gov/wp-content/uploads/2026/01/25f40bk.pdf#page=21 diff --git a/policyengine_us/tests/core/test_al_agi_dependent_invariants.py b/policyengine_us/tests/core/test_al_agi_dependent_invariants.py index 4715b562e27..cf2a7cd94f4 100644 --- a/policyengine_us/tests/core/test_al_agi_dependent_invariants.py +++ b/policyengine_us/tests/core/test_al_agi_dependent_invariants.py @@ -14,8 +14,9 @@ with the dependents' income and deduction inputs as drawn and with them set to zero. For every tax unit: -1. The dependents' inputs never change Alabama AGI, the standard deduction - or the personal and dependent exemptions. Alabama income tax is unchanged +1. The dependents' inputs never change Alabama AGI, the standard deduction, + the personal and dependent exemptions or the miscellaneous itemized + deduction. Alabama income tax is unchanged too wherever the itemized deductions and the federal income tax deduction are. Two leaks outside AGI remain, and are left out here: Alabama itemized deductions still count a dependent's FICA and self-employment @@ -57,24 +58,29 @@ "rental_income", "long_term_capital_gains", "taxable_public_pension_income", + # Alabama miscellaneous itemized deduction sources. + "unreimbursed_business_employee_expenses", + "tax_preparation_fees", ] UNIT_OUTPUTS = [ "al_agi", "al_standard_deduction", "al_personal_exemption", "al_dependent_exemption", + "al_misc_deduction", "al_itemized_deductions", "al_federal_income_tax_deduction", "al_income_tax", "tax_unit_dependents", ] -# Outputs that depend on Alabama AGI but not on federal tax or itemized -# deductions. +# Outputs that depend on Alabama AGI but not on federal tax, and on no +# itemized deduction that still leaks a dependent's items (#9941). INVARIANT_OUTPUTS = [ "al_agi", "al_standard_deduction", "al_personal_exemption", "al_dependent_exemption", + "al_misc_deduction", ] amount = st.integers(1, 40_000).map(float) @@ -110,6 +116,8 @@ def person_amounts(draw): # A public pension is both in pension income and subtracted from # Alabama gross income. "taxable_public_pension_income": public_pension, + "unreimbursed_business_employee_expenses": draw(small), + "tax_preparation_fees": draw(st.integers(0, 1_000).map(float)), } @@ -156,6 +164,8 @@ def some(low, high, p=0.5): "rental_income": some(-5_000, 20_000, 0.3), "long_term_capital_gains": some(1, 5_000, 0.3), "taxable_public_pension_income": public_pension, + "unreimbursed_business_employee_expenses": some(1, 5_000, 0.3), + "tax_preparation_fees": some(1, 1_000, 0.3), } diff --git a/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/deductions/itemized/al_misc_deduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/deductions/itemized/al_misc_deduction.yaml index a2de34c3f83..dd94d1e9f53 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/deductions/itemized/al_misc_deduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/al/tax/income/deductions/itemized/al_misc_deduction.yaml @@ -1,20 +1,138 @@ -- name: Alabama work related itemized deductions unit test 1 +# Ala. Code 40-18-15(a)(23) allows the subdivision (1) unreimbursed employee +# business expenses and the subdivision (14) deduction only to the extent they +# exceed 2% of Alabama AGI. Alabama applies that one floor to the expenses in +# every year; it does not start from the federal miscellaneous deduction, which +# is already net of the federal floor and is zero from 2018. + +- name: Case 1, 2021 expenses above 2% of Alabama AGI. period: 2021 input: - misc_deduction: 2_000 + unreimbursed_business_employee_expenses: 2_000 al_agi: 70_000 state_code: AL output: + # 2,000 - 0.02 * 70,000 al_misc_deduction: 600 -#2000-70000*0.2=600 - -- name: Alabama work related itemized deductions unit test 2 +- name: Case 2, 2021 expenses well above the floor. period: 2021 input: - misc_deduction: 7_000 + unreimbursed_business_employee_expenses: 7_000 al_agi: 30_000 state_code: AL output: + # 7,000 - 0.02 * 30,000 al_misc_deduction: 6_400 -#7000-30000*0.02=6400 + +- name: Case 3, 2017 Alabama applies one floor to the expenses, not a second floor to the federal deduction. + period: 2017 + input: + unreimbursed_business_employee_expenses: 5_000 + tax_preparation_fees: 0 + positive_agi: 50_000 + al_agi: 50_000 + state_code: AL + output: + # Federal and Alabama each allow 5,000 - 0.02 * 50,000 = 4,000. Before the + # fix Alabama took a further 1,000 off the federal 4,000. + misc_deduction: 4_000 + al_misc_deduction: 4_000 + +- name: Case 4, 2017 Alabama floors on Alabama AGI, the federal deduction on federal AGI. + period: 2017 + input: + unreimbursed_business_employee_expenses: 5_000 + positive_agi: 100_000 + al_agi: 90_000 + state_code: AL + output: + # Federal 5,000 - 0.02 * 100,000 = 3,000; Alabama 5,000 - 0.02 * 90,000. + misc_deduction: 3_000 + al_misc_deduction: 3_200 + +- name: Case 5, 2025 Alabama keeps the deduction the federal return suspends. + period: 2025 + input: + unreimbursed_business_employee_expenses: 5_000 + tax_preparation_fees: 1_000 + al_agi: 50_000 + state_code: AL + output: + misc_deduction: 0 + # 5,000 + 1,000 - 0.02 * 50,000 + al_misc_deduction: 5_000 + +- name: Case 6, 2025 expenses equal to the floor yield no deduction. + period: 2025 + input: + unreimbursed_business_employee_expenses: 1_000 + al_agi: 50_000 + state_code: AL + output: + # max(1,000 - 0.02 * 50,000, 0) + al_misc_deduction: 0 + +- name: Case 7, 2025 Alabama adds both spouses' expenses before one floor. + period: 2025 + input: + people: + head: + unreimbursed_business_employee_expenses: 1_500 + spouse: + tax_preparation_fees: 700 + tax_units: + tax_unit: + members: [head, spouse] + al_agi: 60_000 + households: + household: + members: [head, spouse] + state_code: AL + output: + # 1,500 + 700 - 0.02 * 60,000 + al_misc_deduction: 1_000 + +- name: Case 8, 2025 Alabama reads its own expense list, not the federal total. + period: 2025 + input: + total_misc_deductions: 5_000 + al_agi: 50_000 + state_code: AL + output: + al_misc_deduction: 0 + +- name: Case 9, 2025 a tax unit dependent's expenses stay off the filer's Alabama return. + period: 2025 + input: + people: + head: + unreimbursed_business_employee_expenses: 1_500 + child: + age: 17 + is_tax_unit_dependent: true + unreimbursed_business_employee_expenses: 2_000 + tax_units: + tax_unit: + members: [head, child] + al_agi: 50_000 + households: + household: + members: [head, child] + state_code: AL + output: + # The child's 2,000 belongs on the child's own return. + # 1,500 - 0.02 * 50,000 + al_misc_deduction: 500 + +- name: Case 10, 2017 Alabama floors on Alabama AGI even when federal AGI is lower. + period: 2017 + input: + unreimbursed_business_employee_expenses: 5_000 + positive_agi: 40_000 + al_agi: 50_000 + state_code: AL + output: + # Federal: 5,000 - 0.02 * 40,000 + misc_deduction: 4_200 + # Alabama: 5,000 - 0.02 * 50,000 + al_misc_deduction: 4_000 diff --git a/policyengine_us/tests/unit/test_al_misc_deduction_properties.py b/policyengine_us/tests/unit/test_al_misc_deduction_properties.py new file mode 100644 index 00000000000..70ad16768c5 --- /dev/null +++ b/policyengine_us/tests/unit/test_al_misc_deduction_properties.py @@ -0,0 +1,249 @@ +"""Properties of the Alabama miscellaneous itemized deduction. + +Ala. Code 40-18-15(a)(23) allows unreimbursed employee business expenses and +the subdivision (14) deduction only above 2% of Alabama AGI. Alabama applies +that one floor to the expenses themselves, whether or not the federal +deduction is suspended. For every generated tax unit (one or two filers): + +1. For Alabama AGI of zero or more, the deduction is never negative, never + exceeds the unit's Alabama expenses, and is at least the expenses less 2% + of Alabama AGI. Federal AGI is drawn independently of Alabama AGI, so a + floor at federal AGI breaks the lower bound whenever federal AGI exceeds + Alabama AGI and the expenses exceed 2% of Alabama AGI. +2. It does not fall when expenses rise and does not rise when Alabama AGI + rises. +3. It is the same in 2017 and 2025: the federal suspension from 2018 + (26 U.S.C. 67(g)) does not reach it. +4. In 2017, when Alabama AGI equals federal AGI, it equals the federal + miscellaneous deduction for units whose only miscellaneous expenses are + on both lists, since each then applies one 2% floor to the same expenses. +5. A federal total supplied directly, with no Alabama expenses, yields no + Alabama deduction: Alabama reads its own list of expenses. + +A deduction that starts from the federal misc_deduction fails property 1 in +2025 whenever the expenses exceed the Alabama floor, because the federal +deduction is zero. In 2017 it also fails property 4 wherever the two AGIs +agree and the expenses exceed the floor, and property 3 wherever the expenses +exceed the two floors combined. + +The strategy draws Alabama AGI from 0 to $200,000, so floors of up to $4,000 +($4,200 in the arrangement with $10,000 more AGI). It draws expenses of up to +$20,000 for single filers ($21,000 with the extra $1,000) and up to $40,000 +for couples ($41,000), so most generated units have a positive deduction. +test_worked_cases checks the exact values of three worked cases and runs the +properties on them; it does not draw from the strategy. +""" + +import hypothesis +import hypothesis.strategies as st +import numpy as np +import pytest + +from policyengine_us import Simulation + +YEARS = (2017, 2025) +FLOOR = 0.02 +EXTRA_EXPENSE = 1_000 +EXTRA_AGI = 10_000 +ARRANGEMENTS = ("base", "more_expenses", "more_agi") +TOLERANCE = 0.01 + + +def federal_agi_of(case): + # None draws federal AGI equal to the base Alabama AGI. + if case["federal_agi"] is None: + return case["al_agi"] + return case["federal_agi"] + + +def unit_inputs(case, arrangement): + head = { + "unreimbursed_business_employee_expenses": case["head_employee"], + "tax_preparation_fees": case["head_prep"], + } + spouse = { + "unreimbursed_business_employee_expenses": case["spouse_employee"], + "tax_preparation_fees": case["spouse_prep"], + } + agi = case["al_agi"] + if arrangement == "more_expenses": + head["unreimbursed_business_employee_expenses"] += EXTRA_EXPENSE + elif arrangement == "more_agi": + agi += EXTRA_AGI + elif arrangement == "federal_only": + head = {name: 0 for name in head} + spouse = {name: 0 for name in spouse} + return head, spouse, agi + + +def build_situation(cases, arrangements): + # A variable supplied for any tax unit is an input for every tax unit, so + # the federal-only units, which supply total_misc_deductions, get their + # own simulation. + people, tax_units, households = {}, {}, {} + for i, case in enumerate(cases): + for arrangement in arrangements: + key = f"{arrangement}_{i}" + head_inputs, spouse_inputs, agi = unit_inputs(case, arrangement) + members = [f"head_{key}"] + people[f"head_{key}"] = { + name: {year: value for year in YEARS} + for name, value in head_inputs.items() + } + people[f"head_{key}"]["age"] = {year: 40 for year in YEARS} + if case["couple"]: + members.append(f"spouse_{key}") + people[f"spouse_{key}"] = { + name: {year: value for year in YEARS} + for name, value in spouse_inputs.items() + } + people[f"spouse_{key}"]["age"] = {year: 40 for year in YEARS} + tax_unit = { + "members": members, + "al_agi": {year: agi for year in YEARS}, + "positive_agi": {year: federal_agi_of(case) for year in YEARS}, + } + if arrangement == "federal_only": + expenses = case["head_employee"] + case["head_prep"] + tax_unit["total_misc_deductions"] = {year: expenses for year in YEARS} + tax_units[f"tax_unit_{key}"] = tax_unit + households[f"household_{key}"] = { + "members": members, + "state_code": {year: "AL" for year in YEARS}, + } + return {"people": people, "tax_units": tax_units, "households": households} + + +def calculate(cases): + simulation = Simulation(situation=build_situation(cases, ARRANGEMENTS)) + shape = (len(cases), len(ARRANGEMENTS)) + al = { + year: np.asarray(simulation.calculate("al_misc_deduction", year)).reshape(shape) + for year in YEARS + } + federal_2017 = np.asarray(simulation.calculate("misc_deduction", 2017)).reshape( + shape + ) + federal_only = Simulation(situation=build_situation(cases, ("federal_only",))) + al_federal_only = { + year: np.asarray(federal_only.calculate("al_misc_deduction", year)) + for year in YEARS + } + return al, federal_2017, al_federal_only + + +def expenses_of(case, arrangement): + head, spouse, _ = unit_inputs(case, arrangement) + total = sum(head.values()) + if case["couple"]: + total += sum(spouse.values()) + return total + + +def assert_properties(cases): + al, federal_2017, al_federal_only = calculate(cases) + for i, case in enumerate(cases): + for j, arrangement in enumerate(ARRANGEMENTS): + expenses = expenses_of(case, arrangement) + _, _, agi = unit_inputs(case, arrangement) + for year in YEARS: + value = al[year][i, j] + assert value >= 0, (case, arrangement, year) + assert value <= expenses + TOLERANCE, (case, arrangement, year) + assert value >= expenses - FLOOR * agi - TOLERANCE, ( + case, + arrangement, + year, + ) + # The federal suspension does not reach the Alabama deduction. + assert al[2017][i, j] == pytest.approx(al[2025][i, j], abs=TOLERANCE), ( + case, + arrangement, + ) + base, more_expenses, more_agi = range(len(ARRANGEMENTS)) + for year in YEARS: + assert al[year][i, more_expenses] >= al[year][i, base] - TOLERANCE, case + assert al[year][i, more_agi] <= al[year][i, base] + TOLERANCE, case + assert al_federal_only[year][i] == 0, case + # One floor each on the same expenses, where the two AGIs agree. + for j, arrangement in enumerate(ARRANGEMENTS): + _, _, agi = unit_inputs(case, arrangement) + if agi != federal_agi_of(case): + continue + assert al[2017][i, j] == pytest.approx(federal_2017[i, j], abs=TOLERANCE), ( + case, + ARRANGEMENTS[j], + ) + + +WORKED_CASES = [ + # 5,000 - 0.02 * 50,000 = 4,000 in both years. + { + "couple": False, + "head_employee": 5_000, + "head_prep": 0, + "spouse_employee": 0, + "spouse_prep": 0, + "al_agi": 50_000, + "federal_agi": 50_000, + }, + # 1,500 + 700 - 0.02 * 60,000 = 1,000. + { + "couple": True, + "head_employee": 1_500, + "head_prep": 0, + "spouse_employee": 0, + "spouse_prep": 700, + "al_agi": 60_000, + "federal_agi": 60_000, + }, + # Expenses equal to the floor: no deduction. + { + "couple": False, + "head_employee": 1_000, + "head_prep": 0, + "spouse_employee": 0, + "spouse_prep": 0, + "al_agi": 50_000, + "federal_agi": 50_000, + }, +] + + +def test_worked_cases(): + al, federal_2017, _ = calculate(WORKED_CASES) + assert federal_2017[:, 0] == pytest.approx([4_000, 1_000, 0], abs=TOLERANCE) + assert al[2025][:, 0] == pytest.approx([4_000, 1_000, 0], abs=TOLERANCE) + assert al[2017][:, 0] == pytest.approx([4_000, 1_000, 0], abs=TOLERANCE) + assert_properties(WORKED_CASES) + + +AMOUNTS = st.integers(min_value=0, max_value=10_000) + + +@hypothesis.settings( + max_examples=10, + deadline=None, + suppress_health_check=[hypothesis.HealthCheck.too_slow], +) +@hypothesis.given( + st.lists( + st.fixed_dictionaries( + { + "couple": st.booleans(), + "head_employee": AMOUNTS, + "head_prep": AMOUNTS, + "spouse_employee": AMOUNTS, + "spouse_prep": AMOUNTS, + "al_agi": st.integers(min_value=0, max_value=200_000), + "federal_agi": st.one_of( + st.none(), st.integers(min_value=0, max_value=200_000) + ), + } + ), + min_size=1, + max_size=8, + ) +) +def test_al_misc_deduction_properties(cases): + assert_properties(cases) diff --git a/policyengine_us/variables/gov/states/al/tax/income/deductions/itemized/al_misc_deduction.py b/policyengine_us/variables/gov/states/al/tax/income/deductions/itemized/al_misc_deduction.py index a671f82d69c..e063778f165 100644 --- a/policyengine_us/variables/gov/states/al/tax/income/deductions/itemized/al_misc_deduction.py +++ b/policyengine_us/variables/gov/states/al/tax/income/deductions/itemized/al_misc_deduction.py @@ -4,18 +4,34 @@ class al_misc_deduction(Variable): value_type = float entity = TaxUnit - label = "Alabama Work Related Expense" + label = "Alabama miscellaneous itemized deduction" unit = USD definition_period = YEAR reference = ( - "https://law.justia.com/codes/alabama/2022/title-40/chapter-18/article-1/section-40-18-15/", # Code of Alabama Section 40-18-15, h(23) + "https://law.justia.com/codes/alabama/2022/title-40/chapter-18/article-1/section-40-18-15/", # Code of Alabama Section 40-18-15(a)(23) + # Act 2026-604, Section 1. PDF pages 7-8 + "https://alison.legislature.state.al.us/files/pdf/SearchableInstruments/2026RS/HB527-enr.pdf#page=7", "https://www.revenue.alabama.gov/ultraviewer/viewer/basic_viewer/index.html?form=2023/01/22f40schabdc_blk.pdf#page=1", # 2022 Schedule A (Form 1040) "https://www.revenue.alabama.gov/ultraviewer/viewer/basic_viewer/index.html?form=2022/06/21f40schabdc_blk.pdf#page=1", # 2021 Schedule A (Form 1040) + # 2024 Form 40 instructions, Schedule A lines 20 to 24. PDF pages 20-21 + "https://www.revenue.alabama.gov/wp-content/uploads/2025/01/24f40bk.pdf#page=20", + # 2025 Form 40 instructions, Schedule A lines 20 to 24. + "https://www.revenue.alabama.gov/wp-content/uploads/2026/01/25f40bk.pdf#page=21", ) defined_for = StateCode.AL def formula(tax_unit, period, parameters): - misc_expense = add(tax_unit, period, ["misc_deduction"]) + # Ala. Code 40-18-15(a)(23) allows the subdivision (1) unreimbursed + # employee business expenses and the subdivision (14) deduction only + # above 2% of Alabama AGI. Alabama applies this floor to the expenses + # themselves, in every year, so the formula does not start from the + # federal misc_deduction: that is already net of the federal 2% floor + # and is zero once 26 U.S.C. 67(g) suspends it from 2018. Alabama keeps + # its own list of expenses so that federal categories added later do + # not flow in without a reading of the Alabama statute. Like al_agi, + # it sums the head's and spouse's expenses only: a tax unit + # dependent's expenses belong on the dependent's own Alabama return. p = parameters(period).gov.states.al.tax.income.deductions.itemized + expenses = tax_unit_non_dep_add(tax_unit, period, p.misc_sources) misc_floor = p.work_related_expense_rate * tax_unit("al_agi", period) - return max_(0, misc_expense - misc_floor) + return max_(0, expenses - misc_floor)