mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
203 lines
7.9 KiB
Python
203 lines
7.9 KiB
Python
from sqlalchemy import Column, BigInteger, String, Float, Boolean, TIMESTAMP, ForeignKey, Enum
|
|
from sqlalchemy.orm import declarative_base
|
|
from sqlalchemy.sql import func
|
|
from backend.app.db.models.portfolio import Portfolio, PropertyModel
|
|
from backend.app.db.models.materials import Material
|
|
from backend.app.db.models.portfolio import Epc
|
|
from datatypes.enums import QuantityUnits
|
|
import enum
|
|
|
|
Base = declarative_base()
|
|
|
|
|
|
class Recommendation(Base):
|
|
__tablename__ = 'recommendation'
|
|
|
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
|
property_id = Column(BigInteger, ForeignKey(PropertyModel.id), nullable=False)
|
|
created_at = Column(TIMESTAMP, nullable=False, server_default=func.now())
|
|
type = Column(String, nullable=False)
|
|
measure_type = Column(String)
|
|
description = Column(String, nullable=False)
|
|
estimated_cost = Column(Float)
|
|
default = Column(Boolean, nullable=False)
|
|
starting_u_value = Column(Float)
|
|
new_u_value = Column(Float)
|
|
sap_points = Column(Float)
|
|
heat_demand = Column(Float)
|
|
kwh_savings = Column(Float)
|
|
co2_equivalent_savings = Column(Float)
|
|
energy_savings = Column(Float)
|
|
energy_cost_savings = Column(Float)
|
|
property_valuation_increase = Column(Float)
|
|
rental_yield_increase = Column(Float)
|
|
total_work_hours = Column(Float)
|
|
labour_days = Column(Float)
|
|
already_installed = Column(Boolean, nullable=False, default=False)
|
|
|
|
|
|
class RecommendationMaterials(Base):
|
|
__tablename__ = 'recommendation_materials'
|
|
|
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
|
recommendation_id = Column(BigInteger, ForeignKey('recommendation.id'), nullable=False)
|
|
material_id = Column(BigInteger, ForeignKey(Material.id), nullable=False)
|
|
created_at = Column(TIMESTAMP, nullable=False, server_default=func.now())
|
|
depth = Column(Float, nullable=False)
|
|
quantity = Column(Float, nullable=False)
|
|
quantity_unit = Column(Enum(QuantityUnits, values_callable=lambda x: [e.value for e in x]), nullable=False)
|
|
estimated_cost = Column(Float, nullable=False)
|
|
|
|
|
|
class PlanTypeEnum(enum.Enum):
|
|
SOLAR_ECO4 = "solar_eco4"
|
|
SOLAR_HHRSH_ECO4 = "solar_hhrsh_eco4"
|
|
EMPTY_CAVITY_ECO = "empty_cavity_eco"
|
|
PARTIAL_CAVITY_ECO = "partial_cavity_eco"
|
|
EXTRACTION_ECO = "extraction_eco"
|
|
|
|
|
|
class Plan(Base):
|
|
__tablename__ = 'plan'
|
|
|
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
|
name = Column(String, nullable=True, default="")
|
|
portfolio_id = Column(BigInteger, ForeignKey(Portfolio.id), nullable=False)
|
|
property_id = Column(BigInteger, ForeignKey(PropertyModel.id), nullable=False)
|
|
scenario_id = Column(BigInteger, ForeignKey('scenario.id')) # Doesn't have to be linked to a scenario
|
|
created_at = Column(TIMESTAMP, nullable=False, server_default=func.now())
|
|
is_default = Column(Boolean, nullable=False)
|
|
valuation_increase_lower_bound = Column(Float)
|
|
valuation_increase_upper_bound = Column(Float)
|
|
valuation_increase_average = Column(Float)
|
|
plan_type = Column(
|
|
Enum(
|
|
PlanTypeEnum,
|
|
name="plan_type",
|
|
values_callable=lambda e: [m.value for m in e],
|
|
create_type=False,
|
|
),
|
|
nullable=True,
|
|
)
|
|
post_sap_points = Column(Float)
|
|
post_epc_rating = Column(Enum(Epc))
|
|
post_co2_emissions = Column(Float)
|
|
co2_savings = Column(Float)
|
|
post_energy_bill = Column(Float)
|
|
energy_bill_savings = Column(Float)
|
|
post_energy_consumption = Column(Float) # energy demand in kWh/year
|
|
energy_consumption_savings = Column(Float)
|
|
valuation_post_retrofit = Column(Float)
|
|
valuation_increase = Column(Float)
|
|
# Financial metrics, excluding funding
|
|
cost_of_works = Column(Float)
|
|
contingency_cost = Column(Float)
|
|
|
|
|
|
class PlanRecommendations(Base):
|
|
__tablename__ = 'plan_recommendations'
|
|
|
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
|
plan_id = Column(BigInteger, ForeignKey('plan.id'), nullable=False)
|
|
recommendation_id = Column(BigInteger, ForeignKey('recommendation.id'), nullable=False)
|
|
|
|
|
|
class Scenario(Base):
|
|
__tablename__ = 'scenario'
|
|
|
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
|
name = Column(String, nullable=False)
|
|
created_at = Column(TIMESTAMP, nullable=False, server_default=func.now())
|
|
budget = Column(Float)
|
|
portfolio_id = Column(BigInteger, ForeignKey(Portfolio.id), nullable=False)
|
|
housing_type = Column(String, nullable=False)
|
|
goal = Column(String, nullable=False)
|
|
goal_value = Column(String, nullable=False)
|
|
trigger_file_path = Column(String, nullable=False)
|
|
already_installed_file_path = Column(String)
|
|
patches_file_path = Column(String)
|
|
non_invasive_recommendations_file_path = Column(String)
|
|
exclusions = Column(String)
|
|
multi_plan = Column(Boolean, default=False)
|
|
is_default = Column(Boolean, default=False, nullable=False)
|
|
|
|
# Add in the fields we need, which were previously sitting at the portfolio level
|
|
cost = Column(Float)
|
|
contingency = Column(Float)
|
|
funding = Column(Float)
|
|
total_work_hours = Column(Float)
|
|
energy_savings = Column(Float)
|
|
co2_equivalent_savings = Column(Float)
|
|
energy_cost_savings = Column(Float)
|
|
epc_breakdown_pre_retrofit = Column(String)
|
|
epc_breakdown_post_retrofit = Column(String)
|
|
number_of_properties = Column(BigInteger)
|
|
n_units_to_retrofit = Column(BigInteger)
|
|
co2_per_unit_pre_retrofit = Column(String)
|
|
co2_per_unit_post_retrofit = Column(String)
|
|
energy_bill_per_unit_pre_retrofit = Column(String)
|
|
energy_bill_per_unit_post_retrofit = Column(String)
|
|
energy_consumption_per_unit_pre_retrofit = Column(String)
|
|
energy_consumption_per_unit_post_retrofit = Column(String)
|
|
valuation_improvement_per_unit = Column(String)
|
|
cost_per_unit = Column(String)
|
|
cost_per_co2_saved = Column(String)
|
|
cost_per_sap_point = Column(String)
|
|
valuation_return_on_investment = Column(String)
|
|
property_valuation_increase = Column(Float)
|
|
labour_days = Column(Float)
|
|
|
|
|
|
class MeasureType(enum.Enum):
|
|
air_source_heat_pump = "air_source_heat_pump"
|
|
boiler_upgrade = "boiler_upgrade"
|
|
high_heat_retention_storage_heaters = "high_heat_retention_storage_heaters"
|
|
secondary_heating = "secondary_heating"
|
|
|
|
roomstat_programmer_trvs = "roomstat_programmer_trvs"
|
|
time_temperature_zone_control = "time_temperature_zone_control"
|
|
cylinder_thermostat = "cylinder_thermostat"
|
|
|
|
cavity_wall_insulation = "cavity_wall_insulation"
|
|
extension_cavity_wall_insulation = "extension_cavity_wall_insulation"
|
|
external_wall_insulation = "external_wall_insulation"
|
|
internal_wall_insulation = "internal_wall_insulation"
|
|
loft_insulation = "loft_insulation"
|
|
flat_roof_insulation = "flat_roof_insulation"
|
|
room_roof_insulation = "room_roof_insulation"
|
|
solid_floor_insulation = "solid_floor_insulation"
|
|
suspended_floor_insulation = "suspended_floor_insulation"
|
|
|
|
double_glazing = "double_glazing"
|
|
secondary_glazing = "secondary_glazing"
|
|
draught_proofing = "draught_proofing"
|
|
|
|
mechanical_ventilation = "mechanical_ventilation"
|
|
low_energy_lighting = "low_energy_lighting"
|
|
solar_pv = "solar_pv"
|
|
hot_water_tank_insulation = "hot_water_tank_insulation"
|
|
sealing_open_fireplace = "sealing_open_fireplace"
|
|
|
|
|
|
class InstalledMeasure(Base):
|
|
__tablename__ = "installed_measure"
|
|
|
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
|
uprn = Column(BigInteger, nullable=False)
|
|
measure_type = Column(
|
|
Enum(
|
|
MeasureType,
|
|
name="measure_type",
|
|
values_callable=lambda e: [m.value for m in e],
|
|
create_type=False, # <-- critical
|
|
),
|
|
nullable=False,
|
|
)
|
|
installed_at = Column(TIMESTAMP)
|
|
sap_points = Column(Float)
|
|
carbon_savings = Column(Float)
|
|
kwh_savings = Column(Float)
|
|
bill_savings = Column(Float)
|
|
heat_demand_savings = Column(Float)
|
|
source = Column(String)
|
|
is_active = Column(Boolean, nullable=False, default=True)
|