feat(epc): persist PV arrays and floor heat-loss flags

Add EPC persistence schema for two round-trip-fidelity gaps so the Model
backend can store the full EpcPropertyData faithfully:

- New child table epc_photovoltaic_array (one row per PV array), mirroring
  the epc_window child-table pattern.
- epc_floor_dimension: add is_exposed_floor and is_above_partially_heated_space
  boolean flags (NOT NULL DEFAULT false; additive, no backfill).

Includes generated migration 0245_magenta_nomad.sql + snapshot/journal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-06-26 16:38:36 +00:00
parent e96c5ced16
commit a1548ca3a9
4 changed files with 11628 additions and 0 deletions

View file

@ -0,0 +1,13 @@
CREATE TABLE "epc_photovoltaic_array" (
"id" bigserial PRIMARY KEY NOT NULL,
"epc_property_id" bigint NOT NULL,
"array_index" integer NOT NULL,
"peak_power" real NOT NULL,
"pitch" integer NOT NULL,
"overshading" integer NOT NULL,
"orientation" integer
);
--> statement-breakpoint
ALTER TABLE "epc_floor_dimension" ADD COLUMN "is_exposed_floor" boolean DEFAULT false NOT NULL;--> statement-breakpoint
ALTER TABLE "epc_floor_dimension" ADD COLUMN "is_above_partially_heated_space" boolean DEFAULT false NOT NULL;--> statement-breakpoint
ALTER TABLE "epc_photovoltaic_array" ADD CONSTRAINT "epc_photovoltaic_array_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;

File diff suppressed because it is too large Load diff

View file

@ -1709,6 +1709,13 @@
"when": 1782387040698,
"tag": "0244_unknown_puck",
"breakpoints": true
},
{
"idx": 245,
"version": "7",
"when": 1782491854452,
"tag": "0245_magenta_nomad",
"breakpoints": true
}
]
}

View file

@ -776,6 +776,8 @@ export const epcFloorDimension = pgTable(
heatLossPerimeterM: real("heat_loss_perimeter_m").notNull(),
floorInsulation: integer("floor_insulation"),
floorConstruction: integer("floor_construction"),
isExposedFloor: boolean("is_exposed_floor").notNull().default(false),
isAbovePartiallyHeatedSpace: boolean("is_above_partially_heated_space").notNull().default(false),
},
);
@ -810,6 +812,24 @@ export const epcWindow = pgTable(
},
);
// ─── epc_photovoltaic_array ───────────────────────────────────────────────────
export const epcPhotovoltaicArray = pgTable(
"epc_photovoltaic_array",
{
id: bigserial("id", { mode: "bigint" }).primaryKey(),
epcPropertyId: bigint("epc_property_id", { mode: "bigint" })
.notNull()
.references(() => epcProperty.id),
arrayIndex: integer("array_index").notNull(), // preserves list order for round-trip equality
peakPower: real("peak_power").notNull(), // kWp, float (e.g. 3.24)
pitch: integer("pitch").notNull(), // SAP pitch CODE (categorical int, not degrees)
overshading: integer("overshading").notNull(), // SAP overshading CODE (categorical int)
orientation: integer("orientation"), // SAP orientation CODE, nullable
},
);
// ─── epc_energy_element ───────────────────────────────────────────────────────
export const epcEnergyElement = pgTable(