mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
Log a landlord fuel that contradicts the heating archetype's natural fuel 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
648013e05c
commit
79fe54a822
2 changed files with 48 additions and 0 deletions
|
|
@ -198,6 +198,16 @@ def _gas_boiler_overlay(code: int) -> HeatingOverlay:
|
|||
)
|
||||
|
||||
|
||||
def natural_fuel_for(main_heating_value: str) -> Optional[int]:
|
||||
"""The RdSAP `main_fuel` code a heating archetype unambiguously implies — its
|
||||
natural fuel (ADR-0041) — or None for an unmapped archetype. Exposed so a
|
||||
plausibility check can compare it against a landlord `main_fuel` override."""
|
||||
code = _MAIN_HEATING_CODES.get(main_heating_value)
|
||||
if code is None:
|
||||
return None
|
||||
return _natural_fuel_for(code)
|
||||
|
||||
|
||||
def main_heating_overlay_for(
|
||||
main_heating_value: str, building_part: int
|
||||
) -> Optional[EpcSimulation]:
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ values are live vs no-op before any write.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Callable, Optional
|
||||
|
||||
from domain.epc.property_overlays.attribute_overlay import (
|
||||
|
|
@ -41,6 +42,7 @@ from domain.epc.property_overlays.glazing_overlay import glazing_overlay_for
|
|||
from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for
|
||||
from domain.epc.property_overlays.main_heating_system_overlay import (
|
||||
main_heating_overlay_for,
|
||||
natural_fuel_for,
|
||||
)
|
||||
from domain.epc.property_overlays.water_heating_overlay import (
|
||||
water_heating_overlay_for,
|
||||
|
|
@ -50,6 +52,8 @@ from domain.epc.property_overlays.wall_type_overlay import wall_overlay_for
|
|||
from domain.modelling.simulation import EpcSimulation
|
||||
from repositories.property.property_overrides_reader import ResolvedPropertyOverrides
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Each override component maps its value (+ building part) to an overlay, or None
|
||||
# when the value isn't resolvable. Fabric (wall/roof) folds onto building parts;
|
||||
# property_type / built_form_type are whole-dwelling categorical corrections
|
||||
|
|
@ -90,3 +94,37 @@ def overlays_from(overrides: ResolvedPropertyOverrides) -> list[EpcSimulation]:
|
|||
if overlay is not None:
|
||||
overlays.append(overlay)
|
||||
return overlays
|
||||
|
||||
|
||||
def _override_value(overrides: ResolvedPropertyOverrides, component: str) -> Optional[str]:
|
||||
for row in overrides.rows:
|
||||
if row.override_component == component:
|
||||
return row.override_value
|
||||
return None
|
||||
|
||||
|
||||
def flag_fuel_mismatch(overrides: ResolvedPropertyOverrides) -> None:
|
||||
"""Log (not raise) when a landlord `main_fuel` override contradicts the
|
||||
`main_heating_system` archetype's natural fuel — a plausibility signal (e.g.
|
||||
a gas fuel on an electric room heater). The override is still honoured (it
|
||||
wins, ADR-0041); we only record the implausibility. Deferred handling."""
|
||||
heating_value = _override_value(overrides, "main_heating_system")
|
||||
fuel_value = _override_value(overrides, "main_fuel")
|
||||
if heating_value is None or fuel_value is None:
|
||||
return
|
||||
natural = natural_fuel_for(heating_value)
|
||||
fuel_overlay = fuel_overlay_for(fuel_value, 0)
|
||||
override_fuel = (
|
||||
fuel_overlay.heating.main_fuel_type
|
||||
if fuel_overlay is not None and fuel_overlay.heating is not None
|
||||
else None
|
||||
)
|
||||
if natural is None or override_fuel is None:
|
||||
return
|
||||
if natural != override_fuel:
|
||||
logger.warning(
|
||||
"Landlord main_fuel %r contradicts the natural fuel of heating "
|
||||
"system %r (override is honoured; flagged for review)",
|
||||
fuel_value,
|
||||
heating_value,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue