Merge pull request #240 from Hestia-Homes/feature/new-epc-tables

New EPC tables
This commit is contained in:
Daniel Roth 2026-04-24 11:29:59 +01:00 committed by GitHub
commit 06c2e83404
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 9252 additions and 0 deletions

View file

@ -0,0 +1,261 @@
CREATE TYPE "public"."energy_element_type" AS ENUM('roof', 'wall', 'floor', 'main_heating', 'window', 'lighting', 'hot_water', 'secondary_heating', 'main_heating_controls');--> statement-breakpoint
CREATE TABLE "epc_building_part" (
"id" bigserial PRIMARY KEY NOT NULL,
"epc_property_id" bigint NOT NULL,
"identifier" text NOT NULL,
"construction_age_band" text NOT NULL,
"wall_construction" text NOT NULL,
"wall_insulation_type" text NOT NULL,
"wall_thickness_measured" boolean NOT NULL,
"party_wall_construction" text NOT NULL,
"building_part_number" integer,
"wall_dry_lined" boolean,
"wall_thickness_mm" integer,
"wall_insulation_thickness" text,
"floor_heat_loss" integer,
"floor_insulation_thickness" text,
"flat_roof_insulation_thickness" text,
"floor_type" text,
"floor_construction_type" text,
"floor_insulation_type_str" text,
"floor_u_value_known" boolean,
"roof_construction" integer,
"roof_insulation_location" text,
"roof_insulation_thickness" text,
"room_in_roof_floor_area" real,
"room_in_roof_construction_age_band" text,
"alt_wall_1_area" real,
"alt_wall_1_dry_lined" text,
"alt_wall_1_construction" integer,
"alt_wall_1_insulation_type" integer,
"alt_wall_1_thickness_measured" text,
"alt_wall_1_insulation_thickness" text,
"alt_wall_2_area" real,
"alt_wall_2_dry_lined" text,
"alt_wall_2_construction" integer,
"alt_wall_2_insulation_type" integer,
"alt_wall_2_thickness_measured" text,
"alt_wall_2_insulation_thickness" text
);
--> statement-breakpoint
CREATE TABLE "epc_energy_element" (
"id" bigserial PRIMARY KEY NOT NULL,
"epc_property_id" bigint NOT NULL,
"element_type" "energy_element_type" NOT NULL,
"description" text NOT NULL,
"energy_efficiency_rating" integer NOT NULL,
"environmental_efficiency_rating" integer NOT NULL
);
--> statement-breakpoint
CREATE TABLE "epc_flat_details" (
"id" bigserial PRIMARY KEY NOT NULL,
"epc_property_id" bigint NOT NULL,
"level" integer NOT NULL,
"top_storey" text NOT NULL,
"flat_location" integer NOT NULL,
"heat_loss_corridor" integer NOT NULL,
"storey_count" integer,
"unheated_corridor_length_m" integer,
CONSTRAINT "epc_flat_details_epc_property_id_unique" UNIQUE("epc_property_id")
);
--> statement-breakpoint
CREATE TABLE "epc_floor_dimension" (
"id" bigserial PRIMARY KEY NOT NULL,
"epc_building_part_id" bigint NOT NULL,
"floor" integer,
"room_height_m" real NOT NULL,
"total_floor_area_m2" real NOT NULL,
"party_wall_length_m" real NOT NULL,
"heat_loss_perimeter_m" real NOT NULL,
"floor_insulation" integer,
"floor_construction" integer
);
--> statement-breakpoint
CREATE TABLE "epc_main_heating_detail" (
"id" bigserial PRIMARY KEY NOT NULL,
"epc_property_id" bigint NOT NULL,
"has_fghrs" boolean NOT NULL,
"main_fuel_type" text NOT NULL,
"heat_emitter_type" text NOT NULL,
"emitter_temperature" text NOT NULL,
"main_heating_control" text NOT NULL,
"fan_flue_present" boolean,
"boiler_flue_type" integer,
"boiler_ignition_type" integer,
"central_heating_pump_age" integer,
"central_heating_pump_age_str" text,
"main_heating_index_number" integer,
"sap_main_heating_code" integer,
"main_heating_number" integer,
"main_heating_category" integer,
"main_heating_fraction" integer,
"main_heating_data_source" integer,
"condensing" boolean,
"weather_compensator" boolean
);
--> statement-breakpoint
CREATE TABLE "epc_property" (
"id" bigserial PRIMARY KEY NOT NULL,
"property_id" bigint NOT NULL,
"portfolio_id" bigint NOT NULL,
"uprn" bigint,
"uprn_source" text,
"report_reference" text,
"report_type" text,
"assessment_type" text,
"sap_version" real,
"schema_type" text,
"schema_versions_original" text,
"status" text,
"calculation_software_version" text,
"address_line_1" text,
"address_line_2" text,
"post_town" text,
"postcode" text,
"region_code" text,
"country_code" text,
"language_code" text,
"dwelling_type" text NOT NULL,
"property_type" text,
"built_form" text,
"tenure" text NOT NULL,
"transaction_type" text NOT NULL,
"inspection_date" timestamp NOT NULL,
"completion_date" timestamp,
"registration_date" timestamp,
"total_floor_area_m2" real NOT NULL,
"measurement_type" integer,
"solar_water_heating" boolean NOT NULL,
"has_hot_water_cylinder" boolean NOT NULL,
"has_fixed_air_conditioning" boolean NOT NULL,
"has_conservatory" boolean,
"has_heated_separate_conservatory" boolean,
"conservatory_type" integer,
"door_count" integer NOT NULL,
"wet_rooms_count" integer NOT NULL,
"extensions_count" integer NOT NULL,
"heated_rooms_count" integer NOT NULL,
"open_chimneys_count" integer NOT NULL,
"habitable_rooms_count" integer NOT NULL,
"insulated_door_count" integer NOT NULL,
"cfl_fixed_lighting_bulbs_count" integer NOT NULL,
"led_fixed_lighting_bulbs_count" integer NOT NULL,
"incandescent_fixed_lighting_bulbs_count" integer NOT NULL,
"blocked_chimneys_count" integer,
"draughtproofed_door_count" integer,
"energy_rating_average" integer,
"low_energy_fixed_lighting_bulbs_count" integer,
"fixed_lighting_outlets_count" integer,
"low_energy_fixed_lighting_outlets_count" integer,
"number_of_storeys" integer,
"any_unheated_rooms" boolean,
"hydro" boolean,
"photovoltaic_array" boolean,
"waste_water_heat_recovery" text,
"pressure_test" integer,
"pressure_test_certificate_number" integer,
"percent_draughtproofed" integer,
"insulated_door_u_value" real,
"multiple_glazed_proportion" integer,
"windows_transmission_u_value" real,
"windows_transmission_data_source" integer,
"windows_transmission_solar_transmittance" real,
"energy_mains_gas" boolean NOT NULL,
"energy_meter_type" text NOT NULL,
"energy_pv_battery_count" integer NOT NULL,
"energy_wind_turbines_count" integer NOT NULL,
"energy_gas_smart_meter_present" boolean NOT NULL,
"energy_is_dwelling_export_capable" boolean NOT NULL,
"energy_wind_turbines_terrain_type" text NOT NULL,
"energy_electricity_smart_meter_present" boolean NOT NULL,
"energy_pv_connection" text,
"energy_pv_percent_roof_area" integer,
"energy_pv_battery_capacity" real,
"energy_wind_turbine_hub_height" real,
"energy_wind_turbine_rotor_diameter" real,
"heating_cylinder_size" text,
"heating_water_heating_code" integer,
"heating_water_heating_fuel" integer,
"heating_immersion_heating_type" text,
"heating_cylinder_insulation_type" text,
"heating_cylinder_thermostat" text,
"heating_secondary_fuel_type" integer,
"heating_secondary_heating_type" text,
"heating_cylinder_insulation_thickness_mm" integer,
"heating_wwhrs_index_number_1" integer,
"heating_wwhrs_index_number_2" integer,
"heating_shower_outlet_type" text,
"heating_shower_wwhrs" integer,
"ventilation_type" text,
"ventilation_draught_lobby" boolean,
"ventilation_pressure_test" text,
"ventilation_open_flues_count" integer,
"ventilation_closed_flues_count" integer,
"ventilation_boiler_flues_count" integer,
"ventilation_other_flues_count" integer,
"ventilation_extract_fans_count" integer,
"ventilation_passive_vents_count" integer,
"ventilation_flueless_gas_fires_count" integer,
"ventilation_in_pcdf_database" boolean,
"mechanical_ventilation" integer,
"mechanical_vent_duct_type" integer,
"mechanical_vent_duct_placement" integer,
"mechanical_vent_duct_insulation" integer,
"mechanical_ventilation_index_number" integer,
"mechanical_vent_measured_installation" text
);
--> statement-breakpoint
CREATE TABLE "epc_property_energy_performance" (
"id" bigserial PRIMARY KEY NOT NULL,
"epc_property_id" bigint NOT NULL,
"energy_rating_current" integer,
"energy_consumption_current" integer,
"environmental_impact_current" integer,
"heating_cost_current" real,
"lighting_cost_current" real,
"hot_water_cost_current" real,
"co2_emissions_current" real,
"co2_emissions_current_per_floor_area" integer,
"current_energy_efficiency_band" text,
"energy_rating_potential" real,
"energy_consumption_potential" integer,
"environmental_impact_potential" integer,
"heating_cost_potential" real,
"lighting_cost_potential" real,
"hot_water_cost_potential" real,
"co2_emissions_potential" real,
"potential_energy_efficiency_band" text,
CONSTRAINT "epc_property_energy_performance_epc_property_id_unique" UNIQUE("epc_property_id")
);
--> statement-breakpoint
CREATE TABLE "epc_window" (
"id" bigserial PRIMARY KEY NOT NULL,
"epc_property_id" bigint NOT NULL,
"pvc_frame" text NOT NULL,
"glazing_gap" text NOT NULL,
"orientation" text NOT NULL,
"window_type" text NOT NULL,
"glazing_type" text NOT NULL,
"window_width" real NOT NULL,
"window_height" real NOT NULL,
"draught_proofed" boolean NOT NULL,
"window_location" text NOT NULL,
"window_wall_type" text NOT NULL,
"permanent_shutters_present" boolean NOT NULL,
"frame_factor" real,
"permanent_shutters_insulated" text,
"transmission_u_value" real,
"transmission_data_source" integer,
"transmission_solar_transmittance" real
);
--> statement-breakpoint
ALTER TABLE "epc_building_part" ADD CONSTRAINT "epc_building_part_epc_property_id_epc_property_id_fk" FOREIGN KEY ("epc_property_id") REFERENCES "public"."epc_property"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "epc_energy_element" ADD CONSTRAINT "epc_energy_element_epc_property_id_epc_property_id_fk" FOREIGN KEY ("epc_property_id") REFERENCES "public"."epc_property"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "epc_flat_details" ADD CONSTRAINT "epc_flat_details_epc_property_id_epc_property_id_fk" FOREIGN KEY ("epc_property_id") REFERENCES "public"."epc_property"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "epc_floor_dimension" ADD CONSTRAINT "epc_floor_dimension_epc_building_part_id_epc_building_part_id_fk" FOREIGN KEY ("epc_building_part_id") REFERENCES "public"."epc_building_part"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "epc_main_heating_detail" ADD CONSTRAINT "epc_main_heating_detail_epc_property_id_epc_property_id_fk" FOREIGN KEY ("epc_property_id") REFERENCES "public"."epc_property"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "epc_property" ADD CONSTRAINT "epc_property_property_id_property_id_fk" FOREIGN KEY ("property_id") REFERENCES "public"."property"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "epc_property" ADD CONSTRAINT "epc_property_portfolio_id_portfolio_id_fk" FOREIGN KEY ("portfolio_id") REFERENCES "public"."portfolio"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "epc_property_energy_performance" ADD CONSTRAINT "epc_property_energy_performance_epc_property_id_epc_property_id_fk" FOREIGN KEY ("epc_property_id") REFERENCES "public"."epc_property"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "epc_window" ADD CONSTRAINT "epc_window_epc_property_id_epc_property_id_fk" FOREIGN KEY ("epc_property_id") REFERENCES "public"."epc_property"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "uq_epc_property_property_portfolio" ON "epc_property" USING btree ("property_id","portfolio_id");

