From 45916f4297ee576dd136e37bb76e89cbbb79916a Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 11 Aug 2026 09:22:39 -0400 Subject: [PATCH 1/4] Implement Maine PTFC unknown-utilities 15% rule (Schedule PTFC line 5c) Maine's property tax fairness credit computes rent constituting property taxes as 15% of rent, after excluding any heat/utilities included in the rent. Schedule PTFC/STFC line 5c provides that when the rent includes utilities but the amount is not known, 15% of gross rent is treated as the utility portion. me_property_tax_fairness_credit_countable_rent previously left that fallback unimplemented, so a filer whose rent includes utilities but who did not itemize a utility amount received no utility exclusion. Add the 15% fallback and a parameter for the fraction. Co-Authored-By: Claude Fable 5 --- changelog.d/me-ptfc-utilities-in-rent.fixed.md | 1 + .../rate/utilities_included_in_rent.yaml | 12 ++++++++++++ ..._property_tax_fairness_credit_countable_rent.yaml | 11 +++++++++++ ...me_property_tax_fairness_credit_countable_rent.py | 11 +++++++---- 4 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 changelog.d/me-ptfc-utilities-in-rent.fixed.md create mode 100644 policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_included_in_rent.yaml diff --git a/changelog.d/me-ptfc-utilities-in-rent.fixed.md b/changelog.d/me-ptfc-utilities-in-rent.fixed.md new file mode 100644 index 00000000000..d29a0ecc45b --- /dev/null +++ b/changelog.d/me-ptfc-utilities-in-rent.fixed.md @@ -0,0 +1 @@ +Implemented the Schedule PTFC/STFC line 5c rule for the Maine property tax fairness credit: when rent includes heat or utilities and the amount is not known, exclude 15% of gross rent before computing rent constituting property taxes. diff --git a/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_included_in_rent.yaml b/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_included_in_rent.yaml new file mode 100644 index 00000000000..dd8e682b933 --- /dev/null +++ b/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_included_in_rent.yaml @@ -0,0 +1,12 @@ +description: When rent includes heat or utilities and the amount is not known, Maine treats this fraction of gross rent as attributable to utilities and excludes it before computing rent constituting property taxes under the property tax fairness credit. +values: + 2014-01-01: 0.15 +metadata: + unit: /1 + period: year + label: Maine property tax fairness credit utilities-in-rent fraction + reference: + - title: 2022 Form 1040ME Schedule PTFC/STFC, line 5c + href: https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/22_1040me_sched_pstfc_ff.pdf#page=2 + - title: 2023 Form 1040ME Schedule PTFC/STFC, line 5c + href: https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/23_1040me_sched_pstfc_ff.pdf#page=1 diff --git a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml index 2fce45e5176..95d61d51f34 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml @@ -19,3 +19,14 @@ output: me_property_tax_fairness_credit_countable_rent: 142.5 # 950*0.15 = 142.5 + +- name: Case 3, utilities included in rent but amount unknown, deduct 15% of rent (Schedule PTFC/STFC line 5c) + period: 2022 + input: + state_code: ME + rent: 1_000 + utilities_included_in_rent: true + utility_expense: 0 + output: + me_property_tax_fairness_credit_countable_rent: 127.5 + # utility portion = 15% * 1000 = 150; (1000 - 150) * 0.15 = 127.5 diff --git a/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.py b/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.py index ff7e1701ae6..e7436619a17 100644 --- a/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.py +++ b/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.py @@ -15,9 +15,12 @@ def formula(tax_unit, period, parameters): rent = add(tax_unit, period, ["rent"]) utilities_included_in_rent = tax_unit("utilities_included_in_rent", period) utility_expenses = add(tax_unit, period, ["utility_expense"]) - # A separate calculation exists for the case where utilities are included in rent - # if the filer does not know the portion of rent that is attributable to utilities - # This is not implemented - deductible_utility_expenses = utilities_included_in_rent * utility_expenses + # Schedule PTFC/STFC line 5c: when rent includes heat/utilities, exclude + # the utility portion before taking 15% of rent. If the amount is known, + # subtract it; if it is not known, subtract 15% of gross rent instead. + amount_known = utility_expenses > 0 + deductible_utility_expenses = utilities_included_in_rent * where( + amount_known, utility_expenses, rent * p.rate.utilities_included_in_rent + ) net_rent = rent - deductible_utility_expenses return net_rent * p.rate.rent From c135a8cf24a3f4cd44ed5d6608694511205e1fe7 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Mon, 17 Aug 2026 09:14:21 -0400 Subject: [PATCH 2/4] Address @PavelMakarchuk review: fix ME PTFC utility-portion discriminator and clamp - F1: the known/unknown split for the utility portion of rent was keyed on the household's general utility_expense (SNAP-style total), making the line-5c 15% fallback unreachable whenever any utility expense was reported and subtracting separately-paid utilities from rent. Add a dedicated me_ptfc_utilities_included_in_rent amount and drive the split off the utilities_included_in_rent boolean + that amount: not included -> no subtraction; included & known -> subtract it; included & unknown -> subtract the 15%-of-rent estimate. - F2: clamp net rent with max_(rent - utility_portion, 0) so countable rent can never go negative and offset real_estate_taxes downstream (Schedule PTFC line 5d >= 0). - Tests: add a separately-paid-utilities case (1,530, inverts if F1 reverted) and a utilities-exceed-rent clamp case (0). ME PTFC suite 36/36. Co-Authored-By: Claude Opus 4.8 --- ...ty_tax_fairness_credit_countable_rent.yaml | 39 ++++++++++++++++--- ...erty_tax_fairness_credit_countable_rent.py | 24 ++++++++---- .../me_ptfc_utilities_included_in_rent.py | 11 ++++++ 3 files changed, 60 insertions(+), 14 deletions(-) create mode 100644 policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_ptfc_utilities_included_in_rent.py diff --git a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml index 95d61d51f34..5dba569a5d7 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml @@ -4,21 +4,21 @@ state_code: ME rent: 1_000 utilities_included_in_rent: false - utility_expense: 50 + me_ptfc_utilities_included_in_rent: 0 output: me_property_tax_fairness_credit_countable_rent: 150 # 1000*0.15 = 150 - -- name: Case 2, utilities included in rent + +- name: Case 2, utilities included in rent, amount known period: 2022 input: state_code: ME rent: 1_000 utilities_included_in_rent: true - utility_expense: 50 + me_ptfc_utilities_included_in_rent: 50 output: me_property_tax_fairness_credit_countable_rent: 142.5 - # 950*0.15 = 142.5 + # (1000 - 50) * 0.15 = 142.5 - name: Case 3, utilities included in rent but amount unknown, deduct 15% of rent (Schedule PTFC/STFC line 5c) period: 2022 @@ -26,7 +26,34 @@ state_code: ME rent: 1_000 utilities_included_in_rent: true - utility_expense: 0 + me_ptfc_utilities_included_in_rent: 0 output: me_property_tax_fairness_credit_countable_rent: 127.5 # utility portion = 15% * 1000 = 150; (1000 - 150) * 0.15 = 127.5 + +- name: Case 4, utilities included but amount unknown, with separate general utility_expenses (F1 discriminator ignores utility_expenses) + period: 2022 + input: + state_code: ME + rent: 12_000 + utilities_included_in_rent: true + me_ptfc_utilities_included_in_rent: 0 + heating_cooling_expense: 600 + output: + me_property_tax_fairness_credit_countable_rent: 1_530 + # amount unknown -> line 5c estimate = 15% * 12000 = 1800; + # (12000 - 1800) * 0.15 = 10200 * 0.15 = 1530. + # General household utility expense (heating_cooling_expense 600, part of + # utility_expense) is IGNORED by the discriminator; old buggy discriminator + # gave (12000 - 600) * 0.15 = 1710, so this case inverts if F1 is reverted. + +- name: Case 5, utilities included and known amount exceeds rent, net rent clamped to 0 (F2 non-negative clamp) + period: 2022 + input: + state_code: ME + rent: 2_400 + utilities_included_in_rent: true + me_ptfc_utilities_included_in_rent: 3_600 + output: + me_property_tax_fairness_credit_countable_rent: 0 + # net rent = max(2400 - 3600, 0) = 0; 0 * 0.15 = 0 (not negative). diff --git a/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.py b/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.py index e7436619a17..ce19c965108 100644 --- a/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.py +++ b/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.py @@ -13,14 +13,22 @@ class me_property_tax_fairness_credit_countable_rent(Variable): def formula(tax_unit, period, parameters): p = parameters(period).gov.states.me.tax.income.credits.fairness.property_tax rent = add(tax_unit, period, ["rent"]) - utilities_included_in_rent = tax_unit("utilities_included_in_rent", period) - utility_expenses = add(tax_unit, period, ["utility_expense"]) + included = tax_unit("utilities_included_in_rent", period) + # Dedicated amount of utilities included in rent (Schedule PTFC/STFC + # line 5c). This is distinct from the household's general utility_expense + # (separately-paid utilities), which is not subtracted from rent here. + included_amount = tax_unit("me_ptfc_utilities_included_in_rent", period) # Schedule PTFC/STFC line 5c: when rent includes heat/utilities, exclude - # the utility portion before taking 15% of rent. If the amount is known, - # subtract it; if it is not known, subtract 15% of gross rent instead. - amount_known = utility_expenses > 0 - deductible_utility_expenses = utilities_included_in_rent * where( - amount_known, utility_expenses, rent * p.rate.utilities_included_in_rent + # the utility portion before taking 15% of rent. If the included amount + # is known (> 0), subtract it; if it is not known (0), subtract the + # 15%-of-rent estimate instead. When utilities are not included in rent, + # nothing is subtracted. + amount_known = included_amount > 0 + utility_portion = included * where( + amount_known, + included_amount, + rent * p.rate.utilities_included_in_rent, ) - net_rent = rent - deductible_utility_expenses + # Line 5d (5a - 5c) can never be negative. + net_rent = max_(rent - utility_portion, 0) return net_rent * p.rate.rent diff --git a/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_ptfc_utilities_included_in_rent.py b/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_ptfc_utilities_included_in_rent.py new file mode 100644 index 00000000000..37676477598 --- /dev/null +++ b/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_ptfc_utilities_included_in_rent.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class me_ptfc_utilities_included_in_rent(Variable): + value_type = float + entity = TaxUnit + unit = USD + label = "Amount of utilities included in rent for the Maine property tax fairness credit" + definition_period = YEAR + defined_for = StateCode.ME + reference = "https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/22_1040me_sched_pstfc_ff.pdf#page=2" From 66be72de9aae30a6608c6b3c54a03ea0544f4a99 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Tue, 18 Aug 2026 14:36:10 -0400 Subject: [PATCH 3/4] Address @PavelMakarchuk follow-up: changelog type, docs, refs, tests (ME PTFC) - Changelog: rename me-ptfc-utilities-in-rent.fixed.md -> .added.md (the PR adds a new parameter and input variable, so 'added' per repo convention). - Documentation: me_ptfc_utilities_included_in_rent now documents that 0 means the amount is unknown (triggers the 15%-of-gross-rent line-5c estimate), disambiguating a known $0. - References: utilities_included_in_rent.yaml adds the 2014 Schedule PTFC line-5c form (supports the 2014-01-01 start) alongside the 2022/2023 forms. No value/date change. - Tests: integration case (rent with unknown utilities -> line-5c estimate -> positive credit) and a known-amount-equals-rent boundary (-> 0 countable rent). ME PTFC suite 38/38. Co-Authored-By: Claude Opus 4.8 --- ....md => me-ptfc-utilities-in-rent.added.md} | 0 .../rate/utilities_included_in_rent.yaml | 2 ++ .../me_property_tax_fairness_credit.yaml | 27 +++++++++++++++++++ ...ty_tax_fairness_credit_countable_rent.yaml | 11 ++++++++ .../me_ptfc_utilities_included_in_rent.py | 1 + 5 files changed, 41 insertions(+) rename changelog.d/{me-ptfc-utilities-in-rent.fixed.md => me-ptfc-utilities-in-rent.added.md} (100%) diff --git a/changelog.d/me-ptfc-utilities-in-rent.fixed.md b/changelog.d/me-ptfc-utilities-in-rent.added.md similarity index 100% rename from changelog.d/me-ptfc-utilities-in-rent.fixed.md rename to changelog.d/me-ptfc-utilities-in-rent.added.md diff --git a/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_included_in_rent.yaml b/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_included_in_rent.yaml index dd8e682b933..086fcab2c44 100644 --- a/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_included_in_rent.yaml +++ b/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_included_in_rent.yaml @@ -6,6 +6,8 @@ metadata: period: year label: Maine property tax fairness credit utilities-in-rent fraction reference: + - title: 2014 Form 1040ME Schedule PTFC, line 5c + href: https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/14_1040_sched%20ptfc_download.pdf#page=2 - title: 2022 Form 1040ME Schedule PTFC/STFC, line 5c href: https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/22_1040me_sched_pstfc_ff.pdf#page=2 - title: 2023 Form 1040ME Schedule PTFC/STFC, line 5c diff --git a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit.yaml index 0ca96f3b2cf..580bfeb8bfc 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit.yaml @@ -28,3 +28,30 @@ output: me_property_tax_fairness_credit: 0 +- name: Case 4, rent includes utilities but amount unknown flows through to a positive credit via the 15% line-5c estimate + period: 2022 + input: + people: + person1: + age: 40 + rent: 6_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + utilities_included_in_rent: true + me_ptfc_utilities_included_in_rent: 0 + households: + household: + members: [person1] + state_code: ME + output: + # Amount unknown (0) -> line 5c estimate = 15% * 6000 = 900. + # Countable rent = 15% * (6000 - 900) = 15% * 5100 = 765. + # No real estate taxes -> countable_rent_property_tax = 765. + # Single benefit base (2200) >= 765, income 0 so no phase-out, + # non-senior cap 1000 does not bind: credit = min(765, 1000) = 765. + # Without the estimate the credit would be 15% * 6000 = 900, so the + # line-5c estimate reduces the credit to 765. + me_property_tax_fairness_credit: 765 + diff --git a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml index 5dba569a5d7..c027ab62ba1 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml @@ -57,3 +57,14 @@ output: me_property_tax_fairness_credit_countable_rent: 0 # net rent = max(2400 - 3600, 0) = 0; 0 * 0.15 = 0 (not negative). + +- name: Case 6, utilities included and known amount exactly equals rent, net rent clamps to 0 (boundary) + period: 2022 + input: + state_code: ME + rent: 3_000 + utilities_included_in_rent: true + me_ptfc_utilities_included_in_rent: 3_000 + output: + me_property_tax_fairness_credit_countable_rent: 0 + # net rent = max(3000 - 3000, 0) = 0; 0 * 0.15 = 0 (boundary, not negative). diff --git a/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_ptfc_utilities_included_in_rent.py b/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_ptfc_utilities_included_in_rent.py index 37676477598..ab4ba813c7f 100644 --- a/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_ptfc_utilities_included_in_rent.py +++ b/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_ptfc_utilities_included_in_rent.py @@ -8,4 +8,5 @@ class me_ptfc_utilities_included_in_rent(Variable): label = "Amount of utilities included in rent for the Maine property tax fairness credit" definition_period = YEAR defined_for = StateCode.ME + documentation = "A value of 0 means the utilities-in-rent amount is unknown, which triggers the 15%-of-gross-rent estimate on Schedule PTFC/STFC line 5c (applied in me_property_tax_fairness_credit_countable_rent). A known amount is entered as a positive dollar value." reference = "https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/22_1040me_sched_pstfc_ff.pdf#page=2" From e5a551c17e07b2a99f7b86c041d3f8cf842ac8d9 Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Mon, 24 Aug 2026 09:23:17 -0400 Subject: [PATCH 4/4] Address @PavelMakarchuk review: rename to convention, broaden wording, add coverage (ME PTFC) - A2: rename me_ptfc_utilities_included_in_rent -> me_property_tax_fairness_credit_utilities_in_rent_amount and rate/utilities_included_in_rent.yaml -> rate/utilities_share_of_rent.yaml (spelled-out sibling convention; the amount no longer reads as the adjacent utilities_included_in_rent boolean). - A1: broaden 'heat or utilities' -> 'heat, utilities, furniture, or similar items'; replace 'gross rent' with 'rent paid (Schedule PTFC/STFC line 5a)' (gross rent is the utilities-exclusive base per 5219-KK(1)(E)). - A6: reword the line-5d clamp comment to the modelling rationale (guards inconsistent input), not unprinted form text. - A3/A4: mutation-guard tests (gate mirror; known-branch utility_expense guard) + coverage (multi-person, renter+owner, zero rent, >0 boundary, negative amount, default path, e2e known-amount credit). - A5: absolute_error_margin on all cases; rename review-jargon case names to domain terms. - S2/S3/S5/S7: statute-not-cited-for-15% note; move sentinel doc into the formula comment; comment/style polish; fix pre-existing rate/rent.yaml label + 2024 reference href. No parameter value changed (0.15 intact). ME PTFC suite 50/50. Co-Authored-By: Claude Opus 4.8 --- .../me-ptfc-utilities-in-rent.added.md | 2 +- .../fairness/property_tax/rate/rent.yaml | 4 +- .../rate/utilities_included_in_rent.yaml | 14 -- .../rate/utilities_share_of_rent.yaml | 21 ++ .../me_property_tax_fairness_credit.yaml | 55 ++++- ...ty_tax_fairness_credit_countable_rent.yaml | 189 ++++++++++++++++-- ...erty_tax_fairness_credit_countable_rent.py | 29 +-- ...airness_credit_utilities_in_rent_amount.py | 11 + .../me_ptfc_utilities_included_in_rent.py | 12 -- 9 files changed, 275 insertions(+), 62 deletions(-) delete mode 100644 policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_included_in_rent.yaml create mode 100644 policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_share_of_rent.yaml create mode 100644 policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_utilities_in_rent_amount.py delete mode 100644 policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_ptfc_utilities_included_in_rent.py diff --git a/changelog.d/me-ptfc-utilities-in-rent.added.md b/changelog.d/me-ptfc-utilities-in-rent.added.md index d29a0ecc45b..9b79f75e1f1 100644 --- a/changelog.d/me-ptfc-utilities-in-rent.added.md +++ b/changelog.d/me-ptfc-utilities-in-rent.added.md @@ -1 +1 @@ -Implemented the Schedule PTFC/STFC line 5c rule for the Maine property tax fairness credit: when rent includes heat or utilities and the amount is not known, exclude 15% of gross rent before computing rent constituting property taxes. +Implemented the Schedule PTFC/STFC line 5c rule for the Maine property tax fairness credit: when rent paid (Schedule PTFC/STFC line 5a) includes heat, utilities, furniture, or similar items and the amount is not known, exclude 15% of rent paid before computing rent constituting property taxes. diff --git a/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/rent.yaml b/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/rent.yaml index 50f4a66925e..af3a2700bb0 100644 --- a/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/rent.yaml +++ b/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/rent.yaml @@ -12,7 +12,5 @@ metadata: href: https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/22_1040me_sched_pstfc_ff.pdf#page=2 - title: 2023 Form 1040ME Property Tax Fairness Credit / Sales Tax Fairness Credit Line 5(e) href: https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/23_1040me_sched_pstfc_ff.pdf#page=1 - - title: 2024 Form 1040ME Property Tax Fairness Credit / Sales Tax Fairness Credit Line 5(e) - href: https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/23_1040me_sched_pstfc_ff.pdf#page=1 period: year - label: Maine property tax fairness credit income rate + label: Maine property tax fairness credit rent rate diff --git a/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_included_in_rent.yaml b/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_included_in_rent.yaml deleted file mode 100644 index 086fcab2c44..00000000000 --- a/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_included_in_rent.yaml +++ /dev/null @@ -1,14 +0,0 @@ -description: When rent includes heat or utilities and the amount is not known, Maine treats this fraction of gross rent as attributable to utilities and excludes it before computing rent constituting property taxes under the property tax fairness credit. -values: - 2014-01-01: 0.15 -metadata: - unit: /1 - period: year - label: Maine property tax fairness credit utilities-in-rent fraction - reference: - - title: 2014 Form 1040ME Schedule PTFC, line 5c - href: https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/14_1040_sched%20ptfc_download.pdf#page=2 - - title: 2022 Form 1040ME Schedule PTFC/STFC, line 5c - href: https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/22_1040me_sched_pstfc_ff.pdf#page=2 - - title: 2023 Form 1040ME Schedule PTFC/STFC, line 5c - href: https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/23_1040me_sched_pstfc_ff.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_share_of_rent.yaml b/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_share_of_rent.yaml new file mode 100644 index 00000000000..ff603e6e986 --- /dev/null +++ b/policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_share_of_rent.yaml @@ -0,0 +1,21 @@ +description: Maine excludes this share of rent paid as attributable to heat, utilities, furniture, or similar items when the amount is not known under the property tax fairness credit. +values: + 2014-01-01: 0.15 +# §5219-KK is intentionally NOT cited for this 15%: the statute defines the +# utilities-exclusion concept but gives no estimate for an unknown amount, and +# its only 15% is the separate line-5e rent rate (see rate/rent.yaml). The +# unknown-amount estimate appears only in the Schedule PTFC/STFC line 5c +# instructions. +metadata: + unit: /1 + period: year + label: Maine property tax fairness credit utilities share of rent estimate + reference: + - title: §5219-KK. Property tax fairness credit (1) (E) + href: https://legislature.maine.gov/statutes/36/title36sec5219-KK.html + - title: 2014 Form 1040ME Schedule PTFC, line 5c + href: https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/14_1040_sched%20ptfc_download.pdf#page=2 + - title: 2022 Form 1040ME Schedule PTFC/STFC, line 5c + href: https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/22_1040me_sched_pstfc_ff.pdf#page=2 + - title: 2023 Form 1040ME Schedule PTFC/STFC, line 5c + href: https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/23_1040me_sched_pstfc_ff.pdf#page=1 diff --git a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit.yaml b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit.yaml index 580bfeb8bfc..9ece3f4f8f0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit.yaml @@ -40,7 +40,7 @@ members: [person1] filing_status: SINGLE utilities_included_in_rent: true - me_ptfc_utilities_included_in_rent: 0 + me_property_tax_fairness_credit_utilities_in_rent_amount: 0 households: household: members: [person1] @@ -54,4 +54,57 @@ # Without the estimate the credit would be 15% * 6000 = 900, so the # line-5c estimate reduces the credit to 765. me_property_tax_fairness_credit: 765 + absolute_error_margin: 0.01 +- name: Case 5, renter and owner combined, rent with unknown utilities plus real estate taxes. + period: 2022 + input: + people: + person1: + age: 40 + rent: 4_000 + real_estate_taxes: 200 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + utilities_included_in_rent: true + me_property_tax_fairness_credit_utilities_in_rent_amount: 0 + households: + household: + members: [person1] + state_code: ME + output: + # Amount unknown (0) -> line 5c estimate = 15% * 4000 = 600. + # Countable rent = 15% * (4000 - 600) = 15% * 3400 = 510. + # Property tax equivalent = countable rent 510 + real estate taxes 200 = 710. + # Single benefit base (2200) >= 710, income 0 so no phase-out, non-senior cap + # 1000 does not bind: credit = min(710, 1000) = 710. + me_property_tax_fairness_credit: 710 + absolute_error_margin: 0.01 + +- name: Case 6, rent includes utilities with a known amount, flows to a positive credit. + period: 2022 + input: + people: + person1: + age: 40 + rent: 6_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + utilities_included_in_rent: true + me_property_tax_fairness_credit_utilities_in_rent_amount: 1_000 + households: + household: + members: [person1] + state_code: ME + output: + # Known amount 1000 subtracted from rent paid 6000. + # Countable rent = 15% * (6000 - 1000) = 15% * 5000 = 750. + # No real estate taxes -> countable_rent_property_tax = 750. + # Single benefit base (2200) >= 750, income 0 so no phase-out, non-senior cap + # 1000 does not bind: credit = min(750, 1000) = 750. + me_property_tax_fairness_credit: 750 + absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml index c027ab62ba1..273d7b8d613 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml @@ -1,70 +1,223 @@ -- name: Case 1, utilities did not include in rent +# Note: p.rate.utilities_share_of_rent and p.rate.rent are both 0.15, so +# baseline cases cannot distinguish the two rates. Avoid any known-amount case +# where the amount equals 0.15 * rent (both branches would coincide). +- name: Case 1, utilities not included in rent, full rent counts. period: 2022 input: state_code: ME rent: 1_000 utilities_included_in_rent: false - me_ptfc_utilities_included_in_rent: 0 output: me_property_tax_fairness_credit_countable_rent: 150 - # 1000*0.15 = 150 + # 1000 * 0.15 = 150 + absolute_error_margin: 0.01 -- name: Case 2, utilities included in rent, amount known +- name: Case 2, utilities included in rent, amount known. period: 2022 input: state_code: ME rent: 1_000 utilities_included_in_rent: true - me_ptfc_utilities_included_in_rent: 50 + me_property_tax_fairness_credit_utilities_in_rent_amount: 50 output: me_property_tax_fairness_credit_countable_rent: 142.5 # (1000 - 50) * 0.15 = 142.5 + absolute_error_margin: 0.01 -- name: Case 3, utilities included in rent but amount unknown, deduct 15% of rent (Schedule PTFC/STFC line 5c) +- name: Case 3, utilities included but amount unknown, deduct 15% of rent (line 5c). period: 2022 input: state_code: ME rent: 1_000 utilities_included_in_rent: true - me_ptfc_utilities_included_in_rent: 0 + me_property_tax_fairness_credit_utilities_in_rent_amount: 0 output: me_property_tax_fairness_credit_countable_rent: 127.5 # utility portion = 15% * 1000 = 150; (1000 - 150) * 0.15 = 127.5 + absolute_error_margin: 0.01 -- name: Case 4, utilities included but amount unknown, with separate general utility_expenses (F1 discriminator ignores utility_expenses) +- name: Case 4, utilities included, amount unknown; separately-paid utility expenses ignored. period: 2022 input: state_code: ME rent: 12_000 utilities_included_in_rent: true - me_ptfc_utilities_included_in_rent: 0 + me_property_tax_fairness_credit_utilities_in_rent_amount: 0 heating_cooling_expense: 600 output: me_property_tax_fairness_credit_countable_rent: 1_530 # amount unknown -> line 5c estimate = 15% * 12000 = 1800; # (12000 - 1800) * 0.15 = 10200 * 0.15 = 1530. - # General household utility expense (heating_cooling_expense 600, part of - # utility_expense) is IGNORED by the discriminator; old buggy discriminator - # gave (12000 - 600) * 0.15 = 1710, so this case inverts if F1 is reverted. + # The household's separately-paid utility expense (heating_cooling_expense + # 600, part of utility_expense) is not subtracted from rent paid. + absolute_error_margin: 0.01 -- name: Case 5, utilities included and known amount exceeds rent, net rent clamped to 0 (F2 non-negative clamp) +- name: Case 5, known amount exceeds rent, net rent clamped to 0 (invalid-input guard). period: 2022 input: state_code: ME rent: 2_400 utilities_included_in_rent: true - me_ptfc_utilities_included_in_rent: 3_600 + me_property_tax_fairness_credit_utilities_in_rent_amount: 3_600 output: me_property_tax_fairness_credit_countable_rent: 0 - # net rent = max(2400 - 3600, 0) = 0; 0 * 0.15 = 0 (not negative). + # Invalid input: line 5c (3600) exceeds line 5a rent (2400). The clamp guards + # this inconsistency; this is not a Maine-published result. + # net rent = max(2400 - 3600, 0) = 0; 0 * 0.15 = 0. + absolute_error_margin: 0.01 -- name: Case 6, utilities included and known amount exactly equals rent, net rent clamps to 0 (boundary) +- name: Case 6, known amount exactly equals rent, net rent clamps to 0 (invalid-input guard). period: 2022 input: state_code: ME rent: 3_000 utilities_included_in_rent: true - me_ptfc_utilities_included_in_rent: 3_000 + me_property_tax_fairness_credit_utilities_in_rent_amount: 3_000 output: me_property_tax_fairness_credit_countable_rent: 0 - # net rent = max(3000 - 3000, 0) = 0; 0 * 0.15 = 0 (boundary, not negative). + # Invalid input: line 5c (3000) equals line 5a rent (3000). The clamp is + # exercised at the boundary; this is not a Maine-published result. + # net rent = max(3000 - 3000, 0) = 0; 0 * 0.15 = 0. + absolute_error_margin: 0.01 + +- name: Case 7, utilities not included but nonzero amount recorded, amount ignored. + period: 2022 + input: + state_code: ME + rent: 1_000 + utilities_included_in_rent: false + me_property_tax_fairness_credit_utilities_in_rent_amount: 400 + output: + me_property_tax_fairness_credit_countable_rent: 150 + # Line 5b is "no", so line 5c is entered as 0 regardless of the recorded + # amount. Full rent counts: 1000 * 0.15 = 150. An ungated subtraction would + # instead give (1000 - 400) * 0.15 = 90. + absolute_error_margin: 0.01 + +- name: Case 8, utilities included, known amount, separately-paid utility expenses ignored. + period: 2022 + input: + state_code: ME + rent: 12_000 + utilities_included_in_rent: true + me_property_tax_fairness_credit_utilities_in_rent_amount: 1_200 + heating_cooling_expense: 600 + output: + me_property_tax_fairness_credit_countable_rent: 1_620 + # Known amount 1200 subtracted: (12000 - 1200) * 0.15 = 10800 * 0.15 = 1620. + # A reintroduced utility_expense subtraction would give + # (12000 - 1200 - 600) * 0.15 = 1530. + absolute_error_margin: 0.01 + +- name: Case 9, multi-person joint filers, rent aggregated across members, amount unknown. + period: 2022 + input: + people: + person1: + age: 40 + rent: 6_000 + person2: + age: 40 + rent: 4_000 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + utilities_included_in_rent: true + me_property_tax_fairness_credit_utilities_in_rent_amount: 0 + households: + household: + members: [person1, person2] + state_code: ME + output: + me_property_tax_fairness_credit_countable_rent: 1_275 + # Rent aggregates to 6000 + 4000 = 10000; amount unknown -> line 5c estimate + # = 15% * 10000 = 1500; (10000 - 1500) * 0.15 = 8500 * 0.15 = 1275. + absolute_error_margin: 0.01 + +- name: Case 10, zero rent with utilities included, amount known, countable rent 0. + period: 2022 + input: + state_code: ME + rent: 0 + utilities_included_in_rent: true + me_property_tax_fairness_credit_utilities_in_rent_amount: 500 + output: + me_property_tax_fairness_credit_countable_rent: 0 + # net rent = max(0 - 500, 0) = 0; 0 * 0.15 = 0. + absolute_error_margin: 0.01 + +- name: Case 11, zero rent with utilities included, amount unknown, countable rent 0. + period: 2022 + input: + state_code: ME + rent: 0 + utilities_included_in_rent: true + me_property_tax_fairness_credit_utilities_in_rent_amount: 0 + output: + me_property_tax_fairness_credit_countable_rent: 0 + # estimate = 15% * 0 = 0; (0 - 0) * 0.15 = 0. + absolute_error_margin: 0.01 + +- name: Case 12, one-dollar known amount just above the zero sentinel, estimate not used. + period: 2022 + input: + state_code: ME + rent: 1_000 + utilities_included_in_rent: true + me_property_tax_fairness_credit_utilities_in_rent_amount: 1 + output: + me_property_tax_fairness_credit_countable_rent: 149.85 + # Amount 1 > 0 so it is treated as known: (1000 - 1) * 0.15 = 149.85. + # At amount 0 the estimate branch gives 127.5, so 1 dollar pins the >0 + # sentinel boundary. + absolute_error_margin: 0.01 + +- name: Case 13, negative recorded amount falls into the unknown estimate branch. + period: 2022 + input: + state_code: ME + rent: 1_000 + utilities_included_in_rent: true + me_property_tax_fairness_credit_utilities_in_rent_amount: -100 + output: + me_property_tax_fairness_credit_countable_rent: 127.5 + # amount is not > 0, so the 15%-of-rent estimate applies: same as unknown. + # estimate = 15% * 1000 = 150; (1000 - 150) * 0.15 = 127.5. + absolute_error_margin: 0.01 + +- name: Case 14, default inputs, rent only with nothing else set, plain 15% of rent. + period: 2022 + input: + state_code: ME + rent: 1_000 + output: + me_property_tax_fairness_credit_countable_rent: 150 + # utilities_included_in_rent defaults to false -> utility portion 0; + # 1000 * 0.15 = 150. This is the path the microdata population takes. + absolute_error_margin: 0.01 + +- name: Case 15, unknown branch at the 2014 program start pins the start date. + period: 2014 + input: + state_code: ME + rent: 1_000 + utilities_included_in_rent: true + me_property_tax_fairness_credit_utilities_in_rent_amount: 0 + output: + me_property_tax_fairness_credit_countable_rent: 127.5 + # estimate = 15% * 1000 = 150; (1000 - 150) * 0.15 = 127.5. Confirms the + # utilities_share_of_rent parameter is in effect from 2014-01-01. + absolute_error_margin: 0.01 + +- name: Case 16, unknown branch at 2024 confirms parameter continuity. + period: 2024 + input: + state_code: ME + rent: 1_000 + utilities_included_in_rent: true + me_property_tax_fairness_credit_utilities_in_rent_amount: 0 + output: + me_property_tax_fairness_credit_countable_rent: 127.5 + # estimate = 15% * 1000 = 150; (1000 - 150) * 0.15 = 127.5. + absolute_error_margin: 0.01 diff --git a/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.py b/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.py index ce19c965108..6b299ac1d33 100644 --- a/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.py +++ b/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.py @@ -13,22 +13,25 @@ class me_property_tax_fairness_credit_countable_rent(Variable): def formula(tax_unit, period, parameters): p = parameters(period).gov.states.me.tax.income.credits.fairness.property_tax rent = add(tax_unit, period, ["rent"]) + # utilities_included_in_rent is the generic household boolean, used here + # as a narrower-named proxy for Schedule PTFC/STFC line 5b (does rent + # paid include heat, utilities, furniture, or similar items?). included = tax_unit("utilities_included_in_rent", period) - # Dedicated amount of utilities included in rent (Schedule PTFC/STFC - # line 5c). This is distinct from the household's general utility_expense - # (separately-paid utilities), which is not subtracted from rent here. - included_amount = tax_unit("me_ptfc_utilities_included_in_rent", period) - # Schedule PTFC/STFC line 5c: when rent includes heat/utilities, exclude - # the utility portion before taking 15% of rent. If the included amount - # is known (> 0), subtract it; if it is not known (0), subtract the - # 15%-of-rent estimate instead. When utilities are not included in rent, - # nothing is subtracted. - amount_known = included_amount > 0 + # Line 5c: the amount of heat, utilities, furniture, or similar items + # included in rent paid (line 5a). A zero here is a sentinel meaning the + # amount is unknown, so we subtract the 15%-of-rent estimate instead of a + # known dollar amount. This is distinct from the household's general + # utility_expense (separately-paid utilities), which is not subtracted. + included_amount = tax_unit( + "me_property_tax_fairness_credit_utilities_in_rent_amount", period + ) utility_portion = included * where( - amount_known, + included_amount > 0, included_amount, - rent * p.rate.utilities_included_in_rent, + rent * p.rate.utilities_share_of_rent, ) - # Line 5d (5a - 5c) can never be negative. + # Clamp guards inconsistent user input: on the unknown branch the base is + # 0.85 * line 5a (always non-negative), and on the known branch line 5c is + # a component of line 5a, so a subtraction below zero reflects bad input. net_rent = max_(rent - utility_portion, 0) return net_rent * p.rate.rent diff --git a/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_utilities_in_rent_amount.py b/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_utilities_in_rent_amount.py new file mode 100644 index 00000000000..aea0acdfe93 --- /dev/null +++ b/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_property_tax_fairness_credit_utilities_in_rent_amount.py @@ -0,0 +1,11 @@ +from policyengine_us.model_api import * + + +class me_property_tax_fairness_credit_utilities_in_rent_amount(Variable): + value_type = float + entity = TaxUnit + unit = USD + label = "Amount of heat, utilities, furniture, or similar items included in rent for the Maine property tax fairness credit" + definition_period = YEAR + defined_for = StateCode.ME + reference = "https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/22_1040me_sched_pstfc_ff.pdf#page=2" diff --git a/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_ptfc_utilities_included_in_rent.py b/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_ptfc_utilities_included_in_rent.py deleted file mode 100644 index ab4ba813c7f..00000000000 --- a/policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_ptfc_utilities_included_in_rent.py +++ /dev/null @@ -1,12 +0,0 @@ -from policyengine_us.model_api import * - - -class me_ptfc_utilities_included_in_rent(Variable): - value_type = float - entity = TaxUnit - unit = USD - label = "Amount of utilities included in rent for the Maine property tax fairness credit" - definition_period = YEAR - defined_for = StateCode.ME - documentation = "A value of 0 means the utilities-in-rent amount is unknown, which triggers the 15%-of-gross-rent estimate on Schedule PTFC/STFC line 5c (applied in me_property_tax_fairness_credit_countable_rent). A known amount is entered as a positive dollar value." - reference = "https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/22_1040me_sched_pstfc_ff.pdf#page=2"