from __future__ import annotations from dataclasses import dataclass from typing import Optional from domain.billing.bill import Bill from domain.property_baseline.performance import Performance from domain.property_baseline.rebaseliner import RebaselineReason @dataclass(frozen=True) class PropertyBaselinePerformance: """A Property's current performance aggregate (CONTEXT.md, ADR-0004). Holds both halves — ``lodged`` (what the gov register says) and ``effective`` (what the modelling pipeline scored against) — plus the ``rebaseline_reason`` recording *why* they differ (``"none"`` when equal). Both halves are populated for a Property with a real record of itself; the ``lodged`` half is ``None`` for a predicted Property, which has no lodged cert to read a Lodged Performance off — only the Effective half is established then (ADR-0004 amendment, #1361). Carries the part of the energy block that needs no derivation: annual ``space_heating_kwh`` / ``water_heating_kwh`` read off the EPC's RHI. Carries the derived ``bill`` (ADR-0014): the calculator's delivered kWh per end use priced at current Fuel Rates. It is ``None`` only when no calculator ran (the stub path produced no ``SapResult`` to price). """ lodged: Optional[Performance] effective: Performance rebaseline_reason: RebaselineReason space_heating_kwh: float water_heating_kwh: float bill: Optional[Bill] = None