Model/domain/property_baseline/property_baseline_performance.py
Khalim Conn-Kowlessar ced6287baa refactor(billing): relocate Bill Derivation to domain/billing/ (cross-stage)
Bill / EnergyBreakdown / BillDerivation / sap_fuel were under
domain/property_baseline/ only because Baseline was built first. The Modelling
stage now needs them too, so move them (and their tests) to a neutral
domain/billing/ — Fuel/FuelRates already live in the shared domain/fuel_rates/.
Avoids a modelling -> property_baseline cross-stage import and a package name
that wrongly implies ownership (ADR-0011, ADR-0014 amendment). Pure git mv +
import rewrite across 10 files; 40 billing/baseline/repo tests pass, pyright
strict clean. CONTEXT.md Bill Derivation location updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 17:19:23 +00:00

33 lines
1.2 KiB
Python

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 always populated, even when equal.
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: Performance
effective: Performance
rebaseline_reason: RebaselineReason
space_heating_kwh: float
water_heating_kwh: float
bill: Optional[Bill] = None