mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-08 11:37:25 +00:00
Add EPC round-trip fidelity fixes and property_baseline_performance table to Drizzle schema
This commit is contained in:
parent
84aeeff117
commit
5553fee32e
1 changed files with 132 additions and 25 deletions
|
|
@ -10,6 +10,7 @@ import {
|
|||
smallint,
|
||||
bigint,
|
||||
uniqueIndex,
|
||||
jsonb,
|
||||
} from "drizzle-orm/pg-core";
|
||||
import { portfolio, PortfolioStatus } from "./portfolio";
|
||||
import { InferModel } from "drizzle-orm";
|
||||
|
|
@ -514,25 +515,25 @@ export const epcProperty = pgTable(
|
|||
energyIsDwellingExportCapable: boolean("energy_is_dwelling_export_capable").notNull(),
|
||||
energyWindTurbinesTerrainType: text("energy_wind_turbines_terrain_type").notNull(),
|
||||
energyElectricitySmartMeterPresent: boolean("energy_electricity_smart_meter_present").notNull(),
|
||||
energyPvConnection: text("energy_pv_connection"),
|
||||
energyPvConnection: jsonb("energy_pv_connection"),
|
||||
energyPvPercentRoofArea: integer("energy_pv_percent_roof_area"),
|
||||
energyPvBatteryCapacity: real("energy_pv_battery_capacity"),
|
||||
energyWindTurbineHubHeight: real("energy_wind_turbine_hub_height"),
|
||||
energyWindTurbineRotorDiameter: real("energy_wind_turbine_rotor_diameter"),
|
||||
|
||||
// Heating config
|
||||
heatingCylinderSize: text("heating_cylinder_size"),
|
||||
heatingCylinderSize: jsonb("heating_cylinder_size"),
|
||||
heatingWaterHeatingCode: integer("heating_water_heating_code"),
|
||||
heatingWaterHeatingFuel: integer("heating_water_heating_fuel"),
|
||||
heatingImmersionHeatingType: text("heating_immersion_heating_type"),
|
||||
heatingCylinderInsulationType: text("heating_cylinder_insulation_type"),
|
||||
heatingImmersionHeatingType: jsonb("heating_immersion_heating_type"),
|
||||
heatingCylinderInsulationType: jsonb("heating_cylinder_insulation_type"),
|
||||
heatingCylinderThermostat: text("heating_cylinder_thermostat"),
|
||||
heatingSecondaryFuelType: integer("heating_secondary_fuel_type"),
|
||||
heatingSecondaryHeatingType: text("heating_secondary_heating_type"),
|
||||
heatingSecondaryHeatingType: jsonb("heating_secondary_heating_type"),
|
||||
heatingCylinderInsulationThicknessMm: integer("heating_cylinder_insulation_thickness_mm"),
|
||||
heatingWwhrsIndexNumber1: integer("heating_wwhrs_index_number_1"),
|
||||
heatingWwhrsIndexNumber2: integer("heating_wwhrs_index_number_2"),
|
||||
heatingShowerOutletType: text("heating_shower_outlet_type"),
|
||||
heatingShowerOutletType: jsonb("heating_shower_outlet_type"),
|
||||
heatingShowerWwhrs: integer("heating_shower_wwhrs"),
|
||||
|
||||
// Ventilation
|
||||
|
|
@ -553,6 +554,27 @@ export const epcProperty = pgTable(
|
|||
mechanicalVentDuctInsulation: integer("mechanical_vent_duct_insulation"),
|
||||
mechanicalVentilationIndexNumber: integer("mechanical_ventilation_index_number"),
|
||||
mechanicalVentMeasuredInstallation: text("mechanical_vent_measured_installation"),
|
||||
mechanicalVentDuctInsulationLevel: integer("mechanical_vent_duct_insulation_level"),
|
||||
|
||||
// Addendum flags
|
||||
addendumStoneWalls: boolean("addendum_stone_walls"),
|
||||
addendumSystemBuild: boolean("addendum_system_build"),
|
||||
addendumNumbers: jsonb("addendum_numbers"),
|
||||
|
||||
// Heating counts
|
||||
heatingNumberBaths: integer("heating_number_baths"),
|
||||
heatingNumberBathsWwhrs: integer("heating_number_baths_wwhrs"),
|
||||
heatingElectricShowerCount: integer("heating_electric_shower_count"),
|
||||
heatingMixerShowerCount: integer("heating_mixer_shower_count"),
|
||||
|
||||
// Ventilation detail
|
||||
ventilationPresent: boolean("ventilation_present").notNull().default(false),
|
||||
ventilationShelteredSides: integer("ventilation_sheltered_sides"),
|
||||
ventilationHasSuspendedTimberFloor: boolean("ventilation_has_suspended_timber_floor"),
|
||||
ventilationSuspendedTimberFloorSealed: boolean("ventilation_suspended_timber_floor_sealed"),
|
||||
ventilationHasDraughtLobby: boolean("ventilation_has_draught_lobby"),
|
||||
ventilationAirPermeabilityAp4M3HM2: real("ventilation_air_permeability_ap4_m3_h_m2"),
|
||||
ventilationMechanicalVentilationKind: text("ventilation_mechanical_ventilation_kind"),
|
||||
},
|
||||
(table) => [
|
||||
uniqueIndex("uq_epc_property_property_portfolio").on(
|
||||
|
|
@ -627,10 +649,10 @@ export const epcMainHeatingDetail = pgTable(
|
|||
.references(() => epcProperty.id),
|
||||
|
||||
hasFghrs: boolean("has_fghrs").notNull(),
|
||||
mainFuelType: text("main_fuel_type").notNull(),
|
||||
heatEmitterType: text("heat_emitter_type").notNull(),
|
||||
emitterTemperature: text("emitter_temperature").notNull(),
|
||||
mainHeatingControl: text("main_heating_control").notNull(),
|
||||
mainFuelType: jsonb("main_fuel_type").notNull(),
|
||||
heatEmitterType: jsonb("heat_emitter_type").notNull(),
|
||||
emitterTemperature: jsonb("emitter_temperature").notNull(),
|
||||
mainHeatingControl: jsonb("main_heating_control").notNull(),
|
||||
fanFluePresent: boolean("fan_flue_present"),
|
||||
boilerFlueType: integer("boiler_flue_type"),
|
||||
boilerIgnitionType: integer("boiler_ignition_type"),
|
||||
|
|
@ -661,10 +683,10 @@ export const epcBuildingPart = pgTable(
|
|||
constructionAgeBand: text("construction_age_band").notNull(),
|
||||
|
||||
// Wall
|
||||
wallConstruction: text("wall_construction").notNull(),
|
||||
wallInsulationType: text("wall_insulation_type").notNull(),
|
||||
wallConstruction: jsonb("wall_construction").notNull(),
|
||||
wallInsulationType: jsonb("wall_insulation_type").notNull(),
|
||||
wallThicknessMeasured: boolean("wall_thickness_measured").notNull(),
|
||||
partyWallConstruction: text("party_wall_construction").notNull(),
|
||||
partyWallConstruction: jsonb("party_wall_construction"),
|
||||
buildingPartNumber: integer("building_part_number"),
|
||||
wallDryLined: boolean("wall_dry_lined"),
|
||||
wallThicknessMm: integer("wall_thickness_mm"),
|
||||
|
|
@ -674,7 +696,7 @@ export const epcBuildingPart = pgTable(
|
|||
// Floor
|
||||
floorHeatLoss: integer("floor_heat_loss"),
|
||||
floorInsulationThickness: text("floor_insulation_thickness"),
|
||||
flatRoofInsulationThickness: text("flat_roof_insulation_thickness"),
|
||||
flatRoofInsulationThickness: jsonb("flat_roof_insulation_thickness"),
|
||||
floorType: text("floor_type"),
|
||||
floorConstructionType: text("floor_construction_type"),
|
||||
floorInsulationTypeStr: text("floor_insulation_type_str"),
|
||||
|
|
@ -682,8 +704,11 @@ export const epcBuildingPart = pgTable(
|
|||
|
||||
// Roof
|
||||
roofConstruction: integer("roof_construction"),
|
||||
roofInsulationLocation: text("roof_insulation_location"),
|
||||
roofInsulationThickness: text("roof_insulation_thickness"),
|
||||
roofInsulationLocation: jsonb("roof_insulation_location"),
|
||||
roofInsulationThickness: jsonb("roof_insulation_thickness"),
|
||||
|
||||
roofConstructionType: text("roof_construction_type"),
|
||||
curtainWallAge: text("curtain_wall_age"),
|
||||
|
||||
// Room in roof (inlined)
|
||||
roomInRoofFloorArea: real("room_in_roof_floor_area"),
|
||||
|
|
@ -737,23 +762,23 @@ export const epcWindow = pgTable(
|
|||
.notNull()
|
||||
.references(() => epcProperty.id),
|
||||
|
||||
glazingGap: text("glazing_gap").notNull(),
|
||||
orientation: text("orientation").notNull(),
|
||||
windowType: text("window_type").notNull(),
|
||||
glazingType: text("glazing_type").notNull(),
|
||||
glazingGap: jsonb("glazing_gap").notNull(),
|
||||
orientation: jsonb("orientation").notNull(),
|
||||
windowType: jsonb("window_type").notNull(),
|
||||
glazingType: jsonb("glazing_type").notNull(),
|
||||
windowWidth: real("window_width").notNull(), // add unit?
|
||||
windowHeight: real("window_height").notNull(), // add unit?
|
||||
draughtProofed: boolean("draught_proofed").notNull(),
|
||||
windowLocation: text("window_location").notNull(),
|
||||
windowWallType: text("window_wall_type").notNull(),
|
||||
permanentShuttersPresent: boolean("permanent_shutters_present").notNull(),
|
||||
draughtProofed: jsonb("draught_proofed").notNull(),
|
||||
windowLocation: jsonb("window_location").notNull(),
|
||||
windowWallType: jsonb("window_wall_type").notNull(),
|
||||
permanentShuttersPresent: jsonb("permanent_shutters_present").notNull(),
|
||||
frameMaterial: text("frame_material"),
|
||||
frameFactor: real("frame_factor"),
|
||||
permanentShuttersInsulated: text("permanent_shutters_insulated"),
|
||||
|
||||
// Transmission details (inlined)
|
||||
transmissionUValue: real("transmission_u_value"),
|
||||
transmissionDataSource: text("transmission_data_source"),
|
||||
transmissionDataSource: jsonb("transmission_data_source"),
|
||||
transmissionSolarTransmittance: real("transmission_solar_transmittance"),
|
||||
},
|
||||
);
|
||||
|
|
@ -773,4 +798,86 @@ export const epcEnergyElement = pgTable(
|
|||
energyEfficiencyRating: integer("energy_efficiency_rating").notNull(),
|
||||
environmentalEfficiencyRating: integer("environmental_efficiency_rating").notNull(),
|
||||
},
|
||||
);
|
||||
|
||||
// ─── epc_renewable_heat_incentive ─────────────────────────────────────────────
|
||||
|
||||
export const epcRenewableHeatIncentive = pgTable(
|
||||
"epc_renewable_heat_incentive",
|
||||
{
|
||||
id: bigserial("id", { mode: "bigint" }).primaryKey(),
|
||||
epcPropertyId: bigint("epc_property_id", { mode: "bigint" })
|
||||
.notNull()
|
||||
.unique()
|
||||
.references(() => epcProperty.id),
|
||||
spaceHeatingKwh: real("space_heating_kwh").notNull(),
|
||||
waterHeatingKwh: real("water_heating_kwh").notNull(),
|
||||
impactOfLoftInsulationKwh: real("impact_of_loft_insulation_kwh"),
|
||||
impactOfCavityInsulationKwh: real("impact_of_cavity_insulation_kwh"),
|
||||
impactOfSolidWallInsulationKwh: real("impact_of_solid_wall_insulation_kwh"),
|
||||
},
|
||||
);
|
||||
|
||||
// ─── property_baseline_performance ────────────────────────────────────────────
|
||||
|
||||
export const rebaselineReasonEnum = pgEnum("rebaseline_reason", [
|
||||
"none",
|
||||
"pre_sap10",
|
||||
"physical_state_changed",
|
||||
"both",
|
||||
]);
|
||||
|
||||
export const propertyBaselinePerformance = pgTable(
|
||||
"property_baseline_performance",
|
||||
{
|
||||
id: bigserial("id", { mode: "bigint" }).primaryKey(),
|
||||
propertyId: bigint("property_id", { mode: "bigint" })
|
||||
.notNull()
|
||||
.unique()
|
||||
.references(() => property.id),
|
||||
|
||||
// Lodged performance (from gov EPC register)
|
||||
lodgedSapScore: integer("lodged_sap_score").notNull(),
|
||||
lodgedEpcBand: epcEnum("lodged_epc_band").notNull(),
|
||||
lodgedCo2EmissionsTPerYr: real("lodged_co2_emissions_t_per_yr").notNull(),
|
||||
lodgedPrimaryEnergyIntensityKwhPerM2Yr: integer(
|
||||
"lodged_primary_energy_intensity_kwh_per_m2_yr",
|
||||
).notNull(),
|
||||
|
||||
// Effective performance (what modelling scored against)
|
||||
effectiveSapScore: integer("effective_sap_score").notNull(),
|
||||
effectiveEpcBand: epcEnum("effective_epc_band").notNull(),
|
||||
effectiveCo2EmissionsTPerYr: real(
|
||||
"effective_co2_emissions_t_per_yr",
|
||||
).notNull(),
|
||||
effectivePrimaryEnergyIntensityKwhPerM2Yr: integer(
|
||||
"effective_primary_energy_intensity_kwh_per_m2_yr",
|
||||
).notNull(),
|
||||
|
||||
rebaselineReason: rebaselineReasonEnum("rebaseline_reason").notNull(),
|
||||
|
||||
// Interim energy demand (from EPC RHI data; superseded by bill block below once populated)
|
||||
spaceHeatingKwh: real("space_heating_kwh").notNull(),
|
||||
waterHeatingKwh: real("water_heating_kwh").notNull(),
|
||||
|
||||
// Bill block — nullable until BillDerivation wiring lands
|
||||
fuelRatesPeriod: text("fuel_rates_period"),
|
||||
heatingKwh: real("heating_kwh"),
|
||||
heatingCostGbp: real("heating_cost_gbp"),
|
||||
hotWaterKwh: real("hot_water_kwh"),
|
||||
hotWaterCostGbp: real("hot_water_cost_gbp"),
|
||||
lightingKwh: real("lighting_kwh"),
|
||||
lightingCostGbp: real("lighting_cost_gbp"),
|
||||
appliancesKwh: real("appliances_kwh"),
|
||||
appliancesCostGbp: real("appliances_cost_gbp"),
|
||||
cookingKwh: real("cooking_kwh"),
|
||||
cookingCostGbp: real("cooking_cost_gbp"),
|
||||
pumpsFansKwh: real("pumps_fans_kwh"),
|
||||
pumpsFansCostGbp: real("pumps_fans_cost_gbp"),
|
||||
coolingKwh: real("cooling_kwh"),
|
||||
coolingCostGbp: real("cooling_cost_gbp"),
|
||||
standingChargesGbp: real("standing_charges_gbp"),
|
||||
segCreditGbp: real("seg_credit_gbp"),
|
||||
totalAnnualBillGbp: real("total_annual_bill_gbp"),
|
||||
},
|
||||
);
|
||||
Loading…
Add table
Reference in a new issue