A community override keeps an assessor-observed Group 3 control 🟩

The heat-network mirror of keep_existing_off_peak_meter: the override's
2313 default applies only when the replaced system's control is
cross-family (stale); an observed community control survives.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-03 16:35:08 +00:00
parent 04810896e0
commit 9153fa2523
3 changed files with 36 additions and 2 deletions

View file

@ -445,5 +445,10 @@ def main_heating_overlay_for(
# (e.g. a 24-hour all-low tariff). Measures, which re-meter for real,
# build their HeatingOverlay directly and leave this False.
keep_existing_off_peak_meter=True,
# Likewise a heat-network override's control default (2313) must
# not overwrite an assessor-OBSERVED Group 3 control on a community
# cert being confirmed — only a stale cross-family control is
# replaced (ADR-0053).
keep_existing_heat_network_control=code in _HEAT_NETWORK_CODES,
)
)

View file

@ -152,6 +152,13 @@ _SAP_HEATING_FIELDS: tuple[str, ...] = (
_ENERGY_SOURCE_FIELDS: tuple[str, ...] = ("meter_type", "gas_connection_available")
def _is_heat_network_control(control: object) -> bool:
"""True iff the lodged control is a SAP Table 4e Group 3 (heat network)
code 2301-2314 i.e. an assessor-observed community control a
heat-network override's default must not overwrite (ADR-0053)."""
return isinstance(control, int) and 2301 <= control <= 2314
def _is_off_peak_meter(meter_type: object) -> bool:
"""True iff the meter resolves to an off-peak Table 12a tariff (not the
STANDARD single-rate column). Unparseable / absent meters count as not
@ -177,8 +184,21 @@ def _fold_heating(epc: EpcPropertyData, overlay: HeatingOverlay) -> None:
main = epc.sap_heating.main_heating_details[0]
for field_name in _MAIN_HEATING_FIELDS:
value = getattr(overlay, field_name)
if value is not None:
setattr(main, field_name, value)
if value is None:
continue
# A community override's control is a coherent default, not an observed
# one: when it opts in (`keep_existing_heat_network_control`) and the
# cert already lodges a Table 4e GROUP 3 control (assessor-observed on
# a community cert being confirmed), keep the cert's. A cross-family
# control (boiler 2110, storage 2401) is stale and is still replaced
# (ADR-0053).
if (
field_name == "main_heating_control"
and overlay.keep_existing_heat_network_control
and _is_heat_network_control(main.main_heating_control)
):
continue
setattr(main, field_name, value)
# `main_heating_index_number` (PCDB-resolved, e.g. a heat pump) and
# `sap_main_heating_code` (Table 4a-resolved, e.g. storage heaters) are
# mutually-exclusive efficiency anchors: a whole-system replacement to one

View file

@ -200,6 +200,15 @@ class HeatingOverlay:
# MEASURE re-meters for real (Elmhurst re-lodges 18-hour → Dual on a storage
# install), so it leaves this False. `_fold_heating` reads it.
keep_existing_off_peak_meter: bool = False
# The community-heating mirror of the flag above (ADR-0053): a heat-network
# override's `main_heating_control` is a coherent DEFAULT, not an observed
# control — when the cert already lodges a Table 4e Group 3 control the
# assessor observed it (a community cert being confirmed, not replaced), so
# the default must not overwrite it (e.g. a usage-linked 2306 downgraded to
# flat-rate 2313 destroys ~1-2 real SAP). A cross-family control (a boiler
# 2110, storage 2401) is stale by definition and is still replaced.
# `_fold_heating` reads it.
keep_existing_heat_network_control: bool = False
@dataclass(frozen=True)