diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..a342f183e24 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: patch + changes: + fixed: + - Fix Virginia spouse tax adjustment to calculate separate VAGI per person instead of prorating combined VAGI. diff --git a/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/spouse_tax_adjustment/va_spouse_tax_adjustment.yaml b/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/spouse_tax_adjustment/va_spouse_tax_adjustment.yaml index f3632d55e35..1292a1d931f 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/spouse_tax_adjustment/va_spouse_tax_adjustment.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/spouse_tax_adjustment/va_spouse_tax_adjustment.yaml @@ -63,3 +63,25 @@ va_income_tax_before_non_refundable_credits: 0 output: va_spouse_tax_adjustment: 0 + +- name: Elderly head with income below age deduction - not eligible for STA (issue 6958) + period: 2024 + absolute_error_margin: 1 + input: + people: + head: + age: 75 + employment_income: 11_752.73 + spouse: + age: 40 + employment_income: 55_728.48 + tax_units: + tax_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: VA + output: + va_spouse_tax_adjustment: 0 + va_income_tax: 1_402.22 diff --git a/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/spouse_tax_adjustment/va_spouse_tax_adjustment_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/spouse_tax_adjustment/va_spouse_tax_adjustment_eligible.yaml index a90db8c87d6..63a435e1cec 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/spouse_tax_adjustment/va_spouse_tax_adjustment_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/spouse_tax_adjustment/va_spouse_tax_adjustment_eligible.yaml @@ -105,7 +105,7 @@ output: va_spouse_tax_adjustment_eligible: true -- name: Spouse and Head with AGI less exemption at 0 +- name: Spouse and Head with AGI less exemption at 0 period: 2021 input: people: @@ -128,3 +128,27 @@ tax_unit_is_joint: true output: va_spouse_tax_adjustment_eligible: false + +- name: Elderly head with income below age deduction should not be STA eligible + period: 2021 + input: + people: + person1: + adjusted_gross_income_person: 11_753 + age: 75 + is_tax_unit_head: true + person2: + adjusted_gross_income_person: 55_728 + age: 40 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + adjusted_gross_income: 67_481 + filing_status: JOINT + households: + household: + members: [person1, person2] + state_code: VA + output: + va_spouse_tax_adjustment_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/va_agi_person.yaml b/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/va_agi_person.yaml index 23d360813f4..bdb25acb603 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/va_agi_person.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/va/tax/income/va_agi_person.yaml @@ -9,7 +9,7 @@ tax_units: tax_unit: members: [person1, person2] - va_agi: 30_000 + va_subtractions: 10_000 households: household: members: [person1, person2] @@ -28,10 +28,34 @@ tax_units: tax_unit: members: [person1, person2] - va_agi: 8_000 + va_subtractions: 2_000 households: household: members: [person1, person2] state_code: VA output: va_agi_person: [8_000, 0] + +- name: Age deduction applied directly to eligible person, not prorated + period: 2021 + input: + people: + person1: + adjusted_gross_income_person: 11_753 + age: 75 + is_tax_unit_head_or_spouse: true + person2: + adjusted_gross_income_person: 55_728 + age: 40 + is_tax_unit_head_or_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + va_subtractions: 12_000 + va_age_deduction: 12_000 + households: + household: + members: [person1, person2] + state_code: VA + output: + va_agi_person: [-247, 55_728] diff --git a/policyengine_us/variables/gov/states/va/tax/income/subtractions/age_deduction/va_age_deduction_person.py b/policyengine_us/variables/gov/states/va/tax/income/subtractions/age_deduction/va_age_deduction_person.py new file mode 100644 index 00000000000..5b04750c493 --- /dev/null +++ b/policyengine_us/variables/gov/states/va/tax/income/subtractions/age_deduction/va_age_deduction_person.py @@ -0,0 +1,29 @@ +from policyengine_us.model_api import * + + +class va_age_deduction_person(Variable): + value_type = float + entity = Person + label = "Virginia age deduction allocated to each person" + unit = USD + definition_period = YEAR + reference = "https://www.tax.virginia.gov/sites/default/files/vatax-pdf/2022-760-instructions.pdf#page=16" + defined_for = StateCode.VA + + def formula(person, period, parameters): + p = parameters( + period + ).gov.states.va.tax.income.subtractions.age_deduction + + total_deduction = person.tax_unit("va_age_deduction", period) + + age = person("age", period) + is_head_or_spouse = person("is_tax_unit_head_or_spouse", period) + eligible = is_head_or_spouse & (age >= p.age_minimum) + + count_eligible = person.tax_unit.sum(eligible) + return where( + eligible & (count_eligible > 0), + total_deduction / count_eligible, + 0, + ) diff --git a/policyengine_us/variables/gov/states/va/tax/income/va_agi_person.py b/policyengine_us/variables/gov/states/va/tax/income/va_agi_person.py index 2b2d5bcf0a8..81ba312d721 100644 --- a/policyengine_us/variables/gov/states/va/tax/income/va_agi_person.py +++ b/policyengine_us/variables/gov/states/va/tax/income/va_agi_person.py @@ -12,11 +12,26 @@ class va_agi_person(Variable): defined_for = StateCode.VA def formula(person, period, parameters): - total_agi = person.tax_unit("va_agi", period) - person_agi = person("adjusted_gross_income_person", period) - total_federal_agi = person.tax_unit.sum(person_agi) - - prorate = np.zeros_like(total_agi) - mask = total_federal_agi > 0 - prorate[mask] = person_agi[mask] / total_federal_agi[mask] - return total_agi * prorate + person_fagi = person("adjusted_gross_income_person", period) + # Apply person-level age deduction directly + age_deduction = person("va_age_deduction_person", period) + # Prorate non-age subtractions by federal AGI share + total_subtractions = person.tax_unit("va_subtractions", period) + total_age_deduction = person.tax_unit("va_age_deduction", period) + non_age_subtractions = max_( + total_subtractions - total_age_deduction, 0 + ) + total_federal_agi = person.tax_unit.sum(person_fagi) + prorate = where( + total_federal_agi > 0, person_fagi / total_federal_agi, 0 + ) + person_non_age_subtractions = non_age_subtractions * prorate + # Prorate additions the same way + additions = person.tax_unit("va_additions", period) + person_additions = additions * prorate + return ( + person_fagi + + person_additions + - age_deduction + - person_non_age_subtractions + )