From 081173f00b4c09a472311a53c646f727c7d5241a Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Wed, 4 Mar 2026 15:23:30 +0000 Subject: [PATCH 1/3] add last updated script to db --- src/app/db/migrations/0155_calm_hydra.sql | 4 + src/app/db/migrations/meta/0155_snapshot.json | 5696 +++++++++++++++++ src/app/db/migrations/meta/_journal.json | 7 + src/app/db/schema/addresses.ts | 1 + 4 files changed, 5708 insertions(+) create mode 100644 src/app/db/migrations/0155_calm_hydra.sql create mode 100644 src/app/db/migrations/meta/0155_snapshot.json diff --git a/src/app/db/migrations/0155_calm_hydra.sql b/src/app/db/migrations/0155_calm_hydra.sql new file mode 100644 index 00000000..3e4eb55a --- /dev/null +++ b/src/app/db/migrations/0155_calm_hydra.sql @@ -0,0 +1,4 @@ +ALTER TABLE "postcode_search" ADD COLUMN "last_updated_at" timestamp;--> statement-breakpoint +UPDATE "postcode_search" SET "last_updated_at" = "created_at";--> statement-breakpoint +ALTER TABLE "postcode_search" ALTER COLUMN "last_updated_at" SET DEFAULT now();--> statement-breakpoint +ALTER TABLE "postcode_search" ALTER COLUMN "last_updated_at" SET NOT NULL; \ No newline at end of file diff --git a/src/app/db/migrations/meta/0155_snapshot.json b/src/app/db/migrations/meta/0155_snapshot.json new file mode 100644 index 00000000..478ad582 --- /dev/null +++ b/src/app/db/migrations/meta/0155_snapshot.json @@ -0,0 +1,5696 @@ +{ + "id": "d4b4763c-3866-4da2-be8e-33fa4d778095", + "prevId": "af8bc2d9-bf9c-4dda-845e-068c5952c05b", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.postcode_search": { + "name": "postcode_search", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "postcode": { + "name": "postcode", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "result_data": { + "name": "result_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_updated_at": { + "name": "last_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "postcode_search_postcode_unique": { + "name": "postcode_search_postcode_unique", + "nullsNotDistinct": false, + "columns": [ + "postcode" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.aspect_condition": { + "name": "aspect_condition", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "element_id": { + "name": "element_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "aspect_type": { + "name": "aspect_type", + "type": "aspect_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "aspect_instance": { + "name": "aspect_instance", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "quantity": { + "name": "quantity", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "install_date": { + "name": "install_date", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "renewal_year": { + "name": "renewal_year", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "comments": { + "name": "comments", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "aspect_condition_element_id_element_id_fk": { + "name": "aspect_condition_element_id_element_id_fk", + "tableFrom": "aspect_condition", + "tableTo": "element", + "columnsFrom": [ + "element_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.element": { + "name": "element", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "survey_id": { + "name": "survey_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "element_type": { + "name": "element_type", + "type": "element_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "element_instance": { + "name": "element_instance", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "element_survey_id_property_condition_survey_id_fk": { + "name": "element_survey_id_property_condition_survey_id_fk", + "tableFrom": "element", + "tableTo": "property_condition_survey", + "columnsFrom": [ + "survey_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.property_condition_survey": { + "name": "property_condition_survey", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "uprn": { + "name": "uprn", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "date": { + "name": "date", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.hubspot_company_data": { + "name": "hubspot_company_data", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "company_id": { + "name": "company_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "company_name": { + "name": "company_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "group_id": { + "name": "group_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.hubspot_deal_data": { + "name": "hubspot_deal_data", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "deal_id": { + "name": "deal_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dealname": { + "name": "dealname", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dealstage": { + "name": "dealstage", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "company_id": { + "name": "company_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "project_code": { + "name": "project_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "landlord_property_id": { + "name": "landlord_property_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "uprn": { + "name": "uprn", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "outcome": { + "name": "outcome", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "outcome_notes": { + "name": "outcome_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "major_condition_issue_description": { + "name": "major_condition_issue_description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "major_condition_issue_photos": { + "name": "major_condition_issue_photos", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "major_condition_issue_evidence_s3_url": { + "name": "major_condition_issue_evidence_s3_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "coordination_status": { + "name": "coordination_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "design_status": { + "name": "design_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.property_status_tracker": { + "name": "property_status_tracker", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hubspot_deal_id": { + "name": "hubspot_deal_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "property_id": { + "name": "property_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "portfolio_id": { + "name": "portfolio_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "property_status_tracker_property_id_property_id_fk": { + "name": "property_status_tracker_property_id_property_id_fk", + "tableFrom": "property_status_tracker", + "tableTo": "property", + "columnsFrom": [ + "property_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "property_status_tracker_portfolio_id_portfolio_id_fk": { + "name": "property_status_tracker_portfolio_id_portfolio_id_fk", + "tableFrom": "property_status_tracker", + "tableTo": "portfolio", + "columnsFrom": [ + "portfolio_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.energy_assessments": { + "name": "energy_assessments", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "uprn": { + "name": "uprn", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "uprn_source": { + "name": "uprn_source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "property_type": { + "name": "property_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "building_reference_number": { + "name": "building_reference_number", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "current_energy_efficiency": { + "name": "current_energy_efficiency", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "current_energy_rating": { + "name": "current_energy_rating", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "address1": { + "name": "address1", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "address2": { + "name": "address2", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "address3": { + "name": "address3", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "posttown": { + "name": "posttown", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "postcode": { + "name": "postcode", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "address": { + "name": "address", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "county": { + "name": "county", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "constituency": { + "name": "constituency", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "constituency_label": { + "name": "constituency_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "low_energy_fixed_light_count": { + "name": "low_energy_fixed_light_count", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "construction_age_band": { + "name": "construction_age_band", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "mainheat_energy_eff": { + "name": "mainheat_energy_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "windows_env_eff": { + "name": "windows_env_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lighting_energy_eff": { + "name": "lighting_energy_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "environment_impact_potential": { + "name": "environment_impact_potential", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "mainheatcont_description": { + "name": "mainheatcont_description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sheating_energy_eff": { + "name": "sheating_energy_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "local_authority": { + "name": "local_authority", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "local_authority_label": { + "name": "local_authority_label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "fixed_lighting_outlets_count": { + "name": "fixed_lighting_outlets_count", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "energy_tariff": { + "name": "energy_tariff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "mechanical_ventilation": { + "name": "mechanical_ventilation", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "solar_water_heating_flag": { + "name": "solar_water_heating_flag", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "co2_emissions_potential": { + "name": "co2_emissions_potential", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "number_heated_rooms": { + "name": "number_heated_rooms", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "floor_description": { + "name": "floor_description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "energy_consumption_potential": { + "name": "energy_consumption_potential", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "built_form": { + "name": "built_form", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "number_open_fireplaces": { + "name": "number_open_fireplaces", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "windows_description": { + "name": "windows_description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "glazed_area": { + "name": "glazed_area", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inspection_date": { + "name": "inspection_date", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true + }, + "mains_gas_flag": { + "name": "mains_gas_flag", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "co2_emiss_curr_per_floor_area": { + "name": "co2_emiss_curr_per_floor_area", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "heat_loss_corridor": { + "name": "heat_loss_corridor", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "unheated_corridor_length": { + "name": "unheated_corridor_length", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "flat_storey_count": { + "name": "flat_storey_count", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "roof_energy_eff": { + "name": "roof_energy_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "total_floor_area": { + "name": "total_floor_area", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "environment_impact_current": { + "name": "environment_impact_current", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "roof_description": { + "name": "roof_description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "floor_energy_eff": { + "name": "floor_energy_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "number_habitable_rooms": { + "name": "number_habitable_rooms", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hot_water_env_eff": { + "name": "hot_water_env_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "mainheatc_energy_eff": { + "name": "mainheatc_energy_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "main_fuel": { + "name": "main_fuel", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lighting_env_eff": { + "name": "lighting_env_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "windows_energy_eff": { + "name": "windows_energy_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "floor_env_eff": { + "name": "floor_env_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sheating_env_eff": { + "name": "sheating_env_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lighting_description": { + "name": "lighting_description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "roof_env_eff": { + "name": "roof_env_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "walls_energy_eff": { + "name": "walls_energy_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "photo_supply": { + "name": "photo_supply", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lighting_cost_potential": { + "name": "lighting_cost_potential", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "mainheat_env_eff": { + "name": "mainheat_env_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "multi_glaze_proportion": { + "name": "multi_glaze_proportion", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "main_heating_controls": { + "name": "main_heating_controls", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "flat_top_storey": { + "name": "flat_top_storey", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secondheat_description": { + "name": "secondheat_description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "walls_env_eff": { + "name": "walls_env_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "transaction_type": { + "name": "transaction_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "extension_count": { + "name": "extension_count", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "mainheatc_env_eff": { + "name": "mainheatc_env_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lmk_key": { + "name": "lmk_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "wind_turbine_count": { + "name": "wind_turbine_count", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tenure": { + "name": "tenure", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "floor_level": { + "name": "floor_level", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "potential_energy_efficiency": { + "name": "potential_energy_efficiency", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "potential_energy_rating": { + "name": "potential_energy_rating", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hot_water_energy_eff": { + "name": "hot_water_energy_eff", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "low_energy_lighting": { + "name": "low_energy_lighting", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "walls_description": { + "name": "walls_description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hotwater_description": { + "name": "hotwater_description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "co2_emissions_current": { + "name": "co2_emissions_current", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "heating_cost_current": { + "name": "heating_cost_current", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "heating_cost_potential": { + "name": "heating_cost_potential", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hot_water_cost_current": { + "name": "hot_water_cost_current", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hot_water_cost_potential": { + "name": "hot_water_cost_potential", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lighting_cost_current": { + "name": "lighting_cost_current", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "energy_consumption_current": { + "name": "energy_consumption_current", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lodgement_date": { + "name": "lodgement_date", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "lodgement_datetime": { + "name": "lodgement_datetime", + "type": "timestamp (6)", + "primaryKey": false, + "notNull": true + }, + "mainheat_description": { + "name": "mainheat_description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "floor_height": { + "name": "floor_height", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "glazed_type": { + "name": "glazed_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_location": { + "name": "file_location", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "surveyor_name": { + "name": "surveyor_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "surveyor_company": { + "name": "surveyor_company", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "space_heating_kwh": { + "name": "space_heating_kwh", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "water_heating_kwh": { + "name": "water_heating_kwh", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "number_of_doors": { + "name": "number_of_doors", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "number_of_insulated_doors": { + "name": "number_of_insulated_doors", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "number_of_floors": { + "name": "number_of_floors", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "insulation_wall_area": { + "name": "insulation_wall_area", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "heat_loss_perimeter": { + "name": "heat_loss_perimeter", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "party_wall_length": { + "name": "party_wall_length", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "perimeter": { + "name": "perimeter", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "rooms_with_bath_and_or_shower": { + "name": "rooms_with_bath_and_or_shower", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rooms_with_mixer_shower_no_bath": { + "name": "rooms_with_mixer_shower_no_bath", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "room_with_bath_and_mixer_shower": { + "name": "room_with_bath_and_mixer_shower", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "percent_draftproofed": { + "name": "percent_draftproofed", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "has_hot_water_cylinder": { + "name": "has_hot_water_cylinder", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "cylinder_insulation_type": { + "name": "cylinder_insulation_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cylinder_insulation_thickness": { + "name": "cylinder_insulation_thickness", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cylinder_thermostat": { + "name": "cylinder_thermostat", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "main_dwelling_ground_floor_area": { + "name": "main_dwelling_ground_floor_area", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "number_of_windows": { + "name": "number_of_windows", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "windows_area": { + "name": "windows_area", + "type": "real", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.energy_assessment_documents": { + "name": "energy_assessment_documents", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "uprn": { + "name": "uprn", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "energy_assessment_id": { + "name": "energy_assessment_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "document_type": { + "name": "document_type", + "type": "document_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "document_location": { + "name": "document_location", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "scenario_id": { + "name": "scenario_id", + "type": "bigint", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "energy_assessment_documents_energy_assessment_id_energy_assessments_id_fk": { + "name": "energy_assessment_documents_energy_assessment_id_energy_assessments_id_fk", + "tableFrom": "energy_assessment_documents", + "tableTo": "energy_assessments", + "columnsFrom": [ + "energy_assessment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "energy_assessment_documents_scenario_id_energy_assessment_scenarios_id_fk": { + "name": "energy_assessment_documents_scenario_id_energy_assessment_scenarios_id_fk", + "tableFrom": "energy_assessment_documents", + "tableTo": "energy_assessment_scenarios", + "columnsFrom": [ + "scenario_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.energy_assessment_scenarios": { + "name": "energy_assessment_scenarios", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "scenario_name": { + "name": "scenario_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "energy_assessment_id": { + "name": "energy_assessment_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "energy_assessment_scenarios_energy_assessment_id_energy_assessments_id_fk": { + "name": "energy_assessment_scenarios_energy_assessment_id_energy_assessments_id_fk", + "tableFrom": "energy_assessment_scenarios", + "tableTo": "energy_assessments", + "columnsFrom": [ + "energy_assessment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.epc_store": { + "name": "epc_store", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "uprn": { + "name": "uprn", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "epc_api_created_at": { + "name": "epc_api_created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "epc_api": { + "name": "epc_api", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "epc_page_created_at": { + "name": "epc_page_created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "epc_page": { + "name": "epc_page", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "epc_page_rrn": { + "name": "epc_page_rrn", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "uq_epc_store_uprn": { + "name": "uq_epc_store_uprn", + "columns": [ + { + "expression": "uprn", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.files_from_surveyor": { + "name": "files_from_surveyor", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "portfolio_id": { + "name": "portfolio_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "property_id": { + "name": "property_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "s3_json_url": { + "name": "s3_json_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "files_from_surveyor_portfolio_id_portfolio_id_fk": { + "name": "files_from_surveyor_portfolio_id_portfolio_id_fk", + "tableFrom": "files_from_surveyor", + "tableTo": "portfolio", + "columnsFrom": [ + "portfolio_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "files_from_surveyor_property_id_property_id_fk": { + "name": "files_from_surveyor_property_id_property_id_fk", + "tableFrom": "files_from_surveyor", + "tableTo": "property", + "columnsFrom": [ + "property_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.funding_package": { + "name": "funding_package", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "plan_id": { + "name": "plan_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "scheme": { + "name": "scheme", + "type": "scheme", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "project_funding": { + "name": "project_funding", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "total_uplift": { + "name": "total_uplift", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "full_project_score": { + "name": "full_project_score", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "partial_project_score": { + "name": "partial_project_score", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "uplift_project_score": { + "name": "uplift_project_score", + "type": "real", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "funding_package_plan_id_plan_id_fk": { + "name": "funding_package_plan_id_plan_id_fk", + "tableFrom": "funding_package", + "tableTo": "plan", + "columnsFrom": [ + "plan_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.funding_package_measures": { + "name": "funding_package_measures", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "funding_package_id": { + "name": "funding_package_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "measure": { + "name": "measure", + "type": "type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "material_id": { + "name": "material_id", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "innovation_uplift": { + "name": "innovation_uplift", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "partial_project_score": { + "name": "partial_project_score", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "uplift_project_score": { + "name": "uplift_project_score", + "type": "real", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "funding_package_measures_funding_package_id_funding_package_id_fk": { + "name": "funding_package_measures_funding_package_id_funding_package_id_fk", + "tableFrom": "funding_package_measures", + "tableTo": "funding_package", + "columnsFrom": [ + "funding_package_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "funding_package_measures_material_id_material_id_fk": { + "name": "funding_package_measures_material_id_material_id_fk", + "tableFrom": "funding_package_measures", + "tableTo": "material", + "columnsFrom": [ + "material_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.inspections": { + "name": "inspections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "property_id": { + "name": "property_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "archetype": { + "name": "archetype", + "type": "inspection_archetype", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "archetype_2": { + "name": "archetype_2", + "type": "inspection_archetype_2", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "wall_construction": { + "name": "wall_construction", + "type": "inspections_wall_construction", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "insulation": { + "name": "insulation", + "type": "inspections_wall_insulation", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "insulation_material": { + "name": "insulation_material", + "type": "inspections_insulation_material", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "borescoped": { + "name": "borescoped", + "type": "inspection_borescoped", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "roof_orientation": { + "name": "roof_orientation", + "type": "inspections_roof_orientation", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "tile_hung": { + "name": "tile_hung", + "type": "inspections_tile_hung", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "rendered": { + "name": "rendered", + "type": "inspections_rendered", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "cladding": { + "name": "cladding", + "type": "inspections_cladding", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "access_issues": { + "name": "access_issues", + "type": "inspections_access_issues", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "surveyor_name": { + "name": "surveyor_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "inspections_property_id_property_id_fk": { + "name": "inspections_property_id_property_id_fk", + "tableFrom": "inspections", + "tableTo": "property", + "columnsFrom": [ + "property_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.material": { + "name": "material", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "depth": { + "name": "depth", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "depth_unit": { + "name": "depth_unit", + "type": "depth_unit", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "cost_unit": { + "name": "cost_unit", + "type": "cost_unit", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "r_value_per_mm": { + "name": "r_value_per_mm", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "r_value_unit": { + "name": "r_value_unit", + "type": "r_value_unit", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "thermal_conductivity": { + "name": "thermal_conductivity", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "thermal_conductivity_unit": { + "name": "thermal_conductivity_unit", + "type": "thermal_conductivity_unit", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "link": { + "name": "link", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "prime_material_cost": { + "name": "prime_material_cost", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "material_cost": { + "name": "material_cost", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "labour_cost": { + "name": "labour_cost", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "labour_hours_per_unit": { + "name": "labour_hours_per_unit", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "plant_cost": { + "name": "plant_cost", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "total_cost": { + "name": "total_cost", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "cost": { + "name": "cost", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_installer_quote": { + "name": "is_installer_quote", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "innovation_rate": { + "name": "innovation_rate", + "type": "real", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "size": { + "name": "size", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "size_unit": { + "name": "size_unit", + "type": "size_unit", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "includes_scaffolding": { + "name": "includes_scaffolding", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "includes_battery": { + "name": "includes_battery", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "battery_size": { + "name": "battery_size", + "type": "real", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.portfolio": { + "name": "portfolio", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "budget": { + "name": "budget", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "goal": { + "name": "goal", + "type": "goal", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "cost": { + "name": "cost", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "number_of_properties": { + "name": "number_of_properties", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "co2_equivalent_savings": { + "name": "co2_equivalent_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "energy_savings": { + "name": "energy_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "energy_cost_savings": { + "name": "energy_cost_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "property_valuation_increase": { + "name": "property_valuation_increase", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "rental_yield_increase": { + "name": "rental_yield_increase", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "total_work_hours": { + "name": "total_work_hours", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "labour_days": { + "name": "labour_days", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "epc_breakdown_pre_retrofit": { + "name": "epc_breakdown_pre_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "epc_breakdown_post_retrofit": { + "name": "epc_breakdown_post_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "n_units_to_retrofit": { + "name": "n_units_to_retrofit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "co2_per_unit_pre_retrofit": { + "name": "co2_per_unit_pre_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "co2_per_unit_post_retrofit": { + "name": "co2_per_unit_post_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "energy_bill_per_unit_pre_retrofit": { + "name": "energy_bill_per_unit_pre_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "energy_bill_per_unit_post_retrofit": { + "name": "energy_bill_per_unit_post_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "energy_consumption_per_unit_pre_retrofit": { + "name": "energy_consumption_per_unit_pre_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "energy_consumption_per_unit_post_retrofit": { + "name": "energy_consumption_per_unit_post_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "valuation_improvement_per_unit": { + "name": "valuation_improvement_per_unit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cost_per_unit": { + "name": "cost_per_unit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cost_per_co2_saved": { + "name": "cost_per_co2_saved", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cost_per_sap_point": { + "name": "cost_per_sap_point", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "valuation_return_on_investment": { + "name": "valuation_return_on_investment", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.portfolioUsers": { + "name": "portfolioUsers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "portfolio_id": { + "name": "portfolio_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "portfolioUsers_user_id_user_id_fk": { + "name": "portfolioUsers_user_id_user_id_fk", + "tableFrom": "portfolioUsers", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "portfolioUsers_portfolio_id_portfolio_id_fk": { + "name": "portfolioUsers_portfolio_id_portfolio_id_fk", + "tableFrom": "portfolioUsers", + "tableTo": "portfolio", + "columnsFrom": [ + "portfolio_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.non_intrusive_survey": { + "name": "non_intrusive_survey", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "uprn": { + "name": "uprn", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "survey_date": { + "name": "survey_date", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "surveyor": { + "name": "surveyor", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.non_intrusive_survey_notes": { + "name": "non_intrusive_survey_notes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "survey_id": { + "name": "survey_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "non_intrusive_survey_notes_survey_id_non_intrusive_survey_id_fk": { + "name": "non_intrusive_survey_notes_survey_id_non_intrusive_survey_id_fk", + "tableFrom": "non_intrusive_survey_notes", + "tableTo": "non_intrusive_survey", + "columnsFrom": [ + "survey_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.property": { + "name": "property", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "portfolio_id": { + "name": "portfolio_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "creation_status": { + "name": "creation_status", + "type": "creation_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "uprn": { + "name": "uprn", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "landlord_property_id": { + "name": "landlord_property_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "building_reference_number": { + "name": "building_reference_number", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "status", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "address": { + "name": "address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "postcode": { + "name": "postcode", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "has_pre_condition_report": { + "name": "has_pre_condition_report", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "has_recommendations": { + "name": "has_recommendations", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "property_type": { + "name": "property_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "built_form": { + "name": "built_form", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "local_authority": { + "name": "local_authority", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "constituency": { + "name": "constituency", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "number_of_rooms": { + "name": "number_of_rooms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "year_built": { + "name": "year_built", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tenure": { + "name": "tenure", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "current_epc_rating": { + "name": "current_epc_rating", + "type": "epc", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "current_sap_points": { + "name": "current_sap_points", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "current_valuation": { + "name": "current_valuation", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "installed_measures_sap_point_adjustment": { + "name": "installed_measures_sap_point_adjustment", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "is_sap_points_adjusted_for_installed_measures": { + "name": "is_sap_points_adjusted_for_installed_measures", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "original_sap_points": { + "name": "original_sap_points", + "type": "real", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "uq_property_portfolio_uprn": { + "name": "uq_property_portfolio_uprn", + "columns": [ + { + "expression": "portfolio_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "uprn", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"property\".\"uprn\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "property_portfolio_id_portfolio_id_fk": { + "name": "property_portfolio_id_portfolio_id_fk", + "tableFrom": "property", + "tableTo": "portfolio", + "columnsFrom": [ + "portfolio_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.property_details_epc": { + "name": "property_details_epc", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "property_id": { + "name": "property_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "portfolio_id": { + "name": "portfolio_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "full_address": { + "name": "full_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lodgement_date": { + "name": "lodgement_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "is_expired": { + "name": "is_expired", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "total_floor_area": { + "name": "total_floor_area", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "walls": { + "name": "walls", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "walls_rating": { + "name": "walls_rating", + "type": "smallint", + "primaryKey": false, + "notNull": false + }, + "roof": { + "name": "roof", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "roof_rating": { + "name": "roof_rating", + "type": "smallint", + "primaryKey": false, + "notNull": false + }, + "floor": { + "name": "floor", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "floor_rating": { + "name": "floor_rating", + "type": "smallint", + "primaryKey": false, + "notNull": false + }, + "windows": { + "name": "windows", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "windows_rating": { + "name": "windows_rating", + "type": "smallint", + "primaryKey": false, + "notNull": false + }, + "heating": { + "name": "heating", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "heating_rating": { + "name": "heating_rating", + "type": "smallint", + "primaryKey": false, + "notNull": false + }, + "heating_controls": { + "name": "heating_controls", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "heating_controls_rating": { + "name": "heating_controls_rating", + "type": "smallint", + "primaryKey": false, + "notNull": false + }, + "hot_water": { + "name": "hot_water", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "hot_water_rating": { + "name": "hot_water_rating", + "type": "smallint", + "primaryKey": false, + "notNull": false + }, + "lighting": { + "name": "lighting", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lighting_rating": { + "name": "lighting_rating", + "type": "smallint", + "primaryKey": false, + "notNull": false + }, + "mainfuel": { + "name": "mainfuel", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ventilation": { + "name": "ventilation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "solar_pv": { + "name": "solar_pv", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "solar_hot_water": { + "name": "solar_hot_water", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "wind_turbine": { + "name": "wind_turbine", + "type": "smallint", + "primaryKey": false, + "notNull": false + }, + "floor_height": { + "name": "floor_height", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "number_heated_rooms": { + "name": "number_heated_rooms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "heat_loss_corridor": { + "name": "heat_loss_corridor", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "unheated_corridor_length": { + "name": "unheated_corridor_length", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "number_of_open_fireplaces": { + "name": "number_of_open_fireplaces", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "number_of_extensions": { + "name": "number_of_extensions", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "number_of_storeys": { + "name": "number_of_storeys", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "mains_gas": { + "name": "mains_gas", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "energy_tariff": { + "name": "energy_tariff", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "primary_energy_consumption": { + "name": "primary_energy_consumption", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "co2_emissions": { + "name": "co2_emissions", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "current_energy_demand": { + "name": "current_energy_demand", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "current_energy_demand_heating_hotwater": { + "name": "current_energy_demand_heating_hotwater", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "estimated": { + "name": "estimated", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "sap_05_overwritten": { + "name": "sap_05_overwritten", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "sap_05_score": { + "name": "sap_05_score", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "sap_05_epc_rating": { + "name": "sap_05_epc_rating", + "type": "epc", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "heating_cost_current": { + "name": "heating_cost_current", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "hot_water_cost_current": { + "name": "hot_water_cost_current", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "lighting_cost_current": { + "name": "lighting_cost_current", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "appliances_cost_current": { + "name": "appliances_cost_current", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "gas_standing_charge": { + "name": "gas_standing_charge", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "electricity_standing_charge": { + "name": "electricity_standing_charge", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "original_co2_emissions": { + "name": "original_co2_emissions", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "original_primary_energy_consumption": { + "name": "original_primary_energy_consumption", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "original_current_energy_demand": { + "name": "original_current_energy_demand", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "original_current_energy_demand_heating_hotwater": { + "name": "original_current_energy_demand_heating_hotwater", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "installed_measures_co2_adjustment": { + "name": "installed_measures_co2_adjustment", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "installed_measures_energy_demand_adjustment": { + "name": "installed_measures_energy_demand_adjustment", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "installed_measures_total_energy_bill_adjustment": { + "name": "installed_measures_total_energy_bill_adjustment", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "installed_measures_heat_demand_adjustment": { + "name": "installed_measures_heat_demand_adjustment", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "is_epc_adjusted_for_installed_measures": { + "name": "is_epc_adjusted_for_installed_measures", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + } + }, + "indexes": { + "uq_property_details_epc_property_portfolio": { + "name": "uq_property_details_epc_property_portfolio", + "columns": [ + { + "expression": "property_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "portfolio_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "property_details_epc_property_id_property_id_fk": { + "name": "property_details_epc_property_id_property_id_fk", + "tableFrom": "property_details_epc", + "tableTo": "property", + "columnsFrom": [ + "property_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "property_details_epc_portfolio_id_portfolio_id_fk": { + "name": "property_details_epc_portfolio_id_portfolio_id_fk", + "tableFrom": "property_details_epc", + "tableTo": "portfolio", + "columnsFrom": [ + "portfolio_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.property_details_meter": { + "name": "property_details_meter", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "uprn": { + "name": "uprn", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "energy_supplier": { + "name": "energy_supplier", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gas_supplier": { + "name": "gas_supplier", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "meter_reading_total": { + "name": "meter_reading_total", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "meter_reading_electricity": { + "name": "meter_reading_electricity", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "meter_reading_gas": { + "name": "meter_reading_gas", + "type": "real", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.property_details_spatial": { + "name": "property_details_spatial", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "uprn": { + "name": "uprn", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "x_coordinate": { + "name": "x_coordinate", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "y_coordinate": { + "name": "y_coordinate", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "latitude": { + "name": "latitude", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "longitude": { + "name": "longitude", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "conservation_status": { + "name": "conservation_status", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "is_listed_building": { + "name": "is_listed_building", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "is_heritage_building": { + "name": "is_heritage_building", + "type": "boolean", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "uq_property_details_spatial_uprn": { + "name": "uq_property_details_spatial_uprn", + "columns": [ + { + "expression": "uprn", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.property_targets": { + "name": "property_targets", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "property_id": { + "name": "property_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "portfolio_id": { + "name": "portfolio_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "epc": { + "name": "epc", + "type": "epc", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "heat_demand": { + "name": "heat_demand", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "property_targets_property_id_property_id_fk": { + "name": "property_targets_property_id_property_id_fk", + "tableFrom": "property_targets", + "tableTo": "property", + "columnsFrom": [ + "property_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "property_targets_portfolio_id_portfolio_id_fk": { + "name": "property_targets_portfolio_id_portfolio_id_fk", + "tableFrom": "property_targets", + "tableTo": "portfolio", + "columnsFrom": [ + "portfolio_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.installed_measure": { + "name": "installed_measure", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "uprn": { + "name": "uprn", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "measure_type": { + "name": "measure_type", + "type": "measure_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "installed_at": { + "name": "installed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "sap_points": { + "name": "sap_points", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "carbon_savings": { + "name": "carbon_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "kwh_savings": { + "name": "kwh_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "bill_savings": { + "name": "bill_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "heat_demand_savings": { + "name": "heat_demand_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + } + }, + "indexes": { + "idx_installed_measure_uprn": { + "name": "idx_installed_measure_uprn", + "columns": [ + { + "expression": "uprn", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_installed_measure_uprn_active": { + "name": "idx_installed_measure_uprn_active", + "columns": [ + { + "expression": "uprn", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"installed_measure\".\"is_active\" = true", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_installed_measure_measure_type": { + "name": "idx_installed_measure_measure_type", + "columns": [ + { + "expression": "measure_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_installed_measure_uprn_measure": { + "name": "idx_installed_measure_uprn_measure", + "columns": [ + { + "expression": "uprn", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "measure_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"installed_measure\".\"is_active\" = true", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.plan": { + "name": "plan", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "portfolio_id": { + "name": "portfolio_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "property_id": { + "name": "property_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "scenario_id": { + "name": "scenario_id", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "is_default": { + "name": "is_default", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "valuation_increase_lower_bound": { + "name": "valuation_increase_lower_bound", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "valuation_increase_upper_bound": { + "name": "valuation_increase_upper_bound", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "valuation_increase_average": { + "name": "valuation_increase_average", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "post_sap_points": { + "name": "post_sap_points", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "post_epc_rating": { + "name": "post_epc_rating", + "type": "epc", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "post_co2_emissions": { + "name": "post_co2_emissions", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "co2_savings": { + "name": "co2_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "post_energy_bill": { + "name": "post_energy_bill", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "energy_bill_savings": { + "name": "energy_bill_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "post_energy_consumption": { + "name": "post_energy_consumption", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "energy_consumption_savings": { + "name": "energy_consumption_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "valuation_post_retrofit": { + "name": "valuation_post_retrofit", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "valuation_increase": { + "name": "valuation_increase", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "cost_of_works": { + "name": "cost_of_works", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "contingency_cost": { + "name": "contingency_cost", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "plan_type": { + "name": "plan_type", + "type": "plan_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_plan_portfolio_scenario": { + "name": "idx_plan_portfolio_scenario", + "columns": [ + { + "expression": "portfolio_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scenario_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_plan_latest_per_property": { + "name": "idx_plan_latest_per_property", + "columns": [ + { + "expression": "portfolio_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scenario_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "property_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": false, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "plan_portfolio_id_portfolio_id_fk": { + "name": "plan_portfolio_id_portfolio_id_fk", + "tableFrom": "plan", + "tableTo": "portfolio", + "columnsFrom": [ + "portfolio_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "plan_property_id_property_id_fk": { + "name": "plan_property_id_property_id_fk", + "tableFrom": "plan", + "tableTo": "property", + "columnsFrom": [ + "property_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "plan_scenario_id_scenario_id_fk": { + "name": "plan_scenario_id_scenario_id_fk", + "tableFrom": "plan", + "tableTo": "scenario", + "columnsFrom": [ + "scenario_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.plan_recommendations": { + "name": "plan_recommendations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "plan_id": { + "name": "plan_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "recommendation_id": { + "name": "recommendation_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_plan_recommendations_plan_id": { + "name": "idx_plan_recommendations_plan_id", + "columns": [ + { + "expression": "plan_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_plan_recommendations_plan_rec": { + "name": "idx_plan_recommendations_plan_rec", + "columns": [ + { + "expression": "plan_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "recommendation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "plan_recommendations_plan_id_plan_id_fk": { + "name": "plan_recommendations_plan_id_plan_id_fk", + "tableFrom": "plan_recommendations", + "tableTo": "plan", + "columnsFrom": [ + "plan_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "plan_recommendations_recommendation_id_recommendation_id_fk": { + "name": "plan_recommendations_recommendation_id_recommendation_id_fk", + "tableFrom": "plan_recommendations", + "tableTo": "recommendation", + "columnsFrom": [ + "recommendation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.recommendation": { + "name": "recommendation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "property_id": { + "name": "property_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "measure_type": { + "name": "measure_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "estimated_cost": { + "name": "estimated_cost", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "contingency_cost": { + "name": "contingency_cost", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "default": { + "name": "default", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "starting_u_value": { + "name": "starting_u_value", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "new_u_value": { + "name": "new_u_value", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "sap_points": { + "name": "sap_points", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "heat_demand": { + "name": "heat_demand", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "kwh_savings": { + "name": "kwh_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "co2_equivalent_savings": { + "name": "co2_equivalent_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "energy_savings": { + "name": "energy_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "energy_cost_savings": { + "name": "energy_cost_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "property_valuation_increase": { + "name": "property_valuation_increase", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "rental_yield_increase": { + "name": "rental_yield_increase", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "total_work_hours": { + "name": "total_work_hours", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "labour_days": { + "name": "labour_days", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "already_installed": { + "name": "already_installed", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + } + }, + "indexes": { + "recommendation_property_id_idx": { + "name": "recommendation_property_id_idx", + "columns": [ + { + "expression": "property_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_recommendation_active_defaults": { + "name": "idx_recommendation_active_defaults", + "columns": [ + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"recommendation\".\"default\" = true AND \"recommendation\".\"already_installed\" = false", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_recommendation_active_id_property": { + "name": "idx_recommendation_active_id_property", + "columns": [ + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "property_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"recommendation\".\"default\" = true AND \"recommendation\".\"already_installed\" = false", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "recommendation_property_id_property_id_fk": { + "name": "recommendation_property_id_property_id_fk", + "tableFrom": "recommendation", + "tableTo": "property", + "columnsFrom": [ + "property_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.recommendation_materials": { + "name": "recommendation_materials", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "recommendation_id": { + "name": "recommendation_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "material_id": { + "name": "material_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "depth": { + "name": "depth", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "quantity": { + "name": "quantity", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "quantity_unit": { + "name": "quantity_unit", + "type": "unit_quantity", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "estimated_cost": { + "name": "estimated_cost", + "type": "real", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "recommendation_materials_recommendation_id_idx": { + "name": "recommendation_materials_recommendation_id_idx", + "columns": [ + { + "expression": "recommendation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "recommendation_materials_recommendation_id_recommendation_id_fk": { + "name": "recommendation_materials_recommendation_id_recommendation_id_fk", + "tableFrom": "recommendation_materials", + "tableTo": "recommendation", + "columnsFrom": [ + "recommendation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "recommendation_materials_material_id_material_id_fk": { + "name": "recommendation_materials_material_id_material_id_fk", + "tableFrom": "recommendation_materials", + "tableTo": "material", + "columnsFrom": [ + "material_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.scenario": { + "name": "scenario", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "budget": { + "name": "budget", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "portfolio_id": { + "name": "portfolio_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "housing_type": { + "name": "housing_type", + "type": "housing_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "goal": { + "name": "goal", + "type": "goal", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "goal_value": { + "name": "goal_value", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ashp_cop": { + "name": "ashp_cop", + "type": "real", + "primaryKey": false, + "notNull": false, + "default": 2.8 + }, + "trigger_file_path": { + "name": "trigger_file_path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "already_installed_file_path": { + "name": "already_installed_file_path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "patches_file_path": { + "name": "patches_file_path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "non_invasive_recommendations_file_path": { + "name": "non_invasive_recommendations_file_path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "exclusions": { + "name": "exclusions", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "multi_plan": { + "name": "multi_plan", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "is_default": { + "name": "is_default", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "cost": { + "name": "cost", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "contingency": { + "name": "contingency", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "funding": { + "name": "funding", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "total_work_hours": { + "name": "total_work_hours", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "energy_savings": { + "name": "energy_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "co2_equivalent_savings": { + "name": "co2_equivalent_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "energy_cost_savings": { + "name": "energy_cost_savings", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "property_valuation_increase": { + "name": "property_valuation_increase", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "labour_days": { + "name": "labour_days", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "epc_breakdown_pre_retrofit": { + "name": "epc_breakdown_pre_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "epc_breakdown_post_retrofit": { + "name": "epc_breakdown_post_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "number_of_properties": { + "name": "number_of_properties", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "n_units_to_retrofit": { + "name": "n_units_to_retrofit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "co2_per_unit_pre_retrofit": { + "name": "co2_per_unit_pre_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "co2_per_unit_post_retrofit": { + "name": "co2_per_unit_post_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "energy_bill_per_unit_pre_retrofit": { + "name": "energy_bill_per_unit_pre_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "energy_bill_per_unit_post_retrofit": { + "name": "energy_bill_per_unit_post_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "energy_consumption_per_unit_pre_retrofit": { + "name": "energy_consumption_per_unit_pre_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "energy_consumption_per_unit_post_retrofit": { + "name": "energy_consumption_per_unit_post_retrofit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "valuation_improvement_per_unit": { + "name": "valuation_improvement_per_unit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cost_per_unit": { + "name": "cost_per_unit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cost_per_co2_saved": { + "name": "cost_per_co2_saved", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cost_per_sap_point": { + "name": "cost_per_sap_point", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "valuation_return_on_investment": { + "name": "valuation_return_on_investment", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "scenario_portfolio_id_portfolio_id_fk": { + "name": "scenario_portfolio_id_portfolio_id_fk", + "tableFrom": "scenario", + "tableTo": "portfolio", + "columnsFrom": [ + "portfolio_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.solar": { + "name": "solar", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "longitude": { + "name": "longitude", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "latitude": { + "name": "latitude", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "uprn": { + "name": "uprn", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "google_api_response": { + "name": "google_api_response", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.solar_scenario": { + "name": "solar_scenario", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "solar_id": { + "name": "solar_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "scenario_type": { + "name": "scenario_type", + "type": "scenario_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "number_panels": { + "name": "number_panels", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "array_kwhp": { + "name": "array_kwhp", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "lifetime_dc_kwh": { + "name": "lifetime_dc_kwh", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "yearly_dc_kwh": { + "name": "yearly_dc_kwh", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "lifetime_ac_kwh": { + "name": "lifetime_ac_kwh", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "yearly_ac_kwh": { + "name": "yearly_ac_kwh", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "cost": { + "name": "cost", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "expected_payback_years": { + "name": "expected_payback_years", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "panelled_roof_area": { + "name": "panelled_roof_area", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "is_default": { + "name": "is_default", + "type": "boolean", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "solar_scenario_solar_id_solar_id_fk": { + "name": "solar_scenario_solar_id_solar_id_fk", + "tableFrom": "solar_scenario", + "tableTo": "solar", + "columnsFrom": [ + "solar_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sub_task": { + "name": "sub_task", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "task_id": { + "name": "task_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "job_started": { + "name": "job_started", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": false + }, + "job_completed": { + "name": "job_completed", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'In Progress'" + }, + "inputs": { + "name": "inputs", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "outputs": { + "name": "outputs", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cloud_logs_url": { + "name": "cloud_logs_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "sub_task_task_id_tasks_id_fk": { + "name": "sub_task_task_id_tasks_id_fk", + "tableFrom": "sub_task", + "tableTo": "tasks", + "columnsFrom": [ + "task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.tasks": { + "name": "tasks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "task_source": { + "name": "task_source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "job_started": { + "name": "job_started", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": false + }, + "job_completed": { + "name": "job_completed", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'In Progress'" + }, + "service": { + "name": "service", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "source", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "source_id": { + "name": "source_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "providerAccountId": { + "name": "providerAccountId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "token_type": { + "name": "token_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_state": { + "name": "session_state", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "account_userId_user_id_fk": { + "name": "account_userId_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "account_provider_providerAccountId_pk": { + "name": "account_provider_providerAccountId_pk", + "columns": [ + "provider", + "providerAccountId" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "sessionToken": { + "name": "sessionToken", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_userId_user_id_fk": { + "name": "session_userId_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "firstName": { + "name": "firstName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "emailVerified": { + "name": "emailVerified", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "oauth_id": { + "name": "oauth_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "oauth_provider": { + "name": "oauth_provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "onboarded": { + "name": "onboarded", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "last_login": { + "name": "last_login", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_profiles": { + "name": "user_profiles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "user_type": { + "name": "user_type", + "type": "user_profiles_user_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "property_count": { + "name": "property_count", + "type": "user_profiles_property_count", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "goals": { + "name": "goals", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "referral_source": { + "name": "referral_source", + "type": "user_profiles_referral_source", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "nrla_membership_id": { + "name": "nrla_membership_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "accepted_privacy": { + "name": "accepted_privacy", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "accepted_privacy_at": { + "name": "accepted_privacy_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": false + }, + "marketing_opt_in": { + "name": "marketing_opt_in", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "marketing_opt_in_at": { + "name": "marketing_opt_in_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": false + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp (6) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_profiles_user_id_user_id_fk": { + "name": "user_profiles_user_id_user_id_fk", + "tableFrom": "user_profiles", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verificationToken": { + "name": "verificationToken", + "schema": "", + "columns": { + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "verificationToken_identifier_token_pk": { + "name": "verificationToken_identifier_token_pk", + "columns": [ + "identifier", + "token" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.whlg": { + "name": "whlg", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "postcode": { + "name": "postcode", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.aspect_type": { + "name": "aspect_type", + "schema": "public", + "values": [ + "material", + "condition", + "type", + "area", + "configuration", + "presence", + "risk", + "severity", + "location", + "finish", + "insulation", + "pointing", + "spalling", + "lintels", + "cladding", + "category", + "quantity", + "adequacy", + "rating", + "strategy", + "extent", + "distribution", + "structure", + "covering", + "fire_rating", + "external_decoration", + "work_required", + "age_band", + "construction_type", + "classification", + "system" + ] + }, + "public.element_type": { + "name": "element_type", + "schema": "public", + "values": [ + "property", + "property_construction_type", + "property_classification", + "property_age_band", + "storey_count", + "floor_level", + "floor_level_front_door", + "accessible_housing_register", + "asbestos", + "quality_standard", + "ccu", + "passenger_lift", + "stairlift", + "disabled_hoist_tracking", + "disabled_facilities", + "steps_to_front_door", + "roof", + "pitched_roof_covering", + "flat_roof_covering", + "rainwater_goods", + "loft_insulation", + "porch_canopy", + "chimney", + "fascia", + "soffit", + "fascia_soffit_bargeboards", + "gutters", + "store_roof", + "garage_roof", + "garage_and_store_roof", + "external_wall", + "external_noise_insulation", + "primary_wall", + "secondary_wall", + "downpipes", + "external_decoration", + "cladding", + "spandrel_panels", + "garage_walls", + "party_wall_fire_break", + "external_brickwork_pointing", + "internal_downpipes_external_area", + "external_windows", + "communal_windows", + "secondary_glazing", + "store_windows", + "garage_windows", + "garage_and_store_windows", + "external_door", + "front_door", + "rear_door", + "store_door", + "garage_door", + "garage_and_store_door", + "communal_entrance_door", + "main_door", + "block_entrance_door", + "lintel", + "patio_french_door", + "door_entry_handset", + "paths_and_hardstandings", + "parking_areas", + "boundary_walls", + "front_fencing", + "rear_fencing", + "side_fencing", + "rear_gate", + "front_gate", + "gates", + "retaining_walls", + "private_balcony", + "balcony_balustrade", + "outbuildings", + "garage_structure", + "paving", + "roads", + "soil_and_vent", + "solar_thermals", + "drop_kerb", + "outbuilding_overhaul", + "external_structural_defects", + "access_ramp", + "kitchen", + "kitchen_space_layout", + "tenant_installed_kitchen", + "kitchen_extractor_fan", + "bathroom", + "secondary_bathroom", + "secondary_toilet", + "bathroom_extractor_fan", + "additional_wc_or_whb", + "bathroom_remaining_life_source", + "kitchen_remaining_life_source", + "central_heating", + "heating_boiler", + "heating_distribution", + "secondary_heating", + "hot_water_system", + "cold_water_storage", + "heating_system", + "boiler_fuel", + "water_heating", + "programmable_heating", + "community_heating", + "gas_available", + "heat_recovery_units", + "heating_improvements", + "electrical_wiring", + "consumer_unit", + "smoke_detection", + "heat_detection", + "carbon_monoxide_detection", + "fire_door_rating", + "fire_risk_assessment", + "internal_wiring", + "electrics", + "communal_heating", + "communal_boiler", + "communal_electrics", + "communal_fire_alarm", + "communal_emergency_lighting", + "communal_door_entry", + "communal_cctv", + "communal_bin_store", + "communal_bin_store_doors", + "communal_bin_store_walls", + "communal_bin_store_roof", + "communal_refuse_chute", + "communal_floor_covering", + "communal_kitchen", + "communal_bathroom", + "communal_toilets", + "communal_gates", + "communal_lift", + "communal_passenger_lift", + "communal_balcony_walkway", + "communal_entrance", + "communal_internal_decorations", + "communal_internal_floor", + "communal_walkways", + "communal_external_doors", + "communal_stairs", + "communal_aerial", + "communal_aov", + "communal_internal_doors", + "communal_lateral_mains", + "communal_lighting", + "communal_lighting_conductor", + "communal_store_roof", + "communal_store_walls", + "communal_store_doors", + "communal_warden_call_system", + "communal_bms", + "communal_booster_pump", + "communal_dry_riser", + "communal_wet_riser", + "communal_cold_water_storage", + "communal_sprinkler", + "communal_plug_sockets", + "communal_circulation_space", + "ffhh_damp", + "ffhh_hold_and_cold_water", + "ffhh_drainage_lavatories", + "ffhh_neglected", + "ffhh_natural_light", + "ffhh_ventilation", + "ffhh_food_prep_and_washup", + "ffhh_unsafe_layout", + "ffhh_unstable_building", + "hhsrs_damp_and_mould", + "hhsrs_excess_cold", + "hhsrs_excess_heat", + "hhsrs_asbestos_and_mmf", + "hhsrs_biocides", + "hhsrs_carbon_monoxide", + "hhsrs_lead", + "hhsrs_radiation", + "hhsrs_uncombusted_fuel_gas", + "hhsrs_volatile_organic_compounds", + "hhsrs_crowding_and_space", + "hhsrs_entry_by_intruders", + "hhsrs_lighting", + "hhsrs_noise", + "hhsrs_domestic_hygiene_pests_refuse", + "hhsrs_food_safety", + "hhsrs_personal_hygiene_sanitation", + "hhsrs_water_supply", + "hhsrs_falls_associated_with_baths", + "hhsrs_falls_on_level_surfaces", + "hhsrs_falls_on_stairs", + "hhsrs_falls_between_levels", + "hhsrs_electrical_hazards", + "hhsrs_fire", + "hhsrs_flames_hot_surfaces", + "hhsrs_collision_and_entrapment", + "hhsrs_collision_hazards_low_headroom", + "hhsrs_explosions", + "hhsrs_ergonomics", + "hhsrs_structural_collapse", + "hhsrs_amenities" + ] + }, + "public.document_type": { + "name": "document_type", + "schema": "public", + "values": [ + "EPR", + "Condition Report", + "Evidence Report", + "Summary Information", + "Floor Plan", + "Scenario Draft EPC", + "Scenario Site Notes" + ] + }, + "public.scheme": { + "name": "scheme", + "schema": "public", + "values": [ + "eco4", + "gbis", + "whlg", + "none" + ] + }, + "public.inspection_archetype_2": { + "name": "inspection_archetype_2", + "schema": "public", + "values": [ + "detached", + "mid-terrace", + "enclosed mid-terrace", + "end-terrace", + "enclosed end-terrace", + "semi-detached" + ] + }, + "public.inspection_archetype": { + "name": "inspection_archetype", + "schema": "public", + "values": [ + "Bungalow", + "Flat", + "Maisonette", + "House", + "non-domestic" + ] + }, + "public.inspection_borescoped": { + "name": "inspection_borescoped", + "schema": "public", + "values": [ + "yes", + "no", + "refused" + ] + }, + "public.inspections_access_issues": { + "name": "inspections_access_issues", + "schema": "public", + "values": [ + "see notes", + "damp issues", + "foliage on walls", + "bushes against wall", + "trees around/anove property", + "high rise block flats/maisonettes", + "conservatory", + "lean-to", + "garage", + "extension", + "decking", + "shed against wall" + ] + }, + "public.inspections_cladding": { + "name": "inspections_cladding", + "schema": "public", + "values": [ + "none", + "cladded with “sufficient space to fill the wall”", + "cladded with “insufficient space to fill the wall”" + ] + }, + "public.inspections_insulation_material": { + "name": "inspections_insulation_material", + "schema": "public", + "values": [ + "empty 50-90", + "empty 100+", + "empty 30-40", + "empty less than 30", + "loose fibre/wool", + "eps/celo/king", + "fibre batts - with cavity", + "fibre batts - no cavity", + "loose bead", + "glued bead", + "formaldehyde", + "bubble wrap", + "poly chunks" + ] + }, + "public.inspections_rendered": { + "name": "inspections_rendered", + "schema": "public", + "values": [ + "no render", + "rendered with “insufficient” space between dpc and render", + "rendered with “sufficient” space between dpc and render" + ] + }, + "public.inspections_roof_orientation": { + "name": "inspections_roof_orientation", + "schema": "public", + "values": [ + "north", + "east", + "south", + "west", + "north-east", + "north-west", + "south-east", + "south-west", + "n/s split", + "e/w split", + "ne/sw split", + "nw/se split", + "flat roof", + "no roof", + "roof too small", + "already has solar pv" + ] + }, + "public.inspections_tile_hung": { + "name": "inspections_tile_hung", + "schema": "public", + "values": [ + "yes", + "no", + "first floor flats are tile hung" + ] + }, + "public.inspections_wall_construction": { + "name": "inspections_wall_construction", + "schema": "public", + "values": [ + "cavity", + "solid", + "system built", + "timber framed", + "steel framed", + "re-walled cavity", + "mansard pre-fab", + "mansard ewi", + "mansard re-walled" + ] + }, + "public.inspections_wall_insulation": { + "name": "inspections_wall_insulation", + "schema": "public", + "values": [ + "empty cavity", + "filled at build", + "partial", + "retro drilled", + "ewi", + "iwi", + "solid non-cavity", + "system built", + "timber framed", + "steel framed" + ] + }, + "public.cost_unit": { + "name": "cost_unit", + "schema": "public", + "values": [ + "gbp_sq_meter", + "gbp_per_unit", + "gbp_per_m2", + "gbp_per_m" + ] + }, + "public.depth_unit": { + "name": "depth_unit", + "schema": "public", + "values": [ + "mm" + ] + }, + "public.type": { + "name": "type", + "schema": "public", + "values": [ + "suspended_floor_insulation", + "solid_floor_insulation", + "external_wall_insulation", + "internal_wall_insulation", + "cavity_wall_insulation", + "mechanical_ventilation", + "loft_insulation", + "exposed_floor_insulation", + "flat_roof_insulation", + "room_roof_insulation", + "cavity_wall_extraction", + "iwi_wall_demolition", + "iwi_vapour_barrier", + "iwi_redecoration", + "suspended_floor_demolition", + "suspended_floor_redecoration", + "suspended_floor_vapour_barrier", + "solid_floor_demolition", + "solid_floor_preparation", + "solid_floor_vapour_barrier", + "solid_floor_redecoration", + "ewi_wall_demolition", + "ewi_wall_preparation", + "ewi_wall_redecoration", + "low_energy_lighting_installation", + "flat_roof_preparation", + "flat_roof_vapour_barrier", + "flat_roof_waterproofing", + "windows_glazing", + "secondary_glazing", + "double_glazing", + "trickle_vent", + "door_undercut", + "solar_pv", + "solar_battery", + "scaffolding", + "high_heat_retention_storage_heaters", + "air_source_heat_pump", + "boiler_upgrade", + "roomstat_programmer_trvs", + "time_temperature_zone_control", + "sealing_fireplace" + ] + }, + "public.r_value_unit": { + "name": "r_value_unit", + "schema": "public", + "values": [ + "square_meter_kelvin_per_watt" + ] + }, + "public.size_unit": { + "name": "size_unit", + "schema": "public", + "values": [ + "kWp", + "kW", + "watt", + "storey" + ] + }, + "public.thermal_conductivity_unit": { + "name": "thermal_conductivity_unit", + "schema": "public", + "values": [ + "watt_per_meter_kelvin" + ] + }, + "public.goal": { + "name": "goal", + "schema": "public", + "values": [ + "Valuation Improvement", + "Increasing EPC", + "Reducing CO2 emissions", + "Energy Savings", + "None" + ] + }, + "public.role": { + "name": "role", + "schema": "public", + "values": [ + "creator", + "admin", + "read", + "write" + ] + }, + "public.status": { + "name": "status", + "schema": "public", + "values": [ + "scoping", + "survey", + "assessment", + "tendering", + "project underway", + "completion; status: on track", + "completion; status: delayed", + "completion; status: at risk", + "completion; status: completed", + "needs review" + ] + }, + "public.epc": { + "name": "epc", + "schema": "public", + "values": [ + "A", + "B", + "C", + "D", + "E", + "F", + "G" + ] + }, + "public.creation_status": { + "name": "creation_status", + "schema": "public", + "values": [ + "LOADING", + "READY", + "ERROR" + ] + }, + "public.housing_type": { + "name": "housing_type", + "schema": "public", + "values": [ + "Private", + "Social" + ] + }, + "public.measure_type": { + "name": "measure_type", + "schema": "public", + "values": [ + "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" + ] + }, + "public.plan_type": { + "name": "plan_type", + "schema": "public", + "values": [ + "solar_eco4", + "solar_hhrsh_eco4", + "empty_cavity_eco", + "partial_cavity_eco", + "extraction_eco" + ] + }, + "public.unit_quantity": { + "name": "unit_quantity", + "schema": "public", + "values": [ + "m2", + "part", + "kwp" + ] + }, + "public.scenario_type": { + "name": "scenario_type", + "schema": "public", + "values": [ + "unit", + "building" + ] + }, + "public.source": { + "name": "source", + "schema": "public", + "values": [ + "portfolio_id" + ] + }, + "public.user_profiles_property_count": { + "name": "user_profiles_property_count", + "schema": "public", + "values": [ + "1", + "2–5", + "6–20", + "21+", + "1–50", + "51–100", + "101–300", + "301–1000", + "1000+" + ] + }, + "public.user_profiles_referral_source": { + "name": "user_profiles_referral_source", + "schema": "public", + "values": [ + "search", + "social_media", + "NRLA", + "partner", + "word_of_mouth", + "other" + ] + }, + "public.user_profiles_user_type": { + "name": "user_profiles_user_type", + "schema": "public", + "values": [ + "private_landlord", + "private_tenant", + "social_landlord", + "social_tenant", + "homeowner", + "other" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/src/app/db/migrations/meta/_journal.json b/src/app/db/migrations/meta/_journal.json index 22bbbee6..58fd5a33 100644 --- a/src/app/db/migrations/meta/_journal.json +++ b/src/app/db/migrations/meta/_journal.json @@ -1086,6 +1086,13 @@ "when": 1772194536121, "tag": "0154_workable_stingray", "breakpoints": true + }, + { + "idx": 155, + "version": "7", + "when": 1772637615885, + "tag": "0155_calm_hydra", + "breakpoints": true } ] } \ No newline at end of file diff --git a/src/app/db/schema/addresses.ts b/src/app/db/schema/addresses.ts index 801a80c3..68d0af83 100644 --- a/src/app/db/schema/addresses.ts +++ b/src/app/db/schema/addresses.ts @@ -32,4 +32,5 @@ export const postcodeSearch = pgTable("postcode_search", { // Timestamp for when the entry was first created createdAt: timestamp("created_at").defaultNow().notNull(), + lastUpdatedAt: timestamp("last_updated_at").defaultNow().notNull(), }); From a0bfeae74286eb0b81d615e43ab1fedb81be22a1 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Tue, 10 Mar 2026 14:59:35 +0000 Subject: [PATCH 2/3] changing magic links url to protect against microsoft defender and host domna logo --- public/domna-email-logo.png | Bin 0 -> 42982 bytes src/app/api/auth/[...nextauth]/authOptions.ts | 6 ++-- src/app/email_templates/magic_link.ts | 34 +++++++++++++++--- src/app/login/page.tsx | 20 +++++++++++ 4 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 public/domna-email-logo.png create mode 100644 src/app/login/page.tsx diff --git a/public/domna-email-logo.png b/public/domna-email-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..459375f65cfd73ab6d32f075343cf912486153fd GIT binary patch literal 42982 zcmeFYbyQW++b+6jiB0FGkp`98bmyj|I|S+O?ha{Cx}-a$Q(8hqkQ7B)Is`$$yHLM# z&pqRg^Zj?m`QyhJEY_OydFz?)`_8$x+ZffSau5tC1^@sMdAPJX0ARrY08Qfo5;!u# zOrQk*p)rH2D+7QpBLD=41Hd&n6ubif9vlGh-2?yxGXQ|ZIj2KS7yys}RV7Us5b)(5mT0J!Pt;Q%WuHMJN81wRRi3>g_W5s?@Hfgm29G(J8r4vrWOjxaU_KLjd8N-B&+ zCPqRcKupXBVh9OEKo~wgKR&(~9-asunGi0i01k;54v7dcu`m&l;2(@AA))X+j8v3> zKn$N$7>`51OfXF{E&<9W(G3bWK9~h`d1jG;!-CzG<;U`U`T!jh0}FzKjf;m*KtxDPLP`cDr=X;wrlF;KNYB8?#KO$V#{TH>6An%; zZWs?Qp8&t0kchCTn1r~bl#H~j99&*OQAzo!imIBrhNhN|wyvJOfuYeeV-r)e=N9Ic zR@OFlw)PHAj?OM_uI?V5Ufw>we*OW0LBS!RVc`*xQPDB6FXH185|fisQeURMO3%#5 z&dSZn%P%Z=T~u6BT2@hBSyf$ATUX!E*wp-{rM0cSv!koKx2Lav;O*eh$nfac_`8Y8 z_fyj!W%{r-^qmJnQUTR~ER_@_Jk=kmW{z!C==`F=Y1<{7z!)_;Ef8wMgo z_;LTRc^c$^{NG^zGp$8*@m2f}U8BF>;A#GckpGT>g)k(9d%kFX&&#U*ci{iboAxHu zJcxb`VDuExKC;$DfV&qVXA;>nwl&;ZmA?4Hs1NFc&^K>;hZ2bv*^{8zNJW3n0~isjuYSG{4aW!#WyheiWl4vNv!@YSs9P;G zs(W?eN+s|sKO{`~L^H;pn*PDLhFbx`IUrBjx#&y(F`Ntw>dG7`Co$SsiHJ;W$fWB&kg5V{*hjh;m8ehJzT_6I2^^n97 zJV;hgXFruW@t1)qScy=O6ej!Bp!w>uHK^9=??5F%=}PO#rVyhiCLj(22sJNDBC>TR z1c%Tc+zZqv3|O)MT7E0vjd;%jibwuJTj0>S#2?;5D10jjEVqr;FhS>$`#F{*5= zjk#<5{wS!I;H%E&179UUkZyV;5gU^S_FwU0m(P&yKg$w9$?I^Ci}df_`HGrku^bt6 z+~is1luh8bYA_u&Aiyu)t+hDCCbO zvA|;`bXVpUIel+V%I;f#* zk<_+NTPXk=F}A?z^O00;mEFL*6_O%EY=h&UeL(PvDnvZb{&q19A!?q_G1`;7>AC}? z-&GO@_%v16xaJo&eUcXP=xOnR1LC6Ps5DWYtrHafD{-%^^HT%4%iI8QDsZ$cFJGkj zXqLfAPRPBZW2g-w*br14Skvoan9q`UkZ?*lFZ_|{7qAg*3%EM0uQUXd^%7cC-F<2V zQ%|o98r)@!bkR(AFX$Dbac`KXE1XDpO849R%I z^3Kh8oCOpug#xQ5GZQ@|V&oPA-^c1a9sr|{=YZoUoy0l*wi*U$g&+52J|hBLiZI|N zs^rJW#3Iy!-|xpX5L~Se0gf6yee)}V5@vqr`RW1UvK6SozZ(xe-9etnj0pxgIeGx% zjQ3+7cz-WklN6b!QXk;~NivlPUq$vEp@zd+H*qS;!s2_Wt?Ol z6)=Bc3oMlBJcc&0DxB`h`GF&`wgB_<-RVeWwOG^fL~LLbAJjdOcXiv_&ZaQ!v^xTN zAPpA#<*)~nFfqf<)xszcybsp5e3$bzL!GSaXDR_UfQB37l+JGpVjZ{9A?zIph--t* zGQ348ubvaXs^@nT0zg&>1@I004bAAaZ;M_a0*w+dfWFn^bZ|0RbENYz1Q?M-K;~GESgAx4T00I(E80alZ_g~{YT>t8wu_X4WuRbp3{@B&j?K>Qk9 ziCFK$xKHq}LRO&u1Y4jy?n`dBNbH`s%5NaJ8B86b8UMpg}eH9>5# zLN3OD_`7>~J@@`)HN$SP*9dTOP`!Xyx4Rdi*ZK|+ta&fq{I!y~_S)D>8Y$^9D4pV% zjWJJ~G>fjAqG%W}~SfiIOa>C%-_0@wz}l6_-%c9fK8~^dN=K z7f*#Uzo&o6FYK48*o(buT)rFK>R&w@mdg||qW*4xi6j`e;!)Uvjr-M@3_|c2xaasD zpDIB=^AG?TSfHagXshrdqfd2+9JJtyQp+0jST_WE=m949prmommvg_YYJMn?fed1) z#T+{_7%v?k07~E_!!ia2`%Y=7lsgA2nve${?g4-`T_+=`9Ym!-OqTZ*3uti0$5;9 z?|fVl+5TuU=?<7IfP!_Fm!)G9l|Wwsm~DZSK}-;0p(UWN@BS&i|s(caG1f0a8|Q4m)2oA61SR6+l&h0dYfj zO)Li8Fn~i9Y*y@d3wfw$wO9ZaSOcVqmrqOVuM&Vh4$w(XpB=+@7mv^Zcd)|0pX{xs zJzAy&c0h+`HwLX({5GxuaUGCn#-h(fghp?efN5~=Eq}*US7v|R0f@_iQ;!qxQeO{& z+p-|&l!t&Hy~RgGB;Yf+R_}y;7-bZNdH)JcT-~xP?^+@Ol%U?X3{3s6BW_HA~G)*d3@0Qx4F>%%Rx{P$jgQvSm=5kl}Q5LD80&CGz=iVWz3 zfxhwOmBGoH0-8%ei$4x8S@e9YfC5U;O4U^nOBM#uTm%IwJ-)T3*|#wQ)8KYc{^`q; zV)GBffH)h-n(=!h_}DE%ur{c;J1~%qq4hH^F#3D{vyY+H-1W%Gk*TaWGK@%Ra!r5A z#xk?~>f^+$Yl{*$+lN_ICof$(HNn@Slc<< zUY(yir0Or1tQPzZCeH$Qe`9SA3FLR@y?F)Hq7IWb)%&PE_alts9L{*~_xVUge9VMn znAEKC7|AS-Q)>G4uIhC4uBon(wY0hU%b=S&!terx2Uw^%J_QsDuBT0IuC9%BMjoM@ z!{>PF3|w?{TwHYYq#?A&I0*Iv;=D-)NvXMKA2y}kA2V9s5ad+>BZRsXnW za*CDdbJIljDcU-rb6Eq9;f$<;D0Qx}y_xM5yEO(h%pkisPR3qMW*=NjEejKct!<>r zzP+rcs~(Ij!z6K>+O=O-Su)3?=7Q(vs4pis(^j=VdkxL?k(#0EBQj7{_Q%o5)s87q zYNHEQaNl)uy9v7R-#qD!ex@1XFZnPK4=5ch(_g>%>`rtH*_5&9i(+z=H(Z~8yXo( z?lrToxSA&MkrVoUOY#`|Oxj(X%>D4FRP1PsLD?4EsiUwdvR=zZNt z;EAu{Zhn=m@}>^Cl$q-SAhT34q$m9tR~1qf;sQ%6!ebfZniH4&IzYZ}Ud|>zsfKse z?B{YogzwJc;A-$}r})Fd`=?0-DMoH+nzJf;bH2R|0{P8u6nEy&%Q)(}t}gVoB_rQG zn?;DT0r{WnYlFUXNlIHm|5#4p^@_gU!bE1d-s_{rxEs8vs^XzjXlulIzE>=d>waK& zcZK>QQYBW#C3ky~`*yYnTi9*l^uj~>kbnlF0K9mc;eYx#BhtDsQmvCT#Z&mHbV5*H z+N#{FK7H)s|4YfiNp_=15n~Ltz3o}cv1w&@Hse*Yfsh~)!%4JN#`xOuEm6u~NqD7+ z62)ICoey5O9&kitXrjr}^HuP&h6abQDULxd9yQP&qkhRSzoa{rROi+NlnI_Dp&7|j z8l&u!w3ekMNylnr1#_wyLcmr~RcI&&m$2dAxa@nJqWs}m%@+tH)pgWi(akZeOv`VV zzJ0RYCweHc*8X;j<+SZ}vqXRS@!=x8vEfNAF6G2TNRe5E=qKtc*wqxGtDN!i|D(mT`fo`36qTI#03 zo;wknRVFB}ela_2qD1*Gz0%(ksn_Fh**$UMzIjdaA*&Pj*ZxBsq3L;4oHjEeAKkTy zY!lAA#KVVmZ1M;8QYf?b70r{!FJ>bANfq{dnr4+PP2cCy22cdf_|^pwCCg){7|N%RwN!GxShvL;oGYNz3A>D^ zW4NWQND7za3Nbr9!un9Ws`K|MPU}KqSwziaOx68D_-gI9zo^e-ybXf$%Yzf8(>%%=6O@-_o5?*~ z&&v5PWxa%?8Be6-I7);6mIO1L2}OvusM9OSC#}ojrN+L&5pA8|Dp_qsYeH8g&)AKb z0Ig|)6(4aooPKFc^D!g}1$nYLHGT05W|(IW z0mkTZf=6)0Ra}qsFu&*m7n1SjY2p()4VJiVP6qAAwW#1uHdjy}#W~D6akwE}%2=GM z+2rlu9B+HHyV_|A4iA}g#Cby}o)YWQ*N?+FEORDCv@tXJIhwC#25C67LA!q}Tcff3 zBroPV=E|JCY&32lgsO=K-LRfI6=yryNgDP=6=&}yN`|cUR*9!g{x0$7TAE{;q@2X? z&2Zj5(~)~#AYmeXHPO2lb&K|23I$n4!=-I&7|-4%rkU3X#s#KVl;DpGVf#6o{A@7iA)S8>xEL6aLhjFLKZS;a%ZV&2X)$Et5Dh zOLD^5awHq~FY`!SL|lGGgi5;&2R{mn%AMpSl*+ojq*RJ{XM@{+jyTz&lMU|2Uq);; zFY{q-Z3;Oa9dHndaX@TmYmMGmzOkL7laj0qzh3u>7)lTx*&Nr?)6;2sY}8}kFtQ!T z>9j1tn^xz5x`BK1iIiNp^89UkPF1^(TcevovXxvQOXULYR^svKXms>w<=kF)e^JMQ zpDU5l$mJW7g1WwqSL->dBtr8z*Wa7Vwk0y)zph#(@Fij{aoz`){OrC-p%#AUb7Jr5 zIVEF5w-QFMAHYXXJQ+ZoB#}f!fc&-rZb3-6`RAr$kcd z&v5nWZS!D{HB~c38YIIYAl5uf^;FS0NvU?|t-^N)hQ#*s%ga1!e2oztR>^F4YJndg zyCXI@?QFBGC1Wa%+Z~Sg*i;0@P)eAzyFYDP0{@!NJ9T)!?`R*fSC}xZ-{)$k!&)qd z8^^uhr#d5}53zZ}kO!*@zhiR^uIj52AES`H-jHWbs(^m?mutM5mHcHHwUNTK5pZ@` zo}g72?-Yi{RCZ&{q%yicHfMqkiJDkF^n7Yr8(5=4=?rs*anzzRn877lAj2;VWgOWS z&sL9zdE3|<<=$r5yBe%%aO8Nyq^aq`zz>fZ3bRLt`eaZ~FwL-AR{HNn4*sAHh6P7-P761uX!aC_a| z@0@?o(lB0|oSlMX!hT}weSu82_1rD3?o^xWDIFnP9YRZ;oK_17CYt@Mc<4fv;}b+G z{Ph)6?V-(Y0Fve@*->dc^ew`ydtW2v>=1=wGLcs$*xIH#$W0DNe3#G$^v4 z!%1maZIuW)nVV)w-FU-G!AN4DP%D&5xQ>~Kxtp6JSId^LZp)GD>$0afHh!vuT{rP} zPre&bQa?t)(h3l1-*=WIc<}L#Hz3zg3yPz*RTDY0Z||z2O^{ad&e&DO_yXeko}HPa z18Sd2vC%U#KH^#ZEGJ9wiI1u6_tSVkm93Pheb{a{!*Bd+hW7p9V=1hIP~WnRlyUXY zcIZU$keyhHXsnKyR@mPLdsEh5{1rED_8O~w=Ud$HaczC_@|e~OM4CbOIcMJ=6Ky>Q z(D|5SwBWDN*UCpe<}=TF$LMr&>Jr5;J|F6{?%(aaT+20>tpi^)TcXQR9efi4Z}%RS zY{cpm_AS^xxJp@3JN-BxM7CTdLx0!D*Ku30y>)-6erJt-R{8s3JF}Ieowv?3cwE|e zoeQ1^EI%B-94Kb`wZ$~h25p0q>I@uxPYz81NVj|JHt>I4hulp|tPd(~WF5@W4oc5C zKROtCyv8gyiT3PwOLVg!S^RIJu9#-mL%+)pk-TY-juTw+a~@89E9e`wZL>jZXZ_uo z8J6`^O4)pZJD-ZlYa{d0X)iZ@lws;o!^?uOouBTmlULfH8>%ozzTG+#HLGWTd+#xu z0Tqii#z5R-1|4&yT9odem!IK}uPUg*Gm4?uDv2jyu?jd70&+_fSOY<4Mo*VE0z@|$ z%Wb&U$kA+`AK{=3Ye}uUyUO=h#Lr7)bkH4#W-^QEm&EE}eegnzo6#&(XCf89FySlFlfEPANGca`qg2 z>6X;5KJ5?kiE3unzcIlbT;cH*vQhKqBP7*=aO#YqjNl8QN_OtxDPoSn7!v#9zENz1 zuDj4qYuye~xJuZt>x9j|F0)KZ&iR6UvTa+Be;>9^fD(prFejqu!-IXcPKh8s2J>W3 zlx|w_YuoxKdxw}1L{tYxNXl{ka55?rqjnT=YfrA?x5s?Jh-Q_h(~z0{KDNoPjnn-V zR~r~3@QehzM9vnh^N_>0>r+XX_zs4UnOONpv;#&;rFmWC+jdByUiNzmdVBV}n)I-6hl4%LnzxKOw5DQ_k|B6=$IZDs z9jA_VZ7eqx2OEgn+#H!-8HzLA)3Umg93&(`!;oN0o+T@k?3^h46tpoglDtYvipCX)LquZt7RmEs0o7}ai ziuYaKSt~$22?=Rdq%eTDf+3Cw-z&M<_dTkGy3Rnl$6BK$IedDt@~760DZcybCx*nw zH!yr2bPV^pNbmTebYDJUM)nJ48w+Ygf|vz){hD3^L0knBmoE`+F!)xB&k%iP(Lg{O zl>Pqj)vwiaRa_wGKF=S&{l32m7+NIff_e2+vMwL{2cbJk8xIHnI7s{1*hOzZS2C28#E5HfyK zkLb$WE-AVIIRZ+D_5iK&Bu5ph@RZjv?M&%U(G2O_eEICNhMpuzb9ELQH~!cv3FssB zefkQGhCo9I;|SO{EsL^y(-gZ1m5Dy>-4XSiGr73 zz@^ui$yZ2tmgVV)rBoEh9x8mPL#R8Zbj{*v4-`@=G#0c`&mcv$;W3t3qNtgiqlwzG zp>JAGyaHo_{)x#r$;S6rp5e^fyFic8!OMmh#qwF|XQO(MsaB+~cx%s+qi;hV2ujl> zv;fkpIkj zGle{-nxcum`ssw(rk({i#m+mA$C)uoO7f9cGVw0hsUtCBdSw|K8bx)&^jz)>salYQ zAB*x$n(_!4<<6IE6OT zu?~9Ghl--EHE>Gftt-yz^LCN(xcP8iUQ3%k@SzWkQ28Q6bcur2B~ijsjR~F;Ad6c( z=Z$7l&mC9Q&&=sJX2>OXWl&^~*oS_b7sFXdQ6Gbb5=KZ>4{wamfxXu0oBW#`jU3 zl*zU*l6;~Pzaiok%&DE66A{Y1v#|wH!@U@z6ce}PV?3XXtatfniqRyuu;y~U?;Vu{7i zSWufOWQ(Z-J~jRB-ZdffP{Y<>LiZ3+TPh|~JsgR^4?#>Wsix69Gv6${$8=ramns}5 zWQnC_DgPvinTMXDN?5&VO)h`alccfm6knSI|MUf%!6j%Do#FEvA#ux>AEK)I?eDi? zLq3_%+q^=G8PyoJsX5JB%~htSmFv#6l4(({(|EF6nDI+Ds?)B&PK?cND+ zJ9mB9#7ABvhJUFzW9+jl?bM*}JbEA1nseYo#A=-SL+{Gz)vC*bjwY4B>IctD$J%9B zD$t|@d@eaN-pYC9hnDwZMKKye4t>5lcUANb8Ou%F{@@-S%nb|8E{GDqkx=~*{h@>- zX42tOJn8qht)!)tGW1n$7d%6c4zI^u+p6#VnL7i3VqQO0(YRyzZT1J~H^QW+J}&IY z0!%n8;qv=Vop_=4)Sh9)ppo+HtI7_J)}+B2NIz-SgDG(dtsR=cIOnxN_E4Xkcs)R3 zt?D&xLwq9tnhaqlc5VB0AA|SDDT$}d*{o;VncwgTC^&|vIupc4Yn&tnrAnoyUpjI> zD0O)=q7+K{dzNuJxT+r_f-Q`A*12br1Ab(>CxnSIw-yk#8e9-xbJ3?1o0nxml804; zY?Di-j#0-Nut9IQ=6%lOJ)f0cSnU!7XRGTBNe-wS;KSv*2!xk@lq4VAcQ}Jg42tfq zNk&(sFdkiLzrxQ`(r)05^^(d)If~r+JncAIc6tyw@6jd^y7g76)V0G$d7PBcAJIeLVIvFK2NXCZ%#Ao z%3KCm@_$L<+$yz~VoGz=!$YP$|E5v8ICJboE|?pYfwmf6EPD_!Px+I(*+7uMSWYD; z@^#Cli?Fc?P$+0qJH zl1gE{@!UFI9yoc1=yY&)BR2xqyZ$U(XpSmeI7p!2xS)h_vu1=TujI*;p|xX+udx8_ zPuqk7UP;j-_!P1z2QEOOTU5<%SQ6iow^P(3h%ygFIpdPg< zDamx1%cnL!ZuvP^>cI1x2!73&_Jg{W8)YB@Y_LezQH!QedGkqFlF? zoUEzK*Y?#4cY(q0KXd7aP$!38AD8;Y!bdBvIk*k*V-~+6p+ss9L`_d_7Y|*%n^qiG zS9kqD4XU4l1=HKR!NrXsqlG6h{FFtEQeu_oEoiPV@3ERFxM+J5xm0wGlxxe|fOA7g zU1CT{RaaaBWCBxfHa; z9RHZA7}ql++|V91mE4Yrw&^Dp!x3p?CyTk8r~mm+Gh9gn*?FpbHDkXc3e@2Y3kxX; z{w^jHpGVRB(^tY1@r>wOed9QikAtSd93OWBF627mVs)0{W4NQ6vPWh~sPRUK9x8lc z$oBa>A<^8F*!>$@37+DEgMqkj=L%w;%~%yCO+=KD_hjR^L>%!_1QvI#RpEs8kv5gv z$!ZP63DG`3`fbsFUMj4DYx1iN+q^M|)14|RQtm3Xu-J;({2N6h621%8FRDua z)o^4+VPw3rL*=O5Nosuzgch0BP#^t4-xOsDNe1ifLh!rvK z?v)b#XstfnDu@0X`Li8{c+DTdwN!L!m<4QK28zue(0mA=fx{V3nbhZrBJK2)=n`f_ z8P1>3;xPypZrH@Pc!rs`G%GNNdnQ;Yk8HnYcewBb%qCJA3u%B=b%#O-V&G0LreemK zRdm~>!037>Y+7qcG@2zB+en~Pa!edjt_~O8`9Kxmf`O~r3gc0HB9)H2ASe0kmyx12NL3qC}tRai+$MCT?+{v z1$P1Wh@C3#5?LevX&ch%)!qBkC%osR5QOwYA(Zi--t_$x)fy0l7ptcsnmMV5LP)Ll zPTc9oaxE;+ki$4F1sG)6RroT|5y(EXb737?vtPE9KQS|Q$XcWP7{M5Gy-z(n-BP(q8 z1DFMlcoIR|^O6#1qb6r|NuN$)RJo}lD}FG}s_o0_LWUkkq3aewed}HX8}{r3QBp~M zd?$R!;eP=BLnFJ)Z`6oU>%d{_cUClwCM;j{fXeFn5N*B)Ik663u|gA0MYp&!Gfld?EjT>0 zsec{1x=ka(rYUtJ88m8f$c!euJ0jHjEzy592tAGyvth6Mld2bVHXswQ6I`hyt^Cf= zXWfh+2~UMtDex8eD~Fo4T~*P(sj5`tU?q(#7bgGCD`NV}Oab<8KNn{)vlnXb#JEJ0 zewk0}{psbQ-HBYwu3JDqX;a+u+3shd^;EosvlX|0VljtV7!sjS) z4XB%Eb{Ivufy5~W*F4W&Goa!du7o1^z?6B&PM(z=lxF6xCWX3)Tc=NQK zZB?qgh_X9eh?TXMlVKK*g2+<1{a~8t{sgu)6rNOaP{7<&3e?(+M{Z| z#7^;(Tvk>&3a!*GGO7097}aO~C4`mIPQ7V|687jP@yxg{(L2GpuseUt<$}mOVMNUA z22xjUA6R(p0m9gRzyh{Yy;xox*ST*0yfn8Z5ifPxdu$cI5=PA-hme;q&+(#PS7@0Q zzoj-!I>IQhen?14tR8P#ZNE!R@|*4oAiTnkx*O&RtK>8Pt$RS_D|yPy7uF{{M8R$r8nc- z-dOdE3z=qwsWzfT3Z%!oE<*do6Zo4b1TJC;Vy`8vS`$K`zls*?yN1qaI0U*E~ zvx6{s3dNAu2)sLcltJa0JrJV4pJ7SqK2@~do4+M^g`S0a5uFR@Tk;mWfEp2eYhiKr z2(T93)_)SeJpoaKNw4&(Xq{bjM!`&j)Cpawa=ybw zxmUQ;O75$~qsdQI1w0(=%{oV#RYDJ!c-k*+RY*fQJSKi+`<8=G=?91ZD~;Fj5F~xc z$&Y1f5)($4dYR48oAirt_pL`^*e&ptf;i6BpL;EzRCj&KGc7_pD}{?U8lIPz3t??G z?du~we(fJ2!11&+XO2S*lhO4#SsIW1gWI1^L$aQT$;q66-|(&Y+d$Brwyg<|IQPu)?LBY{PXXiv{!_ z3YPCnGZf$&;^G!JC(B5`0+hWz8i>kt^t<^@?RxpFUS9p~xt54!of4RL6H^?=$?Xn= zWzMOdkCyOT&DThOLpYGdm#^4yH100sTWGlxx?A8Ns#j*E6|Sw_X^Psf@D}aiWqB zn*D8%xbOvTQR2jJ;-cFh=326bmO81-cF%^mB1g>+k?qCgXDQ0Msr(T57#g9D*JOv8 zXY6=3KUb-w=_3T?JfddeyZbMW)&14QddTck{rw}qu!cdO&o-u4ci@re1npYe~T5bA%B zB?iSB)kLPCHhzC zC~N<$n^X-}JZ^|3GDU~a7j|&@WW7)bTMf{XvSYwRT`R~Eie8%7#!F6%vHZmGjcwtA z{(H!BpS?e+Jwft1G-)F{%7Rpl^jz8gO^?wO08p#Y231D#-u>daZY3hpD5)7mkW6HD?k&KauR$74YO=%8;^hhaYv+E(H1zs!SRv=7DmW!kb(9 zo+C%mQsdrEziDHNH4`6H7LIEzXm>}~eP=S;^ChCIIQ@>-xaZ1P$ku^v@MHaFr3Jo^ zI*ejI!1PHD&lPEdcMv{Z3LT}wnB$Xv(q*LO+@E&C#P;jB@-MGnl2$(WJcQKnSu3&C z_y*}p4d!3@bIi?oCWwa6n3MMJ?PG zYLm|8JvAiuz+C@wDDX8+z{vSy2-#ry(uYoK8TuW)fybf8i2QI%zompb)YUId3Yc0UXDhAUtzqtbkSUw8mzq7j)p6QKZ6)O9%>#x6B+DVljF4L ziGXKyg_#0t&=(aKrvCH()F30`bMA&e&ON`uj$qRCl-0K7LgK((1zRbaNDtX2{(Y4y!CuEym#Nuah*^NhLC zO|%p*p@)xEJ)^_nL~DR3L%)<(j*5x85|zsJQZLt|DtcLw4L6zRCw`LdYBb~$vYt>ol=KCz`Jy0*Imye90TlM1u6ZGgU9O5 zO=sh3y=bGum72L+_obm!L0|n}>;2?>Wqi20$CT0= zK-!TKA)5TU>4MUA(+8$R9^Lufay_~eFS)pC@YtC9K${nNd`;#7z#|%FLrAyla!$IK zD{0O3JGf-m1{uhZN)WD#OrBq>x5EA!4I9Tx4hO{^AMkO7S%f^L3j9u{WQHrB9B`sJ zkmSl9v=R>hZe#J=bE<+>527Xq$x=Z9atcpa+}q-a?)6uJp__X~xblfeAl_Q3V`sDN zky9#LewC^3Gm48bjGPAZM|3InFG*X%?JJ559v;3F6qbZN=mC2MUWCg zhF&j|E$JIeJ?*NAl(+iYOc^9CP0t}ERU3)PrAz#SU=kUmG zn2Qk4CaQ3$AT3>t^4r;!KE&ekYg>eV20?Q9@DDqiR?&d^YS|^hW`uEE>0)Qfsgc)3 zMNGDVnH1jo5RF{wJJG0UxQW6PPCJyfVYWLW=PQgo3@`a@?jqSZbOV`fEF^!9!(2GQ zZuU_G9ex3(f@E!^TSIk~+^PP4wX`&bPK3qC)8eF)7wL0JKFy>fw-PvXG4SBWgQ}g$ zo>en%jq^U42vj|!Q?GxAd?V>Oel07SpFZb2pyT}c4CKa&K9Y~zrnO)2Q&QPv6oevW>d`jO$%6>@>`!uR6KOmC_GZ_4}sg(Ag*-2L6eq_R%>7{Iy;DkEXU1H zp!Syu8y#H;nRe_N(bB<-O;XXtgdFplN(p-U%qC8r8Yv9HFI%QC&6VIYcVd0%P#(d3 zk)G}6KI8(6j7G2N@l!%_IW?(eo}OBX=10wOlpt^KO3>rQR6|<=2*HJmA06W@he}Iw z>E^@7()u|EdS0AmY17c*XE>5Xc1gq_TqjH|Z!uyKMZ@{?;YTzH@4jYyAzbU?yPyLx zih_{==%zvJ*-5E${?UcaLUif{2-ngIrC5$+zr5O<(CO&<$-*pTaOVnMcHcM*&XC}- zsER3zrLu%+2tH**(1g(87pswa_L5(Cov$V)cbQd+(LHD8@5pXWSgXc*n#u9ta;`fT zT*m8sqKgAeNLihd((VoBe$SJ%>qQZ$2wfocY zqUU{JA5LD7ib@;4>}P1bphwUKF*$7Y?2rHg7ucy@OBIMX;UlXtqt`%5* zMlSb9j=U5rxV=VuoLS1q8f$F{5V-d?lu5;ckk=Yx{APRTc?hn@-B3 z;jl+eVFge8spWb^*3hyNHQTSe^c7FZ(`qYjCs$)7c#5qWWaKMDjOkX*c&wU%x18NFM zuyoq5oh|163au)Y@SEYRaRN$^f*%AFKiBdtG@`vuNl4b~_%Xj#UGgC_1%Z6Y0 z?J4ZdKd$4adZcWyQdno~YG~C^vIfGXiJ2P?aX<&K4;YWn9n1@>zVZqF(wE``F$W^D zuQ7O{2-I0%E8WEM@7^U#2eyZ>Hxrz!z2j?)g)@Pe&6u=uL}gQR))G|mGv1SyIxHgQ(;-Ms)40ivu;n zG?6F|kSVAgo}*;-m%)dQcxmK4Y*h7q9xm?iz%NEKFr6-{Veq*oE3Rz}o)8WA@DVskp+<9B)WL(t9URHqwyGbN*8NnaSkq(L zJDVELbtse4_`!!KSaD`916^$MW^lJ@Cn)R2uzp311F7?Sac~J%C}v!6Qqtm6(Qo_a-$84}^}{qVZ}Z?Wtkc$=j>>`* zk+0H{TlbYWoOCjvv2J3;X$65*`S-JOsknBK6fRd+q2&DP>W@rWrlX*&++SG}@*@>N zZFaeoMve<-$#m5^{Q+j4X5(#WamN!i1?vS^5C+e}+UMf+KzbH}dJ*G?+2s)3n5v(pVJj;%hv zU;5`c5xih#EHE+Rcho2F`I-Gm@f!N+c05~cl;=~Dy>GMRl8V23q3WBA;zDF z6k8Tjf=tHXmEr1NoOJ{iF%{7&H_Xz^y~R)|mL{?;mV(FLS0jfPV&U2RJPf8JA(geE z3$8_gG_Txbr8trYm9#pTQt$d?%W!=Um(BNGoGw^7N~8K*>F2&lXN6~Jg`h48HI#G( z$);3#&M=1eyorr_#0@k5TrkK*ueDY8XHCVUQeH(R7u!1Aut?gyADErSD#i67lz-{t zTEnECg~2lwjgy?llqZ)`39Cz=#z{|o!*rc%H|kxDz~`d)66y`6qcRF~yAO|kla{_h ze|d_Q$NO<6x$aXFR_Hr}m>VMbkXWh9@DJtkMAkWpDX-8#TLCp;(=QbZdLAj5877Jr zJAhHV0Z&`YE%%@d+92* z=TRxewh*DHg(ruvQK>j#X*E{(A!Yth{Zr}xhpD%WilcenK#AbCi@Out0*gC~EEXIB z!F_QHPH+~NKyY_=55a@GJHg#UaPGdp|GD?vFLP$*bU#&HUDaJZJzX`NP6b-bF{_kN z`@N@3e;a~CX6PVQ-K<0!&`DLQ_A1+lRam5%qsqIH+9&K!r)mDQ4|_gRh8mYXBP{VU z*1m@%=}MXj%@&~X3{%?`?6z9Q6_kyVDp_4z&-Oioo0LxZt0L`StkPS(cS7s(`HMT$=^Cez z$iBsX=2F2^LOc}A4C&~nfI;PhM!|LCu!Nm(4Q6#IrPJgu(yP0x31u!l-mvEb3aDA> z#=%EBvA`~pP82o#A09MG);C&s3vH#w1f`eMDiF;jABx(S`jVu_XPIPcOBw~FI5TKT zI{6AymASgqgjfQJ!w)*m-Mna+{uLm)6r@NQW3au(%Lu`28%U|4H#zW*(kU+rP3@H% z`$$*n9QG}4@yK&_)Hmq8;6{vrX()WUNR`$8Y|A*oo|t2<-s?v_$X4@$^ zf)A@nLa>t<1H0dj@{?ty#>ob1*Cq813Czv^x&cDIn4pG~L1Z#pMi$w%dJ+go0dwX< zJ{n1)E(lc6EHPwk1<@pO1NQlS6KHf5ia-08tGzUXL|&!S)6xJv7eP={${^OZ>JX-UIfb~I z=1cNm3;86=iIlZ2H|PZ7^@A3IZ~fZ+8zAIO3~GYOt^7JLr*)@wZeQUlU}l51-Y<|q zvmp?8;iwD=FACWNX6FZXfcM4m>~i!wFqSySV{ttAg%mQ^S|2+YaA3~;K_y{c5tH(O zM&v6aq-<2#Qf+kAZFV_g1GvQ9;kyXBF_v7QE)^u*y69NrxpAk=<*7_1Q6r0{^uU3X zb;)d;`!C`zsCe@M4p)&o3cNqW7oSV3B~>vrhQWI7FCrZj@Y0Ct)J;b- zv)yis0F}H{5io(^JeB6D*QWxt4okE`>!Ddrd!cF5poD@5vKy|5`%%-`?z}nhElG&{ zW2f`GgtEVrz2Nm)dS*U}MliwjesVFrlJ&%mw<cmpjV4eJ zmxM~_JPBRW`Arbx-g>nPgTfCS>+EQRrp4$600iDF=~7)TP(h3P99+}i zdS@wd9mjrA==cIT7<~KIq8Zoo;agl{KsL?;As-KdqYh!AO~-5vDU%logn42w8J}@) z#9fsS9Ysm`TA4ww--cbgElh8?PxClDil68WWw9As3d!05h!BPuFFJZ zNhZkiUGn8K9kn2r)<=eCrabPJ4`4F5-bcy}4`MF>1))3w?yFYA)6i1m0W7uu25w?6 zKaub}zX#tVyF(gDy))TgZj=fq-g3jk5#=a$?ST2{ zJYp_*J^tK8>R)LeyNudbdmS08`uw5#adjqH^rBF5$TS*VDcEwnsD<0U_>Gn!L1jlAn>UYio;Fds;2QOo1H81OWO8`dS|ZW6R!7#Af5S9df)Fc zcxZ!6`Bq&v5S`$>5nPhiMez7dc>hZEtP>R;VZKbwzI~Qaw7lOCAgK@iQhmxRi5Y^X zZ+D@!vy<_Aqz)IX2^y;_1h;Cd`1>=Q6NZYm(?dHm>7QttrUyt0Dlju-ZD*HuW_DT= z%jeX3=k@8Vd#~lxR2^Esvi3h)V`1`iW-nT+4;EH`#eKYm(wUzKvB1bLm7NbW;{R9U zwxD#PuAyM7NvDOl|L>Sr7Lu3io7#9os@Shf**dR?a>L8$$pD+|?2!QmOP}DYMjdF4 z1VrsPt;O+UKPK6&CCSkj82PQ=RWT=}iJ0emNa~}ESnWRwxfeWk+kD%~A0%p(@V`yz z@EeER9E#psKBfKE^2wC#Cy7ag*Pnwic&*}Ec(=p9^ zukj{sMz~ltR7=_xe~RNv_XV2p!F2-D$1ZM>z%qdkcV9JpULMnw;rj>mAUczdg`b%? zt1h!t(YMz^)VGDJnBZ(NB$I4eHMZ5i3NT+m_jgm*>DNx}Z~r#D3%_bbg4AB}oywt7 zr2l=3$;XdvlK)Hk7nuh_U)3vH0(5Is!i1dAJ&xs(_mELGV8OY<7=_&+2`{b2(OdrF zNp!^OZRgK-Cf=0tSy5S^xW<+^s2T&?tAiJB)Q7%vZ4?Nkk|<&(l=0s0oicVm1f3Nz z`DB^=;>scuaHr|3YDI*Aoc9p=#+TE`1Uf&HJ}6<*dtyPnq-N|><(ZUQe(YVOuTb&w zej*LJT#V8hN%mUgIXV&_;d& z|5^Nu=dz?PSC-3d;IA{VE3(sb`8eJ1lHDQnTHZGP58*{HY?q1(mRAy;Homy?!-Z6B zh|H$SioK=B=tH0YQWZ?s3is@T8ORbdWqN{eaXXJvkn(!wgpt`89(aokt< ztV3*e)#6w7xy1OrkLdp2CuEO{&F=k-h5Zhn3P&0@jw&4+s=RN;CNX?qAJ7g3owG2q zjHG23d4oO*t^3P+nlh#Rb^my+GcMaXcFZeh`!F1he%*J#XV!@%1!1Z!Xdg(LNG_K?s*avN?fOJ14tZ6x? zb|VgkP{tM|Fa1EeV>r*UU|oaCH0!ILPhhy^t#Gd0WgW(Kx2w- zMVCs=olIURvfxZ~!vpWUAA0rA{p_2=asE^kmyR#iZERJ9M1ymAoUl*zTl6dD&dpyN z&YkZYD9iHaSW=dTZ-4^5yL3cX99AUv=ezubgr__uBxOKW0 z0vL^qDz}>7Xi>L~ZQnK<0|X$qVVrmk3M-LO+9p&&^CWkJq`*{7%iVbd6#00MoEB$S z5Qa!CWGS`b8;6NNl-&ygc!%z?*{DP_w}_B9$WqEH!^WsG0Hz4_rhAh|FcH)j!ya1e z$C8^r8LdV1U`zuW{H$EurDGL?%ri@`7hpJoR$R;6?vdnz3BIAN%@#&dW%(clQgf0z9ssr1HiT^?Ocw*jHq!H(LB-967AN(B;9e3|AaLK$CODP5DdY z4=FP{h{FNBqpS`5NG99!Mywo%VUf7_1Nx+bxUow~7g}+=FDe_H7IA5E>H?r=Jx+`V zL0!2kg{@l1b*q^T@9pmlIER{Ez^Ko4H)Y=*&QDP2IYFEtKzxY=!#1`3x`Ikqhq1fS z=y{OxWEk7IJD|pk7B<*gwpG=YVrl>WM%D81yGjtg^340;Ei8JPw`sOZ%kQ@gAOSe? z->Io;4w@%Jv<)0k?s!qbJGO*dCz7xI4-HDoS6QJn6^>~D#>mnD7;CK|R%pvnFrrFd z-6;T2Q%-(kG#2CUKfHghfgO*2G8m}WsN`jLhOX&IqT8nrh)+LmanSdLl@p~QYA(Kd zpuP=^T$V)6I>!is5mN@iz8D=rP#Tp)5y?Fq&ai@moO_@9Y1gNkx-d9hq52k<-{7 zTYkZjFx;3t zUF5)^t!y7b5WZEUX zNIeY@%x)DzIQ_HV?pqt`K}K4T169Uy!3X}n8~#O%vP+$oQ8en?I}lbW2?d8W z_M8qkfw%Z*;u-+{*;VDrJ_2sj_N9Nyi<5)98b*sbB#ikUvjS4E23~NXsH53v65I=L zJv;Z?ae`SJ;2<{g+;IW}>o$VKRA};$i`;&fwsv!#o|SM#WaAThCrc>y>JOSg$7o=-a1C=UnHDR~Oe5@a{cK-j8u^Qj@jL-$Vy!Rmk` zWvpMwTv?^0KDkl3vMb^$m*^47^|*)oKQE+1={-N8Bwjwf5CAktKEDa~==qFC?(|9t zSI1_R{d>siW*l37m6UJ4)448{h1CG{w-6lRefso4r4u>&1ewDeeO}n%i**5w!&SOK zJo^n(kU-lkiN=`h=MwosF^J~HY(?xe| zp8#fUH;Cxh6RbU{i1VuciN5>p3c-|6(FVcf+?!xy#p;27;yObsgFjdlOKGSWG>H}P z?bH`j9m!ABQ_+N1WMQa^vV3K};L(|_W&g0({i#csO)#;-?|(hmW+Ozy{yt_H(t>HH z_%|}FB*nfLTLS7v_*-i6@2^5Cno_g(SGAvX5S?O^%;W_f=1%WiKfy+H5U%0cEWbc<76iLdcR$#p zZ0ZloLArJIL4PQPF^BSJr)GZ*^m)sD+Z@tT_UE38hInb4Pdr2RDLgCgleo-fKBw`i z8NYw21i+mU7*8xwo6cbeyOLH~l{@hy5p3f&5>q@-sT;&jI5bQkgj^Jh&&RsB4=9YtyFq`r`_?=yq! zE7J;=XG0bxA~&<_uXi*FbI%8wwAAA`gj|-=^gEY>d48PqE%eg~w%vEm$i2Z~^UeiHHWnwvD5)zMV;&Xjtm0&Jux3Z__HCHr^*duCoD zwMhJDX+@QgF2Y1!)WG!QB1GggA8r=JWL+1EJ@E5CnLSAZMNGIc zq?Ik?Dy=lV0;7;CtfnC?k%{V`vp9>ppCAe!zxktkfPa!9&Ad$iV};3~rtb6J_mFKQ z4^(+v3xDaNrD;W1Z09W?!ZC#!h2g}1eWEy>%=LXNDnT4zI1eHH?7}OC@Bx&;XR5Bt zlrj2EXF8wLVIqf=ibfhQ7@sEy^1{K;k?r?hc@J0QR5j(F{&_VOcM;M&3G4mMa>NWhXhJ=#)g>jS z3LBNd*TGS#DwJ4vdFP&TW4Mzi$p1~X_N>t)yr|a8b($l4yt75;`@c^8Hn=)Zbnl21 z>x09-wLYw|IHK8{$3J&$!UXD9jmk3R81}Q5t}sR)PuqxX7BYj>b+XBcje}^>@*Je> zS9AMj#S8Mh$zFj;@%pPz!uzM2&l?mMf^V|BJBb^Cnx+ zKbz0z?b9*h?B8nA_Y5q034bUezrS?qy(3TxrnP;3$edWeL4>OI25^1)yqR+TT7wNP zNQ(d#UROH$%X)ZtjsK24EfK*)iaD?dFlA2AlJu$oIaUS8nJ~rmjNw}^Y&J3D##UT~ zNKvGTKDT2xku~J=@|@rdOq7_6l>*W)ziN_3`W$PwmY zN%?6#5p9INe75zWcec^Ccrr;N4MRd8ZOaPGr%+yf)qmjT6*h`h6n1pd7vtbRI^_&S zqLIcABM-|DG;PWp@tViR);aF$*jU&B3j)d{t>BI}xjgvB!MEANO<;9xKex4Gvt|zh z*$oq0e%?4)TT_@(B|^Ta7O+rOZ62Opt>f$^wk8s2kCU$`vG0J;C)5zq1fkHQ^{i7d z$_=7;HxkS%5xL@$qN}CpH09X^B(^f`O0V4X>}GJwVX%Of&Ib+}&iB9ZBadH;OkBH0 zOHoAf{;(Yj#tSgTq@q#%YiqR{RKr$Ph4qUol}%!h)@de&ZG?KLk%UXej*&C`^SgQ^ znuoO&1(|tF1dpcd(nyIr9C?MyrCIw%Wa_c$p1d*7+PI?56S#_g*(kFm#7D`_%gLEH zwQpXQp;FS#%{8-QEx4p?dB?>Fpnd~mK?37N|IXq`kq`@xabKMkPiPpH$LKt%`Pv5j z(dQFn+(9rcvi6J!rfUdg&&Nuz8Xg9C%vqlv5X`X04Dy9L|;tsd#cH0v#sve-bKWb4%OLCF4b)>yE@=RgPD!S)XESYcJOUV-*sz8c#ut0 zlsq0NtVbCrx46*t3yCJJ=U>+y84vC&P{C9X{P!+L#ax8uA##&xCfXJ@tVO^44f2a5 z1q7HXh+Ddw#7_ zf*yVxQ_O6kRVQ^;zxc{@SuS_HL+PrN2ckD7TknNbgvVV5(>AOCW3?5@DH)FLnf^N1V(X^$$ zPL8h%PM)@GyYOQ93op5Nx`mGxFJ-mgBMzzyD;Plx-`g8OTar)!@k>d+|B|=Ie`9&4 z_T-b$B5Ouy==)tec`(tBf|#M|a-5t`%gAc8BESLeH~cd)Fu-Rt8oSje4U+(zGbrd} zg3YwnF+;3*<*t;zfapx1o7Pr&7xNk#HRS}eqUN+kRo-}Ncx?QrG#{%C^KD5Vq$0S{ zZzVpUW6;=VjLnMUA!Wqmb!^G3=&CGv6EJ`!1FyrEsAybVFw*L`MCDXEpVU9Qm9JhE z9fpCyNKiqImVd$}`Bf`?)lmVrBnuxD)(OGj0PD3H-$UVN?7XI;rD{o5IC$%5Txr0d z?UVUqWJJ1z`;PMo;W3hw%{p87w?J5rgs;zDo9d+A%i}&(3L=t|R8_k;c<;}1=}x;8 zW)2lUrc^mfQi&UdK6fV(K)gzoI==ZX1N{P*++>^QNXvb-djPwz zo*DkRi#PD-~A`Qk63)2foxWSTmOAM{hmtl z)Cw9y2*x|hxP+XKpGK+()r($}DE7Y1Z+TygG)@9*C_aMPKshu7Gv{&urI0Ta_}oK* zlTPM^*C;%|wN3fY*UqD}?La}LcD_?>P9S>J^aV=a5faU`nymF}RD(v7xRaDd;?jm7?d`;iRB%u%I z;<*Vn09QVl@ZGS|*^+NH^~K~TpY6N}=u~%tIY<)&m`|jrbtJV`LTQ6d>Xvzd)Uzz* zc6w8(1m=x)bY|1HkA%W&dDF-6g4(eMfmHPtjdpJoEyEHN7C=FYn5X@-;%12`HqgqC z;E)b67|gz~9MmXJ+>;8$UnMDvoJjhTpCeQh+6DgzLp=D={uH(INaO6uGd2izaNG9l z<`1^$Txr@bePICJ`yu%%#)FtrYAU#MCv!}m>G#956kJ4+#X+XMH=Fh@-1 z4=H_`e9x!qwUc!jsh(WkXhnq0q-(1dIPG7YXE0q8R^|D#Q*DRN;r|M(9CucE^>YsP3 z>ai5Mm|gbE?U!BOCw^XB9aH-H-S*I{{Yn3RPT_fYUrgEV&UVs9Y1!+=8>tLBiGun| zH+T)?4(;R~-h}rOiU?<}^QEr3U8^DN8SQS0d>;y$IouB8@G=wZ`1Y~Y`}ruYe0t3N zk-N<1U6=jRGFn$4zdQR=^$&YqZdQ&!c&PZ#3Va)uI`DJR2uF3G5_sZ*8qgQfPIm+Z zmDEaOhAM0XgjsW&#qcC}ng)HgHJ?o5C3s$gl8XI#N6~y|QW6CJVcoV=-z3%ldtI2# z!OiTz_~t)cu_ibgk*b1NF?ZSSF1-HdCM4NJ1Oy|evOkd+@R-r?NcIY1>D!_mZE#4& z^1|$;7D7^c3BoUX=5 zCx0G1{53q*f6F4gJ!SBq;_#@(bB+(TGXFy}Z*=|lRp!4Ea0#~aanmrsMf~4wem#cV z|FzgXJ=+HyWv-Tfv zrMsPEs&#M#f9QW4)=bVhK7~ce{s*Z!LS{=j=79xoHWZo~#`lq8<0rh!HAjSh-g<|+ z9B08{A#B$dGeX4US6*;275r%R0ByH&!|SSzd?8CU=PwHoTWUYQU>t5b-`=o&TcC;$ z006Af76COmc&Y^o3X(u+gE!KJhir^ZD-obT=M5vmLOOpK4U9_X%^L}Ejk4+V8)dmY z->iWS3kBYxlkpQXUT?n_>Trs*piHxUKFii%fFufaUSgzVtqn0yRxRki$6%NmJKBIE z&A2rD9{vKD^aU@57@U#z|9ezAhViJ`{I4`Xby(VHIxle~r2qe(X-FVYPS!KY|6vEi zWZ2P$hQ-2p>cEiy0e~3@Lw0d#qNAkH|AU7e?Bvxbewdbn{$K5>A!*~!tv^uIk^e`W zIxjv_k~1R?Xj)|uU=csrB@Ue6uy<$a>_$qwyr{^jm*UKU(%n~9BStN9jv zuEk*emPX6@`)^2afB*CPml~&q?n;(U`E$)kmA+=uujg(=TTl^?LConxYX3e{T{Gf9 z)5b{}tpZRPzESgStU4@5!^@|idTinHosFnx>BxPG#%FI+1t61XS)Q~Iz@8u=`3eDak*G8pIy?5 zGRf87O6iUYwT_B!AEDG#`Yb zHIcdedYAhVvE6It_4$)M80CX?{4OS$f?5z)0!hYE6|JWM6$?d0Fe*N;RVbNFDE02V zb$2>>m~o@FmFE)o*)mbZ!e$}4Zr1!$Iodo?DRF%n9#TL1_1IRuf~#b+p~Ky|lSF4{IX{h>l*RP>cri%o2ZO2Z)2HRv zdjuO$N=By8fnr-?&W*bvDk%=*p!8Xer_VvA8_PF%;f5AbzzGQ89}*@#(Y1Mu&&29uK0l88tUX~utR`t{RPEk}&hJVpHNV|qWbxkEjd<_Q8n zJ$i2qZS*gtsZmlJOwkOt(q+i21yLuEkR7p9inr_HCY1B^u4C`VE_;S_aSHTDYOMd(OZ@|>mwZEc`QOrhlFkhmAE_8 zQuGq%uApr4_{@Dmph!}7C}@-fT+&^4rog7(T9na1%Ui z)t>BqG!(jPym6mI-Ho-r3o_1C54=Tv|K~SHGH*{J7(=0lAe`ujKSX5e?{5;W>X@(b z%_+qj9HCr~lklw)`g6%yKT2v>bpV! zdUxROxogyOwXMjThTr_zsXp%`!nl9J7{+HC`qVkisHaUG#kgD=a0yOCLZN0|07#wr z357bQ1-#Moqrp>m=G-ack7}_}1t~&*l?in-@tQ!`PHL<{e>lTcGT`SY3Ac+q%`u?5 zh+>4MYPM(;rSvt1irI~8HN7tmjwxdE#xd?<#*z#b7dHU3>1|JpB|h>sqbuMeLYosw zPh4ImiNy(R0(``!!C*ET)z3%C|L6A`hOCVHGxL*)qGwboZ!w-lUzCncY7XejRM5o; zMTQbTYlb3QZY3YEqJQkx zL=l2f_Db=AZX9bh&&Ovs3bk7Fx+mqIMWv7eLSeBmrBur4nP~FG!Q+EKpsUHw_eFZ7 zZ`SWEs0^%hJU50;@nQnRz9^=Uw>`egFyFVk<|;N8`MK)+rbz!z0z*`*^Y4y`lwpcH z4yA)eH!M3juWwy;Jv8U>06`LAuC5U!0e&nZfn2^jo?JerPDTCpFXZxo?0!HI=w%>qOTWrs08K5$?<^Q@Vpyy;?POZXBg1s@+} z)PiU|)p{-ON=2dVdv9wrh)EI#@Onqe!gbuiFr1+)gZy0Qmn)RNkL!K-`4ftb}uz#NCW zC+7E|F~T9T)#Z)_WQnY-3DMQxXY7AjlT(;e(()wz>LfEn*VUqI4M&)du1L5-|0U?7 z_SS`mj1GBCAft#urp3P3xx?9)!Y_T}Sif{^NBvIzg%ux|XrXyIRl@#3Bxc|;5&3r8 z+^g5zqoEt-@+#r}jWr6yNl%VJagqOy2;vv;(@NLsXb zg?k23v7XTm_n|*`6de{{2z?s-I0%d*Wg59Qiz0L?UA=wQeBOK=OkH^F`9|3z8xA=I zcFXl{jk>F=yUIFb1XQn8YUK%GOMS=?FP)3&Li&(no2VP)BrO86a=?`+n5POpo#$Bz ztWwg*PIEpQzdVq~pm|SUWEjw_@4He#CAOR)?0Y@+H(o;^b63*jd3r?qt%S8C#Mf`yDA$FjI z>)@F@k`5AdBCl2f%o9__Hkakf^r)L}^FydfVUhwnLj9M0uHIT`J6 zJNJC3irna~;o!~3JJ0@BYJ6(}Z=4wD0w-PyiYbW~dia@fN|e~sgI&Jx=)L6*y$7q! zuXL)4U&hE3B6%V|L*|;>oyxuG5v_bF>}B^%qSKUA9;{pD?4l}_zoted^Oe(J9EM*F z+1ltPvP<9JV0bR^{29W=GWl|wet?wJWtdcTU?59Gh*@eprA8B4fJBYf`x3&al;?YH z`62g1i7xhbZSA&kVBPL~kjGD8EK2f8>hJwrbybV3ZjufY#}$w#mpsX>pvwSQIKfbg z$mwN_@jJIl8y%po&RoT>U+|nlqI4DW8#bQQ{a?Lcr>Qs+k5rgyEt(|Cqi<}&m+*sI z@;1TuyJH@%D|)B2a-EH00abe_;6=sDUqKVvJ`9OW^A7gIgX7|dyFCU=?qhxV?HbJ( z5Vp{j+ScsM8$o|sv%*QcUcrG6d89Gf1usDOF{ztYNB`7LAXmX671&rOx(aE^Zowe& z=zack+t-RJq{|ly4f$=6|HYT>*F&O|KwJQdq(%YKsU}S*e7U1aNi_gNjHHfj?^Hgax$+cUJ0gSCtK^2Fz=rG|nP z6Tj}FXcDxUu{Inkxb|LvP}YLsd*3W*EslY)?l?>&aJ$-&aD{+dgK|5#;fG{!1i^yhcH2y(tV&2_U(6o)Vg%m?#vLAP1n3azFBmj>{km zW_LoN`SRmAL~plfCtv@gy%2$Ew1uW`-ADs>OOk!$sl_)~m4$oorQ}q_jH6c(Vp87r z!I5bpqK)bn(jPmNwnHI6H}eDBAqooz;M>py17dQFSIsLYMLI(OzJF2Myd!9Pz$0J? zJtY&PI%vc)x4Ggy79035y_#wexVex?Z1DFuG&Lia;MaSoHbRkj2Fi=Rc|{YQ73kD8j?H@E{4Dmu4yHnxrgGp;{^oAoe@bp z)nQLK3#nn_8<>Q-ir1a&RaLSuKXLa@A{9JmWbz$ajP4BiCs_d~YH(}=QE{^tnj^v% zlz``>+!Z-j7FAMn?oc-=zB9ZJwhv^5UD{sbZWNe1n%Um5z)$qZL%E*dsY{?r(i! zSFrWQu)j}y4wc<)ttT-}<(pd5#PTny3qTP@GOuxttl&;j5*GWJ!I-Y<9y(J*29wa|q4pmg3b z?=S}##rSW9Vsn>tllW3^m4t_f?2Fq|4w#X&DwO{j1DI=~9}H-c_dqZoP|I5hs%7Nn ztPmX@k4|Y&k&4$1V(Sl`4XnGtW1VK{I?^8Z3w0J+bf9h<0eBuIMkPS}v00j^z#G2; zV|m4%CV>hWss8pg=p}KX_82rCQ{PEEEJc91^pYrgB5H5U+hjD_ZzvLmC|2<8rwsiB}Ueaf16J7)RH--`}QPI#VHmL(F_130cDd}$7_ZAQ;IIGky>(b@8<%c2AI!{-Z+7$6%UJW#>P#^HO!!^h0e8|(~ht$LFcTF4}f6% zirT!DIasJiW-sQ@L*lE_aOm;qr=4rBx=b*RewK&rm{LBCDlu2|;-o$Vw$_e`%WQMm zM0GBGUT>QvQiQu-1D&M#R@(sT@S@qSxO%Yv9^7v3LNxMr@5I7dCQr#F7ZcAz^7}T+ z$1mKzmu+&n^8KdIw;JF)Wo%Q^;i!Dua}NB5EfnJsc^FXV!LnXgoa_3j>+8TIy=f~! z@*mFTWLggq)9W^>54nj4p{NdXnacK!-17xSzoR-;BE$mh*Uw=pU~T9k9uPa#j7%4H z(Q>&2Y*Wo=U>B`%G=lsTuE{PDxP2Z2QcOgrH=90}CvTaLg9BC2b~R!O`J5m+98JKt z{-b28_5ze*ggnHQU)eVlN?Wlv(9=%0T>bb5J^ zGp~7ZsVx==jCFo{tsKe+q7wSyoOwaIfG@VD-@^8YZc~tJHqo_^(5d2O+>UEp35pAz zp#wB1RHNbDKXpz%Nh+p(7W?b&Y}5W#9D~~Xn6A|>BNjzswlI|T6V4lZY52g{Dur4+ z29BZ4yv2!9XAGZTH_wFKYSaAus50HNk%PBDzT2+P*m^{KI%3qEa1bNg|F>yrl$D40 zF173rL3)J1(hU3YGfQh?7AI}I3i$(U^|u+VB+#xjz&&}}#||jDXeWIn&?7fOXOeOB zlXo^N4@_8;gysOfdnW7?E6VJx^fdR;Xv5;OLz=hJ2hwwAKjCa3wkLtzF-A`Hf_p3U zEsIoc9tEFlA5jbWEX+Uss#vmhKCEkD&Lt`TbAAy9iv#OJ2Pp{NFm$fR1p|5vt{p^` z`J*GFu1yfI8eTr^5X7dKDJq~HD}5P%23~wH`rb+ShhPPhlBu?ZZQbJD7*im7^L!uk z-a$2DQ@1xxonK*|D)6hmT_V$c^c-JBnCFK3PYW4dzbYLcAoatk%~OX988FRC0rQFI z4ffNP`M)v%?_eqig7;eyGL{5>Ct%4_Wa+2WHfyZzmLZ1 z2SwT4rw>OSrC!k+n{}S#-&Kp^R_GEJ@ocq_cP}7;$)X=WVSlZ@?VcWLf?wK;q2!a8(_eW=^ zDZF09(p|s2EpUErOzE4LLl?c$Hc!byI1eTlPVZzDn-?xFGAjOVvsX-^)7ucVK403r zTlMOU>0k%B)!nE5;U6`OHLcZS7ayYYAN|oXXM2S^zbL#}xUYWkb*vs62ghzz=W{y= z^%wpL^v*x7$@AhU#>r!LO|&oZg5Lp8z6iT$itVGbN@O3K0KrjR+wVnGKGw=C%`;wO z@4RO6ltorXEXXeT4~kuJWg=LZg_yFMt3yZTJV>XbCVd?79BewJ_!H6h1%$fpNt?~! zy?NVOLeW!6PQBzmEsXTNY##hM7Nz=gv6GDkseW|1(@1IzNKF9`04`F|xt>(|z7sfN z=wq3PpN?YmDw#;(q_dwM`j32o_Nyc-wZJXKx`7mb5<2pOld!TosU*tr>1v*kKl`m_ z-b6fG8~M@!(gGD;XP!nyETnQ$pp%pAFlJN=f;yYiU{$?Knm9gA7dIxBfAd?5ZK_iG z{bViPaAF`-3*VtfQsC9P1ua&g4L6NTz~e~-|BnWHhSe+igu{ za#o3pxsv`|6N&tjLhzP1`aqq%%si^pd-n4P;;AE)99gc~Hai+WBG>;tr(W`l0i`Tpq=;R zLlm!f*u<#NM4(fDl;B?&)b6*Nda zarE0FH&2&g(Avrq z+qBzWf08vnw>B9VkLV%Icf4 zkCa9M8es3{v`mLXDLJJ0DhMRtN7G5Q65>DyQD?Nlm>*TV`r$d3J%gs*8c~%Gzb@_s z936b1eJe*R*HN>~QLe%+i)TI#|2P@CX+_8*1xG92kX~R$Yp(X13bkUSH=y#Mv|-#A zgAA_2r0*XUf-!~DRmwqctW-8$%@7~Yg$~0-%7jDg|H=oC_ff2pa`ZtXRiHExANPxp z)>A|C3#o%q>IY(E{@!XjC={oz{CapyJ_!9H0rP4U=i@~;4yw=2D|l0o=i`Z|&@zpp z_4sj-rh~3+3Wi|Mpi^6_V<#YQ4HxI;Y?p7lQ{C(q3U!ao26~;ZrsqL$>uLE!ZX_wC ztlV&C;Mrh0ik_l0Boa|gK%@u=M2Z-iAfQ4J=`B=g zQl$z=3rg=@q)6zUP^1e4=}o#cX#s@Lr1v7dmr(8>&$`cN-G}>j{)c3(Z)W!FJu`d$ zm6h4ERoffX38#HYnBJGoJ+z5WX^l^ub2-2BZIB`rI0L=PCHy7v&6+r9jK%WqM(~bb zzcettrQsj`FYL;{0JGafWdpOLZJeAs9`ys4Y|oe^;&I(uI1jI z0ij_iM}PqW0kld@3LtpcM@~Q5&2B*kMP#er1dlGfrH{1_b0ARTQ^Jr;XW&Z%_m^ZB z3ixMuUp}rIkKCZBJRVrwLx~0`ea+1204`Drfe6Oo9yIQaaz1NhV31mN;foq)2*}VT z9<3u-CdguUbb$#>A5iwk57TyjXJmrsXZ~g{X7_ElY;kaEvnH=>VH-?)Q6eY-i=hqP zu3?`Iur4e)nRoH&{aIxvwD)p!Z5ajgoLbUydzBtq`fWwMf>7dd;`37IlQT>I@;hpA zFNGkb+iG;**p%&yQZ=~X-!x<2VUT*qPaP+LwN>!0-|(k;w6J)*)l5|Wg|@eQk}xpV8@HBvyraY z!UsJbfW3Ezeb#&a&SrF3NYJ@avuHe?!H4ko3fn%WY0aD8-`Lx~3jQoUkqAXN!*SoA6Xr^C z5?lL-;SAF%8Ztm%R#5_$6oHi1hkjzq*mjvGh-`l-J$Tfk^}Fd$b;r{2NciQR!<8%8 zbCbi=ZcrP-;3zZlJyFeDM}|kt~ZnWk379k+aZo9I$(*#BSTBjgh*j z`32-@y=a|8Q;;9)?o<0jpelSmy~f8&Sx9{GO?$p7UTM#zylv;RUmbG>N?7sZG1q?o z1DP}_D^Wk3d!j`_4nr+3-ak@!ee>FuUfEfXg~%veh%8GE%`glE;pC(>>Vr|A!W;jZ z=cWnOEMoSq#h%X@YLHzt(18` zn!M*J=AM%+A2_i+Y~xp>C$U-%R1zjIbHq+UH5S}@qE8sWKH-!61PDNfAY&MYgH7n_ zW8_aqEvIlWsr=1RU)7t8=_JzQ+!SKyr+vO(-HBvg$&8`T!^JCVNEKT<5u(b5xjL2? z7Re_(?S8ZtY7?o!66sl-qO1HD!#YFc)4!?7p?b_Y`22@xyZjqvl+~QC$+Pkw*biMC zk31^pdpmEjQeEPZ(V^gFAYy89uDP@V+q>E(q+Ya!MbZUqCD^uh&f~d6qB+zn)aqDu zPGfa0dNM0WUs><8j+I5wLbv(Z@Iw#7q!5U}8^Nntaclk(v$isce2!i(8{%k=50>3> zcBCmkkVk`(_J~L{D<}fDYIOqG|F|@n_+b7>f%ivi@X1ZT1MVz6`C784ZoJl$Mu8dS z{K&nBylsBfm~Sh85!N`}V!Z_~w>nL-$FH~;fMG7R!^WFva-D=E2knLlj3S%Qw=Eth z7b)1Lhc!2Ht(v|rOO#!*a)Z6x)V?ercL$BK(6$XdRb_wP2z`uU5jMfMQL@c3QHj6p z<6HEEK`&i~(mpyGL{p0s3{qyY22F2)9_fb7n0sJgCxh;uzKePtA!I3?!25?tcET)1 zaanYyM5xKQe|WFtYjgbB(dZ&)rweyz^QLUjJ1~)yj2kF!=$F#nE1`8LdylZt#2C5_ zB#zb(j@tct5(3b~4zc-b5v$A8nofek(+R+9^grP240DNiIl zs39{CSwES7vdrrIBgya?JKFInaI^bNNu$K-`IlDNK)qm*l&g07vG#?<$1k5Xt%XJn z|7apnPW#LtlL;FmX3A=5H#44Tnm7=A)IOi5WMhOk1FJ)1c)O11OB;8$_p-gw$#SQP z)AW6dnl%FcP?4e8s{61;+q&~RMnLhE2XRmU*;&%P9`^@@=cYd>-9OXfJz|0ET3ZD3 zqrYlolXWx(kf}*{%1POaDAG8wz7D&-J6);}u(T?(1G}}{p0D-%kIv_>=RPLk!>S%% zShE$u@B70GPJja^Xx!ieXIdG3Lq@Yz6XIlFoaG+HXRx6SO3VJVp+*|KN34)iOR@+` zSH?g~JMVx~p!2q;UEEP)=bp+#@_?8wD4FnQT!}k^l3;&$l1JuvmJ``hr32ZmkB=~7DHky$?HF>cRewfMMWhx}I&mj=p+sn4OvS0v`?FBm>8BddqmY@-6IAJ;+Mp?NM&U{v>F*4EhtT#<3Q#VfKf!4z4n3T8M8#>KT z3~yL@1Z~Uz^r19v*zeed7y6N)wBq3<%fEcmQztUI=!u`*$|EW0DZm|BkVr=^ahf!( z@-S4Xka+PSS3ywLAKnbniU8f1nsv79^+@5(Oqm0Z+KWvVJd=5qHj(+wDcZS4jF$r} zGL^%pafiztnJwbbvrkFk8>`+i2?RFM;cY10q?5F!3n%e`tzdpe#FSu%e(JR!XR-}H z4~J!eN6dW1Y2sTpnPt6Pla{iSA_d=(uN~wEdTgBuNm7`8wIv@jpN=g}>h9a99nBHg zm$P_-EJ68NPpQBWq|-7^?Zd{Y3x-(5AcPTA1&Zv}UOCD7qYe9bCX)N(YVsn1vlOv% z^5M=)-k}TlL~pHQWRg(?ogxoE8wY=weC(a%&1b=e+V3j`ZAkiJz%jy2lsyLx9RSFpNQcMm+YaI`2Q|kNL zd&KbQeVpcm=NH_KC|e8fL4}XGJ|^+o(Nf`~Z*n`qbt9z7J++z8`#m#wZIfLr)1(OS zq%Mcdc^aSW3~Yff<+7!@8POVbo|~rW65BemekNHskLop8^3Q435bN{P;})`FINWka zQlIEP$^d1=9~qf_?~y#49K zbelK4o|5K5wFPF|vVr#{*NbKQHBnA($FU}NGA;GA$`5EA7dEFFRgKr{dQqFZIM9b% zGc}=Go?eXaYGQ?w`-M!+JJ2zB-@p21y8qG`2`0fyAjrp;gYgPmyXmp*cv|jdm09g) zh04C09&HT|IJX~NGbAe7`$c_U%)NFBU41=1TjXW2vHc0-YGYV`SU|3w+igbAhVrWP zjhS+4;VBOqu6mz5l>|9gaF;-*zYD*}ghf9WaQ(B@jfB=jzqy&hNheaC7ip7cXYkZU z=9o%SL=n?599*pV9YpG}(A}a$mAP`scsfuebiz1O;krvWs4|fD8?wxbrs|+4`v*EKIyPC7Ye!Lx)&RYQBWU~v!pu?Xc%loPF>+q`40idE8 zCrTP}tMpyDa9%eWURC=6DB#AC%L3sd(!m3?4xdb{cMX7AWgO-Z7=h)elY9TB3_SM^ zH6d1z8OijyGd*_f5R^*;YdH0~0e}{2cO`^R%NxwiIXn8ZUl0LMKA^yO(Y)7mLbNcc z)&~wiIATa9ntI=_!YkW1;L!;s_6vdlh*Z1VB9aWYmG>wJG|AeF2?a{0aZc6lRv{o| z`d@~ul1)rj2C$e$HVDS+D_JXSwr~XhSkC|yL*rz?G^C0Q8Pr&LtS(^4tl}|A>~v9t~*E*MuIIa4gZkJmC=hDw>5eO2Q0O zUIPLF{1$RR*V`)`sKgMjI^~a)nrj1qfHOii@dpLo4~wHp>~#(|@)E!CQ0s1Dp;&@;rJie`zTyPtYpKDbRMj_dn07U)Xzz~ z!2Rw=HQ^c-+B-Cb$qE%$;ilMS&&fgptQ7|W_u;`auQaEb#Zt$(=8Ql-SkVkXw8@`P zswrBQc*>{oPnO;cT1f*P#Q1^yA4zEw%}B9caNT?TU;5Fo1k4@;*}Xy{z>1Y68X=1| z6-!rTwv_{2OV~o0t(KbD2Go>hr=t!2mw`!d+_6G93xheBVD}ocxsvk4E1idHVuQXZ z688Dm%$0i2(%tS8?<;BEz*V-5>yk)Z_S)+eDJ;ia%=Uvm-iR>UN5GHH+BV$DK`DuM zx>HD1$?h734uC_BE~IYs;d(5}Golwf!E?H>$M3)_;<~f{g($~FW_J4TAjr`YjU zhG*g!wGVEhP0!B`l(3{=P78o+^Nf6MTbwU)%j&?5IfjLV?=woN^FA{Z#Yu6X{V+ zn;pFHJ5a}ZB>@iX2$aYc=iArWy^eVM4U4tZW{lWvPX-zx!!r{7Wxt=eU->DP=Sz=y zApqM2!9K&$2Xzrwg~HaWpNkLR*t{Vi1(B9t_dTkE$s>gG4^?h@a35h~*DfMWJA1h; znl!RGFT25PKv6LQn;8jikB}*y)i&2UqcSMnI}k7Ke|QRAtJuT(jEsuv(P|wTjgz5=7(5sXGp9G z+jP|2SCZ9w)noaDne{K2Dc7IWa1jNSm{0gEB}70NhShAT%3Wvr^O}x#jLwkP`!qK^ z;1>4O1rDEZ8opS$lWf@tbe+w5Wh(Kvf+gACiQyyF&Wk84uH9WT1D6kH`MFX=S32p> z?nr%-{3~czFnv4B>#(-N*51{V40PBH zje~R6%0_5H(T;zAk+oMDt3V#AEL|-5*8hJ1)Yw5F literal 0 HcmV?d00001 diff --git a/src/app/api/auth/[...nextauth]/authOptions.ts b/src/app/api/auth/[...nextauth]/authOptions.ts index abcd1868..09b6b705 100644 --- a/src/app/api/auth/[...nextauth]/authOptions.ts +++ b/src/app/api/auth/[...nextauth]/authOptions.ts @@ -146,8 +146,8 @@ export const AuthOptions: NextAuthOptions = { .where( and( eq(accounts.userId, dbUser.id), - eq(accounts.provider, account.provider) - ) + eq(accounts.provider, account.provider), + ), ); const emailVerified = @@ -157,7 +157,7 @@ export const AuthOptions: NextAuthOptions = { // This handles the case where we had not set up accounts but // signed up users with oauth console.log( - `Linking ${account.provider} account for user ${normalisedEmail}` + `Linking ${account.provider} account for user ${normalisedEmail}`, ); await db diff --git a/src/app/email_templates/magic_link.ts b/src/app/email_templates/magic_link.ts index 12d3f434..e6582ef8 100644 --- a/src/app/email_templates/magic_link.ts +++ b/src/app/email_templates/magic_link.ts @@ -13,7 +13,20 @@ export async function MagicLinksEmail({ url: string; provider: { server: any; from: string }; }) { - const { host } = new URL(url); + const parsed = new URL(url); + const host = parsed.host; + + const baseUrl = parsed.origin; + const logoUrl = `${baseUrl}/domna-email-logo.png`; + + const token = parsed.searchParams.get("token"); + + if (!token) { + throw new Error("Magic link token missing"); + } + + // Create a clean login link instead of the NextAuth callback + const loginUrl = `${parsed.origin}/login?t=${token}`; const transport = createTransport(provider.server); @@ -26,8 +39,19 @@ export async function MagicLinksEmail({ to: identifier, from: provider.from, subject: "Your secure Ara sign-in link", - text: plainText({ url, host }), - html: domnaHtml({ url, host, brandColor, accentColor, brown, background }), + text: plainText({ url: loginUrl, host }), + html: domnaHtml({ + url: loginUrl, + logoUrl, + host, + brandColor, + accentColor, + brown, + background, + }), + headers: { + "List-Unsubscribe": ``, + }, }); const failed = result.rejected.filter(Boolean); @@ -38,6 +62,7 @@ export async function MagicLinksEmail({ function domnaHtml({ url, + logoUrl, host, brandColor, accentColor, @@ -45,6 +70,7 @@ function domnaHtml({ background, }: { url: string; + logoUrl: string; host: string; brandColor: string; accentColor: string; @@ -60,7 +86,7 @@ function domnaHtml({ Domna Logo { + const token = params.get("t"); + + if (!token) return; + + const callback = `/api/auth/callback/email?token=${token}`; + + window.location.href = callback; + }, [params]); + + return

Signing you in…

; +} From 684caad9ea83e981c6db0aceb388ec57a7940543 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Tue, 10 Mar 2026 15:28:01 +0000 Subject: [PATCH 3/3] added safe url structure for magic links and self hosted logo --- src/app/email_templates/magic_link.ts | 9 +++++---- src/app/login/[token]/[email]/page.tsx | 19 +++++++++++++++++++ src/app/login/page.tsx | 20 -------------------- 3 files changed, 24 insertions(+), 24 deletions(-) create mode 100644 src/app/login/[token]/[email]/page.tsx delete mode 100644 src/app/login/page.tsx diff --git a/src/app/email_templates/magic_link.ts b/src/app/email_templates/magic_link.ts index e6582ef8..82c44a8c 100644 --- a/src/app/email_templates/magic_link.ts +++ b/src/app/email_templates/magic_link.ts @@ -20,13 +20,14 @@ export async function MagicLinksEmail({ const logoUrl = `${baseUrl}/domna-email-logo.png`; const token = parsed.searchParams.get("token"); + const email = parsed.searchParams.get("email"); - if (!token) { - throw new Error("Magic link token missing"); + if (!token || !email) { + throw new Error("Magic link token or email missing"); } // Create a clean login link instead of the NextAuth callback - const loginUrl = `${parsed.origin}/login?t=${token}`; + const loginUrl = `${parsed.origin}/login/${token}/${encodeURIComponent(email)}`; const transport = createTransport(provider.server); @@ -38,7 +39,7 @@ export async function MagicLinksEmail({ const result = await transport.sendMail({ to: identifier, from: provider.from, - subject: "Your secure Ara sign-in link", + subject: "Sign in to Ara", text: plainText({ url: loginUrl, host }), html: domnaHtml({ url: loginUrl, diff --git a/src/app/login/[token]/[email]/page.tsx b/src/app/login/[token]/[email]/page.tsx new file mode 100644 index 00000000..94fef5dc --- /dev/null +++ b/src/app/login/[token]/[email]/page.tsx @@ -0,0 +1,19 @@ +import { redirect } from "next/navigation"; + +export default async function LoginPage({ + params, +}: { + params: Promise<{ token: string; email: string }>; +}) { + const { token, email } = await params; + + if (!token || !email) { + redirect("/"); + } + + const decodedEmail = decodeURIComponent(email); + + redirect( + `/api/auth/callback/email?token=${token}&email=${encodeURIComponent(decodedEmail)}`, + ); +} diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx deleted file mode 100644 index d5b83da0..00000000 --- a/src/app/login/page.tsx +++ /dev/null @@ -1,20 +0,0 @@ -"use client"; - -import { useEffect } from "react"; -import { useSearchParams } from "next/navigation"; - -export default function LoginPage() { - const params = useSearchParams(); - - useEffect(() => { - const token = params.get("t"); - - if (!token) return; - - const callback = `/api/auth/callback/email?token=${token}`; - - window.location.href = callback; - }, [params]); - - return

Signing you in…

; -}