mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
fix(modelling): mirror the FE-owned property_baseline_performance columns
The SQLModel had drifted to a `bill_` prefix on the Bill Derivation block, but the FE-owned Drizzle table uses unprefixed names (`heating_kwh`, `hot_water_kwh` … `total_annual_bill_gbp`) plus a nullable `fuel_rates_period`. INSERTs failed with UndefinedColumn. Rename the columns to mirror the live table column-for- column (the prefix's anti-clash purpose is moot: `heating_kwh` != the recorded `space_heating_kwh`), and add the `fuel_rates_period` column — left None until Bill Derivation threads the snapshot period through. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
edf1003dcf
commit
c57ee578de
1 changed files with 34 additions and 29 deletions
|
|
@ -72,26 +72,31 @@ class PropertyBaselinePerformanceModel(SQLModel, table=True):
|
|||
space_heating_kwh: float
|
||||
water_heating_kwh: float
|
||||
|
||||
# The Fuel Rates snapshot period the bill was priced against (FE-owned column,
|
||||
# nullable). Not yet threaded through Bill Derivation, so left None for now.
|
||||
fuel_rates_period: Optional[str] = Field(default=None)
|
||||
|
||||
# Bill Derivation block (ADR-0014 §6). Nullable: all None when no calculator
|
||||
# ran (stub path). The ``bill_`` prefix avoids clashing with the
|
||||
# ran (stub path). Column names are unprefixed to mirror the FE-owned table —
|
||||
# the per-section ``heating_kwh`` / ``hot_water_kwh`` do not clash with the
|
||||
# recorded-demand ``space_heating_kwh`` / ``water_heating_kwh`` above.
|
||||
bill_heating_kwh: Optional[float] = Field(default=None)
|
||||
bill_heating_cost_gbp: Optional[float] = Field(default=None)
|
||||
bill_hot_water_kwh: Optional[float] = Field(default=None)
|
||||
bill_hot_water_cost_gbp: Optional[float] = Field(default=None)
|
||||
bill_lighting_kwh: Optional[float] = Field(default=None)
|
||||
bill_lighting_cost_gbp: Optional[float] = Field(default=None)
|
||||
bill_appliances_kwh: Optional[float] = Field(default=None)
|
||||
bill_appliances_cost_gbp: Optional[float] = Field(default=None)
|
||||
bill_cooking_kwh: Optional[float] = Field(default=None)
|
||||
bill_cooking_cost_gbp: Optional[float] = Field(default=None)
|
||||
bill_pumps_fans_kwh: Optional[float] = Field(default=None)
|
||||
bill_pumps_fans_cost_gbp: Optional[float] = Field(default=None)
|
||||
bill_cooling_kwh: Optional[float] = Field(default=None)
|
||||
bill_cooling_cost_gbp: Optional[float] = Field(default=None)
|
||||
bill_standing_charges_gbp: Optional[float] = Field(default=None)
|
||||
bill_seg_credit_gbp: Optional[float] = Field(default=None)
|
||||
bill_total_annual_bill_gbp: Optional[float] = Field(default=None)
|
||||
heating_kwh: Optional[float] = Field(default=None)
|
||||
heating_cost_gbp: Optional[float] = Field(default=None)
|
||||
hot_water_kwh: Optional[float] = Field(default=None)
|
||||
hot_water_cost_gbp: Optional[float] = Field(default=None)
|
||||
lighting_kwh: Optional[float] = Field(default=None)
|
||||
lighting_cost_gbp: Optional[float] = Field(default=None)
|
||||
appliances_kwh: Optional[float] = Field(default=None)
|
||||
appliances_cost_gbp: Optional[float] = Field(default=None)
|
||||
cooking_kwh: Optional[float] = Field(default=None)
|
||||
cooking_cost_gbp: Optional[float] = Field(default=None)
|
||||
pumps_fans_kwh: Optional[float] = Field(default=None)
|
||||
pumps_fans_cost_gbp: Optional[float] = Field(default=None)
|
||||
cooling_kwh: Optional[float] = Field(default=None)
|
||||
cooling_cost_gbp: Optional[float] = Field(default=None)
|
||||
standing_charges_gbp: Optional[float] = Field(default=None)
|
||||
seg_credit_gbp: Optional[float] = Field(default=None)
|
||||
total_annual_bill_gbp: Optional[float] = Field(default=None)
|
||||
|
||||
@classmethod
|
||||
def from_domain(
|
||||
|
|
@ -122,15 +127,15 @@ class PropertyBaselinePerformanceModel(SQLModel, table=True):
|
|||
return
|
||||
for section, stem in _SECTION_COLUMN_STEM.items():
|
||||
cost = bill.sections.get(section)
|
||||
setattr(self, f"bill_{stem}_kwh", cost.kwh if cost is not None else None)
|
||||
setattr(self, f"{stem}_kwh", cost.kwh if cost is not None else None)
|
||||
setattr(
|
||||
self,
|
||||
f"bill_{stem}_cost_gbp",
|
||||
f"{stem}_cost_gbp",
|
||||
cost.cost_gbp if cost is not None else None,
|
||||
)
|
||||
self.bill_standing_charges_gbp = bill.standing_charges_gbp
|
||||
self.bill_seg_credit_gbp = bill.seg_credit_gbp
|
||||
self.bill_total_annual_bill_gbp = bill.total_gbp
|
||||
self.standing_charges_gbp = bill.standing_charges_gbp
|
||||
self.seg_credit_gbp = bill.seg_credit_gbp
|
||||
self.total_annual_bill_gbp = bill.total_gbp
|
||||
|
||||
def to_domain(self) -> PropertyBaselinePerformance:
|
||||
return PropertyBaselinePerformance(
|
||||
|
|
@ -157,18 +162,18 @@ class PropertyBaselinePerformanceModel(SQLModel, table=True):
|
|||
not-None discriminator: a persisted bill always sets it, so its absence
|
||||
means no calculator ran and the bill was None. A section is rebuilt only
|
||||
when its kWh column is not None (paired with its cost)."""
|
||||
if self.bill_total_annual_bill_gbp is None:
|
||||
if self.total_annual_bill_gbp is None:
|
||||
return None
|
||||
sections: dict[BillSection, BillSectionCost] = {}
|
||||
for section, stem in _SECTION_COLUMN_STEM.items():
|
||||
kwh = cast(Optional[float], getattr(self, f"bill_{stem}_kwh"))
|
||||
kwh = cast(Optional[float], getattr(self, f"{stem}_kwh"))
|
||||
if kwh is None:
|
||||
continue
|
||||
cost_gbp = cast(float, getattr(self, f"bill_{stem}_cost_gbp"))
|
||||
cost_gbp = cast(float, getattr(self, f"{stem}_cost_gbp"))
|
||||
sections[section] = BillSectionCost(kwh=kwh, cost_gbp=cost_gbp)
|
||||
return Bill(
|
||||
sections=sections,
|
||||
standing_charges_gbp=cast(float, self.bill_standing_charges_gbp),
|
||||
seg_credit_gbp=cast(float, self.bill_seg_credit_gbp),
|
||||
total_gbp=self.bill_total_annual_bill_gbp,
|
||||
standing_charges_gbp=cast(float, self.standing_charges_gbp),
|
||||
seg_credit_gbp=cast(float, self.seg_credit_gbp),
|
||||
total_gbp=self.total_annual_bill_gbp,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue