diff --git a/changelog.d/fix-taxable-uc-allocation.fixed.md b/changelog.d/fix-taxable-uc-allocation.fixed.md new file mode 100644 index 00000000000..f457e2818c6 --- /dev/null +++ b/changelog.d/fix-taxable-uc-allocation.fixed.md @@ -0,0 +1 @@ +Allocate taxable unemployment compensation by actual recipient instead of all to head. diff --git a/policyengine_us/tests/variables/gov/irs/income/taxable_income/adjusted_gross_income/adjusted_gross_income_person.yaml b/policyengine_us/tests/variables/gov/irs/income/taxable_income/adjusted_gross_income/adjusted_gross_income_person.yaml new file mode 100644 index 00000000000..43b72665add --- /dev/null +++ b/policyengine_us/tests/variables/gov/irs/income/taxable_income/adjusted_gross_income/adjusted_gross_income_person.yaml @@ -0,0 +1,58 @@ +- name: Per-person AGI reflects actual UC recipient when UC is on spouse only + period: 2025 + input: + people: + head: + age: 75 + unemployment_compensation: 0 + spouse: + age: 40 + employment_income: 10_000 + unemployment_compensation: 19_000 + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + families: + family: + members: [head, spouse] + spm_units: + spm_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + output: + adjusted_gross_income_person: [0, 29_000] + +- name: Per-person AGI reflects proportional UC allocation when both spouses have UC + period: 2025 + input: + people: + head: + age: 50 + employment_income: 30_000 + unemployment_compensation: 4_000 + spouse: + age: 48 + employment_income: 20_000 + unemployment_compensation: 12_000 + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + families: + family: + members: [head, spouse] + spm_units: + spm_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + output: + adjusted_gross_income_person: [34_000, 32_000] diff --git a/policyengine_us/tests/variables/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/unemployment_insurance/taxable_unemployment_compensation.yaml b/policyengine_us/tests/variables/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/unemployment_insurance/taxable_unemployment_compensation.yaml new file mode 100644 index 00000000000..964a4f25cc0 --- /dev/null +++ b/policyengine_us/tests/variables/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/unemployment_insurance/taxable_unemployment_compensation.yaml @@ -0,0 +1,84 @@ +- name: Taxable UC allocated to spouse when only spouse received UC + period: 2025 + input: + people: + head: + age: 75 + unemployment_compensation: 0 + spouse: + age: 40 + unemployment_compensation: 19_000 + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + families: + family: + members: [head, spouse] + spm_units: + spm_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: KY + output: + taxable_unemployment_compensation: [0, 19_000] + +- name: Taxable UC split in proportion to person-level UC + period: 2025 + input: + people: + head: + age: 50 + unemployment_compensation: 5_000 + spouse: + age: 48 + unemployment_compensation: 15_000 + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + families: + family: + members: [head, spouse] + spm_units: + spm_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: CA + output: + taxable_unemployment_compensation: [5_000, 15_000] + +- name: Zero UC produces zero allocation + period: 2025 + input: + people: + head: + age: 35 + employment_income: 50_000 + unemployment_compensation: 0 + tax_units: + tax_unit: + members: [head] + marital_units: + marital_unit: + members: [head] + families: + family: + members: [head] + spm_units: + spm_unit: + members: [head] + households: + household: + members: [head] + state_code: CA + output: + taxable_unemployment_compensation: [0] diff --git a/policyengine_us/tests/variables/gov/states/ky/tax/income/ky_agi.yaml b/policyengine_us/tests/variables/gov/states/ky/tax/income/ky_agi.yaml new file mode 100644 index 00000000000..08b72308990 --- /dev/null +++ b/policyengine_us/tests/variables/gov/states/ky/tax/income/ky_agi.yaml @@ -0,0 +1,32 @@ +- name: KY per-person AGI reflects UC recipient (regression test for #8494) + period: 2025 + input: + people: + head: + age: 75 + unemployment_compensation: 0 + spouse: + age: 40 + employment_income: 10_000 + unemployment_compensation: 19_000 + tax_units: + tax_unit: + members: [head, spouse] + marital_units: + marital_unit: + members: [head, spouse] + families: + family: + members: [head, spouse] + spm_units: + spm_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: KY + output: + # Before the fix, head's KY AGI was inflated by the spouse's UC ($19,000) + # and the spouse's KY AGI was deflated by the same amount. KY's combined- + # return optimization then gave the head an unearned standard deduction. + ky_agi: [0, 29_000] diff --git a/policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/unemployment_insurance/taxable_unemployment_insurance.py b/policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/unemployment_insurance/taxable_unemployment_insurance.py index a4a3d049d22..707baf719c0 100644 --- a/policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/unemployment_insurance/taxable_unemployment_insurance.py +++ b/policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/unemployment_insurance/taxable_unemployment_insurance.py @@ -9,13 +9,15 @@ class taxable_unemployment_compensation(Variable): definition_period = YEAR def formula(person, period, parameters): - # The taxable amount of unemployment compensation is decided at the tax unit level, but - # gross income (which contains taxable UI) is person-level. Therefore, we include the - # taxable UI in gross income by assigning it to the head of the tax unit: this will be - # not affect overall tax liability. - - is_tax_unit_head = person("is_tax_unit_head", period) + # The taxable amount of unemployment compensation is decided at the tax + # unit level, but gross income (which contains taxable UI) is person-level. + # Allocate the tax unit's taxable UC to each person in proportion to their + # unemployment_compensation, so that per-person AGI reflects the actual + # recipient (required by states with combined-return optimization). tax_unit_taxable_uc = person.tax_unit( "tax_unit_taxable_unemployment_compensation", period ) - return where(is_tax_unit_head, tax_unit_taxable_uc, 0) + person_uc = person("unemployment_compensation", period) + tax_unit_uc = person.tax_unit.sum(person_uc) + share = where(tax_unit_uc > 0, person_uc / tax_unit_uc, 0) + return tax_unit_taxable_uc * share