diff --git a/changelog.d/me-ptfc-utilities-in-rent.added.md b/changelog.d/me-ptfc-utilities-in-rent.added.md new file mode 100644 index 00000000000..9b79f75e1f1 --- /dev/null +++ b/changelog.d/me-ptfc-utilities-in-rent.added.md @@ -0,0 +1 @@ +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_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 0ca96f3b2cf..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 @@ -28,3 +28,83 @@ 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_property_tax_fairness_credit_utilities_in_rent_amount: 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 + 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 2fce45e5176..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,21 +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 - utility_expense: 50 output: me_property_tax_fairness_credit_countable_rent: 150 - # 1000*0.15 = 150 - -- name: Case 2, utilities included in rent + # 1000 * 0.15 = 150 + absolute_error_margin: 0.01 + +- 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_property_tax_fairness_credit_utilities_in_rent_amount: 50 output: me_property_tax_fairness_credit_countable_rent: 142.5 - # 950*0.15 = 142.5 + # (1000 - 50) * 0.15 = 142.5 + absolute_error_margin: 0.01 + +- 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_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, amount unknown; 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: 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. + # 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, 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_property_tax_fairness_credit_utilities_in_rent_amount: 3_600 + output: + me_property_tax_fairness_credit_countable_rent: 0 + # 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, 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_property_tax_fairness_credit_utilities_in_rent_amount: 3_000 + output: + me_property_tax_fairness_credit_countable_rent: 0 + # 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 ff7e1701ae6..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,11 +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 = 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 - net_rent = rent - deductible_utility_expenses + # 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) + # 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( + included_amount > 0, + included_amount, + rent * p.rate.utilities_share_of_rent, + ) + # 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"