adding already installed table

This commit is contained in:
Khalim Conn-Kowlessar 2026-01-07 19:33:56 +00:00
parent 3979ae9575
commit 8a08e98340
9 changed files with 15775 additions and 17 deletions

View file

@ -0,0 +1,19 @@
CREATE TYPE "public"."measure_type" AS ENUM('air_source_heat_pump', 'boiler_upgrade', 'high_heat_retention_storage_heaters', 'secondary_heating', 'roomstat_programmer_trvs', 'time_temperature_zone_control', 'cylinder_thermostat', 'cavity_wall_insulation', 'extension_cavity_wall_insulation', 'external_wall_insulation', 'internal_wall_insulation', 'loft_insulation', 'flat_roof_insulation', 'room_roof_insulation', 'solid_floor_insulation', 'suspended_floor_insulation', 'double_glazing', 'secondary_glazing', 'draught_proofing', 'mechanical_ventilation', 'low_energy_lighting', 'solar_pv', 'hot_water_tank_insulation', 'sealing_open_fireplace');--> statement-breakpoint
CREATE TABLE "installed_measure" (
"id" bigserial PRIMARY KEY NOT NULL,
"uprn" text NOT NULL,
"measure_type" "measure_type" NOT NULL,
"installed_at" timestamp DEFAULT now(),
"sap_points" real,
"carbon_savings" real,
"kwh_savings" real,
"bill_savings" real,
"heat_demand_savings" real,
"source" text,
"is_active" boolean DEFAULT true NOT NULL
);
--> statement-breakpoint
CREATE INDEX "idx_installed_measure_uprn" ON "installed_measure" USING btree ("uprn");--> statement-breakpoint
CREATE INDEX "idx_installed_measure_uprn_active" ON "installed_measure" USING btree ("uprn") WHERE "installed_measure"."is_active" = true;--> statement-breakpoint
CREATE INDEX "idx_installed_measure_measure_type" ON "installed_measure" USING btree ("measure_type");--> statement-breakpoint
CREATE INDEX "idx_installed_measure_uprn_measure" ON "installed_measure" USING btree ("uprn","measure_type") WHERE "installed_measure"."is_active" = true;

View file

@ -0,0 +1,3 @@
ALTER TABLE "property" ADD COLUMN "installed_measures_sap_point_adjustment" real;--> statement-breakpoint
ALTER TABLE "property" ADD COLUMN "is_sap_points_adjusted_for_installed_measures" boolean DEFAULT false;--> statement-breakpoint
ALTER TABLE "property" ADD COLUMN "original_sap_points" real;

View file

@ -0,0 +1,2 @@
ALTER TABLE "property_installed_measures" DISABLE ROW LEVEL SECURITY;--> statement-breakpoint
DROP TABLE "property_installed_measures" CASCADE;--> statement-breakpoint

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1016,6 +1016,27 @@
"when": 1767704869539,
"tag": "0144_lovely_moira_mactaggert",
"breakpoints": true
},
{
"idx": 145,
"version": "7",
"when": 1767810791075,
"tag": "0145_brave_power_pack",
"breakpoints": true
},
{
"idx": 146,
"version": "7",
"when": 1767812381964,
"tag": "0146_tiny_george_stacy",
"breakpoints": true
},
{
"idx": 147,
"version": "7",
"when": 1767814056667,
"tag": "0147_confused_killer_shrike",
"breakpoints": true
}
]
}

View file

