diff --git a/domain/epc/property_overlays/main_heating_system_overlay.py b/domain/epc/property_overlays/main_heating_system_overlay.py index a2d9bc634..bc00cf350 100644 --- a/domain/epc/property_overlays/main_heating_system_overlay.py +++ b/domain/epc/property_overlays/main_heating_system_overlay.py @@ -79,6 +79,16 @@ _ROOM_HEATER_CATEGORY = 10 _ROOM_HEATER_CONTROL = 2601 _SOLID_FUEL_ROOM_HEATER_CODES = frozenset(range(631, 637)) +# Natural-fuel coherence (ADR-0041): where an archetype unambiguously implies a +# fuel, the overlay drags it so a system-only override is self-coherent on a cert +# that lodged a different fuel. A later `main_fuel` override still wins (last-wins +# composition); a contradicting landlord fuel is logged, not silently overridden. +# Electric room heaters (Table 4a 691-701) are unambiguously electricity (RdSAP +# main_fuel code 29). Solid/oil room heaters are fuel-ambiguous (coal vs wood vs +# smokeless), so they drag no natural fuel and rely on the `main_fuel` override. +_ELECTRICITY_FUEL = 29 +_ELECTRIC_ROOM_HEATER_CODES = frozenset(range(691, 702)) + # SAP Table 4c full boiler-control code: programmer + room thermostat + TRVs. The # landlord names the boiler, not its controls — but a gas boiler installed under # modern Building Regs must carry compliant controls, and this overlay already @@ -155,6 +165,15 @@ def _category_for(code: int) -> Optional[int]: return None +def _natural_fuel_for(code: int) -> Optional[int]: + """The fuel an archetype unambiguously implies (a coherent default), or None + where the fuel is ambiguous and must come from the `main_fuel` override. A + present `main_fuel` override wins by last-wins composition.""" + if code in _ELECTRIC_ROOM_HEATER_CODES: + return _ELECTRICITY_FUEL + return None + + def _gas_boiler_overlay(code: int) -> HeatingOverlay: """The coherent gas-boiler companion set: a mains-gas connection + gas main fuel, the gas-boiler heating category, a fanned room-sealed flue, full modern @@ -186,6 +205,7 @@ def main_heating_overlay_for( heating=HeatingOverlay( sap_main_heating_code=code, main_heating_category=_category_for(code), + main_fuel_type=_natural_fuel_for(code), meter_type=_meter_for(code), main_heating_control=_control_for(code), # A landlord override describes the existing dwelling, so its assumed