From d0e8c09bbd0d81c76023459dc649f2c665eaf275 Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Thu, 14 May 2026 15:31:56 -0400 Subject: [PATCH 1/7] Add South Carolina homestead property tax exemption --- changelog.d/8201.added.md | 1 + .../household/state_property_tax_credits.yaml | 20 +++++ .../homestead_exemption/age_threshold.yaml | 10 +++ .../property/homestead_exemption/amount.yaml | 10 +++ .../sc_homestead_exemption.yaml | 33 +++++++ .../sc_homestead_exemption_eligible.yaml | 85 +++++++++++++++++++ .../sc_homestead_property_tax_reduction.yaml | 53 ++++++++++++ .../sc_homestead_exemption.py | 17 ++++ .../sc_homestead_exemption_eligible.py | 22 +++++ .../sc_homestead_property_tax_reduction.py | 17 ++++ 10 files changed, 268 insertions(+) create mode 100644 changelog.d/8201.added.md create mode 100644 policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/age_threshold.yaml create mode 100644 policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/amount.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.yaml create mode 100644 policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.yaml create mode 100644 policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.py create mode 100644 policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.py create mode 100644 policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.py diff --git a/changelog.d/8201.added.md b/changelog.d/8201.added.md new file mode 100644 index 00000000000..4f598d11466 --- /dev/null +++ b/changelog.d/8201.added.md @@ -0,0 +1 @@ +Added the South Carolina Homestead Exemption property tax reduction. diff --git a/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml b/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml index b5c719c31cf..db16843a995 100644 --- a/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml +++ b/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml @@ -114,6 +114,26 @@ values: - wi_homestead_credit - wi_property_tax_credit - wv_homestead_excess_property_tax_credit + 2025-01-01: + - az_property_tax_credit + - ct_property_tax_credit + - dc_ptc + - il_property_tax_credit + - ma_senior_circuit_breaker + - me_property_tax_fairness_credit + - mi_homestead_property_tax_credit + - mo_property_tax_credit + - mt_elderly_homeowner_or_renter_credit + - mt_property_tax_rebate + - nj_property_tax_credit + - nm_property_tax_rebate + - ny_real_property_tax_credit + - ok_ptc + - ri_property_tax_credit + - sc_homestead_property_tax_reduction + - wi_homestead_credit + - wi_property_tax_credit + - wv_homestead_excess_property_tax_credit metadata: unit: list diff --git a/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/age_threshold.yaml b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/age_threshold.yaml new file mode 100644 index 00000000000..9ff3a51bbf1 --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/age_threshold.yaml @@ -0,0 +1,10 @@ +description: South Carolina limits age-based eligibility to filers at or above this age under the Homestead Exemption program. +values: + 2025-01-01: 65 +metadata: + unit: year + period: year + label: South Carolina homestead exemption age threshold + reference: + - title: South Carolina Department of Revenue | Exempt Property + href: https://dor.sc.gov/property/exempt-property diff --git a/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/amount.yaml b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/amount.yaml new file mode 100644 index 00000000000..f34c2129272 --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/amount.yaml @@ -0,0 +1,10 @@ +description: South Carolina provides this amount as a homestead exemption under the Homestead Exemption program. +values: + 2025-01-01: 50_000 +metadata: + unit: currency-USD + period: year + label: South Carolina homestead exemption amount + reference: + - title: South Carolina Department of Revenue | Exempt Property + href: https://dor.sc.gov/property/exempt-property diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.yaml new file mode 100644 index 00000000000..95a3027fcf7 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.yaml @@ -0,0 +1,33 @@ +- name: Case 1, exemption is capped at the statutory amount. + period: 2025 + input: + people: + person1: + age: 65 + assessed_property_value: 200_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: SC + output: + sc_homestead_exemption: 50_000 + +- name: Case 2, exemption is limited to assessed property value. + period: 2025 + input: + people: + person1: + age: 65 + assessed_property_value: 40_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: SC + output: + sc_homestead_exemption: 40_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.yaml new file mode 100644 index 00000000000..54b5fd04333 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.yaml @@ -0,0 +1,85 @@ +- name: Case 1, senior homeowner is eligible. + period: 2025 + input: + people: + person1: + age: 65 + assessed_property_value: 200_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: SC + output: + sc_homestead_exemption_eligible: true + +- name: Case 2, disabled homeowner under age 65 is eligible. + period: 2025 + input: + people: + person1: + age: 40 + is_disabled: true + assessed_property_value: 200_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: SC + output: + sc_homestead_exemption_eligible: true + +- name: Case 3, blind homeowner under age 65 is eligible. + period: 2025 + input: + people: + person1: + age: 40 + is_blind: true + assessed_property_value: 200_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: SC + output: + sc_homestead_exemption_eligible: true + +- name: Case 4, non-senior homeowner without disability or blindness is ineligible. + period: 2025 + input: + people: + person1: + age: 64 + assessed_property_value: 200_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: SC + output: + sc_homestead_exemption_eligible: false + +- name: Case 5, senior without assessed property is ineligible. + period: 2025 + input: + people: + person1: + age: 65 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: SC + output: + sc_homestead_exemption_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.yaml new file mode 100644 index 00000000000..a4ca3b53a70 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.yaml @@ -0,0 +1,53 @@ +- name: Case 1, reduction equals the property tax on the exempt share of value. + period: 2025 + input: + people: + person1: + age: 65 + assessed_property_value: 200_000 + real_estate_taxes: 2_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: SC + output: + sc_homestead_property_tax_reduction: 500 + +- name: Case 2, reduction cannot exceed property taxes. + period: 2025 + input: + people: + person1: + age: 65 + assessed_property_value: 40_000 + real_estate_taxes: 800 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: SC + output: + sc_homestead_property_tax_reduction: 800 + +- name: Case 3, ineligible filer gets no reduction. + period: 2025 + input: + people: + person1: + age: 64 + assessed_property_value: 200_000 + real_estate_taxes: 2_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: SC + output: + sc_homestead_property_tax_reduction: 0 diff --git a/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.py b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.py new file mode 100644 index 00000000000..8b3236e41c2 --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class sc_homestead_exemption(Variable): + value_type = float + entity = TaxUnit + label = "South Carolina homestead exemption" + unit = USD + definition_period = YEAR + reference = "https://dor.sc.gov/property/exempt-property" + defined_for = "sc_homestead_exemption_eligible" + + def formula(tax_unit, period, parameters): + return min_( + add(tax_unit, period, ["assessed_property_value"]), + parameters(period).gov.states.sc.tax.property.homestead_exemption.amount, + ) diff --git a/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.py b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.py new file mode 100644 index 00000000000..d830fb31c69 --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class sc_homestead_exemption_eligible(Variable): + value_type = bool + entity = TaxUnit + label = "Eligible for the South Carolina Homestead Exemption" + definition_period = YEAR + reference = "https://dor.sc.gov/property/exempt-property" + defined_for = StateCode.SC + + def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.sc.tax.property.homestead_exemption + person = tax_unit.members + head_or_spouse = person("is_tax_unit_head_or_spouse", period) + age = person("age", period.this_year) + is_disabled = person("is_disabled", period) + is_blind = person("is_blind", period) + + return tax_unit.any( + ((age >= p.age_threshold) | is_disabled | is_blind) & head_or_spouse, + ) & (add(tax_unit, period, ["assessed_property_value"]) > 0) diff --git a/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.py b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.py new file mode 100644 index 00000000000..e1aa10c4a0b --- /dev/null +++ b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class sc_homestead_property_tax_reduction(Variable): + value_type = float + entity = TaxUnit + label = "South Carolina homestead property tax reduction" + unit = USD + definition_period = YEAR + reference = "https://dor.sc.gov/property/exempt-property" + defined_for = "sc_homestead_exemption_eligible" + + def formula(tax_unit, period, parameters): + assessed_value = add(tax_unit, period, ["assessed_property_value"]) + return add(tax_unit, period, ["real_estate_taxes"]) * ( + tax_unit("sc_homestead_exemption", period) / max_(assessed_value, 1) + ) From 5174ecafc5cd7d57ca4d6f269b99611f78529ce7 Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Thu, 14 May 2026 16:53:52 -0400 Subject: [PATCH 2/7] Rename changelog fragment for PR 8311 --- changelog.d/{8201.added.md => 8311.added.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog.d/{8201.added.md => 8311.added.md} (100%) diff --git a/changelog.d/8201.added.md b/changelog.d/8311.added.md similarity index 100% rename from changelog.d/8201.added.md rename to changelog.d/8311.added.md From c098569378143ab20efa0dfa4f3b802280c7d389 Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Fri, 15 May 2026 13:29:38 -0400 Subject: [PATCH 3/7] Convert South Carolina homestead exemption to assessed value --- .../sc/tax/property/homestead_exemption/amount.yaml | 2 +- .../property/homestead_exemption/assessment_rate.yaml | 10 ++++++++++ .../homestead_exemption/sc_homestead_exemption.yaml | 8 ++++---- .../sc_homestead_exemption_eligible.yaml | 8 ++++---- .../sc_homestead_property_tax_reduction.yaml | 6 +++--- .../homestead_exemption/sc_homestead_exemption.py | 4 +++- 6 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/assessment_rate.yaml diff --git a/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/amount.yaml b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/amount.yaml index f34c2129272..a6caf4e4ea2 100644 --- a/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/amount.yaml +++ b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/amount.yaml @@ -1,4 +1,4 @@ -description: South Carolina provides this amount as a homestead exemption under the Homestead Exemption program. +description: South Carolina provides this fair market value exemption amount under the Homestead Exemption program. values: 2025-01-01: 50_000 metadata: diff --git a/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/assessment_rate.yaml b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/assessment_rate.yaml new file mode 100644 index 00000000000..83befa917a7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/assessment_rate.yaml @@ -0,0 +1,10 @@ +description: South Carolina assesses legal residence value at this rate under the Homestead Exemption program. +values: + 2025-01-01: 0.04 +metadata: + unit: /1 + period: year + label: South Carolina homestead exemption legal residence assessment rate + reference: + - title: South Carolina Department of Revenue | Exempt Property + href: https://dor.sc.gov/property/exempt-property diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.yaml index 95a3027fcf7..d5d3974dae5 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.yaml @@ -4,7 +4,7 @@ people: person1: age: 65 - assessed_property_value: 200_000 + assessed_property_value: 8_000 tax_units: tax_unit: members: [person1] @@ -13,7 +13,7 @@ members: [person1] state_code: SC output: - sc_homestead_exemption: 50_000 + sc_homestead_exemption: 2_000 - name: Case 2, exemption is limited to assessed property value. period: 2025 @@ -21,7 +21,7 @@ people: person1: age: 65 - assessed_property_value: 40_000 + assessed_property_value: 1_600 tax_units: tax_unit: members: [person1] @@ -30,4 +30,4 @@ members: [person1] state_code: SC output: - sc_homestead_exemption: 40_000 + sc_homestead_exemption: 1_600 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.yaml index 54b5fd04333..9527f0c933b 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.yaml @@ -4,7 +4,7 @@ people: person1: age: 65 - assessed_property_value: 200_000 + assessed_property_value: 8_000 tax_units: tax_unit: members: [person1] @@ -22,7 +22,7 @@ person1: age: 40 is_disabled: true - assessed_property_value: 200_000 + assessed_property_value: 8_000 tax_units: tax_unit: members: [person1] @@ -40,7 +40,7 @@ person1: age: 40 is_blind: true - assessed_property_value: 200_000 + assessed_property_value: 8_000 tax_units: tax_unit: members: [person1] @@ -57,7 +57,7 @@ people: person1: age: 64 - assessed_property_value: 200_000 + assessed_property_value: 8_000 tax_units: tax_unit: members: [person1] diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.yaml index a4ca3b53a70..205eb288e0c 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.yaml @@ -4,7 +4,7 @@ people: person1: age: 65 - assessed_property_value: 200_000 + assessed_property_value: 8_000 real_estate_taxes: 2_000 tax_units: tax_unit: @@ -22,7 +22,7 @@ people: person1: age: 65 - assessed_property_value: 40_000 + assessed_property_value: 1_600 real_estate_taxes: 800 tax_units: tax_unit: @@ -40,7 +40,7 @@ people: person1: age: 64 - assessed_property_value: 200_000 + assessed_property_value: 8_000 real_estate_taxes: 2_000 tax_units: tax_unit: diff --git a/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.py b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.py index 8b3236e41c2..d2793bba05b 100644 --- a/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.py +++ b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.py @@ -11,7 +11,9 @@ class sc_homestead_exemption(Variable): defined_for = "sc_homestead_exemption_eligible" def formula(tax_unit, period, parameters): + p = parameters(period).gov.states.sc.tax.property.homestead_exemption + assessed_exemption_amount = p.amount * p.assessment_rate return min_( add(tax_unit, period, ["assessed_property_value"]), - parameters(period).gov.states.sc.tax.property.homestead_exemption.amount, + assessed_exemption_amount, ) From 6605cf853fe309dd62388d6dfc268657b748af1c Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Thu, 21 May 2026 16:11:10 -0400 Subject: [PATCH 4/7] Keep property tax relief household-only --- .../household/state_property_tax_credits.yaml | 153 +++--------------- 1 file changed, 19 insertions(+), 134 deletions(-) diff --git a/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml b/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml index db16843a995..6a9b8dfc6a4 100644 --- a/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml +++ b/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml @@ -1,139 +1,24 @@ description: All state property tax credits and circuit breaker programs. values: - # Year-gated: each credit appears from the year its - # parameters are first defined in PE-US. - 1977-01-01: - - ri_property_tax_credit - 1996-01-01: - - nj_property_tax_credit - - ri_property_tax_credit - 1997-01-01: - - mo_property_tax_credit - - nj_property_tax_credit - - ri_property_tax_credit - 2000-01-01: - - mo_property_tax_credit - - nj_property_tax_credit - - ny_real_property_tax_credit - - ri_property_tax_credit - - wi_property_tax_credit - 2001-01-01: - - ma_senior_circuit_breaker - - mo_property_tax_credit - - nj_property_tax_credit - - ny_real_property_tax_credit - - ri_property_tax_credit - - wi_property_tax_credit - 2008-01-01: - - ma_senior_circuit_breaker - - mo_property_tax_credit - - nj_property_tax_credit - - ny_real_property_tax_credit - - ri_property_tax_credit - - wi_property_tax_credit - - wv_homestead_excess_property_tax_credit - 2009-01-01: - - ma_senior_circuit_breaker - - mo_property_tax_credit - - mt_elderly_homeowner_or_renter_credit - - nj_property_tax_credit - - ny_real_property_tax_credit - - ri_property_tax_credit - - wi_property_tax_credit - - wv_homestead_excess_property_tax_credit - 2011-01-01: - - ct_property_tax_credit - - ma_senior_circuit_breaker - - mo_property_tax_credit - - mt_elderly_homeowner_or_renter_credit - - nj_property_tax_credit - - ny_real_property_tax_credit - - ri_property_tax_credit - - wi_homestead_credit - - wi_property_tax_credit - - wv_homestead_excess_property_tax_credit - 2014-01-01: - - ct_property_tax_credit - - ma_senior_circuit_breaker - - me_property_tax_fairness_credit - - mo_property_tax_credit - - mt_elderly_homeowner_or_renter_credit - - nj_property_tax_credit - - ny_real_property_tax_credit - - ri_property_tax_credit - - wi_homestead_credit - - wi_property_tax_credit - - wv_homestead_excess_property_tax_credit - 2016-01-01: - - ct_property_tax_credit - - ma_senior_circuit_breaker - - me_property_tax_fairness_credit - - mi_homestead_property_tax_credit - - mo_property_tax_credit - - mt_elderly_homeowner_or_renter_credit - - nj_property_tax_credit - - ny_real_property_tax_credit - - ri_property_tax_credit - - wi_homestead_credit - - wi_property_tax_credit - - wv_homestead_excess_property_tax_credit - 2021-01-01: - - az_property_tax_credit - - ct_property_tax_credit - - dc_ptc - - il_property_tax_credit - - ma_senior_circuit_breaker - - me_property_tax_fairness_credit - - mi_homestead_property_tax_credit - - mo_property_tax_credit - - mt_elderly_homeowner_or_renter_credit - - nj_property_tax_credit - - nm_property_tax_rebate - - ny_real_property_tax_credit - - ok_ptc - - ri_property_tax_credit - - wi_homestead_credit - - wi_property_tax_credit - - wv_homestead_excess_property_tax_credit - 2022-01-01: - - az_property_tax_credit - - ct_property_tax_credit - - dc_ptc - - il_property_tax_credit - - ma_senior_circuit_breaker - - me_property_tax_fairness_credit - - mi_homestead_property_tax_credit - - mo_property_tax_credit - - mt_elderly_homeowner_or_renter_credit - - mt_property_tax_rebate - - nj_property_tax_credit - - nm_property_tax_rebate - - ny_real_property_tax_credit - - ok_ptc - - ri_property_tax_credit - - wi_homestead_credit - - wi_property_tax_credit - - wv_homestead_excess_property_tax_credit - 2025-01-01: - - az_property_tax_credit - - ct_property_tax_credit - - dc_ptc - - il_property_tax_credit - - ma_senior_circuit_breaker - - me_property_tax_fairness_credit - - mi_homestead_property_tax_credit - - mo_property_tax_credit - - mt_elderly_homeowner_or_renter_credit - - mt_property_tax_rebate - - nj_property_tax_credit - - nm_property_tax_rebate - - ny_real_property_tax_credit - - ok_ptc - - ri_property_tax_credit - - sc_homestead_property_tax_reduction - - wi_homestead_credit - - wi_property_tax_credit - - wv_homestead_excess_property_tax_credit + 0000-01-01: + - az_property_tax_credit # Arizona Property Tax Credit + - ct_property_tax_credit # Connecticut Property Tax Credit + # Exclude ca_renter_credit as it is for renters, not homeowners. + - dc_ptc # DC Property Tax Credit + # Exclude hi_tax_credit_for_low_income_household_renters as it is for renters, not homeowners. + - ma_senior_circuit_breaker # Massachusetts Senior Circuit Breaker Credit + - me_property_tax_fairness_credit # Maine Property Tax Fairness Credit + - mi_homestead_property_tax_credit # Michigan homestead property tax credit + - mo_property_tax_credit # Missouri property tax credit + - mt_elderly_homeowner_or_renter_credit # Montana Elderly Homeowner/Renter Credit + - nj_property_tax_credit # New Jersey property tax credit + - nm_property_tax_rebate # New Mexico property tax rebate + - ny_real_property_tax_credit # New York real property tax credit + - ri_property_tax_credit # Rhode Island property tax credit + # Omit vt_renter_credit + - wi_homestead_credit # Wisconsin homestead credit + - wi_property_tax_credit # Wisconsin property tax credit + - wv_homestead_excess_property_tax_credit # West Virginia metadata: unit: list From d79efeb93ffd4acaafd2333d8a34ad3d1b60794b Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Thu, 21 May 2026 16:14:53 -0400 Subject: [PATCH 5/7] Restore property tax aggregate base --- .../household/state_property_tax_credits.yaml | 178 ++++++++++++++++-- 1 file changed, 159 insertions(+), 19 deletions(-) diff --git a/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml b/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml index 6a9b8dfc6a4..5fc7a8116bf 100644 --- a/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml +++ b/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml @@ -1,24 +1,164 @@ description: All state property tax credits and circuit breaker programs. values: - 0000-01-01: - - az_property_tax_credit # Arizona Property Tax Credit - - ct_property_tax_credit # Connecticut Property Tax Credit - # Exclude ca_renter_credit as it is for renters, not homeowners. - - dc_ptc # DC Property Tax Credit - # Exclude hi_tax_credit_for_low_income_household_renters as it is for renters, not homeowners. - - ma_senior_circuit_breaker # Massachusetts Senior Circuit Breaker Credit - - me_property_tax_fairness_credit # Maine Property Tax Fairness Credit - - mi_homestead_property_tax_credit # Michigan homestead property tax credit - - mo_property_tax_credit # Missouri property tax credit - - mt_elderly_homeowner_or_renter_credit # Montana Elderly Homeowner/Renter Credit - - nj_property_tax_credit # New Jersey property tax credit - - nm_property_tax_rebate # New Mexico property tax rebate - - ny_real_property_tax_credit # New York real property tax credit - - ri_property_tax_credit # Rhode Island property tax credit - # Omit vt_renter_credit - - wi_homestead_credit # Wisconsin homestead credit - - wi_property_tax_credit # Wisconsin property tax credit - - wv_homestead_excess_property_tax_credit # West Virginia + # Year-gated: each credit appears from the year its + # parameters are first defined in PE-US. + 1977-01-01: + - ri_property_tax_credit + 1996-01-01: + - nj_property_tax_credit + - ri_property_tax_credit + 1997-01-01: + - mo_property_tax_credit + - nj_property_tax_credit + - ri_property_tax_credit + 2000-01-01: + - mo_property_tax_credit + - nj_property_tax_credit + - ny_real_property_tax_credit + - ri_property_tax_credit + - wi_property_tax_credit + 2001-01-01: + - ma_senior_circuit_breaker + - mo_property_tax_credit + - nj_property_tax_credit + - ny_real_property_tax_credit + - ri_property_tax_credit + - wi_property_tax_credit + 2008-01-01: + - ma_senior_circuit_breaker + - mo_property_tax_credit + - nj_property_tax_credit + - ny_real_property_tax_credit + - ri_property_tax_credit + - wi_property_tax_credit + - wv_homestead_excess_property_tax_credit + 2009-01-01: + - ma_senior_circuit_breaker + - mo_property_tax_credit + - mt_elderly_homeowner_or_renter_credit + - nj_property_tax_credit + - ny_real_property_tax_credit + - ri_property_tax_credit + - wi_property_tax_credit + - wv_homestead_excess_property_tax_credit + 2011-01-01: + - ct_property_tax_credit + - ma_senior_circuit_breaker + - mo_property_tax_credit + - mt_elderly_homeowner_or_renter_credit + - nj_property_tax_credit + - ny_real_property_tax_credit + - ri_property_tax_credit + - wi_homestead_credit + - wi_property_tax_credit + - wv_homestead_excess_property_tax_credit + 2014-01-01: + - ct_property_tax_credit + - ma_senior_circuit_breaker + - me_property_tax_fairness_credit + - mo_property_tax_credit + - mt_elderly_homeowner_or_renter_credit + - nj_property_tax_credit + - ny_real_property_tax_credit + - ri_property_tax_credit + - wi_homestead_credit + - wi_property_tax_credit + - wv_homestead_excess_property_tax_credit + 2016-01-01: + - ct_property_tax_credit + - ma_senior_circuit_breaker + - me_property_tax_fairness_credit + - mi_homestead_property_tax_credit + - mo_property_tax_credit + - mt_elderly_homeowner_or_renter_credit + - nj_property_tax_credit + - ny_real_property_tax_credit + - ri_property_tax_credit + - wi_homestead_credit + - wi_property_tax_credit + - wv_homestead_excess_property_tax_credit + 2021-01-01: + - az_property_tax_credit + - ct_property_tax_credit + - dc_ptc + - il_property_tax_credit + - ma_senior_circuit_breaker + - me_property_tax_fairness_credit + - mi_homestead_property_tax_credit + - mo_property_tax_credit + - mt_elderly_homeowner_or_renter_credit + - nj_property_tax_credit + - nm_property_tax_rebate + - ny_real_property_tax_credit + - ok_ptc + - ri_property_tax_credit + - wi_homestead_credit + - wi_property_tax_credit + - wv_homestead_excess_property_tax_credit + 2022-01-01: + - az_property_tax_credit + - ct_property_tax_credit + - dc_ptc + - il_property_tax_credit + - ma_senior_circuit_breaker + - me_property_tax_fairness_credit + - mi_homestead_property_tax_credit + - mo_property_tax_credit + - mt_elderly_homeowner_or_renter_credit + - mt_property_tax_rebate + - nj_property_tax_credit + - nm_property_tax_rebate + - ny_real_property_tax_credit + - ok_ptc + - ri_property_tax_credit + - wi_homestead_credit + - wi_property_tax_credit + - wv_homestead_excess_property_tax_credit + 2024-01-01: + - az_property_tax_credit + - ct_property_tax_credit + - dc_ptc + - il_property_tax_credit + - ma_senior_circuit_breaker + - me_property_tax_fairness_credit + - mi_homestead_property_tax_credit + - mn_renters_credit + - mo_property_tax_credit + - mt_elderly_homeowner_or_renter_credit + - mt_property_tax_rebate + - nd_renters_refund + - nj_property_tax_credit + - nm_property_tax_rebate + - ny_real_property_tax_credit + - ok_ptc + - ri_property_tax_credit + - wi_homestead_credit + - wi_property_tax_credit + - wv_homestead_excess_property_tax_credit + 2025-01-01: + - az_property_tax_credit + - ct_property_tax_credit + - dc_ptc + - dc_senior_disabled_property_tax_relief + - il_property_tax_credit + - ma_senior_circuit_breaker + - me_property_tax_fairness_credit + - mi_homestead_property_tax_credit + - mn_renters_credit + - mo_property_tax_credit + - mt_elderly_homeowner_or_renter_credit + - mt_property_tax_rebate + - nd_renters_refund + - nj_property_tax_credit + - nm_property_tax_rebate + - ny_real_property_tax_credit + - ok_ptc + - pa_property_tax_or_rent_rebate + - ri_property_tax_credit + - ut_homeowner_renter_relief + - wi_homestead_credit + - wi_property_tax_credit + - wv_homestead_excess_property_tax_credit metadata: unit: list From 0cd4c7c385a37196cda0ee0ac267199409a8e86b Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Thu, 21 May 2026 16:17:30 -0400 Subject: [PATCH 6/7] Drop property tax aggregate diff --- .../household/state_property_tax_credits.yaml | 45 ------------------- 1 file changed, 45 deletions(-) diff --git a/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml b/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml index 5fc7a8116bf..b5c719c31cf 100644 --- a/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml +++ b/policyengine_us/parameters/gov/states/household/state_property_tax_credits.yaml @@ -114,51 +114,6 @@ values: - wi_homestead_credit - wi_property_tax_credit - wv_homestead_excess_property_tax_credit - 2024-01-01: - - az_property_tax_credit - - ct_property_tax_credit - - dc_ptc - - il_property_tax_credit - - ma_senior_circuit_breaker - - me_property_tax_fairness_credit - - mi_homestead_property_tax_credit - - mn_renters_credit - - mo_property_tax_credit - - mt_elderly_homeowner_or_renter_credit - - mt_property_tax_rebate - - nd_renters_refund - - nj_property_tax_credit - - nm_property_tax_rebate - - ny_real_property_tax_credit - - ok_ptc - - ri_property_tax_credit - - wi_homestead_credit - - wi_property_tax_credit - - wv_homestead_excess_property_tax_credit - 2025-01-01: - - az_property_tax_credit - - ct_property_tax_credit - - dc_ptc - - dc_senior_disabled_property_tax_relief - - il_property_tax_credit - - ma_senior_circuit_breaker - - me_property_tax_fairness_credit - - mi_homestead_property_tax_credit - - mn_renters_credit - - mo_property_tax_credit - - mt_elderly_homeowner_or_renter_credit - - mt_property_tax_rebate - - nd_renters_refund - - nj_property_tax_credit - - nm_property_tax_rebate - - ny_real_property_tax_credit - - ok_ptc - - pa_property_tax_or_rent_rebate - - ri_property_tax_credit - - ut_homeowner_renter_relief - - wi_homestead_credit - - wi_property_tax_credit - - wv_homestead_excess_property_tax_credit metadata: unit: list From 5c6e909d5fa8f61666b31d6f8b1cd56d4539c0f0 Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Wed, 27 May 2026 12:07:11 -0400 Subject: [PATCH 7/7] Fix South Carolina homestead spouse eligibility --- .../homestead_exemption/age_threshold.yaml | 4 +- .../property/homestead_exemption/amount.yaml | 2 + .../homestead_exemption/assessment_rate.yaml | 4 +- .../sc_homestead_exemption.yaml | 21 +++++++++ .../sc_homestead_exemption_eligible.yaml | 44 +++++++++++++++++++ .../sc_homestead_property_tax_reduction.yaml | 23 ++++++++++ .../sc_homestead_exemption.py | 10 ++++- .../sc_homestead_exemption_eligible.py | 11 +++-- .../sc_homestead_property_tax_reduction.py | 16 ++++++- 9 files changed, 127 insertions(+), 8 deletions(-) diff --git a/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/age_threshold.yaml b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/age_threshold.yaml index 9ff3a51bbf1..4ae027e4ed5 100644 --- a/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/age_threshold.yaml +++ b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/age_threshold.yaml @@ -1,4 +1,4 @@ -description: South Carolina limits age-based eligibility to filers at or above this age under the Homestead Exemption program. +description: South Carolina limits age-based eligibility to this threshold under the Homestead Exemption program. values: 2025-01-01: 65 metadata: @@ -8,3 +8,5 @@ metadata: reference: - title: South Carolina Department of Revenue | Exempt Property href: https://dor.sc.gov/property/exempt-property + - title: South Carolina Code Section 12-37-250 + href: https://www.scstatehouse.gov/code/t12c037.php diff --git a/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/amount.yaml b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/amount.yaml index a6caf4e4ea2..9855929068f 100644 --- a/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/amount.yaml +++ b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/amount.yaml @@ -8,3 +8,5 @@ metadata: reference: - title: South Carolina Department of Revenue | Exempt Property href: https://dor.sc.gov/property/exempt-property + - title: South Carolina Code Section 12-37-250 + href: https://www.scstatehouse.gov/code/t12c037.php diff --git a/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/assessment_rate.yaml b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/assessment_rate.yaml index 83befa917a7..d0c8e4d90ee 100644 --- a/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/assessment_rate.yaml +++ b/policyengine_us/parameters/gov/states/sc/tax/property/homestead_exemption/assessment_rate.yaml @@ -1,4 +1,4 @@ -description: South Carolina assesses legal residence value at this rate under the Homestead Exemption program. +description: South Carolina uses this share of fair market value as assessed value under the Homestead Exemption program. values: 2025-01-01: 0.04 metadata: @@ -8,3 +8,5 @@ metadata: reference: - title: South Carolina Department of Revenue | Exempt Property href: https://dor.sc.gov/property/exempt-property + - title: South Carolina Code Section 12-37-252 + href: https://www.scstatehouse.gov/code/t12c037.php diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.yaml index d5d3974dae5..cb8126eb086 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.yaml @@ -31,3 +31,24 @@ state_code: SC output: sc_homestead_exemption: 1_600 + +- name: Case 3, exemption excludes non-joint adult property value. + period: 2025 + input: + people: + person1: + age: 65 + assessed_property_value: 1_600 + person2: + age: 40 + assessed_property_value: 8_000 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: SC + output: + sc_homestead_exemption: 1_600 diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.yaml index 9527f0c933b..0185d3fe47e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.yaml @@ -83,3 +83,47 @@ state_code: SC output: sc_homestead_exemption_eligible: false + +- name: Case 6, joint spouse meeting the age test is eligible. + period: 2025 + input: + people: + person1: + age: 40 + assessed_property_value: 8_000 + is_tax_unit_head: true + person2: + age: 65 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + households: + household: + members: [person1, person2] + state_code: SC + output: + sc_homestead_exemption_eligible: true + +- name: Case 7, non-joint adult meeting the age test is ineligible. + period: 2025 + input: + people: + person1: + age: 40 + assessed_property_value: 8_000 + is_tax_unit_head: true + person2: + age: 65 + is_tax_unit_spouse: true + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: SC + output: + sc_homestead_exemption_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.yaml b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.yaml index 205eb288e0c..2a4a8340aeb 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.yaml @@ -51,3 +51,26 @@ state_code: SC output: sc_homestead_property_tax_reduction: 0 + +- name: Case 4, reduction excludes non-joint adult property tax. + period: 2025 + input: + people: + person1: + age: 65 + assessed_property_value: 1_600 + real_estate_taxes: 800 + person2: + age: 40 + assessed_property_value: 8_000 + real_estate_taxes: 2_000 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: SINGLE + households: + household: + members: [person1, person2] + state_code: SC + output: + sc_homestead_property_tax_reduction: 800 diff --git a/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.py b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.py index d2793bba05b..e0b2dda4fb7 100644 --- a/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.py +++ b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption.py @@ -12,8 +12,16 @@ class sc_homestead_exemption(Variable): def formula(tax_unit, period, parameters): p = parameters(period).gov.states.sc.tax.property.homestead_exemption + person = tax_unit.members + head = person("is_tax_unit_head", period) + joint_spouse = person("is_tax_unit_spouse", period) & person.tax_unit( + "tax_unit_is_joint", period + ) + assessed_value = tax_unit.sum( + person("assessed_property_value", period) * (head | joint_spouse) + ) assessed_exemption_amount = p.amount * p.assessment_rate return min_( - add(tax_unit, period, ["assessed_property_value"]), + assessed_value, assessed_exemption_amount, ) diff --git a/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.py b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.py index d830fb31c69..e10985332bb 100644 --- a/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.py +++ b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_exemption_eligible.py @@ -12,11 +12,16 @@ class sc_homestead_exemption_eligible(Variable): def formula(tax_unit, period, parameters): p = parameters(period).gov.states.sc.tax.property.homestead_exemption person = tax_unit.members - head_or_spouse = person("is_tax_unit_head_or_spouse", period) + head = person("is_tax_unit_head", period) + joint_spouse = person("is_tax_unit_spouse", period) & person.tax_unit( + "tax_unit_is_joint", period + ) + head_or_joint_spouse = head | joint_spouse age = person("age", period.this_year) is_disabled = person("is_disabled", period) is_blind = person("is_blind", period) + assessed_value = person("assessed_property_value", period) return tax_unit.any( - ((age >= p.age_threshold) | is_disabled | is_blind) & head_or_spouse, - ) & (add(tax_unit, period, ["assessed_property_value"]) > 0) + ((age >= p.age_threshold) | is_disabled | is_blind) & head_or_joint_spouse, + ) & (tax_unit.sum(assessed_value * head_or_joint_spouse) > 0) diff --git a/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.py b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.py index e1aa10c4a0b..bce4dafd3ec 100644 --- a/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.py +++ b/policyengine_us/variables/gov/states/sc/tax/property/homestead_exemption/sc_homestead_property_tax_reduction.py @@ -11,7 +11,19 @@ class sc_homestead_property_tax_reduction(Variable): defined_for = "sc_homestead_exemption_eligible" def formula(tax_unit, period, parameters): - assessed_value = add(tax_unit, period, ["assessed_property_value"]) - return add(tax_unit, period, ["real_estate_taxes"]) * ( + person = tax_unit.members + head = person("is_tax_unit_head", period) + joint_spouse = person("is_tax_unit_spouse", period) & person.tax_unit( + "tax_unit_is_joint", period + ) + head_or_joint_spouse = head | joint_spouse + assessed_value = tax_unit.sum( + person("assessed_property_value", period) * head_or_joint_spouse + ) + real_estate_taxes = tax_unit.sum( + person("real_estate_taxes", period) * head_or_joint_spouse + ) + + return real_estate_taxes * ( tax_unit("sc_homestead_exemption", period) / max_(assessed_value, 1) )