@ -132,6 +132,17 @@ export const property = pgTable(
currentEpcRating: epcEnum("current_epc_rating"),
currentSapPoints: real("current_sap_points"),
currentValuation: real("current_valuation"),
// When we have already installed measures, we will adjust the SAP points to reflect this. We keep a record of
// 1) The number of points we've adjusted by
// 2) a flag to indicate whether the SAP points have been adjusted, for easily filtering
installedMeasuresSapPointAdjustment: real(
"installed_measures_sap_point_adjustment"
),
isSapPointsAdjustedForInstalledMeasures: boolean(
"is_sap_points_adjusted_for_installed_measures"
).default(false),
originalSapPoints: real("original_sap_points"),
},
(table) => [
uniqueIndex("uq_property_portfolio_uprn")
@ -283,23 +294,6 @@ export const nonIntrusiveSurveyNotes = pgTable("non_intrusive_survey_notes", {
note: text("note").notNull(),
});
// This model is a record of the measures that have already been installed for a property
// This is considered as supplementary daa and stored against the UPRN
// RecommendationType is the
export const propertyInstalledMeasures = pgTable(
"property_installed_measures",
{
id: bigserial("id", { mode: "bigint" }).primaryKey(),
uprn: bigint("uprn", { mode: "bigint" }).notNull(),
// The material types define the list of measures we should expect
measureType: materialTypeEnum("measure_type").notNull(),
// Record of when this measure was inserted into the db
createdAt: timestamp("created_at").notNull().defaultNow(),
// Record of when this measure was actually installed
installedAt: timestamp("installed_at").notNull().defaultNow(),
}
);
export type Property = InferModel<typeof property, "select">;
export type PropertyDetailsEpc = InferModel<
typeof propertyDetailsEpc,

View file

@ -16,6 +16,50 @@ import { Material, material } from "./materials";
import { InferModel, sql } from "drizzle-orm";
import { z } from "zod";
// For recommendations, measure types was initially defined as a string but we should convert this to an enum in the future
export const measureTypeEnum = pgEnum("measure_type", [
// Heating systems
"air_source_heat_pump",
"boiler_upgrade",
"high_heat_retention_storage_heaters",
"secondary_heating",
// Heating controls
"roomstat_programmer_trvs",
"time_temperature_zone_control",
"cylinder_thermostat",
// Insulation
"cavity_wall_insulation",
"extension_cavity_wall_insulation",
"external_wall_insulation",
"internal_wall_insulation",
"loft_insulation",
"flat_roof_insulation",
"room_roof_insulation",
"solid_floor_insulation",
"suspended_floor_insulation",
// Windows & doors
"double_glazing",
"secondary_glazing",
"draught_proofing",
// Ventilation
"mechanical_ventilation",
// Lighting
"low_energy_lighting",
// Renewables
"solar_pv",
// Other fabric / hot water
"hot_water_tank_insulation",
"sealing_open_fireplace",
]);
export const recommendation = pgTable(
"recommendation",
{
@ -266,6 +310,44 @@ export const scenario = pgTable("scenario", {
valuationReturnOnInvestment: text("valuation_return_on_investment"),
});
export const installedMeasure = pgTable(
"installed_measure",
{
id: bigserial("id", { mode: "bigint" }).primaryKey(),
uprn: bigint("uprn", { mode: "bigint" }).notNull(),
measureType: measureTypeEnum("measure_type").notNull(),
installedAt: timestamp("installed_at").defaultNow(),
// Impacts
sapPoints: real("sap_points"),
carbonSavings: real("carbon_savings"), // tonnes CO₂e / yr
kwhSavings: real("kwh_savings"), // kWh / yr
billSavings: real("bill_savings"), // £ / yr
heatDemandSavings: real("heat_demand_savings"),
//
source: text("source"), // e.g. "EPC", "Survey", "Installer"
// Soft delete / supersession
isActive: boolean("is_active").notNull().default(true),
},
(table) => [
index("idx_installed_measure_uprn").on(table.uprn),
index("idx_installed_measure_uprn_active")
.on(table.uprn)
.where(sql`${table.isActive} = true`),
index("idx_installed_measure_measure_type").on(table.measureType),
index("idx_installed_measure_uprn_measure")
.on(table.uprn, table.measureType)
.where(sql`${table.isActive} = true`),
]
);
export type Plan = InferModel<typeof plan, "select">;
export type Recommendation = InferModel<typeof recommendation, "select">;
export type PlanRecommendations = InferModel<