mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
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:
parent
1c79b69648
commit
6883864c32
2 changed files with 24 additions and 4 deletions
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue