Model/docs/migrations/property-baseline-performance-table.md
Khalim Conn-Kowlessar 3cad599fd1 refactor(property-baseline): units on co2 / PEUI columns (PR #1139 review)
Make the stored units explicit on the property_baseline_performance columns:
- `*_co2_emissions` → `*_co2_emissions_t_per_yr` (tonnes CO₂/yr, whole dwelling)
- `*_primary_energy_intensity` → `*_primary_energy_intensity_kwh_per_m2_yr`

Column names only; the domain `Performance` VO stays unit-suffix-free (units are
a storage concern, mapped in from_domain/to_domain). Migration doc updated.
Round-trip stays green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 14:57:00 +00:00

2.6 KiB

property_baseline_performance table — FE-owned migration

Context: Slice 6 (Hestia-Homes/Model#1135) of the ara_first_run rebuild. The PropertyBaselineOrchestrator establishes a Property's Baseline Performance (ADR-0004) and persists it via a new PropertyBaselineRepository port. This is a brand-new table — no predecessor.

Per ADR-0004's amendment, the lodged/effective pair does not land on property_details_epc (which is being retired as too coupled to the legacy EPC-API schema). It lands here, as its own aggregate's table.

The SQLModel row is defined in infrastructure/postgres/ so the ephemeral-Postgres tests build it via SQLModel.metadata.create_all. The production migration is FE-owned (Drizzle ORM) — a straight lift-and-shift of the columns below.

property_baseline_performance — one row per Property

Column Type Notes
id serial PK
property_id int, FK → property.id, unique one Baseline Performance per Property
lodged_sap_score int Lodged Performance — gov register, off the Effective EPC
lodged_epc_band text the Epc enum, stored as its string value (e.g. "C")
lodged_co2_emissions_t_per_yr float tonnes CO₂/yr (whole dwelling)
lodged_primary_energy_intensity_kwh_per_m2_yr int PEUI (kWh/m²/yr); not "heat demand" — see CONTEXT.md
effective_sap_score int Effective Performance — what modelling scored against
effective_epc_band text
effective_co2_emissions_t_per_yr float tonnes CO₂/yr (whole dwelling)
effective_primary_energy_intensity_kwh_per_m2_yr int kWh/m²/yr
rebaseline_reason text none | pre_sap10 | physical_state_changed | both
space_heating_kwh float off renewable_heat_incentive; deterministic (ADR-0006)
water_heating_kwh float off renewable_heat_incentive

This slice has no ML rebaselining, so effective_* == lodged_* and rebaseline_reason = 'none' for every row written (a pre-SAP10 cert raises rather than persisting a wrong-but-plausible row — see #1135). The effective_* columns exist now so the table shape is stable when ML lands.

Deferred (follow-up — EPC Energy Derivation + Fuel Rates)

fuel_split and bills are not in this table yet. They are produced by EpcEnergyDerivationService, which needs a current Fuel Rates source (Ofgem-cap ETL) that does not exist yet. They land together in the follow-up so this table is not migrated twice. Likely shape: a bills-style block (per-fuel kWh + standing charge + SEG) — to be specified in that slice's migration note.