File diff suppressed because it is too large Load diff

View file

@ -1289,6 +1289,13 @@
"when": 1776947867497,
"tag": "0183_careless_darkhawk",
"breakpoints": true
},
{
"idx": 184,
"version": "7",
"when": 1776962910255,
"tag": "0184_tiny_annihilus",
"breakpoints": true
}
]
}

View file

@ -401,3 +401,371 @@ export interface NonIntrusiveSurveyData {
surveyor: string;
notes: { title: string; note: string }[];
}
// ─── Enums ────────────────────────────────────────────────────────────────────
export const energyElementTypeEnum = pgEnum("energy_element_type", [
"roof", "wall", "floor", "main_heating", "window",
"lighting", "hot_water", "secondary_heating", "main_heating_controls",
]);
// ─── epc_property ─────────────────────────────────────────────────────────────
export const epcProperty = pgTable(
"epc_property",
{
id: bigserial("id", { mode: "bigint" }).primaryKey(),
propertyId: bigint("property_id", { mode: "bigint" })
.notNull()
.references(() => property.id),
portfolioId: bigint("portfolio_id", { mode: "bigint" })
.notNull()
.references(() => portfolio.id),
// Identity / admin
uprn: bigint("uprn", { mode: "bigint" }),
uprnSource: text("uprn_source"),
reportReference: text("report_reference"),
reportType: text("report_type"),
assessmentType: text("assessment_type"),
sapVersion: real("sap_version"),
schemaType: text("schema_type"),
schemaVersionsOriginal: text("schema_versions_original"),
status: text("status"),
calculationSoftwareVersion: text("calculation_software_version"),
// Address
addressLine1: text("address_line_1"),
addressLine2: text("address_line_2"),
postTown: text("post_town"),
postcode: text("postcode"),
regionCode: text("region_code"),
countryCode: text("country_code"),
languageCode: text("language_code"),
// Property description
dwellingType: text("dwelling_type").notNull(),
propertyType: text("property_type"),
builtForm: text("built_form"),
tenure: text("tenure").notNull(),
transactionType: text("transaction_type").notNull(),
// Dates
inspectionDate: timestamp("inspection_date").notNull(),
completionDate: timestamp("completion_date"),
registrationDate: timestamp("registration_date"),
// Measurements
totalFloorAreaM2: real("total_floor_area_m2").notNull(),
measurementType: integer("measurement_type"),
// Flags
solarWaterHeating: boolean("solar_water_heating").notNull(),
hasHotWaterCylinder: boolean("has_hot_water_cylinder").notNull(),
hasFixedAirConditioning: boolean("has_fixed_air_conditioning").notNull(),
hasConservatory: boolean("has_conservatory"),
hasHeatedSeparateConservatory: boolean("has_heated_separate_conservatory"),
conservatoryType: integer("conservatory_type"),
// Counts
doorCount: integer("door_count").notNull(),
wetRoomsCount: integer("wet_rooms_count").notNull(),
extensionsCount: integer("extensions_count").notNull(),
heatedRoomsCount: integer("heated_rooms_count").notNull(),
openChimneysCount: integer("open_chimneys_count").notNull(),
habitableRoomsCount: integer("habitable_rooms_count").notNull(),
insulatedDoorCount: integer("insulated_door_count").notNull(),
cflFixedLightingBulbsCount: integer("cfl_fixed_lighting_bulbs_count").notNull(),
ledFixedLightingBulbsCount: integer("led_fixed_lighting_bulbs_count").notNull(),
incandescentFixedLightingBulbsCount: integer("incandescent_fixed_lighting_bulbs_count").notNull(),
blockedChimneysCount: integer("blocked_chimneys_count"),
draughtproofedDoorCount: integer("draughtproofed_door_count"),
energyRatingAverage: integer("energy_rating_average"),
lowEnergyFixedLightingBulbsCount: integer("low_energy_fixed_lighting_bulbs_count"),
fixedLightingOutletsCount: integer("fixed_lighting_outlets_count"),
lowEnergyFixedLightingOutletsCount: integer("low_energy_fixed_lighting_outlets_count"),
numberOfStoreys: integer("number_of_storeys"),
anyUnheatedRooms: boolean("any_unheated_rooms"),
// Misc
hydro: boolean("hydro"),
photovoltaicArray: boolean("photovoltaic_array"),
wasteWaterHeatRecovery: text("waste_water_heat_recovery"),
pressureTest: integer("pressure_test"),
pressureTestCertificateNumber: integer("pressure_test_certificate_number"),
percentDraughtproofed: integer("percent_draughtproofed"),
insulatedDoorUValue: real("insulated_door_u_value"),
multipleGlazedProportion: integer("multiple_glazed_proportion"),
windowsTransmissionUValue: real("windows_transmission_u_value"),
windowsTransmissionDataSource: integer("windows_transmission_data_source"),
windowsTransmissionSolarTransmittance: real("windows_transmission_solar_transmittance"),
// Energy source
energyMainsGas: boolean("energy_mains_gas").notNull(),
energyMeterType: text("energy_meter_type").notNull(),
energyPvBatteryCount: integer("energy_pv_battery_count").notNull(),
energyWindTurbinesCount: integer("energy_wind_turbines_count").notNull(),
energyGasSmartMeterPresent: boolean("energy_gas_smart_meter_present").notNull(),
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"),
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"),
heatingWaterHeatingCode: integer("heating_water_heating_code"),
heatingWaterHeatingFuel: integer("heating_water_heating_fuel"),
heatingImmersionHeatingType: text("heating_immersion_heating_type"),
heatingCylinderInsulationType: text("heating_cylinder_insulation_type"),
heatingCylinderThermostat: text("heating_cylinder_thermostat"),
heatingSecondaryFuelType: integer("heating_secondary_fuel_type"),
heatingSecondaryHeatingType: text("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"),
heatingShowerWwhrs: integer("heating_shower_wwhrs"),
// Ventilation
ventilationType: text("ventilation_type"),
ventilationDraughtLobby: boolean("ventilation_draught_lobby"),
ventilationPressureTest: text("ventilation_pressure_test"),
ventilationOpenFluesCount: integer("ventilation_open_flues_count"),
ventilationClosedFluesCount: integer("ventilation_closed_flues_count"),
ventilationBoilerFluesCount: integer("ventilation_boiler_flues_count"),
ventilationOtherFluesCount: integer("ventilation_other_flues_count"),
ventilationExtractFansCount: integer("ventilation_extract_fans_count"),
ventilationPassiveVentsCount: integer("ventilation_passive_vents_count"),
ventilationFluelessGasFiresCount: integer("ventilation_flueless_gas_fires_count"),
ventilationInPcdfDatabase: boolean("ventilation_in_pcdf_database"),
mechanicalVentilation: integer("mechanical_ventilation"),
mechanicalVentDuctType: integer("mechanical_vent_duct_type"),
mechanicalVentDuctPlacement: integer("mechanical_vent_duct_placement"),
mechanicalVentDuctInsulation: integer("mechanical_vent_duct_insulation"),
mechanicalVentilationIndexNumber: integer("mechanical_ventilation_index_number"),
mechanicalVentMeasuredInstallation: text("mechanical_vent_measured_installation"),
},
(table) => [
uniqueIndex("uq_epc_property_property_portfolio").on(
table.propertyId,
table.portfolioId,
),
],
);
// ─── epc_property_energy_performance ─────────────────────────────────────────
export const epcPropertyEnergyPerformance = pgTable(
"epc_property_energy_performance",
{
id: bigserial("id", { mode: "bigint" }).primaryKey(),
epcPropertyId: bigint("epc_property_id", { mode: "bigint" })
.notNull()
.unique()
.references(() => epcProperty.id),
// Current
energyRatingCurrent: integer("energy_rating_current"),
energyConsumptionCurrent: integer("energy_consumption_current"),
environmentalImpactCurrent: integer("environmental_impact_current"),
heatingCostCurrent: real("heating_cost_current"),
lightingCostCurrent: real("lighting_cost_current"),
hotWaterCostCurrent: real("hot_water_cost_current"),
co2EmissionsCurrent: real("co2_emissions_current"),
co2EmissionsCurrentPerFloorArea: integer("co2_emissions_current_per_floor_area"),
currentEnergyEfficiencyBand: text("current_energy_efficiency_band"),
// Potential
energyRatingPotential: real("energy_rating_potential"),
energyConsumptionPotential: integer("energy_consumption_potential"),
environmentalImpactPotential: integer("environmental_impact_potential"),
heatingCostPotential: real("heating_cost_potential"),
lightingCostPotential: real("lighting_cost_potential"),
hotWaterCostPotential: real("hot_water_cost_potential"),
co2EmissionsPotential: real("co2_emissions_potential"),
potentialEnergyEfficiencyBand: text("potential_energy_efficiency_band"),
},
);
// ─── epc_flat_details ─────────────────────────────────────────────────────────
export const epcFlatDetails = pgTable(
"epc_flat_details",
{
id: bigserial("id", { mode: "bigint" }).primaryKey(),
epcPropertyId: bigint("epc_property_id", { mode: "bigint" })
.notNull()
.unique()
.references(() => epcProperty.id),
level: integer("level").notNull(),
topStorey: text("top_storey").notNull(),
flatLocation: integer("flat_location").notNull(),
heatLossCorridor: integer("heat_loss_corridor").notNull(),
storeyCount: integer("storey_count"),
unheatedCorridorLengthM: integer("unheated_corridor_length_m"),
},
);
// ─── epc_main_heating_detail ──────────────────────────────────────────────────
export const epcMainHeatingDetail = pgTable(
"epc_main_heating_detail",
{
id: bigserial("id", { mode: "bigint" }).primaryKey(),
epcPropertyId: bigint("epc_property_id", { mode: "bigint" })
.notNull()
.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(),
fanFluePresent: boolean("fan_flue_present"),
boilerFlueType: integer("boiler_flue_type"),
boilerIgnitionType: integer("boiler_ignition_type"),
centralHeatingPumpAge: integer("central_heating_pump_age"),
centralHeatingPumpAgeStr: text("central_heating_pump_age_str"),
mainHeatingIndexNumber: integer("main_heating_index_number"),
sapMainHeatingCode: integer("sap_main_heating_code"),
mainHeatingNumber: integer("main_heating_number"),
mainHeatingCategory: integer("main_heating_category"),
mainHeatingFraction: integer("main_heating_fraction"),
mainHeatingDataSource: integer("main_heating_data_source"),
condensing: boolean("condensing"),
weatherCompensator: boolean("weather_compensator"),
},
);
// ─── epc_building_part ────────────────────────────────────────────────────────
export const epcBuildingPart = pgTable(
"epc_building_part",
{
id: bigserial("id", { mode: "bigint" }).primaryKey(),
epcPropertyId: bigint("epc_property_id", { mode: "bigint" })
.notNull()
.references(() => epcProperty.id),
identifier: text("identifier").notNull(),
constructionAgeBand: text("construction_age_band").notNull(),
// Wall
wallConstruction: text("wall_construction").notNull(),
wallInsulationType: text("wall_insulation_type").notNull(),
wallThicknessMeasured: boolean("wall_thickness_measured").notNull(),
partyWallConstruction: text("party_wall_construction").notNull(),
buildingPartNumber: integer("building_part_number"),
wallDryLined: boolean("wall_dry_lined"),
wallThicknessMm: integer("wall_thickness_mm"),
wallInsulationThickness: text("wall_insulation_thickness"),
// age band source
// Floor
floorHeatLoss: integer("floor_heat_loss"),
floorInsulationThickness: text("floor_insulation_thickness"),
flatRoofInsulationThickness: text("flat_roof_insulation_thickness"),
floorType: text("floor_type"),
floorConstructionType: text("floor_construction_type"),
floorInsulationTypeStr: text("floor_insulation_type_str"),
floorUValueKnown: boolean("floor_u_value_known"),
// Roof
roofConstruction: integer("roof_construction"),
roofInsulationLocation: text("roof_insulation_location"),
roofInsulationThickness: text("roof_insulation_thickness"),
// Room in roof (inlined)
roomInRoofFloorArea: real("room_in_roof_floor_area"),
roomInRoofConstructionAgeBand: text("room_in_roof_construction_age_band"),
// Alternative wall 1 (inlined)
altWall1Area: real("alt_wall_1_area"),
altWall1DryLined: text("alt_wall_1_dry_lined"),
altWall1Construction: integer("alt_wall_1_construction"),
altWall1InsulationType: integer("alt_wall_1_insulation_type"),
altWall1ThicknessMeasured: text("alt_wall_1_thickness_measured"),
altWall1InsulationThickness: text("alt_wall_1_insulation_thickness"),
// Alternative wall 2 (inlined)
altWall2Area: real("alt_wall_2_area"),
altWall2DryLined: text("alt_wall_2_dry_lined"),
altWall2Construction: integer("alt_wall_2_construction"),
altWall2InsulationType: integer("alt_wall_2_insulation_type"),
altWall2ThicknessMeasured: text("alt_wall_2_thickness_measured"),
altWall2InsulationThickness: text("alt_wall_2_insulation_thickness"),
},
);
// ─── epc_floor_dimension ──────────────────────────────────────────────────────
export const epcFloorDimension = pgTable(
"epc_floor_dimension",
{
id: bigserial("id", { mode: "bigint" }).primaryKey(),
epcBuildingPartId: bigint("epc_building_part_id", { mode: "bigint" })
.notNull()
.references(() => epcBuildingPart.id),
floor: integer("floor"),
roomHeightM: real("room_height_m").notNull(),
totalFloorAreaM2: real("total_floor_area_m2").notNull(),
partyWallLengthM: real("party_wall_length_m").notNull(),
heatLossPerimeterM: real("heat_loss_perimeter_m").notNull(),
floorInsulation: integer("floor_insulation"),
floorConstruction: integer("floor_construction"),
},
);
// ─── epc_window ───────────────────────────────────────────────────────────────
export const epcWindow = pgTable(
"epc_window",
{
id: bigserial("id", { mode: "bigint" }).primaryKey(),
epcPropertyId: bigint("epc_property_id", { mode: "bigint" })
.notNull()
.references(() => epcProperty.id),
pvcFrame: text("pvc_frame").notNull(),
glazingGap: text("glazing_gap").notNull(),
orientation: text("orientation").notNull(),
windowType: text("window_type").notNull(),
glazingType: text("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(),
frameFactor: real("frame_factor"),
permanentShuttersInsulated: text("permanent_shutters_insulated"),
// Transmission details (inlined)
transmissionUValue: real("transmission_u_value"),
transmissionDataSource: integer("transmission_data_source"),
transmissionSolarTransmittance: real("transmission_solar_transmittance"),
},
);
// ─── epc_energy_element ───────────────────────────────────────────────────────
export const epcEnergyElement = pgTable(
"epc_energy_element",
{
id: bigserial("id", { mode: "bigint" }).primaryKey(),
epcPropertyId: bigint("epc_property_id", { mode: "bigint" })
.notNull()
.references(() => epcProperty.id),
elementType: energyElementTypeEnum("element_type").notNull(),
description: text("description").notNull(),
energyEfficiencyRating: integer("energy_efficiency_rating").notNull(),
environmentalEfficiencyRating: integer("environmental_efficiency_rating").notNull(),
},
);