mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
S0380.231: Dual-meter electric room heaters resolve to 10-hour tariff (RdSAP 10 §12 Rule 3)
RdSAP 10 §12 (PDF p.62) Dual-meter dispatch: "the choice between 7-hour and 10-hour is made by the main heating type ... if the main system is a direct-acting electric boiler (191), or electric room heaters ... it is 10-hour tariff." The electric room-heater codes — Table 4a 691 (panel/ convector/radiant), 692 (fan), 693 (portable), 694 (water-/oil-filled), 699 (assumed) — were missing from `_RULE_3_TEN_HOUR_CODES` (the long- standing TODO there), so a Dual-meter room-heater cert fell through to Rule 4 (7-hour default). Compounded with S0380.230 (which routes room heaters to Table 12a OTHER_DIRECT_ACTING_ELECTRIC): at 7-hour the high-rate fraction is 1.00 (all at 15.29 p), but at the correct 10-hour it is 0.50 split over the 10-hour rates (14.68 / 7.50 p) → blended ~11 p. Without this fix .230 over-charged and flipped the cluster from over- to under-rating. 1,000-cert 2026 API sample: cat-10 mean |err| 7.11 → 5.26, signed mean +5.08 → -0.86 (now balanced, 22 over / 26 under — the systematic directional bias is gone). Overall mean |err| 2.16 → 2.04. Full §4 suite green (2406 passed). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
0476b4b235
commit
3684a142ac
2 changed files with 29 additions and 3 deletions
|
|
@ -250,13 +250,16 @@ _RULE_2_STORAGE_CODES: Final[frozenset[int]] = frozenset(
|
|||
# Rule 3: direct-acting electric + heat pumps + electric room heaters
|
||||
# → 10-hour. §12 lists "heat pump (211 to 224, 521 to 524, or
|
||||
# database)" — the "database" branch fires when the cert lodges a
|
||||
# PCDB Table 362 heat-pump index regardless of SAP code.
|
||||
# PCDB Table 362 heat-pump index regardless of SAP code. §12 also
|
||||
# names "electric room heaters" verbatim (RdSAP 10 PDF p.62) — Table 4a
|
||||
# electric room-heater codes 691 (panel/convector/radiant), 692 (fan),
|
||||
# 693 (portable), 694 (water-/oil-filled), 699 (assumed). Without these
|
||||
# a Dual-meter room-heater cert fell through to Rule 4 (7-hour default).
|
||||
_RULE_3_TEN_HOUR_CODES: Final[frozenset[int]] = frozenset(
|
||||
[191] # direct-acting electric boiler
|
||||
+ list(range(211, 225)) # heat pumps 211-224
|
||||
+ list(range(521, 525)) # warm-air heat pumps 521-524
|
||||
# TODO: electric room heater codes (SAP Table 4a row 6xx for
|
||||
# electric panel / radiant heaters) when a fixture surfaces them.
|
||||
+ [691, 692, 693, 694, 699] # electric room heaters (Table 4a)
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,12 +17,35 @@ from domain.sap10_calculator.tables.table_12a import (
|
|||
Table12aSystem,
|
||||
Tariff,
|
||||
other_use_high_rate_fraction,
|
||||
rdsap_tariff_for_cert,
|
||||
space_heating_high_rate_fraction,
|
||||
tariff_from_meter_type,
|
||||
water_heating_high_rate_fraction,
|
||||
)
|
||||
|
||||
|
||||
def test_dual_meter_electric_room_heater_resolves_to_ten_hour_tariff() -> None:
|
||||
# Arrange — RdSAP 10 §12 (PDF p.62) Dual-meter tariff dispatch: for a
|
||||
# Dual meter the choice between 7-hour and 10-hour is made by the main
|
||||
# heating type. Rule 3 verbatim: "if the main system ... is a direct-
|
||||
# acting electric boiler (191), or electric room heaters ... it is
|
||||
# 10-hour tariff." The electric room-heater codes are Table 4a 691
|
||||
# (panel/convector/radiant), 692 (fan), 693 (portable), 694 (water-/
|
||||
# oil-filled), 699 (assumed). Pre-slice these fell through to Rule 4
|
||||
# (7-hour default), so a Dual-meter room-heater cert was billed at the
|
||||
# 7-hour rates with Table 12a high-rate fraction 1.00 instead of the
|
||||
# 10-hour rates with fraction 0.50 — over-charging direct-acting heat
|
||||
# once S0380.230 routed it to OTHER_DIRECT_ACTING_ELECTRIC.
|
||||
|
||||
# Act / Assert — every electric room-heater code on a Dual meter → 10-hour.
|
||||
for code in (691, 692, 693, 694, 699):
|
||||
assert rdsap_tariff_for_cert(1, main_1_sap_code=code) is Tariff.TEN_HOUR
|
||||
# Storage heaters (Rule 2) stay 7-hour; a gas room heater (non-Rule-3
|
||||
# code) keeps the Rule 4 Dual default of 7-hour.
|
||||
assert rdsap_tariff_for_cert(1, main_1_sap_code=401) is Tariff.SEVEN_HOUR
|
||||
assert rdsap_tariff_for_cert(1, main_1_sap_code=601) is Tariff.SEVEN_HOUR
|
||||
|
||||
|
||||
def test_tariff_enum_has_five_members() -> None:
|
||||
"""Table 12a columns: standard (no off-peak split), 7-hour, 10-hour,
|
||||
18-hour, 24-hour. Worksheet-shape fidelity: TEN_HOUR is included for
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue