Defer the screed-underfloor meter to the cert while off-peak underfloor asserts Dual 🟩

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-01 16:46:33 +00:00
parent 1c79b69648
commit 6883864c32
2 changed files with 24 additions and 4 deletions

View file

@ -45,6 +45,10 @@ _OFF_PEAK_METER = "Dual"
# meter bleed through and bill the new gas/direct-acting system on an Economy-7
# split (the mirror of the storage→Dual drag, ADR-0035).
_SINGLE_RATE_METER = "Single"
# Meter-agnostic codes: the archetype cannot determine the tariff, so the overlay
# defers `meter_type` to the cert (`_meter_for` → None). Screed underfloor (424) is
# "standard or off peak" — 81% of the corpus lodge off-peak (ADR-0046).
_METER_AGNOSTIC_CODES = frozenset({424})
# Electric room heaters (SAP Table 4a 691). They don't *require* off-peak the way
# storage/CPSU do, so they're absent from the calculator's §12
@ -228,11 +232,19 @@ _MAIN_HEATING_CODES: dict[str, int] = {
}
def _meter_for(code: int) -> str:
def _meter_for(code: int) -> Optional[str]:
"""The coherent meter a heating code implies: an off-peak ("Dual") meter for
the §12 off-peak systems and all-electric room-heater dwellings
(`_ASSUMED_DUAL_METER_CODES`), an explicit single-rate ("Single") meter for
every other system. Always set never left to bleed."""
every other system set explicitly so it never bleeds.
Exception: a **meter-agnostic** code (`_METER_AGNOSTIC_CODES` screed
underfloor 424, "standard or off peak") returns ``None`` so the overlay leaves
`meter_type` unset and the cert's lodged tariff stands. The archetype genuinely
cannot know the tariff, and unlike a switched-off storage system it is not a
re-metering, so deferring is faithful, not a bleed (ADR-0046)."""
if code in _METER_AGNOSTIC_CODES:
return None
return _OFF_PEAK_METER if code in _ASSUMED_DUAL_METER_CODES else _SINGLE_RATE_METER

View file

@ -13,6 +13,7 @@ from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for
from domain.epc.property_overlays.main_heating_system_overlay import (
_ASSUMED_DUAL_METER_CODES,
_MAIN_HEATING_CODES,
_METER_AGNOSTIC_CODES,
main_heating_overlay_for,
)
from domain.epc.property_overlays.water_heating_overlay import (
@ -367,11 +368,18 @@ def test_off_peak_archetypes_drag_dual_others_drag_single() -> None:
# the calculator's single off-peak classification, so any archetype whose
# code implies off-peak MUST synthesise a Dual meter and every other code
# MUST synthesise a Single meter — a system switch can never silently leave
# the previous system's meter in place.
# the previous system's meter in place. The one exception is a meter-agnostic
# code (screed underfloor, tariff-ambiguous), which defers to the cert's
# lodged meter (None) rather than assert one (ADR-0046).
for value, code in _MAIN_HEATING_CODES.items():
simulation = main_heating_overlay_for(value, 0)
assert simulation is not None and simulation.heating is not None
expected = "Dual" if code in _ASSUMED_DUAL_METER_CODES else "Single"
if code in _METER_AGNOSTIC_CODES:
expected = None
elif code in _ASSUMED_DUAL_METER_CODES:
expected = "Dual"
else:
expected = "Single"
assert simulation.heating.meter_type == expected, value