Merge branch 'main' into feature/pashub-to-ara

This commit is contained in:
Daniel Roth 2026-03-31 08:26:33 +00:00
commit 3085edb0e9
75 changed files with 2999 additions and 2335 deletions

35
.github/workflows/integration_tests.yml vendored Normal file
View file

@ -0,0 +1,35 @@
name: Rebaselining Integration Test
on:
pull_request:
branches:
- main
jobs:
rebaselining-integration-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install tox via Makefile
run: |
make setup
- name: Configure AWS credentials for dev
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.DEV_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-2
- name: Run only rebaselining integration test
env:
EPC_AUTH_TOKEN: ${{ secrets.DEV_EPC_AUTH_TOKEN }}
run: |
make test ARGS="-m integration"

View file

@ -27,4 +27,4 @@ jobs:
env:
EPC_AUTH_TOKEN: ${{ secrets.DEV_EPC_AUTH_TOKEN }}
run: |
make test
make test ARGS="-m 'not integration'"

1
.idea/Model.iml generated
View file

@ -6,6 +6,7 @@
<sourceFolder url="file://$MODULE_DIR$/model_data" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/open_uprn" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/recommendations" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/infrastructure/terraform/.terraform" />
</content>
<orderEntry type="jdk" jdkName="Fastapi-backend" jdkType="Python SDK" />

View file

@ -73,15 +73,49 @@ def app():
Property UPRN
"""
data_folder = "/workspaces/model/asset_list"
# data_folder = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/E.ON/202603 modelling project"
# # data_filename = "For Modelling - Final - reviewed.xlsx"
# data_filename = "eon - 20260323 address sanitisation.xlsx"
# sheet_name = "in"
# postcode_column = "postcode"
# address1_column = "Address 1"
# address1_method = None
# fulladdress_column = "Address 1"
# address_cols_to_concat = []
# missing_postcodes_method = None
# landlord_year_built = None
# landlord_os_uprn = "address2uprn_uprn"
# landlord_property_type = "PropertyType"
# landlord_built_form = "BuiltForm"
# landlord_wall_construction = None
# landlord_roof_construction = None
# landlord_heating_system = None
# landlord_existing_pv = None
# landlord_property_id = "UPRN"
# landlord_sap = None
# outcomes_filename = None
# outcomes_sheetname = None
# outcomes_postcode = None
# outcomes_houseno = None
# outcomes_id = None
# outcomes_address = None
# master_filepaths = []
# master_id_colnames = []
# master_to_asset_list_filepath = None
# phase = False
# ecosurv_landlords = None
# asset_list_header = 0
# landlord_block_reference = None
data_folder = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/SMS"
# data_filename = "For Modelling - Final - reviewed.xlsx"
data_filename = "assests.xlsx"
sheet_name = "Sheet1"
postcode_column = "POSTCODE"
address1_column = "ADDRESS"
data_filename = "SMS Data sample to sense check before WHLG deploy.xlsx"
sheet_name = "All Darlaston Properties"
postcode_column = "Postcode"
address1_column = "House Number"
address1_method = None
fulladdress_column = "ADDRESS"
address_cols_to_concat = []
fulladdress_column = None
address_cols_to_concat = ["House Number", "Street name"]
missing_postcodes_method = None
landlord_year_built = None
landlord_os_uprn = None
@ -91,7 +125,7 @@ def app():
landlord_roof_construction = None
landlord_heating_system = None
landlord_existing_pv = None
landlord_property_id = "UPRN"
landlord_property_id = "id"
landlord_sap = None
outcomes_filename = None
outcomes_sheetname = None
@ -243,7 +277,7 @@ def app():
if skip is not None and not force_retrieve_data:
if i <= skip:
continue
chunk = asset_list.standardised_asset_list[i : i + chunk_size]
chunk = asset_list.standardised_asset_list[i: i + chunk_size]
epc_data_chunk, errors_chunk, no_epc_chunk = get_data(
df=chunk,
row_id_name=asset_list.DOMNA_PROPERTY_ID,
@ -386,7 +420,7 @@ def app():
# Retrieve just the data we need
epc_df = epc_df[
[asset_list.DOMNA_PROPERTY_ID] + list(asset_list.EPC_API_DATA_NAMES.keys())
].rename(columns=asset_list.EPC_API_DATA_NAMES)
].rename(columns=asset_list.EPC_API_DATA_NAMES)
# Look for columns not in the find my EPC data, which will have happened if we didn't
# retrieve it in the first place
@ -403,7 +437,7 @@ def app():
find_my_epc_data[
[asset_list.DOMNA_PROPERTY_ID, "epc_has_floor_recommendation"]
+ list(asset_list.FIND_EPC_DATA_NAMES.keys())
].rename(columns=asset_list.FIND_EPC_DATA_NAMES),
].rename(columns=asset_list.FIND_EPC_DATA_NAMES),
how="left",
on=asset_list.DOMNA_PROPERTY_ID,
)

View file

@ -631,4 +631,6 @@ BUILT_FORM_MAPPINGS = {
'First & Second Floor Flat': 'mid-floor',
'First Floor Purpose Built': 'mid-floor',
'Purpose built First Floor': 'mid-floor',
'Mid-Terrace': 'mid-terrace'
}

View file

@ -173,6 +173,7 @@ def get_data(
errors = []
no_epc = []
for _, home in tqdm(df.iterrows(), total=len(df)):
try:
# If we have a block of flats, we cannot retrieve this data

View file

@ -3,6 +3,7 @@ import ast
from itertools import groupby
import pandas as pd
import numpy as np
from typing import Set
from datetime import datetime, timedelta
from etl.epc.Dataset import TrainingDataset
@ -55,12 +56,11 @@ class Property:
walls = None
windows = None
lighting = None
energy_source = None
spatial = None
base_difference_record = None
DATA_ANOMALY_MATCHES = DATA_ANOMALY_MATCHES
DATA_ANOMALY_MATCHES: Set = DATA_ANOMALY_MATCHES
# Surplus information, that can be provided as optional inputs, by a customer
n_bathrooms = None
@ -100,12 +100,8 @@ class Property:
self.address = address
self.postcode = postcode
self.data = {
k.replace("_", "-"): v for k, v in epc_record.get("prepared_epc").items()
}
self.old_data = epc_record.get("old_data")
self.property_dimensions = None
self.old_data = self.epc_record.old_data
# This is a list of measures that have already been installed in the property, typically found as a result
# of the non-invasive surveys. We reflect that this has been installed in the recommendations, but remove the
# cost and instead, provide a message that the measure has already been installed
@ -124,17 +120,17 @@ class Property:
self.valuation = property_valuation
self.uprn = uprn if uprn is not None else epc_record.get("uprn")
self.uprn_source = self.data.get("uprn-source")
self.uprn = uprn if uprn is not None else epc_record.uprn
self.uprn_source = self.epc_record.uprn_source
self.full_sap_epc = epc_record.get("full_sap_epc")
self.full_sap_epc = self.epc_record.full_sap_epc
self.in_conservation_area, self.is_listed, self.is_heritage = None, None, None
self.restricted_measures = False
self.year_built = epc_record.get("year_built")
self.number_of_rooms = epc_record.prepared_epc.get("number_habitable_rooms")
self.age_band = epc_record.get("age_band")
self.construction_age_band = epc_record.get("construction_age_band")
self.number_of_floors = epc_record.get("number_of_floors")
self.year_built = self.epc_record.year_built
self.number_of_rooms = epc_record.number_habitable_rooms
self.age_band = epc_record.age_band
self.construction_age_band = epc_record.construction_age_band
self.number_of_floors = epc_record.number_of_floors
self.perimeter = None
self.wall_type = None
self.floor_type = None
@ -144,63 +140,27 @@ class Property:
# when storing the energy, we'll also
self.energy = {
"primary_energy_consumption": epc_record.get("energy_consumption_current"),
"epc_co2_emissions": epc_record.get("co2_emissions_current"),
"primary_energy_consumption": epc_record.energy_consumption_current,
"epc_co2_emissions": epc_record.co2_emissions_current,
# These will be added in once we estimate the amount of emissions from appliances - using the carbon
# intensity of electricity
"appliances_co2_emissions": None,
"co2_emissions": None
}
self.ventilation = {
"ventilation": epc_record.get("mechanical_ventilation"),
}
self.solar_pv = {
"solar_pv": epc_record.get("photo_supply"),
}
self.solar_hot_water = {
"solar_hot_water": epc_record.get("solar_water_heating_flag"),
"solar_hot_water_boolean": epc_record.get("solar_water_heating_flag_bool"),
}
self.wind_turbine = {
"wind_turbine": epc_record.prepared_epc.get("wind_turbine_count"),
}
self.number_of_open_fireplaces = {
"number_of_open_fireplaces": epc_record.prepared_epc.get(
"number_open_fireplaces"
),
}
self.number_of_extensions = {
"number_of_extensions": epc_record.prepared_epc.get("extension_count"),
}
self.number_of_storeys = {
"number_of_storeys": epc_record.prepared_epc.get("flat_storey_count"),
}
self.heat_loss_corridor = {
"heat_loss_corridor": epc_record.prepared_epc.get("heat_loss_corridor"),
"length": epc_record.prepared_epc.get("unheated_corridor_length"),
"heat_loss_corridor_boolean": epc_record.get("heat_loss_corridor_bool"),
}
self.mains_gas = epc_record.prepared_epc.get("mains_gas_flag")
self.floor_height = epc_record.prepared_epc.get("floor_height")
self.mains_gas = self.epc_record.mains_gas_flag
self.floor_height = self.epc_record.floor_height
self.insulation_wall_area = None
self.floor_area = epc_record.prepared_epc.get("total_floor_area")
self.floor_area = self.epc_record.total_floor_area
self.roof_area = None
self.insulation_floor_area = None
self.number_lighting_outlets = epc_record.prepared_epc.get(
"fixed_lighting_outlets_count"
)
self.number_lighting_outlets = self.epc_record.fixed_lighting_outlets_count
self.floor_level = None
self.number_of_windows = None
self.windows_area = None
self.solar_pv_percentage = None
self.current_energy_consumption = None
self.current_energy_consumption_heating_hotwater = None
self.current_energy_bill = None
self.expected_energy_bill = None
self.heating_energy_source = None
self.hot_water_energy_source = None
self.recommendations_scoring_data = []
self.simulation_epcs = {}
@ -217,13 +177,8 @@ class Property:
# Store inspections
self.inspections = inspections
# TODO: We keep this but only temporarily until we add bathrooms, bedrooms, building id to the condition data
self.parse_kwargs(kwargs)
# Funding
# self.gbis_eligibiltiy = None
# self.eco4_eligibility = None
# self.whlg_eligibility = None
self.scheme = None
self.funded_measures = None
self.project_funding = None
@ -235,6 +190,12 @@ class Property:
# Ventilation
self.has_ventilation = self.identify_ventilation()
@staticmethod
def _safe_int(value: str | int | float | None) -> int | None:
if value in [None, ""]:
return None
return int(round(float(value) + 1e-5))
@classmethod
def extract_kwargs(cls, kwargs):
"""
@ -247,24 +208,24 @@ class Property:
# Note - none of this data is contained in an energy asssessment, but we should consider how this is done
# as we collect more data from the energy assessment
n_bathrooms = kwargs.get("n_bathrooms", None)
n_bathrooms = kwargs.get("n_bathrooms")
# We add on a small value to ensure that the number of bathrooms is rounded up, in case the value is 0.5
n_bathrooms = int(round(float(n_bathrooms) + 1e-5)) if n_bathrooms not in [None, ""] else None
n_bathrooms = cls._safe_int(n_bathrooms) if n_bathrooms not in [None, ""] else None
n_bedrooms = kwargs.get("n_bedrooms", None)
n_bedrooms = int(round(float(n_bedrooms) + 1e-5)) if n_bedrooms not in [None, ""] else None
n_bedrooms = kwargs.get("n_bedrooms")
n_bedrooms = cls._safe_int(n_bedrooms) if n_bedrooms not in [None, ""] else None
number_of_floors = kwargs.get("number_of_floors", None)
number_of_floors = int(round(float(number_of_floors) + 1e-5)) if number_of_floors not in [None, ""] else None
number_of_floors = kwargs.get("number_of_floors")
number_of_floors = cls._safe_int(number_of_floors) if number_of_floors not in [None, ""] else None
insulation_floor_area = kwargs.get("insulation_floor_area", None)
insulation_floor_area = kwargs.get("insulation_floor_area")
insulation_floor_area = float(insulation_floor_area) if insulation_floor_area not in [None, ""] else None
insulation_wall_area = kwargs.get("insulation_wall_area", None)
insulation_wall_area = kwargs.get("insulation_wall_area")
insulation_wall_area = float(insulation_wall_area) if insulation_wall_area not in [None, ""] else None
# We allow for the asset owner to provide us with total floor area, in the event of it being incorrect
floor_area = kwargs.get("floor_area", None)
floor_area = kwargs.get("floor_area")
floor_area = float(floor_area) if floor_area not in [None, ""] else None
return {
@ -293,18 +254,15 @@ class Property:
It will be the same starting and ending EPC, as we don't have the expected EPC yet
"""
fixed_data_col_names = MANDATORY_FIXED_FEATURES + LATEST_FIELD
fixed_data_col_names = [
x.lower().replace("_", "-") for x in fixed_data_col_names
]
fixed_data_col_names = [x.lower() for x in MANDATORY_FIXED_FEATURES + LATEST_FIELD]
fixed_data = {
k.replace("-", "_"): v
for k, v in self.data.items()
for k, v in vars(self.epc_record).items()
if k in fixed_data_col_names
}
difference_record = self.epc_record.create_EPCDifferenceRecord(self.epc_record, fixed_data)
difference_record = self.epc_record.create_epc_difference_record(self.epc_record, fixed_data)
# We have rare cases where entire description columns are missing. EpcRecords will convert this to None.
# Due to the sensitivity of the EPCDifferenceRecord creation to missing data, we will fill in these missing
@ -321,7 +279,7 @@ class Property:
# If we have variables that have been given to us by the landlord that we know are correct, whereas the EPC
# may not be, we use them
if self.owner_floor_area is not None:
if self.owner_floor_area:
self.base_difference_record.df["total_floor_area_ending"] = self.floor_area
self.base_difference_record.df["estimated_perimeter_ending"] = self.perimeter
@ -420,10 +378,7 @@ class Property:
self.recommendations_scoring_data.append(scoring_dict)
simulation_epc = self.epc_record.prepared_epc.copy()
# Insert static values
simulation_epc["lodgement_date"] = simulation_lodgment_date
simulation_epc = {k.replace("_", "-"): v for k, v in simulation_epc.items()}
simulation_epc = self.epc_record.to_dict(case="kebab", source="prepared")
types = [x["type"] for x in previous_phase_representatives]
if "external_wall_insulation" in types and "internal_wall_insulation" in types:
@ -497,7 +452,7 @@ class Property:
# CO₂ emissions per square metre floor area per year in kg/m². Since CO₂ emissions are in tonnes
# per year, we multiply by 1000 to get kg/m²
"co2-emiss-curr-per-floor-area": round(
1000 * (rec_impact["carbon"] / self.data["total-floor-area"])
1000 * (rec_impact["carbon"] / self.epc_record.total_floor_area)
),
"co2-emissions-current": rec_impact["carbon"],
"current-energy-rating": sap_to_epc(rec_impact["sap"]),
@ -604,21 +559,22 @@ class Property:
if not cleaned:
raise ValueError("Cleaner does not contain cleaned data")
if not self.data:
if not self.epc_record:
raise ValueError("Property does not contain data")
for description, attribute in cleaned.items():
cleaner_cls = all_cleaner_map[description]
description_underscore = description.replace("-", "_")
if self.data[description] in self.DATA_ANOMALY_MATCHES:
if getattr(self.epc_record, description_underscore) in self.DATA_ANOMALY_MATCHES:
if description == "lighting-description":
cleaner_cls = cleaner_cls("", averages=None)
else:
cleaner_cls = cleaner_cls("")
fill_dict = {
"original_description": self.data[description],
"clean_description": self.data[description],
"original_description": getattr(self.epc_record, description_underscore),
"clean_description": getattr(self.epc_record, description_underscore),
**cleaner_cls.process()
}
setattr(self, self.ATTRIBUTE_MAP[description], fill_dict)
@ -627,7 +583,7 @@ class Property:
attributes = [
x
for x in cleaned[description]
if x["original_description"] == self.data[description]
if x["original_description"] == getattr(self.epc_record, description_underscore)
]
if len(attributes) > 1:
@ -638,11 +594,11 @@ class Property:
if len(attributes) == 0:
# We attempt to perform the clean on the fly
if description == "lighting-description":
cleaner_cls = cleaner_cls(self.data[description], averages=None)
cleaner_cls = cleaner_cls(getattr(self.epc_record, description_underscore), averages=None)
else:
cleaner_cls = cleaner_cls(self.data[description])
cleaner_cls = cleaner_cls(getattr(self.epc_record, description_underscore))
processed = {
"original_description": self.data[description],
"original_description": getattr(self.epc_record, description_underscore),
"clean_description": cleaner_cls.description.replace(
"(assumed)", ""
)
@ -681,12 +637,12 @@ class Property:
# Today's costs
todays_lighting_cost = kwh_client.convert_cost_to_today(
original_cost=float(self.data["lighting-cost-current"]),
lodgement_date=pd.Timestamp(self.epc_record.prepared_epc["lodgement_date"]).tz_localize(None)
original_cost=float(self.epc_record.lighting_cost_current),
lodgement_date=pd.Timestamp(self.epc_record.lodgement_date).tz_localize(None)
)
# If we have the kwh figures, we don't need to predict them
condition_data = self.energy_assessment_condition_data.copy()
condition_data = self.energy_assessment_condition_data
heating_kwh_predictions = kwh_predictions["heating_kwh_predictions"]
hotwater_kwh_predictions = kwh_predictions["hotwater_kwh_predictions"]
@ -725,19 +681,13 @@ class Property:
}
# Sum up the adjusted kwh figures
self.current_energy_consumption = sum(list(unadjusted_kwh_estimates.values()))
self.current_energy_consumption = sum(unadjusted_kwh_estimates.values())
self.current_energy_consumption_heating_hotwater = (
unadjusted_kwh_estimates["heating"] + unadjusted_kwh_estimates["hot_water"]
)
self.energy_cost_estimates = {
"unadjusted": unadjusted_heating_costs,
# Don't think we need the EPC
# "epc": {
# "heating": float(self.data["heating-cost-current"]),
# "hot_water": float(self.data["hot-water-cost-current"]),
# "lighting": float(self.data["lighting-cost-current"]),
# }
}
self.energy_consumption_estimates = {
@ -797,7 +747,7 @@ class Property:
:return:
"""
current_sap_rating = float(self.data["current-energy-efficiency"])
current_sap_rating = float(self.epc_record.current_energy_efficiency)
if needs_rebaselining:
current_sap_rating += rebaselining_sap
@ -805,24 +755,24 @@ class Property:
property_data = {
"creation_status": "READY",
"uprn": int(self.data["uprn"]),
"uprn": int(self.epc_record.uprn),
"building_reference_number": (
int(self.data["building-reference-number"]) if
self.data["building-reference-number"] is not None else None
int(self.epc_record.building_reference_number) if
self.epc_record.building_reference_number is not None else None
),
"has_pre_condition_report": True,
"has_recommendations": True,
"property_type": self.data["property-type"],
"built_form": self.data["built-form"],
"local_authority": self.data["local-authority-label"],
"constituency": self.data["constituency-label"],
"property_type": self.epc_record.property_type,
"built_form": self.epc_record.built_form,
"local_authority": self.epc_record.local_authority_label,
"constituency": self.epc_record.constituency_label,
"number_of_rooms": self.number_of_rooms,
"year_built": self.year_built,
"tenure": self.data["tenure"],
"tenure": self.epc_record.tenure,
"current_epc_rating": current_epc_rating,
"current_sap_points": current_sap_rating,
"current_valuation": current_valuation,
"original_sap_points": self.data["current-energy-efficiency"],
"original_sap_points": self.epc_record.original_epc["current-energy-efficiency"],
"is_sap_points_adjusted_for_installed_measures": needs_rebaselining,
"installed_measures_sap_point_adjustment": rebaselining_sap,
}
@ -851,7 +801,7 @@ class Property:
raise ValueError("Current energy bill has not been set")
# IF we have a SAP05 overwrite, we pull out the relevant information
sap_05_overwritten = self.data.get("sap-05-overwritten", False)
sap_05_overwritten = self.epc_record.sap_05_overwritten
sap_05_score, sap_05_epc_rating = None, None
if sap_05_overwritten:
@ -864,9 +814,9 @@ class Property:
sap_05_score = int(newest_old_epc["current-energy-efficiency"])
sap_05_epc_rating = newest_old_epc["current-energy-rating"]
lodgement_date = self.data["lodgement-date"]
lodgement_date = self.epc_record.lodgement_date
# We check if the lodgement date is more than 10 years old
is_expired = (datetime.now() - pd.to_datetime(lodgement_date)) > timedelta(days=3650)
is_expired = self.epc_is_expired
# Handle re-baselining
co2_emissions = self.energy["co2_emissions"]
@ -886,42 +836,42 @@ class Property:
"portfolio_id": portfolio_id,
"lodgement_date": datetime.fromisoformat(lodgement_date),
"is_expired": is_expired,
"full_address": self.data["address"],
"total_floor_area": float(self.data["total-floor-area"]),
"full_address": self.epc_record.address,
"total_floor_area": float(self.epc_record.total_floor_area),
"walls": self.walls["clean_description"],
"walls_rating": self._prepare_rating_field(self.data["walls-energy-eff"]),
"walls_rating": self._prepare_rating_field(self.epc_record.walls_energy_eff),
"roof": self.roof["clean_description"],
"roof_rating": self._prepare_rating_field(self.data["roof-energy-eff"]),
"roof_rating": self._prepare_rating_field(self.epc_record.roof_energy_eff),
"floor": self.floor["clean_description"],
"floor_rating": self._prepare_rating_field(self.data["floor-energy-eff"]),
"floor_rating": self._prepare_rating_field(self.epc_record.floor_energy_eff),
"windows": self.windows["clean_description"],
"windows_rating": self._prepare_rating_field(self.data["windows-energy-eff"]),
"windows_rating": self._prepare_rating_field(self.epc_record.windows_energy_eff),
"heating": self.main_heating["clean_description"],
"heating_rating": self._prepare_rating_field(self.data["mainheat-energy-eff"]),
"heating_rating": self._prepare_rating_field(self.epc_record.mainheat_energy_eff),
"heating_controls": self.main_heating_controls["clean_description"],
"heating_controls_rating": self._prepare_rating_field(self.data["mainheatc-energy-eff"]),
"heating_controls_rating": self._prepare_rating_field(self.epc_record.mainheatc_energy_eff),
"hot_water": self.hotwater["clean_description"],
"hot_water_rating": self._prepare_rating_field(self.data["hot-water-energy-eff"]),
"hot_water_rating": self._prepare_rating_field(self.epc_record.hot_water_energy_eff),
"lighting": self.lighting["clean_description"],
"lighting_rating": self._prepare_rating_field(self.data["lighting-energy-eff"]),
"lighting_rating": self._prepare_rating_field(self.epc_record.lighting_energy_eff),
"mainfuel": self.main_fuel["clean_description"],
"ventilation": self.ventilation["ventilation"],
"solar_pv": self.solar_pv["solar_pv"],
"solar_hot_water": self.solar_hot_water["solar_hot_water_boolean"],
"wind_turbine": self.wind_turbine["wind_turbine"],
"ventilation": self.epc_record.mechanical_ventilation,
"solar_pv": self.epc_record.photo_supply,
"solar_hot_water": self.epc_record.solar_water_heating_flag_bool,
"wind_turbine": self.epc_record.wind_turbine_count,
"floor_height": self.floor_height,
"heat_loss_corridor": self.heat_loss_corridor["heat_loss_corridor_boolean"],
"unheated_corridor_length": self.heat_loss_corridor["length"],
"number_of_open_fireplaces": self.number_of_open_fireplaces["number_of_open_fireplaces"],
"number_of_extensions": self.number_of_extensions["number_of_extensions"],
"number_of_storeys": self.number_of_storeys["number_of_storeys"],
"heat_loss_corridor": self.epc_record.heat_loss_corridor_bool,
"unheated_corridor_length": self.epc_record.unheated_corridor_length,
"number_of_open_fireplaces": self.epc_record.number_open_fireplaces,
"number_of_extensions": self.epc_record.extension_count,
"number_of_storeys": self.epc_record.flat_storey_count,
"mains_gas": self.mains_gas,
"energy_tariff": self.data["energy-tariff"],
"energy_tariff": self.epc_record.energy_tariff,
"primary_energy_consumption": primary_energy_consumption,
"co2_emissions": co2_emissions,
"current_energy_demand": current_kwh_demand, # This is kwh - naming is confusing
"current_energy_demand_heating_hotwater": current_kwh_heating_hotwater, # This is kwh
"estimated": self.data.get("estimated", False),
"estimated": self.epc_record.estimated,
# We indicate if we've overwritten a SAP 05 EPC
"sap_05_overwritten": sap_05_overwritten,
"sap_05_score": sap_05_score,
@ -936,6 +886,10 @@ class Property:
"installed_measures_total_energy_bill_adjustment": rebaselining_bills,
"installed_measures_heat_demand_adjustment": rebaselining_heat_demand,
"is_epc_adjusted_for_installed_measures": needs_rebaselining,
# Re-baselining variables - to replace already installed variables entirely
"lodged_co2_emissions": float(self.epc_record.original_epc["co2-emissions-current"]),
"lodged_heat_demand": float(self.epc_record.original_epc["energy-consumption-current"]),
"has_been_remodelled": self.epc_record.has_been_remodelled,
}
return property_details_epc
@ -984,7 +938,7 @@ class Property:
"""
result = property_dimensions[
(property_dimensions["PROPERTY_TYPE"] == self.data["property-type"])
(property_dimensions["PROPERTY_TYPE"] == self.epc_record.property_type)
]
if (
@ -996,10 +950,10 @@ class Property:
]
if (
self.data["built-form"] not in self.DATA_ANOMALY_MATCHES
and self.data["built-form"] in result["BUILT_FORM"]
self.epc_record.built_form not in self.DATA_ANOMALY_MATCHES
and self.epc_record.built_form in result["BUILT_FORM"]
):
result = result[(result["BUILT_FORM"] == self.data["built-form"])]
result = result[(result["BUILT_FORM"] == self.epc_record.built_form)]
return result[
["NUMBER_HABITABLE_ROOMS", "TOTAL_FLOOR_AREA", "FLOOR_HEIGHT"]
@ -1042,7 +996,7 @@ class Property:
num_floors=self.number_of_floors,
floor_height=self.floor_height,
perimeter=self.perimeter,
built_form=self.data["built-form"],
built_form=self.epc_record.built_form,
)
if self.insulation_floor_area is None:
@ -1061,15 +1015,15 @@ class Property:
def set_floor_level(self):
self.floor_level = (
FLOOR_LEVEL_MAP[self.data["floor-level"]]
if self.data["floor-level"] not in self.DATA_ANOMALY_MATCHES
and self.data["floor-level"] is not None
FLOOR_LEVEL_MAP[self.epc_record.floor_level]
if self.epc_record.floor_level not in self.DATA_ANOMALY_MATCHES
and self.epc_record.floor_level is not None
else None
)
if self.floor_level is None:
if self.data["property-type"] != "Flat":
if self.epc_record.property_type != "Flat":
return
if self.floor["another_property_below"]:
@ -1129,21 +1083,6 @@ class Property:
)
self.floor_type = "suspended"
@staticmethod
def _extract_component(
component_data, component_rename_cols, component_drop_cols, rename_prefix=None
):
for k in component_rename_cols:
component_data[f"{rename_prefix}_{k}"] = component_data.get(k)
component_data = {
k: v
for k, v in component_data.items()
if k not in component_drop_cols + component_rename_cols
}
return component_data
def set_windows_count(self):
"""
Using the estimate_windows function, this method will set the number of windows in the property
@ -1155,8 +1094,8 @@ class Property:
self.number_of_windows = int(condition_data["number_of_windows"]) \
if condition_data.get("number_of_windows") is not None \
else estimate_windows(
property_type=self.data["property-type"],
built_form=self.data["built-form"],
property_type=self.epc_record.property_type,
built_form=self.epc_record.built_form,
construction_age_band=self.construction_age_band,
floor_area=self.floor_area,
number_habitable_rooms=self.number_of_rooms,
@ -1176,14 +1115,14 @@ class Property:
# If we have a house over a floor area threshold, we recommend an ASHP
if (
self.data["property-type"] in ["House", "Bungalow"] and
self.epc_record.property_type in ["House", "Bungalow"] and
self.floor_area > assumptions.ASHP_FLOOR_AREA_THRESHOLD
):
return True
suitable_property_type = (
self.data["property-type"] in ["House", "Bungalow"] and
self.data["built-form"] not in ["Enclosed Mid-Terrace", "Enclosed End-Terrace"]
self.epc_record.property_type in ["House", "Bungalow"] and
self.epc_record.built_form not in ["Enclosed Mid-Terrace", "Enclosed End-Terrace"]
)
has_air_source_heat_pump = self.main_heating["has_air_source_heat_pump"]
@ -1205,12 +1144,12 @@ class Property:
# may be installed such that they are not visible from the street
return False
if (self.data["property-type"] in ["House", "Bungalow"]) and (
if (self.epc_record.property_type in ["House", "Bungalow"]) and (
not pd.isnull(self.roof["thermal_transmittance"])
):
return True
is_valid_property_type = self.data["property-type"] in ["House", "Bungalow", "Maisonette"]
is_valid_property_type = self.epc_record.property_type in ["House", "Bungalow", "Maisonette"]
is_valid_roof_type = (
self.roof["is_flat"] or self.roof["is_pitched"] or self.roof["is_roof_room"]
)
@ -1223,7 +1162,7 @@ class Property:
"already has solar pv", "roof too small", "no roof"
]
else:
has_no_existing_solar_pv = self.data["photo-supply"] in [
has_no_existing_solar_pv = self.epc_record.photo_supply in [
None, 0, self.DATA_ANOMALY_MATCHES
]
@ -1295,9 +1234,25 @@ class Property:
def identify_ventilation(self):
ventilation_descriptions = [
return self.epc_record.mechanical_ventilation in {
'mechanical, extract only',
'mechanical, supply and extract'
]
}
return self.data.get("mechanical-ventilation") in ventilation_descriptions
@property
def epc_is_expired(self) -> bool:
"""
This property indicates that the EPC is expired. This is based on the lodgement date, where an EPC is
valid for 10 years.
:return: boolean indicating whether the EPC is expired
"""
lodgement_date = self.epc_record.lodgement_date
return (datetime.now() - pd.to_datetime(lodgement_date)) > timedelta(days=3650)
@property
def epc_is_estimated(self) -> bool:
"""
This property indicates that the EPC is estimated, based on the presence of the "estimated" flag in the data
:return: boolean indicating whether the EPC is estimated
"""
return self.epc_record.estimated

View file

@ -1,36 +1,52 @@
from dataclasses import dataclass
from typing import Optional
import datatypes.epc as epc_datatypes
from typing import Optional, Union
@dataclass(slots=True)
class Address:
# address: Optional[str]
# full_address: Optional[str]
# property_type: Optional[str]
# built_form: Optional[str]
# estimated: bool
# New fields
uprn: Optional[int]
landlord_property_id: Optional[str]
address: Optional[str]
full_address: Optional[str]
address_1: str
address_2: Optional[str]
address_3: Optional[str]
full_address: str
postcode: str
property_type: Optional[str]
built_form: Optional[str]
estimated: bool
landlord_total_floor_area_m2: Union[float, None]
# Property components
landlord_property_type: Optional[epc_datatypes.property_type_built_form.PropertyType]
landlord_built_form: Optional[epc_datatypes.property_type_built_form.BuiltForm]
landlord_wall_construction: Optional[epc_datatypes.walls.EpcWallDescriptions]
landlord_roof_construction: Optional[epc_datatypes.roof.EpcRoofDescriptions]
landlord_floor_construction: Optional[epc_datatypes.floor.EpcFloorDescriptions]
landlord_windows_type: Optional[epc_datatypes.windows.EpcWindowDescriptions]
landlord_heating_system: Optional[epc_datatypes.main_heating.EpcHeatingSystems]
landlord_fuel_type: Optional[epc_datatypes.fuel.EpcFuel]
landlord_heating_controls: Optional[epc_datatypes.heating_controls.EpcHeatingControls]
landlord_hot_water_system: Optional[epc_datatypes.hotwater.EpcHotWaterSystems]
# Efficiency
landlord_wall_efficiency: Optional[epc_datatypes.efficiency.EpcEfficiency]
landlord_roof_efficiency: Optional[epc_datatypes.efficiency.EpcEfficiency]
landlord_windows_efficiency: Optional[epc_datatypes.efficiency.EpcEfficiency]
landlord_heating_efficiency: Optional[epc_datatypes.efficiency.EpcEfficiency]
landlord_heating_controls_efficiency: Optional[epc_datatypes.efficiency.EpcEfficiency]
landlord_hot_water_efficiency: Optional[epc_datatypes.efficiency.EpcEfficiency]
# Additionals
landlord_has_sloping_ceiling: Optional[bool]
landlord_multi_glaze_proportion: Optional[float]
landlord_construction_age_band: Optional[epc_datatypes.construction_age_band.EpcConstructionAgeBand]
# Additional address data, associated to a standardised asset list
domna_full_address: Optional[str]
domna_address_1: Optional[str]
landlord_heating_system: Optional[str] = None
solar_reason: Optional[str] = None
cavity_reason: Optional[str] = None
@property
def address1(self):
if self.domna_address_1 is not None:
address1 = self.domna_address_1
else:
address1 = self.address
# Format
address1 = str(int(address1)) if isinstance(address1, float) else str(address1)
return address1
# domna_full_address: Optional[str]
# domna_address_1: Optional[str]
@property
def request_data(self) -> dict[str, Optional[str]]:
@ -41,27 +57,9 @@ class Address:
"uprn": self.uprn,
"landlord_property_id": self.landlord_property_id,
"postcode": self.postcode,
"address1": self.address1,
"address1": self.address_1,
"full_address": self.full_address,
}
# Drop nulls
return {k: v for k, v in data.items() if v is not None}
@property
def heating_system(self):
"""
Helper function to extract a heating system, which can be used to estimate EPC. This is a very limited,
placeholder function to cover some initial immediate cases.
:return:
"""
ll_heating = self.landlord_property_id
if not ll_heating:
return None
if ll_heating == "electric storage heaters":
# Return with the same format at the EPC
return "Electric storage heaters"
return None

View file

@ -1,5 +1,8 @@
import warnings
import pandas as pd
from typing import Iterator
from backend.addresses.Address import Address
from datatypes.epc.property_type_built_form import PropertyType
class Addresses:
@ -19,9 +22,28 @@ class Addresses:
@classmethod
def from_plan_input(cls, plan_input: list[dict], body) -> "Addresses":
addresses = []
for row in plan_input:
addresses.append(cls._parse_row(row, body))
return cls(addresses)
try:
if body.file_format == "ara_property_list":
addr = cls.parse_ara_row(row, body)
else:
addr = cls._parse_row_deprecated(row, body)
# Fallback if new parser fails
except Exception:
warnings.warn(
"Falling back to deprecated parser for row",
RuntimeWarning,
stacklevel=2,
)
addr = cls._parse_row_deprecated(row, body)
addresses.append(addr)
addresses = cls(addresses)
addresses.validate_uprns()
return addresses
def get_uprns(self):
return [x.uprn for x in self._addresses if x.uprn is not None]
@ -35,54 +57,115 @@ class Addresses:
def get_postcodes_for_flats(self):
# Method to extract all of the postcodes associated to a flat, which is used for remote assessments
# on flats
return [x.postcode for x in self._addresses if x.property_type in ["Flat", "flat"]]
return [x.postcode for x in self._addresses if x.landlord_property_type in [PropertyType.flat.value]]
def get_property_requests(self):
return [x.request_data for x in self._addresses]
def validate_uprns(self):
"""Raise ValueError if any address has a non-int UPRN."""
for addr in self._addresses:
if addr.uprn is not None and not isinstance(addr.uprn, int):
raise ValueError(f"Address with non-integer UPRN detected: {addr.uprn} in {addr}")
@staticmethod
def _parse_row(row: dict, body) -> Address:
def parse_ara_row(row: dict, body) -> Address:
"""
Method to parse a row from the ARA property list format, which is a more standardised format that we are
moving towards.
:param row: A dictionary representing a row from the ARA property list, which should have keys corresponding
to the Address dataclass fields. The method will attempt to parse these fields and create an Address object.
:param body: The PlanTriggerRequest body, which may contain additional information about the file format and
other details that could be relevant for parsing.
:return: An Address object created from the parsed row data.
"""
return Address(
uprn=int(row["uprn"]),
landlord_property_id=str(row["landlord_property_id"]) if row.get("landlord_property_id") else None,
address_1=row["address_1"],
address_2=row.get("address_2"),
address_3=row.get("address_3"),
full_address=row["full_address"],
postcode=str(row["postcode"]),
landlord_total_floor_area_m2=float(row["landlord_total_floor_area_m2"]) if row.get(
"landlord_total_floor_area_m2") else None,
landlord_property_type=row.get("landlord_property_type"),
landlord_built_form=row.get("landlord_built_form"),
landlord_wall_construction=row.get("landlord_wall_construction"),
landlord_roof_construction=row.get("landlord_roof_construction"),
landlord_floor_construction=row.get("landlord_floor_construction"),
landlord_windows_type=row.get("landlord_windows_type"),
landlord_heating_system=row.get("landlord_heating_system"),
landlord_fuel_type=row.get("landlord_fuel_type"),
landlord_heating_controls=row.get("landlord_heating_controls"),
landlord_hot_water_system=row.get("landlord_hot_water_system"),
landlord_wall_efficiency=row.get("landlord_wall_efficiency"),
landlord_roof_efficiency=row.get("landlord_roof_efficiency"),
landlord_windows_efficiency=row.get("landlord_windows_efficiency"),
landlord_heating_efficiency=row.get("landlord_heating_efficiency"),
landlord_heating_controls_efficiency=row.get("landlord_heating_controls_efficiency"),
landlord_hot_water_efficiency=row.get("landlord_hot_water_efficiency"),
landlord_has_sloping_ceiling=bool(row.get("landlord_has_sloping_ceiling")) if row.get(
"landlord_has_sloping_ceiling") is not None else None,
landlord_multi_glaze_proportion=float(row["landlord_multi_glaze_proportion"]) if row.get(
"landlord_multi_glaze_proportion") else None,
landlord_construction_age_band=row.get("landlord_construction_age_band"),
)
@staticmethod
def _parse_row_deprecated(row: dict, body) -> Address:
def clean_uprn(v):
if v is None:
return None
try:
return int(float(v))
except (TypeError, ValueError):
return None
raise ValueError(f"Invalid UPRN value: {v}")
uprn = clean_uprn(row.get("uprn"))
uprn_option1 = row.get("uprn")
uprn_option1 = uprn_option1 if not pd.isnull(uprn_option1) else None
uprn_option2 = row.get("ordnance_survey_uprn")
uprn_option2 = uprn_option2 if not pd.isnull(uprn_option2) else None
address = row.get("address")
if not address and body.file_format == "domna_asset_list":
address = row.get("domna_address_1")
uprn = clean_uprn(uprn_option1 or uprn_option2)
full_address = (
row.get("domna_full_address")
if body.file_format == "domna_asset_list"
else None
)
if not isinstance(full_address, str):
full_address = None
address = row.get("address") or row.get("domna_address_1") or ""
full_address = row.get("domna_full_address") or address or ""
postcode = str(row["postcode"]).strip().upper()
postcode = str(row.get("postcode", "")).strip().upper()
return Address(
uprn=uprn,
landlord_property_id=str(row["landlord_property_id"])
if row.get("landlord_property_id") else None,
address=str(address).strip() if address else None,
full_address=str(full_address).strip() if full_address else None,
landlord_property_id=str(row["landlord_property_id"]) if row.get("landlord_property_id") else None,
address_1=str(address).strip(),
address_2=None,
address_3=None,
full_address=str(full_address).strip(),
postcode=postcode,
property_type=row.get("property_type"),
built_form=row.get("built_form"),
estimated=bool(row.get("estimated", False)),
domna_full_address=row.get("domna_full_address"),
domna_address_1=row.get("domna_address_1"),
)
# def _build_identity_index(self) -> dict:
# index = {}
# for addr in self._addresses:
# key = addr.identity_key()
# if key in index:
# raise ValueError(f"Duplicate address identity detected: {key}")
# index[key] = addr
# return index
landlord_total_floor_area_m2=None,
# Map old to new fields
landlord_property_type=row.get("property_type") or row.get("landlord_property_type"),
landlord_built_form=row.get("built_form") or row.get("landlord_built_form"),
landlord_wall_construction=None,
landlord_roof_construction=None,
landlord_floor_construction=None,
landlord_windows_type=None,
landlord_heating_system=row.get("epc_heating_type"),
landlord_fuel_type=None,
landlord_heating_controls=None,
landlord_hot_water_system=None,
landlord_wall_efficiency=None,
landlord_roof_efficiency=None,
landlord_windows_efficiency=None,
landlord_heating_efficiency=None,
landlord_heating_controls_efficiency=None,
landlord_hot_water_efficiency=None,
landlord_has_sloping_ceiling=None,
landlord_multi_glaze_proportion=None,
landlord_construction_age_band=None,
)

View file

@ -182,8 +182,8 @@ class GoogleSolarApi:
self.exclude_north_facing_segments(property_instance=property_instance)
# If a property is semi-detached, it's possible for us to include segments from an attached unit
if property_instance is not None:
if (property_instance.data["built-form"] == "Semi-Detached") and (
property_instance.data["extension-count"] == 0
if (property_instance.epc_record.built_form == "Semi-Detached") and (
property_instance.epc_record.extension_count == 0
):
self.exclude_likely_duplicate_surfaces()
@ -708,7 +708,7 @@ class GoogleSolarApi:
# We set the target rating to EPC C, which is the typical EPC rating we would expect the
# property to achieve post retrofit of just the fabric
"energy_consumption": cls.estimate_new_consumption(
current_energy_efficiency=min(p.data["current-energy-efficiency"], 100),
current_energy_efficiency=min(p.epc_record.current_energy_efficiency, 100),
target_efficiency="69",
current_consumption=p.estimate_electrical_consumption(
assumed_ashp_efficiency=assumptions.AVERAGE_ASHP_EFFICIENCY, exclusions=body.exclusions
@ -727,7 +727,7 @@ class GoogleSolarApi:
# We set the target rating to EPC C, which is the typical EPC rating we would expect the
# property to achieve post retrofit of just the fabric
"energy_consumption": cls.estimate_new_consumption(
current_energy_efficiency=min(int(p.data["current-energy-efficiency"]), 100),
current_energy_efficiency=min(p.epc_record.current_energy_efficiency, 100),
target_efficiency="69",
current_consumption=p.estimate_electrical_consumption(
assumed_ashp_efficiency=assumptions.AVERAGE_ASHP_EFFICIENCY, exclusions=body.exclusions

View file

@ -54,11 +54,11 @@ class Settings(BaseSettings):
SAP_PREDICTIONS_BUCKET: str = "changeme"
CARBON_PREDICTIONS_BUCKET: str = "changeme"
HEAT_PREDICTIONS_BUCKET: str = "changeme"
# LIGHTING_COST_PREDICTIONS_BUCKET: str
# HEATING_COST_PREDICTIONS_BUCKET: str
# HOT_WATER_COST_PREDICTIONS_BUCKET: str
HEATING_KWH_PREDICTIONS_BUCKET: str = "changeme"
HOTWATER_KWH_PREDICTIONS_BUCKET: str = "changeme"
SAP_BASELINE_PREDICTIONS_BUCKET: str = "changeme"
CARBON_BASELINE_PREDICTIONS_BUCKET: str = "changeme"
HEAT_BASELINE_PREDICTIONS_BUCKET: str = "changeme"
# Other S3 buckts
ENERGY_ASSESSMENTS_BUCKET: str = "changeme"
@ -102,4 +102,9 @@ def get_prediction_buckets():
"carbon_change_predictions": get_settings().CARBON_PREDICTIONS_BUCKET,
"heating_kwh_predictions": get_settings().HEATING_KWH_PREDICTIONS_BUCKET,
"hotwater_kwh_predictions": get_settings().HOTWATER_KWH_PREDICTIONS_BUCKET,
# Score model - SAP re-baselining model
"retrofit_sap_baseline_predictions": get_settings().SAP_BASELINE_PREDICTIONS_BUCKET,
"retrofit_carbon_baseline_predictions": get_settings().CARBON_BASELINE_PREDICTIONS_BUCKET,
"retrofit_heat_baseline_predictions": get_settings().HEAT_BASELINE_PREDICTIONS_BUCKET,
}

View file

@ -1,5 +1,5 @@
from typing import Optional
from sqlalchemy.orm import Session
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy import func
from backend.app.db.models.addresses import PostcodeSearch
from utils.logger import setup_logger
@ -20,7 +20,7 @@ def _get_associated_records(results, uprn, uprn_key="UPRN"):
return matched_record
def get_associated_uprns(postcode_search: PostcodeSearch, uprn: str | int):
def get_associated_uprns(postcode_search: Optional[PostcodeSearch], uprn: str | int):
"""
Given a postcode and UPRN, for a remote assessment, fetch all associated UPRNs, based
on parent UPRN. This will be properties in the same building

View file

@ -101,7 +101,7 @@ def get_latest_assessments_for_uprns(
found_set = set(result.keys())
missing_uprns = uprn_set - found_set
for uprn in missing_uprns:
result[uprn] = EnergyAssessment.empty_response()

View file

@ -11,7 +11,7 @@ class EpcStoreService:
Service layer for EPC data lookup and persistence.
"""
FRESHNESS_DAYS = 30
FRESHNESS_DAYS = 180 # Upgraded to 180 days
# status labels
FRESH = "fresh"

View file

@ -15,8 +15,9 @@ from backend.app.db.models.portfolio import (
)
def create_property(session: Session, portfolio_id: int, address: str, postcode: str, uprn: str,
energy_assessment: dict, landlord_property_id: str | None = None) -> (int, bool):
def create_property(
session: Session, portfolio_id: int, address: str, postcode: str, uprn: str,
energy_assessment: dict, landlord_property_id: str | None = None) -> (int, bool):
"""
This function will create a record for the property in the database if it does not exist.
If it does exist, it will just update the updated_at field.
@ -252,7 +253,7 @@ def bulk_create_properties(
rows.append(
{
"address": addr.address1,
"address": addr.address_1,
"postcode": addr.postcode,
"portfolio_id": body.portfolio_id,
"uprn": addr.uprn,

View file

@ -64,7 +64,7 @@ class SubTaskInterface:
self,
subtask_id: UUID,
status: str,
outputs: Optional[Dict[str, str]] = None,
outputs: Optional[Dict[str, str] | str] = None,
cloud_logs_url: Optional[str] = None,
) -> SubTask:
"""

View file

@ -147,6 +147,10 @@ class PropertyModel(Base):
is_sap_points_adjusted_for_installed_measures = Column(Boolean, default=False)
original_sap_points = Column(Float)
# New for re-scoring - we will need to delete some of the redundant fields but there is a ticket for this
lodged_sap_points = Column(Float)
lodged_epc_rating = Column(Enum(Epc))
class FeatureRating(enum.Enum):
VERY_GOOD = 5
@ -253,6 +257,12 @@ class PropertyDetailsEpcModel(Base):
installed_measures_heat_demand_adjustment = Column(Float)
is_epc_adjusted_for_installed_measures = Column(Boolean, default=False)
# New columns - we'll need to delete some of the redundant fields, associated to "already installed" but
# we have a ticket for this piece of work
lodged_co2_emissions = Column(Float)
lodged_heat_demand = Column(Float)
has_been_remodelled = Column(Boolean, default=False)
class PropertyDetailsSpatial(Base):
__tablename__ = "property_details_spatial"

View file

@ -0,0 +1,109 @@
import logging
import numpy as np
import pandas as pd
from backend.addresses.Addresses import Addresses
from backend.app.config import get_settings
from utils.s3 import read_csv_from_s3, read_excel_from_s3
class PlanInputProcessor:
def __init__(self, body):
self.body = body
self.logger = logging.getLogger(__name__)
self.plan_input = None
self.valuation_data = []
self.index_start = getattr(body, 'index_start', None)
self.index_end = getattr(body, 'index_end', None)
def process(self):
if self.body.file_type == "xlsx":
self.logger.info("Getting the plan input")
self.plan_input = read_excel_from_s3(
bucket_name=get_settings().PLAN_TRIGGER_BUCKET,
file_key=self.body.trigger_file_path,
sheet_name=self.body.sheet_name,
header_row=0,
)
self.logger.info("Got the plan input from excel")
if self.body.file_format == "domna_asset_list":
self._process_domna_asset_list()
elif self.body.file_format == "ara_property_list":
self._process_ara_property_list()
else:
raise ValueError("Other formats not yet supported")
else:
self.logger.info("Getting the plan input from csv")
self.plan_input = read_csv_from_s3(
bucket_name=get_settings().PLAN_TRIGGER_BUCKET, filepath=self.body.trigger_file_path
)
self.logger.info("Got the plan input from csv")
# Slice if needed
if self.index_start is not None and self.index_end is not None:
self.plan_input = self.plan_input[self.index_start:self.index_end]
# Extract valuation data if present
self._extract_valuation_data()
return self.to_addresses()
def _extract_valuation_data(self):
# Only for domna_asset_list, extract domna_valuation if present
if self.body.file_format == "domna_asset_list" and self.plan_input:
first = self.plan_input[0]
if "domna_valuation" in first:
self.valuation_data = [
{"uprn": x.get("uprn"), "valuation": x.get("domna_valuation")}
for x in self.plan_input if x.get("domna_valuation") is not None
]
# Could add more formats here in future
def _process_domna_asset_list(self):
df = self.plan_input
df = df.rename(
columns={"domna_address_1": "address", "domna_postcode": "postcode", "epc_os_uprn": "uprn"}
)
if "estimated" not in df.columns:
df["estimated"] = False
df["uprn"] = np.where(
df["estimated"].isin([1, True]) & ((df["uprn"] < 0) | pd.isnull(df["uprn"])), None, df["uprn"]
)
df["property_type"] = df["landlord_property_type"].copy()
if "landlord_built_form" in df.columns:
df["built_form"] = df["landlord_built_form"].copy()
else:
df["built_form"] = None
if "epc_property_type" not in df.columns:
df["epc_property_type"] = None
df["property_type"] = np.where(
df["property_type"] == "unknown", df["epc_property_type"], df["property_type"]
)
if "epc_archetype" not in df.columns:
df["epc_archetype"] = None
df["built_form"] = np.where(
df["built_form"] == "unknown", df["epc_archetype"], df["built_form"]
)
property_type_map = {
"house": "House",
"flat": "Flat",
"maisonette": "Maisonette",
"bungalow": "Bungalow",
"block house": "House",
"coach house": "House",
"bedsit": "Flat",
}
built_form_map = {
"mid-terrace": "Mid-Terrace",
"end-terrace": "End-Terrace",
"semi-detached": "Semi-Detached",
"detached": "Detached",
"enclosed end-terrace": "Enclosed End-Terrace",
"enclosed mid-terrace": "Enclosed Mid-Terrace",
}
df["property_type"] = df["property_type"].map(property_type_map).fillna(df["property_type"])
df["built_form"] = df["built_form"].map(built_form_map).fillna(df["built_form"])
self.plan_input = df.to_dict("records")
def _process_ara_property_list(self):
df = self.plan_input
self.plan_input = df.to_dict("records")
def to_addresses(self):
return Addresses.from_plan_input(self.plan_input, self.body)

View file

@ -174,6 +174,8 @@ async def trigger_plan_entrypoint(body: PlanTriggerRequest):
service="plan_engine",
inputs=data,
task_only=True,
source=SourceEnum.PORTFOLIO,
source_id=str(body.portfolio_id),
)
subtask_interface = SubTaskInterface()
@ -222,6 +224,8 @@ async def trigger_plan_entrypoint(body: PlanTriggerRequest):
service="plan_engine",
inputs=data,
task_only=False,
source=SourceEnum.PORTFOLIO,
source_id=str(body.portfolio_id),
)
data["task_id"] = str(task_id)
data["subtask_id"] = str(subtask_id)

View file

@ -130,7 +130,7 @@ class PlanTriggerRequest(BaseModel):
# Add in optional fields which describe the format of the asset list being used
file_type: Optional[Literal["csv", "xlsx"]] = None
file_format: Optional[Literal["domna_asset_list"]] = None
file_format: Optional[Literal["domna_asset_list", "ara_property_list"]] = None
sheet_name: Optional[str] = None
sheet_count: Optional[int] = None
# If one of index_start or index_end is set, the other must be set too

View file

@ -64,7 +64,7 @@ def extract_property_request_data(
x
for x in patches
if (x["address"] == address.address)
and (x["postcode"] == address.postcode)
and (x["postcode"] == address.postcode)
),
{},
)
@ -92,7 +92,7 @@ def extract_property_request_data(
x
for x in non_invasive_recommendations
if (x["address"] == address.address)
and (x["postcode"] == address.postcode)
and (x["postcode"] == address.postcode)
),
{},
)
@ -134,7 +134,7 @@ def extract_property_request_data(
float(x["valuation"])
for x in valuation_data
if (x["address"] == address.address)
and (x["postcode"] == address.postcode)
and (x["postcode"] == address.postcode)
),
None,
)
@ -241,7 +241,7 @@ def parse_eco_packages(
return measures, mapped["target_sap"], mapped["plan_type"], already_installed
def build_cloudwatch_log_url(start_ms: int) -> str:
def build_cloudwatch_log_url(start_ms: Optional[int]) -> str:
"""
Build a CloudWatch Logs URL for the current Lambda invocation,
including timestamp window from start_ms to end_ms (epoch ms).
@ -271,7 +271,7 @@ def build_cloudwatch_log_url(start_ms: int) -> str:
def handle_error(
msg: str,
exception: Exception,
subtask_id: str,
subtask_id: Optional[str],
status_code: int = 500,
start_ms: Optional[int] = None,
):

View file

@ -3,6 +3,7 @@ import string
import secrets
import logging
from io import BytesIO
from typing import Optional
def setup_logger(log_file=None, level=logging.INFO, overwrite_handler=False):
@ -73,7 +74,7 @@ def sap_to_epc(sap_points: int | float):
return "G"
def epc_to_sap_lower_bound(epc: str):
def epc_to_sap_lower_bound(epc: Optional[str]):
"""
Given an EPC rating, returns the lower bound SAP score required
to hit that EPC rating

View file

@ -2,18 +2,19 @@ import time
import json
from copy import deepcopy
from datetime import datetime
import pandas as pd
from uuid import UUID
from typing import List
from tqdm import tqdm
import pandas as pd
import numpy as np
from uuid import UUID
from sqlalchemy.exc import IntegrityError, OperationalError
from starlette.responses import Response
from backend.SearchEpc import SearchEpc
from etl.epc.Record import EPCRecord
from sqlalchemy.exc import IntegrityError, OperationalError
from starlette.responses import Response
from backend.app.BatterySapScorer import BatterySAPScorer
from etl.epc.PredictionMatrix import PredictionMatrix
from backend.app.config import get_settings, get_prediction_buckets
from backend.app.db.connection import db_session, db_read_session
@ -22,7 +23,7 @@ from backend.app.db.functions.tasks.Tasks import SubTaskInterface
from backend.app.plan.schemas import PlanTriggerRequest
from backend.app.plan.utils import (
get_cleaned, patch_epc, extract_property_request_data, parse_eco_packages, handle_error, build_cloudwatch_log_url
get_cleaned, patch_epc, extract_property_request_data, handle_error, build_cloudwatch_log_url
)
from backend.app.utils import sap_to_epc
import backend.app.assumptions as assumptions
@ -44,7 +45,9 @@ from etl.spatial.OpenUprnClient import OpenUprnClient
from etl.find_my_epc.RetrieveFindMyEpc import RetrieveFindMyEpc
from utils.logger import setup_logger
from utils.s3 import read_dataframe_from_s3_parquet, read_csv_from_s3, read_excel_from_s3
from utils.s3 import read_dataframe_from_s3_parquet, read_csv_from_s3
from backend.app.plan.plan_input_processor import PlanInputProcessor
logger = setup_logger()
@ -121,20 +124,31 @@ def extract_portfolio_aggregation_data(
cost = sum([r["total"] for r in default_recommendations])
sap_point_improvement = sum([r["sap_points"] for r in default_recommendations])
if not pd.isnull(property_value_increase_ranges[p.id]["current_value"]):
# Fix ambiguous Series/DataFrame truth value for current_value
current_value = property_value_increase_ranges[p.id]["current_value"]
if isinstance(current_value, (pd.Series, pd.DataFrame)):
# Reduce to scalar
is_null = bool(
current_value.isnull().all().item() if
hasattr(current_value.isnull().all(), 'item') else current_value.isnull().all().all()
)
else:
is_null = bool(pd.isnull(current_value))
if (not is_null) and (current_value is not None):
lower_bound_valuation_uplift = (
property_value_increase_ranges[p.id]["lower_bound_increased_value"] -
property_value_increase_ranges[p.id]["current_value"]
current_value
)
upper_bound_valuation_uplift = (
property_value_increase_ranges[p.id]["upper_bound_increased_value"] -
property_value_increase_ranges[p.id]["current_value"]
current_value
)
else:
lower_bound_valuation_uplift, upper_bound_valuation_uplift = 0, 0
agg_data.append({
"pre_retrofit_epc": p.data["current-energy-rating"],
"pre_retrofit_epc": p.epc_record.current_energy_rating,
"post_retrofit_epc": new_epc_bands[p.id],
"pre_retrofit_co2": pre_retrofit_co2,
"post_retrofit_co2": post_retrofit_co2,
@ -285,7 +299,7 @@ def create_epc_records(epc_searcher: SearchEpc, energy_assessment: dict):
"old_data": epc_searcher.older_epcs.copy()
}, energy_assessment_is_newer
# In this case, our EPC is older than the newest publically avaible one, but is not contained in
# In this case, our EPC is older than the newest publically availe one, but is not contained in
# the historicals, so it can't have been lodged, so we include it in the old data
return {
'original_epc': newest_epc,
@ -363,14 +377,13 @@ def get_funding_data():
return project_scores_matrix, partial_project_scores_matrix, whlg_eligible_postcodes
def check_duplicate_uprns(plan_input):
def check_duplicate_uprns(input_uprns: List[int]):
"""
Simple function to check if the input data contains duplicated UPRNS.
If there are duplicates, an exception will be rasied
:return:
"""
# Check for duplicate UPRNS
input_uprns = [x.get("uprn") for x in plan_input if "uprn" in x and x.get("uprn")]
if input_uprns:
# Check for dupes
@ -413,104 +426,19 @@ def check_duplicate_property_ids(input_properties):
return True
def averages_cleaning(prepared_epc: EPCRecord, cleaning_data: pd.DataFrame):
"""
Placeholder cleaning function to handle edge cases where we have missing data for
number of habitable rooms, number of heated rooms and floor height. We take the median
This need was born out of the Peabody project
:param prepared_epc:
:param cleaning_data:
:return:
"""
variables_to_clean = [
"number_habitable_rooms",
"number_heated_rooms",
"floor_height",
]
if not any([pd.isnull(prepared_epc.prepared_epc[k]) for k in variables_to_clean]):
# Nothing to do
return prepared_epc
# Clean with cleaning_data
clean_with = cleaning_data[
(cleaning_data["property_type"] == prepared_epc.prepared_epc["property_type"]) &
(cleaning_data["property_type"] == prepared_epc.prepared_epc["property_type"])
]
if prepared_epc.prepared_epc["local_authority"] in clean_with["local_authority"].values:
clean_with = clean_with[
clean_with["local_authority"] == prepared_epc.prepared_epc["local_authority"]
]
floor_area_clean_with = clean_with[
(clean_with["total_floor_area"] <= prepared_epc.prepared_epc["total_floor_area"] * 1.1) &
(clean_with["total_floor_area"] >= prepared_epc.prepared_epc["total_floor_area"] * 0.9)
]
if not floor_area_clean_with.empty:
clean_with = floor_area_clean_with
clean_n_habitable_rooms = int(round(clean_with["number_habitable_rooms"].median()))
clean_n_heated_rooms = int(round(clean_with["number_heated_rooms"].median()))
if clean_n_heated_rooms > clean_n_habitable_rooms:
clean_n_heated_rooms = clean_n_habitable_rooms
clean_floor_height = clean_with["floor_height"].median()
# We now fill
if not pd.isnull(clean_n_habitable_rooms) and pd.isnull(
prepared_epc.prepared_epc["number_habitable_rooms"]):
prepared_epc.prepared_epc["number_habitable_rooms"] = clean_n_habitable_rooms
prepared_epc.number_habitable_rooms = clean_n_habitable_rooms
if not pd.isnull(clean_n_heated_rooms) and pd.isnull(
prepared_epc.prepared_epc["number_heated_rooms"]):
prepared_epc.prepared_epc["number_heated_rooms"] = clean_n_heated_rooms
prepared_epc.number_heated_rooms = clean_n_heated_rooms
if not pd.isnull(clean_floor_height) and pd.isnull(
prepared_epc.prepared_epc["floor_height"]):
prepared_epc.prepared_epc["floor_height"] = clean_floor_height
prepared_epc.floor_height = clean_floor_height
# if pd.isnull(prepared_epc.lighting_cost_current):
# # This is a basic assumption as an average
# prepared_epc.prepared_epc["lighting_cost_current"] = assumptions.AVERAGE_LIGHTING_COST
# prepared_epc.lighting_cost_current = assumptions.AVERAGE_LIGHTING_COST
# if pd.isnull(prepared_epc.heating_cost_current):
# # This is a basic assumption as an average
# appliance_cost = AnnualBillSavings.estimate_appliances_energy_use(
# total_floor_area=prepared_epc.total_floor_area
# ) * AnnualBillSavings.ELECTRICITY_PRICE_CAP
# heating_cleaned_value = assumptions.AVERAGE_HEATING_AND_APPLIANCE_COST - appliance_cost
# prepared_epc.prepared_epc["heating_cost_current"] = heating_cleaned_value
# prepared_epc.heating_cost_current = heating_cleaned_value
#
# if pd.isnull(prepared_epc.hot_water_cost_current):
# # This is a basic assumption as an average
# prepared_epc.prepared_epc["hot_water_cost_current"] = assumptions.AVERAGE_HOT_WATER_COST
# prepared_epc.hot_water_cost_current = assumptions.AVERAGE_HOT_WATER_COST
#
# if pd.isnull(prepared_epc.energy_consumption_potential):
# # Set to current
# prepared_epc.prepared_epc["energy_consumption_potential"] = prepared_epc.energy_consumption_current
# prepared_epc.energy_consumption_potential = prepared_epc.energy_consumption_current
return prepared_epc
def extract_address_data(config, body):
"""
Simple helper to grab address data from the config
:return:
"""
uprn = config.get("uprn", None)
if pd.isnull(uprn):
try:
uprn = config.get("uprn", None)
if uprn is not None and pd.notnull(uprn):
uprn = int(float(uprn))
else:
uprn = None
except Exception:
uprn = None
if uprn:
uprn = int(float(uprn))
address1 = config.get("address", None)
# Handle domna address list format
@ -542,131 +470,32 @@ def keep_max_sap_per_measure_type(items):
async def model_engine(body: PlanTriggerRequest):
logger.info("Model Engine triggered with body: %s", json.loads(body.model_dump_json()))
created_at = datetime.now().isoformat()
start_ms = int(time.time() * 1000)
logger.info("Model Engine triggered with body: %s", json.loads(body.model_dump_json()))
if body.subtask_id:
SubTaskInterface().update_subtask_status(
subtask_id=UUID(body.subtask_id), status="in progress", cloud_logs_url=build_cloudwatch_log_url(start_ms)
)
try:
logger.info("Getting the inputs")
if body.file_type == "xlsx":
logger.info("Getting the plan input")
plan_input = read_excel_from_s3(
bucket_name=get_settings().PLAN_TRIGGER_BUCKET,
file_key=body.trigger_file_path,
sheet_name=body.sheet_name,
header_row=0,
)
logger.info("Got the plan input from excel")
# We now handle the case where the input data is a Domna standardised assset list
if body.file_format == "domna_asset_list":
# We rename the columns to match the expected format
plan_input = plan_input.rename(
columns={"domna_address_1": "address", "domna_postcode": "postcode", "epc_os_uprn": "uprn"}
)
# Where the EPC has been estimated, that is because a UPRN wasn't avaialble and so we remove UPRN
# This will be reflexted
if "estimated" not in plan_input.columns:
plan_input["estimated"] = False
plan_input["uprn"] = np.where(
plan_input["estimated"].isin([1, True]) & (
(plan_input["uprn"] < 0) | pd.isnull(plan_input["uprn"])
), None, plan_input["uprn"]
)
# We handle the landlord property type and built form
plan_input["property_type"] = plan_input["landlord_property_type"].copy()
if "landlord_built_form" in plan_input.columns:
plan_input["built_form"] = plan_input["landlord_built_form"].copy()
else:
plan_input["built_form"] = None
if "epc_property_type" not in plan_input.columns:
plan_input["epc_property_type"] = None
plan_input["property_type"] = np.where(
plan_input["property_type"] == "unknown",
plan_input["epc_property_type"],
plan_input["property_type"]
)
if "epc_archetype" not in plan_input.columns:
plan_input["epc_archetype"] = None
plan_input["built_form"] = np.where(
plan_input["built_form"] == "unknown", plan_input["epc_archetype"], plan_input["built_form"]
)
property_type_map = {
"house": "House",
"flat": "Flat",
"maisonette": "Maisonette",
"bungalow": "Bungalow",
"block house": "House",
"coach house": "House",
"bedsit": "Flat",
}
built_form_map = {
"mid-terrace": "Mid-Terrace",
"end-terrace": "End-Terrace",
"semi-detached": "Semi-Detached",
"detached": "Detached",
"enclosed end-terrace": "Enclosed End-Terrace",
"enclosed mid-terrace": "Enclosed Mid-Terrace",
}
# We remap the values to match the EPC expected formats
# This syntax will actually retain any original values, if they don't get mapped
plan_input["property_type"] = (
plan_input["property_type"]
.map(property_type_map)
.fillna(plan_input["property_type"])
)
plan_input["built_form"] = (
plan_input["built_form"]
.map(built_form_map)
.fillna(plan_input["built_form"])
)
plan_input = plan_input.to_dict("records")
else:
raise ValueError("Other formats not yet supported")
else:
logger.info("Getting the plan input from csv")
plan_input = read_csv_from_s3(
bucket_name=get_settings().PLAN_TRIGGER_BUCKET, filepath=body.trigger_file_path
)
logger.info("Got the plan input from csv")
# We then slide it on the indexes if they are provided
if body.index_start is not None and body.index_end is not None:
plan_input = plan_input[body.index_start:body.index_end]
# Use PlanInputProcessor for all plan input processing
plan_input_processor = PlanInputProcessor(body)
addresses = plan_input_processor.process()
valuation_data = plan_input_processor.valuation_data
# Confirm no duplicate UPRNS
check_duplicate_uprns(plan_input)
check_duplicate_uprns([a.uprn for a in addresses])
# If we have patches or overrides, we should read them in here
patches, already_installed, non_invasive_recommendations, valuation_data = get_request_property_data(body)
if body.file_type == "xlsx" and body.file_format == "domna_asset_list":
# We check if we have valution data
if not valuation_data and body.valuation_file_path in [None, ""]:
# We check plan_input
if "domna_valuation" in plan_input[0]:
valuation_data = [{"uprn": x["uprn"], "valuation": x["domna_valuation"]} for x in plan_input]
patches, already_installed, non_invasive_recommendations, _ = get_request_property_data(body)
logger.info("Getting cleaning_data")
cleaning_data = read_dataframe_from_s3_parquet(
bucket_name=get_settings().DATA_BUCKET, file_key="sap_change_model/cleaning_dataset.parquet",
)
# Prepare input data
addresses = Addresses.from_plan_input(plan_input, body)
logger.info("Checking database for existing properties")
uprns = addresses.get_uprns()
@ -725,8 +554,8 @@ async def model_engine(body: PlanTriggerRequest):
logger.info("Processing each property for model input preparation")
input_properties, inspections_map, eco_packages, epc_upserts = [], {}, {}, []
for addr, config in tqdm(
zip(addresses, plan_input),
for addr in tqdm(
addresses,
total=len(addresses),
desc="Processing properties",
):
@ -747,17 +576,17 @@ async def model_engine(body: PlanTriggerRequest):
property_already_installed = list(already_installed_by_uprn[addr.uprn])
epc_searcher = SearchEpc(
address1=addr.address1,
address1=addr.address_1,
postcode=addr.postcode,
uprn=addr.uprn,
auth_token=get_settings().EPC_AUTH_TOKEN,
os_api_key="",
full_address=addr.full_address,
heating_system=addr.heating_system,
heating_system=addr.landlord_heating_system,
associated_uprns=associated_uprns
)
epc_searcher.ordnance_survey_client.built_form = addr.built_form
epc_searcher.ordnance_survey_client.property_type = addr.property_type
epc_searcher.ordnance_survey_client.built_form = addr.landlord_built_form
epc_searcher.ordnance_survey_client.property_type = addr.landlord_property_type
# For the moment, our OS API access is unavailable, so we skip and interpolate
epc_searcher.find_property(skip_os=True, api_data=epc_api_data, overwrite_sap05=True)
@ -781,6 +610,8 @@ async def model_engine(body: PlanTriggerRequest):
# Otherwise, we use the newest EPC
# energy_assessment_is_newer will tell us if the energy assessment is newer than the newest EPC that
# has been publically lodged
if energy_assessment is None:
energy_assessment = {}
epc_records, energy_assessment["energy_assessment_is_newer"] = create_epc_records(
epc_searcher, energy_assessment
)
@ -804,7 +635,7 @@ async def model_engine(body: PlanTriggerRequest):
epc_page=epc_page,
rrn=rrn,
cleaned_address=epc_searcher.address_clean,
config_address=addr.address,
config_address=addr.address_1,
address_postal_town=epc_searcher.address_postal_town
)
)
@ -813,18 +644,6 @@ async def model_engine(body: PlanTriggerRequest):
prepared_epc = EPCRecord(epc_records=epc_records, run_mode="newdata", cleaning_data=cleaning_data)
# TODO: This is a temp function to handle a specific edge case with Peabody. We should
# factor this into EPCRecord as part of the cleaning however we need some more testing
prepared_epc = averages_cleaning(prepared_epc, cleaning_data)
# If we have an ECO project, we parse the cavity/solar reasons
eco_packages[property_id] = parse_eco_packages(addr, prepared_epc)
# Final step - extract inspections data, if we have it - we inject into property for usage
property_inspections = db_funcs.inspections_functions.extract_inspection_data(config)
if property_inspections:
inspections_map[property_id] = property_inspections
input_properties.append(
Property(
id=property_id,
@ -833,13 +652,12 @@ async def model_engine(body: PlanTriggerRequest):
address=epc_searcher.address_clean,
postcode=epc_searcher.postcode_clean,
epc_record=prepared_epc,
already_installed=property_already_installed + eco_packages.get(property_id)[3],
already_installed=property_already_installed,
find_my_epc_components=find_my_epc_components,
property_valuation=req_data.valuation,
non_invasive_recommendations=property_non_invasive_recommendations,
energy_assessment=energy_assessment,
inspections=inspections_map.get(property_id),
**Property.extract_kwargs(config), # TODO: Depraecate this
)
)
@ -881,16 +699,79 @@ async def model_engine(body: PlanTriggerRequest):
prediction_buckets=get_prediction_buckets(),
max_retries=1
)
await model_api.async_warm_up_lambdas(
model_prefies=model_api.KWH_MODEL_PREFIXES + model_api.MODEL_PREFIXES
)
await model_api.async_warm_up_lambdas(model_prefies=model_api.models_for_warm_up)
# The materials data could be cached or local so we don't need to make
# consistent requests to the backend for the same data
logger.info("Reading in materials and cleaned datasets")
cleaned = get_cleaned()
with db_read_session() as session:
materials = db_funcs.materials_functions.get_materials(session)
cleaned = get_cleaned()
logger.info("Preparing rebaselining")
rebaselining_scoring_data = []
for p in tqdm(input_properties):
# 1) EPC expired 2) Missing EPC 3) Different information from landlord vs EPC
needs_rebaselining = p.epc_is_expired | p.epc_is_estimated | (len(p.epc_record.landlord_differences) > 0)
if needs_rebaselining:
p.create_base_difference_epc_record(cleaned_lookup=cleaned)
scoring_data = p.base_difference_record.df.copy()
rebaselining_scoring_data.append(scoring_data)
rebaselining_scoring_data = (
pd.concat(rebaselining_scoring_data) if len(rebaselining_scoring_data) else pd.DataFrame([])
)
predictions_by_model_and_uprn = {}
if not rebaselining_scoring_data.empty:
logger.info(f"{rebaselining_scoring_data.shape[0]} properties require re-baselineing")
# Trigger re-scoring
rebaselining_scoring_data["is_post_sap10_starting"] = True
rebaselining_response = model_api.predict_all(
df=rebaselining_scoring_data,
bucket=get_settings().DATA_BUCKET,
model_prefixes=model_api.BASELINE_MODEL_PREFIXES,
extract_ids=False,
extract_uprn=True
)
# Update EPC records with new model predictions
input_properties_by_uprn = {int(p.uprn): p for p in input_properties if p.uprn is not None}
# Pre-index predictions for each model by UPRN
model_names = [
"retrofit_sap_baseline_predictions",
"retrofit_carbon_baseline_predictions",
"retrofit_heat_baseline_predictions",
]
for model in model_names:
df = rebaselining_response[model]
predictions_by_model_and_uprn[model] = dict(zip(df["uprn"].astype(int), df["predictions"]))
for uprn_int in rebaselining_scoring_data["uprn"].unique().astype(int):
try:
property_instance = input_properties_by_uprn[uprn_int]
if property_instance is None:
logger.warning(f"No property found for UPRN {uprn_int} during rebaselining update.")
continue
# Gather predictions for this UPRN
try:
new_sap = predictions_by_model_and_uprn["retrofit_sap_baseline_predictions"][uprn_int]
new_carbon = predictions_by_model_and_uprn["retrofit_carbon_baseline_predictions"][uprn_int]
new_heat_demand = predictions_by_model_and_uprn["retrofit_heat_baseline_predictions"][uprn_int]
except KeyError as e:
logger.warning(f"Missing prediction for UPRN {uprn_int}: {e}")
continue
# Update EPC record
property_instance.epc_record.insert_new_performance_values(
new_sap=new_sap,
new_epc=sap_to_epc(new_sap),
new_carbon=new_carbon,
new_heat_demand=new_heat_demand,
)
except Exception as e:
logger.error(f"Error updating EPC record for UPRN {uprn_int}: {e}")
kwh_client = KwhData(bucket=get_settings().DATA_BUCKET, read_consumption_data=True)
@ -967,6 +848,12 @@ async def model_engine(body: PlanTriggerRequest):
if not property_recommendations:
continue
# Perform a check for properties (temp) where we've remodelled
if p.epc_record.has_been_remodelled:
for x in property_recommendations:
if any(y.get("survey") for y in x):
raise ValueError("Should not have survey true for remodelled properties")
recommendations[p.id] = property_recommendations
representative_recommendations[p.id] = property_representative_recommendations
@ -986,7 +873,6 @@ async def model_engine(body: PlanTriggerRequest):
"carbon_ending"
]
)
# TODO: Temp putting this here
recommendations_scoring_data["is_post_sap10_ending"] = True
all_predictions = await model_api.async_paginated_predictions(
@ -1042,6 +928,8 @@ async def model_engine(body: PlanTriggerRequest):
)
p.current_energy_bill = property_current_energy_bill
# Create matrix of all predictions for debug: - any rebaselining and measure level predictions
# Insert the predictions into the recommendations and run the optimiser
logger.info("Optimising measures")
for p in input_properties:
@ -1095,8 +983,7 @@ async def model_engine(body: PlanTriggerRequest):
property_required_measures, recommendations, p, needs_ventilation
)
gain = optimiser_functions.calculate_gain(
body=body, p=p, fixed_gain=fixed_gain, eco_packages=eco_packages,
already_installed_gain=already_installed_sap
body=body, p=p, fixed_gain=fixed_gain, already_installed_gain=already_installed_sap
)
# We insert the innovation uplift
@ -1158,21 +1045,22 @@ async def model_engine(body: PlanTriggerRequest):
# We optimise and then we determine eligibility for funding, based on the measures selected
optimiser = (
GainOptimiser(
input_measures, max_cost=body.budget, max_gain=gain, allow_slack=False
) if body.budget else CostOptimiser(input_measures, min_gain=gain)
input_measures, max_cost=body.budget, max_gain=float(gain) if gain is not None else 0,
allow_slack=False
) if body.budget else CostOptimiser(input_measures, min_gain=float(gain) if gain is not None else 0)
)
optimiser.setup()
optimiser.solve()
solution = optimiser.solution
gain = optimiser.solution_gain
post_sap = int(p.data["current-energy-efficiency"]) + gain
post_sap = p.epc_record.current_energy_efficiency + gain
pv_size = next(
(m["array_size"] for m in solution if m["type"] == "solar_pv"), 0
)
battery_sap_score = BatterySAPScorer.score(starting_sap=post_sap, pv_size=pv_size)
# We add the defauly already installed measures to the solution
# We add the defaulty already installed measures to the solution
selected = {r["id"] for r in solution + default_already_installed}
if property_required_measures:
@ -1262,7 +1150,7 @@ async def model_engine(body: PlanTriggerRequest):
# This will include everything, including already installed
total_sap_points = sum([r["sap_points"] for r in default_recommendations])
new_sap_points = float(p.data["current-energy-efficiency"]) + total_sap_points
new_sap_points = p.epc_record.current_energy_efficiency + total_sap_points
new_epc = sap_to_epc(new_sap_points)
# Already installed measures do not have a cost but we remove anyway
total_cost = sum([r["total"] for r in default_recommendations if not r["already_installed"]])
@ -1378,12 +1266,40 @@ async def model_engine(body: PlanTriggerRequest):
except Exception as e: # General exception handling
return handle_error("An unexpected error occurred.", e, body.subtask_id, 500, start_ms)
cloud_logs_url = build_cloudwatch_log_url(start_ms)
# Mark the subtask as successful
SubTaskInterface().update_subtask_status(
subtask_id=UUID(body.subtask_id), status="complete", cloud_logs_url=cloud_logs_url
)
SubTaskInterface().update_subtask_status(subtask_id=UUID(body.subtask_id), status="complete")
logger.info("Model Engine completed successfully")
prediction_matrix = PredictionMatrix()
# --- Add rebaselining and measure-level predictions to PredictionMatrix ---
for p in input_properties:
# Add rebaselined predictions if available
uprn = p.uprn
if uprn is None:
continue
# Rebaselined SAP prediction
rebaselined_sap = None
if uprn in predictions_by_model_and_uprn.get("retrofit_sap_baseline_predictions", {}):
rebaselined_sap = predictions_by_model_and_uprn["retrofit_sap_baseline_predictions"][uprn]
# Add original EPC and landlord differences for comparison
prediction_matrix.set_original_epc(
uprn=uprn,
original_epc=p.epc_record.original_epc,
landlord_differences=p.epc_record.landlord_differences,
lodgement_date=p.epc_record.lodgement_date,
)
prediction_matrix.set_rebaselined_prediction(uprn, rebaselined_sap)
# Add measure-level predictions
property_recommendations = recommendations.get(p.id, [])
for rec in property_recommendations:
prediction_matrix.add_recommendation(
uprn=uprn,
measure_id=rec.get("recommendation_id", rec.get("id", rec.get("type", "unknown"))),
prediction=rec.get("sap_points"),
metadata={k: v for k, v in rec.items() if k not in ("sap_points", "recommendation_id", "id")}
)
# --- End PredictionMatrix population ---
return Response(status_code=200)

View file

@ -134,10 +134,18 @@ def handler(event: Mapping[str, Any], context: Optional[Any]) -> Mapping[str, Un
body_dict = {
"task_id": "test",
"subtask_id": "test",
"portfolio_id": 569,
"portfolio_id": 655,
"scenario_ids": [],
"default_plans_only": True,
}
body_dict = {
"task_id": "test",
"subtask_id": "test",
"portfolio_id": 655,
"scenario_ids": [1174],
"default_plans_only": False,
}
:param event: Lambda event containing export request details
:param context: Lambda context (not used in this handler but included for completeness)
:return: HTTP response indicating success or failure of the export operation

View file

@ -69,7 +69,7 @@ def test_default_export_integration(db_session):
properties = []
for row in properties_df.itertuples(index=False):
row_dict = row._asdict()
row_dict = {field: getattr(row, field) for field in row._fields}
row_dict["uprn"] = int(row_dict["uprn"]) if row_dict.get("uprn") else None
row_dict["building_reference_number"] = (
@ -106,7 +106,7 @@ def test_default_export_integration(db_session):
epc_rows = []
for row in property_details_epc_df.itertuples(index=False):
row_dict = row._asdict()
row_dict = {field: getattr(row, field) for field in row._fields}
# Build only fields that exist on the model
epc_data = {
@ -133,7 +133,7 @@ def test_default_export_integration(db_session):
plans = []
for row in plans_df.itertuples(index=False):
row_dict = row._asdict()
row_dict = {field: getattr(row, field) for field in row._fields}
if row_dict.get("post_epc_rating"):
row_dict["post_epc_rating"] = Epc[
@ -263,7 +263,7 @@ def test_default_export_integration(db_session):
"Expected total SAP points increase to be 100.10000000000001, got {}".format(df["sap_points"].sum())
)
assert df.shape == (10, 95), "Expected dataframe shape to be (10, 11), got {}".format(df.shape)
assert df.shape == (10, 100), "Expected dataframe shape to be (10, 100), got {}".format(df.shape)
def test_solar_with_battery_example(db_session):

View file

@ -216,7 +216,7 @@ class PropertyValuation:
cls.UPRN_VALUE_LOOKUP.get(property_instance.uprn)
)
current_epc = property_instance.data["current-energy-rating"]
current_epc = property_instance.epc_record.current_energy_rating
if not current_value:
# In this case, we return a % improvement rather than an absolute

View file

@ -1,8 +1,7 @@
import json
import random
import aiohttp
import asyncio
import pandas as pd
from typing import List, Dict
from tqdm import tqdm
import requests
from requests.exceptions import RequestException
@ -23,12 +22,22 @@ class ModelApi:
KWH_MODEL_PREFIXES = ["heating_kwh_predictions", "hotwater_kwh_predictions"]
MODEL_URLS = {
BASELINE_MODEL_PREFIXES = [
"retrofit_sap_baseline_predictions",
"retrofit_heat_baseline_predictions",
"retrofit_carbon_baseline_predictions",
]
MODEL_URLS: Dict[str, str] = {
"sap_change_predictions": "sapmodel",
"heat_demand_predictions": "heatmodel",
"carbon_change_predictions": "carbonmodel",
"hotwater_kwh_predictions": "hotwaterkwhmodel",
"heating_kwh_predictions": "heatingkwhmodel",
# Baseline prediction models
"retrofit_sap_baseline_predictions": "sapbaselinemodel",
"retrofit_heat_baseline_predictions": "heatbaselinemodel",
"retrofit_carbon_baseline_predictions": "carbonbaselinemodel",
}
def __init__(
@ -147,7 +156,13 @@ class ModelApi:
else:
return None
def predict_all(self, df, bucket, model_prefixes=None, extract_ids=True) -> dict:
def predict_all(
self, df: pd.DataFrame,
bucket: str,
model_prefixes: List[str] | None = None,
extract_ids: bool = True,
extract_uprn: bool = False
) -> dict:
"""
For each model prefix, this method will upload the scoring data to s3 and then make a request to the
@ -159,6 +174,8 @@ class ModelApi:
:param model_prefixes: List of model prefixes to generate predictions for. If None, all model prefixes will be
used
:param extract_ids: Boolean to determine if the property_id and recommendation_id should be extracted from the
scoring data
:param extract_uprn: Boolean to determine if the uprn should be extracted from the scoring data
id column
:return:
"""
@ -196,6 +213,9 @@ class ModelApi:
# Convert back to int
predictions_df['phase'] = predictions_df['recommendation_id'].apply(self.extract_phase)
if extract_uprn and "uprn" in df.columns:
predictions_df["uprn"] = df["uprn"].values
predictions[model_prefix] = predictions_df
return predictions
@ -325,3 +345,7 @@ class ModelApi:
)
return all_predictions
@property
def models_for_warm_up(self):
return self.KWH_MODEL_PREFIXES + self.MODEL_PREFIXES + self.BASELINE_MODEL_PREFIXES

View file

@ -13,7 +13,7 @@ class OnboarderBase:
landlord_roof_construction: str = "landlord_roof_construction"
landlord_floor_construction: str = "landlord_floor_construction"
landlord_windows_type: str = "landlord_windows_type"
landlord_heating_construction: str = "landlord_heating_construction"
landlord_heating_system: str = "landlord_heating_system"
landlord_fuel_type: str = "landlord_fuel_type"
landlord_heating_controls: str = "landlord_heating_controls"
landlord_hot_water_system: str = "landlord_hot_water_system"
@ -53,7 +53,7 @@ class OnboarderBase:
)
else:
self.data = read_from_s3(bucket_name=self.bucket_name, s3_file_name=self.input_file_name)
def write(self):
if self.data is None:
raise ValueError("No data to write. Please run transform() before writing.")

View file

@ -12,8 +12,8 @@ parity_map = {
"1996-2002": EpcConstructionAgeBand.from_1996_to_2002,
"2003-2006": EpcConstructionAgeBand.from_2003_to_2006,
"2007-2011": EpcConstructionAgeBand.from_2007_to_2011,
"2012 onwards": EpcConstructionAgeBand.from_2012_onwards,
# Newer age bands, under SAP10
"2012 onwards": EpcConstructionAgeBand.from_2012_to_2022,
"2012-2022": EpcConstructionAgeBand.from_2012_to_2022,
"2023 onwards": EpcConstructionAgeBand.from_2023_onwards,
}

View file

@ -1,20 +1,23 @@
from datatypes.epc.efficiency import EpcEfficiency
from datatypes.epc.windows import EpcWindowDescriptions
glazing_map = {
# (description, energy efficiency, multi_glaze_proportion, glazed_type, glazed_area
# For SAP 10 assessments, The glazed type and glazed area are not populated in the EPC API data any more
"Double 2002 or later": ("Fully double glazed", EpcEfficiency.AVERAGE, 1, None, None),
"Double before 2002": ("Fully double glazed", EpcEfficiency.POOR, 1, None, None),
"Double but age unknown": ("Fully double glazed", EpcEfficiency.POOR, 1, None, None),
"Single": ("Single glazed", EpcEfficiency.VERY_POOR, 0, None, None),
"Double 2002 or later": (EpcWindowDescriptions.fully_double_glazed, EpcEfficiency.AVERAGE, 100, None, None),
"Double before 2002": (EpcWindowDescriptions.fully_double_glazed, EpcEfficiency.POOR, 100, None, None),
"Double but age unknown": (EpcWindowDescriptions.fully_double_glazed, EpcEfficiency.POOR, 100, None, None),
"Single": (EpcWindowDescriptions.single_glazed, EpcEfficiency.VERY_POOR, 0, None, None),
# For triple glazing, with age unknown, the performance is only average, whereas if it's a post 2022
# installation, it's classed as high performance glazing with good efficiency. We'll need to be considerate as to
# how we make updates to the windows data.
# Triple known data is high performance glazing with Good efficiency (at least)
"Triple": ("Fully triple glazed", EpcEfficiency.AVERAGE, 1, None, None),
"Triple": (EpcWindowDescriptions.fully_triple_glazed, EpcEfficiency.AVERAGE, 100, None, None),
# This is also classed as high performance glazing
"DoubleKnownData": ("High performance glazing", EpcEfficiency.GOOD, 1, None, None),
"DoubleKnownData": (
EpcWindowDescriptions.fully_double_glazed.high_performance_glazing, EpcEfficiency.GOOD, 100, None, None
),
# Under SAP 10, secondary glazing is classed as poor efficiency (whereas under SAP 2012 it was generally good)
"Secondary": ("Full secondary glazing", EpcEfficiency.POOR, 1, None, None),
"TripleKnownData": ("High performance glazing", EpcEfficiency.GOOD, 1, None, None),
"Secondary": (EpcWindowDescriptions.full_secondary_glazing, EpcEfficiency.POOR, 100, None, None),
"TripleKnownData": (EpcWindowDescriptions.high_performance_glazing, EpcEfficiency.GOOD, 100, None, None),
}

View file

@ -262,7 +262,7 @@ class ParityOnboarder(OnboarderBase):
# controls. E.g. it may be programmer and room thermostat
self.data[
[
self.landlord_heating_construction,
self.landlord_heating_system,
self.landlord_heating_efficiency,
self.landlord_fuel_type,
self.landlord_heating_controls,
@ -309,7 +309,7 @@ class ParityOnboarder(OnboarderBase):
self.landlord_multi_glaze_proportion,
self.landlord_glazed_type,
self.landlord_glazed_area,
self.landlord_heating_construction,
self.landlord_heating_system,
self.landlord_heating_efficiency,
self.landlord_fuel_type,
self.landlord_heating_controls,
@ -332,7 +332,7 @@ class ParityOnboarder(OnboarderBase):
self.landlord_construction_age_band, self.landlord_property_type, self.landlord_built_form,
self.landlord_wall_construction, self.landlord_wall_efficiency, self.landlord_roof_construction,
self.landlord_roof_efficiency, self.landlord_floor_construction, self.landlord_windows_type,
self.landlord_windows_efficiency, self.landlord_heating_construction, self.landlord_heating_efficiency,
self.landlord_windows_efficiency, self.landlord_heating_system, self.landlord_heating_efficiency,
self.landlord_fuel_type, self.landlord_heating_controls, self.landlord_heating_controls_efficiency,
self.landlord_hot_water_system, self.landlord_hot_water_efficiency
]:

View file

@ -0,0 +1,214 @@
import pytest
from backend.addresses.Addresses import Addresses
# -------------------------
# Helpers
# -------------------------
class AraBody:
file_format = "ara_property_list"
class LegacyBody:
file_format = "legacy"
# -------------------------
# ARA FORMAT TESTS
# -------------------------
def test_parse_ara_row_valid():
row = {
"uprn": "123",
"address_1": "10 Downing St",
"full_address": "10 Downing St, London",
"postcode": "SW1A 2AA",
}
addresses = Addresses.from_plan_input([row], AraBody())
assert len(addresses) == 1
addr = addresses[0]
assert addr.uprn == 123
assert addr.address_1 == "10 Downing St"
assert addr.full_address == "10 Downing St, London"
assert addr.postcode == "SW1A 2AA"
def test_parse_ara_row_optional_fields():
row = {
"uprn": "456",
"address_1": "Flat 2",
"full_address": "Flat 2, Test House",
"postcode": "AB1 2CD",
"landlord_property_id": "ABC123",
}
addresses = Addresses.from_plan_input([row], AraBody())
addr = addresses[0]
assert addr.uprn == 456
assert addr.landlord_property_id == "ABC123"
# -------------------------
# LEGACY FORMAT TESTS
# -------------------------
def test_parse_legacy_basic():
row = {
"landlord_property_id": 144002000000,
"address": "15 Rosebank Hall Angle Terrace",
"postcode": "NE28 7BQ",
"ordnance_survey_uprn": 47002793,
"property_type": "Bungalow",
}
addresses = Addresses.from_plan_input([row], LegacyBody())
addr = addresses[0]
assert addr.uprn == 47002793
assert addr.address_1 == "15 Rosebank Hall Angle Terrace"
assert addr.postcode == "NE28 7BQ"
assert addr.landlord_property_type == "Bungalow"
def test_legacy_uses_domna_address_if_missing_address():
row = {
"domna_address_1": "Domna Address",
"postcode": "AA1 1AA",
"ordnance_survey_uprn": 123456,
}
addresses = Addresses.from_plan_input([row], LegacyBody())
addr = addresses[0]
assert addr.address_1 == "Domna Address"
def test_legacy_full_address_fallback():
row = {
"address": "Fallback Address",
"postcode": "ZZ1 1ZZ",
"ordnance_survey_uprn": 999,
}
addresses = Addresses.from_plan_input([row], LegacyBody())
addr = addresses[0]
assert addr.full_address == "Fallback Address"
# -------------------------
# UPRN HANDLING
# -------------------------
def test_uprn_from_float_string():
row = {
"uprn": "123.0",
"address": "Test Address",
"postcode": "AA1 1AA",
}
addresses = Addresses.from_plan_input([row], LegacyBody())
assert addresses[0].uprn == 123
def test_uprn_fallback_to_os_uprn():
row = {
"uprn": None,
"ordnance_survey_uprn": 555,
"address": "Test Address",
"postcode": "AA1 1AA",
}
addresses = Addresses.from_plan_input([row], LegacyBody())
assert addresses[0].uprn == 555
def test_missing_uprn_is_none():
row = {
"address": "No UPRN Address",
"postcode": "BB1 1BB",
}
addresses = Addresses.from_plan_input([row], LegacyBody())
assert addresses[0].uprn is None
# -------------------------
# FALLBACK LOGIC
# -------------------------
def test_fallback_to_legacy_when_ara_fails():
"""
If ARA parser fails (missing required fields),
system should fallback to legacy parser.
"""
row = {
"address": "Fallback Address",
"postcode": "ZZ1 1ZZ",
}
addresses = Addresses.from_plan_input([row], AraBody())
addr = addresses[0]
assert addr.address_1 == "Fallback Address"
# -------------------------
# VALIDATION
# -------------------------
def test_validate_uprn_rejects_invalid():
row = {
"uprn": "not_a_number",
"address_1": "Test",
"full_address": "Test",
"postcode": "AA1 1AA",
}
with pytest.raises(ValueError):
Addresses.from_plan_input([row], AraBody())
# -------------------------
# COLLECTION METHODS
# -------------------------
def test_get_uprns():
rows = [
{"uprn": "1", "address_1": "A", "full_address": "A", "postcode": "AA"},
{"uprn": "2", "address_1": "B", "full_address": "B", "postcode": "BB"},
]
addresses = Addresses.from_plan_input(rows, AraBody())
assert addresses.get_uprns() == [1, 2]
def test_get_unique_postcodes():
rows = [
{"uprn": "1", "address_1": "A", "full_address": "A", "postcode": "AA"},
{"uprn": "2", "address_1": "B", "full_address": "B", "postcode": "AA"},
]
addresses = Addresses.from_plan_input(rows, AraBody())
assert addresses.get_unique_postcodes() == ["AA"]
def test_get_property_requests():
row = {
"uprn": "123",
"address_1": "10 Downing St",
"full_address": "10 Downing St",
"postcode": "SW1A 2AA",
}
addresses = Addresses.from_plan_input([row], AraBody())
request = addresses.get_property_requests()[0]
assert request["uprn"] == 123
assert request["postcode"] == "SW1A 2AA"

View file

@ -0,0 +1,101 @@
LMK_KEY,ADDRESS1,ADDRESS2,ADDRESS3,POSTCODE,BUILDING_REFERENCE_NUMBER,CURRENT_ENERGY_RATING,POTENTIAL_ENERGY_RATING,CURRENT_ENERGY_EFFICIENCY,POTENTIAL_ENERGY_EFFICIENCY,PROPERTY_TYPE,BUILT_FORM,INSPECTION_DATE,LOCAL_AUTHORITY,CONSTITUENCY,COUNTY,LODGEMENT_DATE,TRANSACTION_TYPE,ENVIRONMENT_IMPACT_CURRENT,ENVIRONMENT_IMPACT_POTENTIAL,ENERGY_CONSUMPTION_CURRENT,ENERGY_CONSUMPTION_POTENTIAL,CO2_EMISSIONS_CURRENT,CO2_EMISS_CURR_PER_FLOOR_AREA,CO2_EMISSIONS_POTENTIAL,LIGHTING_COST_CURRENT,LIGHTING_COST_POTENTIAL,HEATING_COST_CURRENT,HEATING_COST_POTENTIAL,HOT_WATER_COST_CURRENT,HOT_WATER_COST_POTENTIAL,TOTAL_FLOOR_AREA,ENERGY_TARIFF,MAINS_GAS_FLAG,FLOOR_LEVEL,FLAT_TOP_STOREY,FLAT_STOREY_COUNT,MAIN_HEATING_CONTROLS,MULTI_GLAZE_PROPORTION,GLAZED_TYPE,GLAZED_AREA,EXTENSION_COUNT,NUMBER_HABITABLE_ROOMS,NUMBER_HEATED_ROOMS,LOW_ENERGY_LIGHTING,NUMBER_OPEN_FIREPLACES,HOTWATER_DESCRIPTION,HOT_WATER_ENERGY_EFF,HOT_WATER_ENV_EFF,FLOOR_DESCRIPTION,FLOOR_ENERGY_EFF,FLOOR_ENV_EFF,WINDOWS_DESCRIPTION,WINDOWS_ENERGY_EFF,WINDOWS_ENV_EFF,WALLS_DESCRIPTION,WALLS_ENERGY_EFF,WALLS_ENV_EFF,SECONDHEAT_DESCRIPTION,SHEATING_ENERGY_EFF,SHEATING_ENV_EFF,ROOF_DESCRIPTION,ROOF_ENERGY_EFF,ROOF_ENV_EFF,MAINHEAT_DESCRIPTION,MAINHEAT_ENERGY_EFF,MAINHEAT_ENV_EFF,MAINHEATCONT_DESCRIPTION,MAINHEATC_ENERGY_EFF,MAINHEATC_ENV_EFF,LIGHTING_DESCRIPTION,LIGHTING_ENERGY_EFF,LIGHTING_ENV_EFF,MAIN_FUEL,WIND_TURBINE_COUNT,HEAT_LOSS_CORRIDOR,UNHEATED_CORRIDOR_LENGTH,FLOOR_HEIGHT,PHOTO_SUPPLY,SOLAR_WATER_HEATING_FLAG,MECHANICAL_VENTILATION,ADDRESS,LOCAL_AUTHORITY_LABEL,CONSTITUENCY_LABEL,POSTTOWN,CONSTRUCTION_AGE_BAND,LODGEMENT_DATETIME,TENURE,FIXED_LIGHTING_OUTLETS_COUNT,LOW_ENERGY_FIXED_LIGHT_COUNT,UPRN,UPRN_SOURCE,REPORT_TYPE
626337830252011050922425395090286,Flat 20 Kingsley House,"15, Newton Street",,M1 1HE,2684056868,D,D,62,66,Flat,End-Terrace,2011-05-06,E08000003,E14000807,,2011-05-09,rental (private),41,44,654,608.0,3.6,116,3.3,28.0,28.0,340.0,289.0,88.0,88.0,30.72,dual,N,5th,Y,,2402.0,100.0,double glazing installed before 2002,Normal,0.0,1.0,1.0,75.0,0.0,"Electric immersion, off-peak",Average,Very Poor,(other premises below),,,Fully double glazed,Average,Average,"Solid brick, as built, insulated (assumed)",Good,Good,"Room heaters, electric",,,"Flat, insulated (assumed)",Average,Average,Electric storage heaters,Average,Very Poor,Automatic charge control,Average,Average,Low energy lighting in 75% of fixed outlets,Very Good,Very Good,electricity (not community),0.0,unheated corridor,12.89,3.29,0.0,,natural,"Flat 20 Kingsley House, 15, Newton Street",Manchester,Manchester Central,MANCHESTER,England and Wales: 1996-2002,2011-05-09 22:42:53,rental (private),4.0,3.0,77232195.0,Address Matched,100
761477339962012031418342406148782,"22, Tuscan Road",,,M20 5GS,8041346968,D,C,63,69,House,Semi-Detached,2012-03-14,E08000003,E14000809,,2012-03-14,marketed sale,59,67,231,187.0,4.2,45,3.4,61.0,61.0,701.0,562.0,93.0,93.0,94.78,Single,Y,NODATA!,,,2106.0,43.0,"double glazing, unknown install date",Normal,1.0,6.0,5.0,77.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Partial double glazing,Poor,Poor,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,"Room heaters, mains gas",,,"Pitched, 200 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 77% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,NO DATA!,,2.48,0.0,,natural,"22, Tuscan Road",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1930-1949,2012-03-14 18:34:24,owner-occupied,13.0,10.0,77068965.0,Address Matched,100
746429639842012020315284198520028,"16, Balliol Street",,,M8 0WS,2853035968,E,C,48,71,House,Semi-Detached,2012-02-02,E08000003,E14000571,,2012-02-03,rental (private),44,69,346,178.0,5.9,67,3.0,86.0,48.0,853.0,494.0,215.0,112.0,88.878,Single,Y,NODATA!,,,2104,,not defined,Much More Than Typical,1.0,5.0,5.0,22.0,0.0,"From main system, no cylinder thermostat",Poor,Poor,"Suspended, no insulation (assumed)",,,Mostly double glazing,Good,Good,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,"Room heaters, mains gas",,,"Pitched, 200mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,Low energy lighting in 22% of fixed outlets,Poor,Poor,mains gas (not community),0.0,NO DATA!,,2.554,0.0,,natural,"16, Balliol Street",Manchester,Blackley and Broughton,MANCHESTER,England and Wales: 1930-1949,2012-02-03 15:28:41,rental (private),9.0,2.0,77006454.0,Address Matched,100
6a63605a294b7005030427aaae897ca2cfdead115cceb1e34ddf22f340aba0a1,83 THORNTON ROAD,MANCHESTER,,M14 7NT,10000480583,D,B,65,87,House,Mid-Terrace,2021-01-06,E08000003,E14000807,,2021-01-06,marketed sale,61,87,255,81.0,3.0,45,1.0,70.0,70.0,524.0,344.0,92.0,65.0,67.0,off-peak 7 hour,Y,,,,,100.0,double glazing installed during or after 2002,Normal,2.0,4.0,4.0,78.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Good,Good,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,,,,"Pitched, no insulation",Very Poor,Very Poor,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 78% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,,,2.74,0.0,N,natural,"83 THORNTON ROAD, MANCHESTER",Manchester,Manchester Central,MANCHESTER,England and Wales: 1900-1929,2021-01-06 00:00:00,Owner-occupied,9.0,7.0,77112974.0,Energy Assessor,100
9a6bc31be4b07d7f189572eb38beaa1fd49fa418fcd5f5476fed91776ab8d8d3,639A STOCKPORT ROAD,MANCHESTER,,M12 4QA,10000398504,D,C,66,70,Flat,Mid-Terrace,2020-10-06,E08000003,E14000808,,2020-10-08,rental,62,67,248,215.0,3.0,44,2.6,72.0,72.0,521.0,449.0,81.0,81.0,68.0,off-peak 7 hour,Y,01,Y,,,100.0,double glazing installed during or after 2002,Normal,0.0,4.0,4.0,78.0,0.0,From main system,Good,Good,(other premises below),,,Fully double glazed,Good,Good,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,,,,"Pitched, no insulation (assumed)",Very Poor,Very Poor,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 78% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,heated corridor,,2.75,0.0,N,natural,"639A STOCKPORT ROAD, MANCHESTER",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1900-1929,2020-10-08,Rented (private),9.0,7.0,10090237291.0,Energy Assessor,100
96054d6c9df6eefc64f8ece8f5a889697bf31627565c68b0cdf2be201076cb4c,APARTMENT 7,67 PALATINE ROAD,MANCHESTER,M20 3AP,10000787735,C,B,74,81,Flat,Detached,2020-11-23,E08000003,E14000809,,2020-11-23,marketed sale,71,71,202,205.0,2.2,34,2.3,58.0,68.0,338.0,226.0,211.0,191.0,66.0,off-peak 10 hour,N,02,Y,,,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,2.0,100.0,0.0,"Electric immersion, off-peak",Poor,Poor,(another dwelling below),,,Fully double glazed,Good,Good,"Timber frame, as built, insulated (assumed)",Good,Good,Portable electric heaters (assumed),,,"Pitched, insulated (assumed)",Good,Good,"Room heaters, electric",Very Poor,Poor,Appliance thermostats,Good,Good,Low energy lighting in all fixed outlets,Very Good,Very Good,electricity (not community),0.0,unheated corridor,8.7,1.8,0.0,N,natural,"APARTMENT 7, 67 PALATINE ROAD, MANCHESTER",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 2003-2006,2020-11-23 00:00:00,Owner-occupied,15.0,15.0,10023046299.0,Energy Assessor,100
b04c73c7eb6d7193ee2fbb37ef45d7a6fe013012ed4aecae02e314db95c8d814,FLAT 403,ICON 25,101 HIGH STREET,M4 1HG,10000571763,C,B,78,87,Flat,End-Terrace,2020-09-25,E08000003,E14000807,,2020-09-26,rental,80,79,132,139.0,1.6,22,1.7,66.0,74.0,172.0,88.0,346.0,187.0,72.0,off-peak 7 hour,N,05,N,,,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,100.0,0.0,"Electric immersion, standard tariff",Very Poor,Poor,(another dwelling below),,,Fully double glazed,Good,Good,"System built, as built, insulated (assumed)",Good,Good,,,,(another dwelling above),,,"Room heaters, electric",Very Poor,Poor,Programmer and appliance thermostats,Good,Good,Low energy lighting in all fixed outlets,Very Good,Very Good,electricity (not community),0.0,heated corridor,,2.46,0.0,N,natural,"FLAT 403, ICON 25, 101 HIGH STREET",Manchester,Manchester Central,MANCHESTER,England and Wales: 2007-2011,2020-09-26 00:00:00,Rented (private),7.0,7.0,10014178048.0,Energy Assessor,100
5460819602012012418330046222678,"7, Johns Close",,,M21 9EH,3664112468,C,C,78,79,Flat,NO DATA!,2012-01-23,E08000003,E14000809,,2012-01-24,rental (social),83,84,130,122.0,1.2,25,1.1,53.0,31.0,221.0,224.0,68.0,68.0,48.9,Unknown,Y,1st,Y,,2106.0,100.0,double glazing installed during or after 2002,Normal,0.0,2.0,2.0,29.0,0.0,From main system,Good,Good,(other premises below),,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,,,,"Pitched, 200mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 29% of fixed outlets,Average,Average,mains gas (not community),0.0,no corridor,,2.31,0.0,,natural,"7, Johns Close",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1983-1990,2012-01-24 18:33:00,rental (social),7.0,2.0,77077064.0,Address Matched,100
666225219952011081514391692990386,"5, Beckfield Road",,,M23 2GF,3659929868,D,D,63,63,House,Semi-Detached,2011-08-15,E08000003,E14001059,,2011-08-15,marketed sale,59,59,238,238.0,4.1,46,4.1,57.0,57.0,688.0,688.0,87.0,87.0,88.5,Single,Y,NODATA!,,,2106.0,100.0,double glazing installed during or after 2002,Normal,1.0,4.0,4.0,78.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"System built, as built, no insulation (assumed)",Very Poor,Very Poor,"Room heaters, mains gas",,,"Pitched, 200 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 78% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,NO DATA!,,2.0,0.0,,natural,"5, Beckfield Road",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1930-1949,2011-08-15 14:39:16,owner-occupied,9.0,7.0,77052370.0,Address Matched,100
740955219712012011913012398920095,"18b, Greton Close",,,M13 0YR,589984968,C,B,79,82,Flat,NO DATA!,2012-01-18,E08000003,E14000808,,2012-01-19,marketed sale,69,71,255,238.0,2.2,45,2.0,64.0,32.0,160.0,149.0,107.0,107.0,47.97,dual,N,1st,N,,2401.0,100.0,double glazing installed before 2002,Normal,0.0,3.0,3.0,0.0,0.0,"Electric immersion, off-peak",Average,Very Poor,(other premises below),,,Fully double glazed,Average,Average,"Cavity wall, as built, insulated (assumed)",Good,Good,Portable electric heaters (assumed),,,(another dwelling above),,,Electric storage heaters,Average,Very Poor,Manual charge control,Poor,Poor,No low energy lighting,Very Poor,Very Poor,electricity (not community),0.0,unheated corridor,4.5,2.343,0.0,,natural,"18b, Greton Close",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1991-1995,2012-01-19 13:01:23,owner-occupied,7.0,0.0,77151965.0,Address Matched,100
f32f46284a1afe1e99156dca4c97c64ee8f466cd646eaac907514c96095f9382,FLAT 315,THE BOX WORKS,4 WORSLEY STREET,M15 4NU,10000804989,C,B,79,81,Flat,Mid-Terrace,2020-10-31,E08000003,E14000807,,2020-10-31,marketed sale,68,71,244,224.0,2.1,41,1.9,66.0,66.0,226.0,178.0,169.0,169.0,51.0,off-peak 10 hour,N,02,N,,,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,78.0,0.0,"Electric immersion, off-peak",Average,Poor,(another dwelling below),,,Fully double glazed,Good,Good,"System built, as built, insulated (assumed)",Good,Good,Portable electric heaters (assumed),,,(another dwelling above),,,Electric storage heaters,Average,Very Poor,Manual charge control,Poor,Poor,Low energy lighting in 78% of fixed outlets,Very Good,Very Good,electricity (not community),0.0,unheated corridor,8.51,3.1,0.0,N,natural,"FLAT 315, THE BOX WORKS, 4 WORSLEY STREET",Manchester,Manchester Central,MANCHESTER,England and Wales: 2003-2006,2020-10-31 00:00:00,Owner-occupied,9.0,7.0,10003799820.0,Energy Assessor,100
413809754212011120117031199099872,Flat 4,"5, Derby Road",,M14 6UN,8296490768,D,D,56,65,Flat,End-Terrace,2011-12-01,E08000003,E14000809,,2011-12-01,rental (private),55,67,379,284.0,2.8,73,2.1,27.0,27.0,503.0,393.0,73.0,61.0,37.97,Unknown,Y,1st,N,,2102.0,10.0,double glazing installed before 2002,Normal,0.0,2.0,2.0,80.0,0.0,From main system,Good,Good,(other premises below),,,Some double glazing,Very Poor,Very Poor,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,,,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, no room thermostat",Very Poor,Very Poor,Low energy lighting in 80% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,unheated corridor,10.08,2.52,0.0,,natural,"Flat 4, 5, Derby Road",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1900-1929,2011-12-01 17:03:11,rental (private),5.0,4.0,77203368.0,Address Matched,100
f725eb075fb7f9e87af04780806b6a4ae5c8ae44d006df38e24b01266be2b2cf,72 BLUESTONE ROAD,MANCHESTER,,M40 9HY,10000725404,E,C,46,69,House,Semi-Detached,2020-12-18,E08000003,E14000807,,2020-12-21,marketed sale,40,61,435,257.0,5.3,77,3.2,57.0,57.0,954.0,748.0,90.0,65.0,69.0,off-peak 7 hour,Y,,,,,90.0,"double glazing, unknown install date",Normal,0.0,4.0,4.0,100.0,1.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Mostly double glazing,Average,Average,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,"Room heaters, mains gas",,,"Pitched, no insulation (assumed)",Very Poor,Very Poor,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (not community),0.0,,,2.5,0.0,N,natural,"72 BLUESTONE ROAD, MANCHESTER",Manchester,Manchester Central,MANCHESTER,England and Wales: 1930-1949,2020-12-21 00:00:00,Owner-occupied,8.0,8.0,77031060.0,Energy Assessor,100
684540547352011093012023195790691,Apartment 5 Park Brow,"128, St. Werburghs Road",,M21 8UQ,6184750968,C,B,80,82,Flat,NO DATA!,2011-09-30,E08000003,E14000809,,2011-09-30,rental (private),70,72,211,200.0,2.5,37,2.4,60.0,44.0,190.0,171.0,115.0,115.0,67.04,Unknown,N,1st,N,,2401.0,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,64.0,0.0,"Electric immersion, off-peak",Average,Very Poor,(other premises below),,,Fully double glazed,Good,Good,"System built, as built, insulated (assumed)",Good,Good,Portable electric heaters (assumed),,,(another dwelling above),,,Electric storage heaters,Average,Very Poor,Manual charge control,Poor,Poor,Low energy lighting in 64% of fixed outlets,Good,Good,electricity (not community),0.0,unheated corridor,10.25,2.35,0.0,,natural,"Apartment 5 Park Brow, 128, St. Werburghs Road",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 2003-2006,2011-09-30 12:02:31,rental (private),11.0,7.0,10012206708.0,Address Matched,100
746479909062012020316372915378642,Flat 11,Lorna Lodge,233 Brownley Road,M22 9XA,4179035968,B,B,86,88,Flat,End-Terrace,2012-02-03,E08000003,E14001059,,2012-02-03,rental (social),82,82,153,159.0,1.1,27,1.2,38.0,30.0,57.0,53.0,120.0,94.0,42.1,dual,N,1st,N,,2603.0,100.0,double glazing installed during or after 2002,Normal,0.0,2.0,2.0,57.0,0.0,"Electric immersion, off-peak",Poor,Very Poor,(other premises below),,,Fully double glazed,Good,Good,"Cavity wall, as built, insulated (assumed)",Good,Good,"Room heaters, electric",,,(another dwelling above),,,"Room heaters, electric",Poor,Very Poor,Programmer and appliance thermostats,Good,Good,Low energy lighting in 57% of fixed outlets,Good,Good,electricity (not community),0.0,heated corridor,,2.34,0.0,,natural,"Flat 11, Lorna Lodge, 233 Brownley Road",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 2003-2006,2012-02-03 16:37:29,rental (social),7.0,4.0,10070865592.0,Address Matched,100
0815d544b81eccdfbcd570b8db517bb27d9e36bf9337dff91d83f365f8405f5b,FLAT 36,PARKFIELD COURT,38-40 BARLOW MOOR ROAD,M20 2GE,10000754172,D,C,65,80,Flat,Enclosed End-Terrace,2021-01-06,E08000003,E14000809,,2021-01-26,rental,39,65,645,329.0,3.9,109,2.0,67.0,37.0,73.0,170.0,568.0,174.0,36.0,standard tariff,N,01,N,,,100.0,"double glazing, unknown install date",Normal,0.0,2.0,2.0,20.0,0.0,"Electric immersion, off-peak",Poor,Poor,(another dwelling below),,,Fully double glazed,Average,Average,"Cavity wall, filled cavity",Good,Good,Portable electric heaters (assumed),,,(another dwelling above),,,Electric storage heaters,Average,Poor,Controls for high heat retention storage heaters,Good,Good,Low energy lighting in 20% of fixed outlets,Poor,Poor,electricity (not community),0.0,heated corridor,,2.4,0.0,N,natural,"FLAT 36, PARKFIELD COURT, 38-40 BARLOW MOOR ROAD",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1991-1995,2021-01-26 00:00:00,Rented (social),5.0,1.0,77191954.0,Energy Assessor,100
762935166212012031922534895920198,"7, May Drive",,,M19 1FY,1893656968,C,C,71,72,Flat,End-Terrace,2012-03-19,E08000003,E14000809,,2012-03-19,rental (social),73,74,182,176.0,2.2,35,2.1,58.0,37.0,374.0,377.0,75.0,75.0,62.17,Single,Y,Ground,N,,2106.0,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,43.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,"Room heaters, mains gas",,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 43% of fixed outlets,Average,Average,mains gas (not community),0.0,unheated corridor,4.93,2.43,0.0,,natural,"7, May Drive",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1900-1929,2012-03-19 22:53:48,rental (social),7.0,3.0,77144094.0,Address Matched,100
300000899702011081910022367299458,"8, Telfer Road",,,M13 0XS,4762992668,D,C,60,72,House,Semi-Detached,2011-08-15,E08000003,E14000808,,2011-08-19,rental (private),56,71,253,165.0,4.5,49,2.9,76.0,48.0,702.0,470.0,140.0,120.0,93.0,Single,Y,NODATA!,,,2104.0,90.0,double glazing installed during or after 2002,Normal,1.0,6.0,6.0,42.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Mostly double glazing,Good,Good,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,,,,"Pitched, 250 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,Low energy lighting in 42% of fixed outlets,Average,Average,mains gas (not community),0.0,NO DATA!,,2.65,0.0,,natural,"8, Telfer Road",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1930-1949,2011-08-19 10:02:23,rental (private),12.0,5.0,77149101.0,Address Matched,100
a2d4f21dfc53c9e8bd48a08848547cabc9481a29411bd48299ea93881849913d,6 RODA STREET,MANCHESTER,,M9 4PJ,10000671391,F,B,34,84,House,Mid-Terrace,2020-09-23,E08000003,E14000571,,2020-10-13,ECO assessment,42,82,402,114.0,5.6,69,1.7,66.0,66.0,1711.0,459.0,94.0,69.0,82.0,off-peak 7 hour,Y,,,,,100.0,"double glazing, unknown install date",Normal,0.0,3.0,3.0,100.0,0.0,Gas multipoint,Average,Average,"Suspended, no insulation (assumed)",,,Fully double glazed,Average,Average,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,"Room heaters, mains gas",,,"Pitched, 300 mm loft insulation",Very Good,Very Good,"Room heaters, electric",Very Poor,Poor,Programmer and appliance thermostats,Good,Good,Low energy lighting in all fixed outlets,Very Good,Very Good,electricity (not community),0.0,,,2.7,0.0,N,natural,"6 RODA STREET, MANCHESTER",Manchester,Blackley and Broughton,MANCHESTER,England and Wales: 1930-1949,2020-10-13,Owner-occupied,10.0,10.0,77023763.0,Energy Assessor,100
638222011112011060614072193090483,"26, Deneford Road",,,M20 2TD,4328137868,D,D,64,67,House,Semi-Detached,2011-06-03,E08000003,E14000809,,2011-06-06,rental (private),63,66,215,198.0,3.8,41,3.5,47.0,47.0,603.0,570.0,156.0,135.0,93.8,Single,Y,NODATA!,,,2106.0,100.0,"double glazing, unknown install date",Normal,1.0,5.0,5.0,100.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Average,Average,"Cavity wall, filled cavity",Good,Good,"Room heaters, electric",,,"Pitched, 250 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (not community),0.0,NO DATA!,,2.47,0.0,,natural,"26, Deneford Road",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1930-1949,2011-06-06 14:07:21,rental (private),9.0,9.0,77102590.0,Address Matched,100
6d70419837e0b18a96a6801877496ef689c0656cac553803fb1e307b14c237c6,FLAT 2,7 BUCKHURST ROAD,MANCHESTER,M19 2DS,10000498503,E,C,53,80,Flat,End-Terrace,2021-02-24,E08000003,E14000808,,2021-03-10,ECO assessment,57,66,570,452.0,2.0,96,1.6,23.0,25.0,398.0,135.0,296.0,138.0,20.0,off-peak 7 hour,N,00,N,,,50.0,double glazing installed during or after 2002,Normal,0.0,2.0,2.0,100.0,0.0,"Electric immersion, standard tariff",Very Poor,Poor,"Suspended, no insulation (assumed)",,,Partial double glazing,Poor,Poor,"Solid brick, with internal insulation",Good,Good,,,,(another dwelling above),,,"Room heaters, electric",Very Poor,Poor,Appliance thermostats,Good,Good,Low energy lighting in all fixed outlets,Very Good,Very Good,electricity (not community),0.0,heated corridor,,2.8,0.0,N,natural,"FLAT 2, 7 BUCKHURST ROAD, MANCHESTER",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1900-1929,2021-03-10 00:00:00,Owner-occupied,6.0,6.0,77207522.0,Energy Assessor,100
741952999402012012213435894422098,Flat 3,"57, Albany Road",,M21 0BH,3463994968,D,D,60,63,Flat,NO DATA!,2012-01-21,E08000003,E14000809,,2012-01-22,rental (private),59,63,318,290.0,2.7,61,2.5,54.0,27.0,480.0,459.0,65.0,65.0,44.459,Unknown,Y,2nd,Y,,2107.0,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,0.0,0.0,From main system,Good,Good,(other premises below),,,Fully double glazed,Good,Good,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,,,,"Pitched, no insulation (assumed)",Very Poor,Very Poor,"Boiler and radiators, mains gas",Good,Good,"Programmer, TRVs and bypass",Average,Average,No low energy lighting,Very Poor,Very Poor,mains gas (not community),0.0,no corridor,,2.2,0.0,,natural,"Flat 3, 57, Albany Road",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1900-1929,2012-01-22 13:43:58,rental (private),6.0,0.0,77213865.0,Address Matched,100
4966252352011052014323391990443,"24, Cranswick Street",,,M14 7JA,4372212468,C,C,72,75,House,Mid-Terrace,2011-05-18,E08000003,E14000807,,2011-05-20,rental (social),74,77,181,159.0,2.1,35,1.8,33.0,33.0,367.0,325.0,72.0,72.0,59.3,Single,Y,NODATA!,,,2106.0,100.0,"double glazing, unknown install date",Normal,0.0,4.0,4.0,100.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Average,Average,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,"Room heaters, mains gas",,,"Pitched, 200mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (not community),0.0,NO DATA!,,2.76,0.0,,natural,"24, Cranswick Street",Manchester,Manchester Central,MANCHESTER,England and Wales: 1900-1929,2011-05-20 14:32:33,rental (social),5.0,5.0,77117462.0,Address Matched,100
645301489802011062220261286792028,"21, Ward Street",Moston,,M40 9WS,3838387868,F,E,37,44,House,Mid-Terrace,2011-06-22,E08000003,E14000571,,2011-06-22,rental (private),34,40,472,410.0,6.4,91,5.6,76.0,38.0,1068.0,956.0,63.0,63.0,70.66,Single,Y,NODATA!,,,2601.0,0.0,not defined,Normal,1.0,3.0,2.0,0.0,0.0,Gas multipoint,Average,Average,"Suspended, no insulation (assumed)",,,Single glazed,Very Poor,Very Poor,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,"Room heaters, mains gas",,,"Pitched, no insulation (assumed)",Very Poor,Very Poor,"Room heaters, mains gas",Average,Average,No thermostatic control of room temperature,Poor,Poor,No low energy lighting,Very Poor,Very Poor,mains gas (not community),0.0,NO DATA!,,2.75,0.0,,natural,"21, Ward Street, Moston",Manchester,Blackley and Broughton,MANCHESTER,England and Wales: 1900-1929,2011-06-22 20:26:12,rental (private),7.0,0.0,100012709992.0,Address Matched,100
683986659902011092918252999092218,"15, Shaldon Drive",,,M40 1GS,3946650968,E,D,48,67,House,Semi-Detached,2011-09-29,E08000003,E14000807,,2011-09-29,marketed sale,47,68,352,203.0,4.7,67,2.7,75.0,39.0,836.0,505.0,92.0,81.0,71.0,Single,Y,NODATA!,,,2102,30.0,double glazing installed during or after 2002,Normal,0.0,4.0,4.0,9.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Some double glazing,Poor,Poor,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,"Room heaters, electric",,,"Pitched, 75 mm loft insulation",Average,Average,"Boiler and radiators, mains gas",Good,Good,"Programmer, no room thermostat",Very Poor,Very Poor,Low energy lighting in 9% of fixed outlets,Very Poor,Very Poor,mains gas (not community),0.0,NO DATA!,,2.4,0.0,,natural,"15, Shaldon Drive",Manchester,Manchester Central,MANCHESTER,England and Wales: 1950-1966,2011-09-29 18:25:29,owner-occupied,22.0,2.0,77188811.0,Address Matched,100
7a4cfa9242f66e157df0d3f37c0545bfeac115c45f23ab0ffa081fd39c62a015,14 SIMISTER STREET,MANCHESTER,,M9 4JL,10000070988,D,C,61,79,House,Mid-Terrace,2020-12-17,E08000003,E14000571,,2021-01-06,rental,55,74,289,164.0,4.2,51,2.4,99.0,66.0,735.0,611.0,86.0,59.0,82.0,off-peak 7 hour,Y,,,,,100.0,"double glazing, unknown install date",Normal,4.0,4.0,4.0,50.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Average,Average,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,,,,"Pitched, no insulation (assumed)",Very Poor,Very Poor,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 50% of fixed outlets,Good,Good,mains gas (not community),0.0,,,2.74,0.0,N,natural,"14 SIMISTER STREET, MANCHESTER",Manchester,Blackley and Broughton,MANCHESTER,England and Wales: 1900-1929,2021-01-06 00:00:00,Rented (private),10.0,5.0,77022202.0,Energy Assessor,100
728844679402011113014364798397808,"158, Heald Place",,,M14 5WJ,5494373968,D,C,65,72,House,Mid-Terrace,2011-11-30,E08000003,E14000808,,2011-11-30,rental (private),63,72,226,172.0,3.4,43,2.6,70.0,43.0,571.0,451.0,83.0,83.0,78.4,Single,Y,NODATA!,,,2107.0,100.0,double glazing installed before 2002,Normal,1.0,4.0,4.0,36.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Average,Average,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,,,,"Pitched, 100mm loft insulation",Average,Average,"Boiler and radiators, mains gas",Good,Good,"Programmer, TRVs and bypass",Average,Average,Low energy lighting in 36% of fixed outlets,Average,Average,mains gas (not community),0.0,NO DATA!,,2.41,0.0,,natural,"158, Heald Place",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1900-1929,2011-11-30 14:36:47,rental (private),11.0,4.0,77111254.0,Address Matched,100
231717462932011120115213414068198,"26, Thornton Road",,,M14 7WT,6874177568,D,C,57,70,House,Mid-Terrace,2011-12-01,E08000003,E14000807,,2011-12-01,rental (social),54,71,306,195.0,3.6,59,2.3,39.0,39.0,625.0,412.0,92.0,76.0,61.91,Single,Y,NODATA!,,,2104.0,100.0,double glazing installed during or after 2002,Normal,0.0,4.0,4.0,88.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Good,Good,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,,,,"Pitched, no insulation",Very Poor,Very Poor,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,Low energy lighting in 88% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,NO DATA!,,2.61,0.0,,natural,"26, Thornton Road",Manchester,Manchester Central,MANCHESTER,England and Wales: before 1900,2011-12-01 15:21:34,rental (social),8.0,7.0,77113730.0,Address Matched,100
762271159312012031619163994920298,"108, Meltham Avenue",,,M20 1EE,2865946968,C,C,75,78,Flat,NO DATA!,2012-03-16,E08000003,E14000809,,2012-03-16,marketed sale,77,80,152,131.0,1.9,29,1.6,38.0,38.0,326.0,288.0,86.0,77.0,63.7,Single,Y,1st,Y,,2107.0,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,100.0,0.0,From main system,Good,Good,(other premises below),,,Fully double glazed,Good,Good,"Solid brick, with external insulation",Good,Good,,,,"Pitched, 300+ mm loft insulation",Very Good,Very Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, TRVs and bypass",Average,Average,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (not community),0.0,no corridor,,2.5,0.0,,natural,"108, Meltham Avenue",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1950-1966,2012-03-16 19:16:39,owner-occupied,9.0,9.0,77105708.0,Address Matched,100
400678909602011082617381773092868,"20, Dundreggan Gardens",,,M20 2EH,3642100768,C,C,71,72,House,Mid-Terrace,2011-08-26,E08000003,E14000809,,2011-08-26,marketed sale,71,72,150,144.0,4.3,28,4.1,117.0,70.0,741.0,747.0,105.0,105.0,103.8,dual,Y,NODATA!,,,2106.0,100.0,double glazing installed during or after 2002,More Than Typical,1.0,6.0,6.0,34.0,0.0,From main system,Good,Good,"Solid, insulated (assumed)",,,Fully double glazed,Good,Good,"Timber frame, as built, insulated (assumed)",Good,Good,,,,"Roof room(s), insulated (assumed)",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 34% of fixed outlets,Average,Average,mains gas (not community),0.0,NO DATA!,,2.55,0.0,,"mechanical, supply and extract","20, Dundreggan Gardens",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 2007 onwards,2011-08-26 17:38:17,owner-occupied,38.0,13.0,10070865623.0,Address Matched,100
634706509542011052610203283792568,Apartment 55 Britannia Mills,"11, Hulme Hall Road",,M15 4LA,6581507868,C,C,80,80,Flat,Mid-Terrace,2011-05-26,E08000003,E14000807,,2011-05-26,none of the above,67,67,220,220.0,3.1,39,3.1,49.0,49.0,223.0,223.0,110.0,110.0,78.5,dual,N,1st,N,,2401.0,100.0,"double glazing, unknown install date",Normal,1.0,1.0,1.0,100.0,0.0,"Electric immersion, off-peak",Average,Very Poor,(other premises below),,,Fully double glazed,Average,Average,"Solid brick, as built, insulated (assumed)",Good,Good,"Room heaters, electric",,,(another dwelling above),,,Electric storage heaters,Average,Very Poor,Manual charge control,Poor,Poor,Low energy lighting in all fixed outlets,Very Good,Very Good,electricity (not community),0.0,unheated corridor,6.95,2.28,0.0,,natural,"Apartment 55 Britannia Mills, 11, Hulme Hall Road",Manchester,Manchester Central,MANCHESTER,England and Wales: 1996-2002,2011-05-26 10:20:32,unknown,5.0,5.0,77233931.0,Address Matched,100
bc53c658a67a4490c2c8cd2291b2396d7235e8c938f724f9aafc36f97cffd6bd,"7, Gleneagles Avenue",Clayton,,M11 4JU,10000415844,D,B,68,82,House,Semi-Detached,2020-11-03,E08000003,E14000807,,2021-02-24,rental,67,81,212,117.0,2.8,37,1.6,55.0,55.0,553.0,509.0,109.0,73.0,76.0,off-peak 7 hour,Y,,,,,100.0,double glazing installed during or after 2002,Normal,0.0,4.0,4.0,89.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Average,Average,"Room heaters, electric",,,"Pitched, 200 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 89% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,,,2.4,0.0,N,natural,"7, Gleneagles Avenue, Clayton",Manchester,Manchester Central,,England and Wales: 1930-1949,2021-02-24 00:00:00,Rented (social),9.0,8.0,77179548.0,Energy Assessor,100
e8227d212d926258058f8cac2e6e1e18cbd55451d7980fda1f5e7a0b10464f4d,"76, Langport Avenue",Ardwick,,M12 4NG,10000463748,C,C,74,76,Flat,Mid-Terrace,2020-09-28,E08000003,E14000807,,2021-02-24,rental,77,80,184,165.0,1.5,32,1.3,47.0,32.0,294.0,274.0,86.0,87.0,46.0,off-peak 7 hour,Y,00,Y,,,100.0,double glazing installed during or after 2002,Normal,0.0,2.0,2.0,50.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Average,Average,"Room heaters, electric",,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 50% of fixed outlets,Good,Good,mains gas (not community),0.0,unheated corridor,3.5,2.4,0.0,N,natural,"76, Langport Avenue, Ardwick",Manchester,Manchester Central,,England and Wales: 1967-1975,2021-02-24 00:00:00,Rented (social),6.0,3.0,77153103.0,Energy Assessor,100
b3b0e1c10d9bf0479069ed65b9b3b657471a67652be33b8f7c21c6a905535c62,35 SANDILANDS ROAD,MANCHESTER,,M23 9JN,10000235547,C,B,69,81,House,Semi-Detached,2021-01-12,E08000003,E14001059,,2021-01-12,marketed sale,64,78,207,127.0,3.5,37,2.2,84.0,84.0,574.0,536.0,127.0,82.0,97.0,off-peak 7 hour,Y,,,,,100.0,double glazing installed before 2002,Normal,1.0,5.0,5.0,89.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Average,Average,"Cavity wall, filled cavity",Average,Average,,,,"Pitched, 200 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 89% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,,,2.6,0.0,N,natural,"35 SANDILANDS ROAD, MANCHESTER",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1950-1966,2021-01-12 00:00:00,Owner-occupied,18.0,16.0,77042816.0,Energy Assessor,100
679334129922011091911524490718129,"7, Whalley Avenue",Whalley Range,,M16 8AT,2954220968,F,E,33,45,House,Mid-Terrace,2011-09-19,E08000003,E14000808,,2011-09-19,marketed sale,32,42,466,368.0,7.5,89,5.9,80.0,45.0,1338.0,1080.0,65.0,65.0,84.1,Single,Y,NODATA!,,,2601.0,0.0,not defined,Normal,1.0,4.0,2.0,20.0,0.0,Gas instantaneous at point of use,Good,Good,"Suspended, no insulation (assumed)",,,Single glazed,Very Poor,Very Poor,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,"Room heaters, electric",,,"Pitched, no insulation",Very Poor,Very Poor,"Room heaters, mains gas",Average,Average,No thermostatic control of room temperature,Poor,Poor,Low energy lighting in 20% of fixed outlets,Poor,Poor,mains gas (not community),0.0,NO DATA!,,2.73,0.0,,natural,"7, Whalley Avenue, Whalley Range",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1900-1929,2011-09-19 11:52:44,owner-occupied,10.0,2.0,10014179643.0,Address Matched,100
488886519262012022219093606838569,"103, Wendover Road",,,M23 9ER,6060126768,C,C,72,74,House,Enclosed End-Terrace,2011-07-27,E08000003,E14001059,,2012-02-22,rental (social),71,74,171,156.0,2.8,33,2.5,51.0,51.0,464.0,423.0,90.0,91.0,84.0,Single,Y,NODATA!,,,2106.0,100.0,double glazing installed during or after 2002,Normal,0.0,5.0,5.0,90.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,,,,"Pitched, 50 mm loft insulation",Poor,Poor,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 90% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,NO DATA!,,2.4,0.0,,natural,"103, Wendover Road",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1950-1966,2012-02-22 19:09:36,rental (social),10.0,9.0,77042522.0,Address Matched,100
718995131812011110709323290099494,"211, Chapman Street",,,M18 8WP,4499103968,D,D,61,67,House,Semi-Detached,2011-11-04,E08000003,E14000808,,2011-11-07,marketed sale,58,66,253,209.0,3.9,49,3.2,82.0,43.0,626.0,549.0,97.0,85.0,79.19,Single,Y,NODATA!,,,2107.0,100.0,double glazing installed during or after 2002,Normal,1.0,5.0,5.0,9.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,"Room heaters, mains gas",,,"Pitched, 100 mm loft insulation",Average,Average,"Boiler and radiators, mains gas",Good,Good,"Programmer, TRVs and bypass",Average,Average,Low energy lighting in 9% of fixed outlets,Very Poor,Very Poor,mains gas (not community),0.0,NO DATA!,,2.44,0.0,,natural,"211, Chapman Street",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1930-1949,2011-11-07 09:32:32,owner-occupied,11.0,1.0,77176530.0,Address Matched,100
cea6cab056864f6114c6509288f6f76f6021a9efcc12cdd74660ebaac24d8a35,"8, Moss Lane",Moss Side,,M16 7BZ,10000747245,C,B,73,86,House,End-Terrace,2020-10-05,E08000003,E14000807,,2021-02-24,rental,71,85,178,87.0,2.5,31,1.3,57.0,57.0,451.0,412.0,110.0,74.0,80.0,off-peak 7 hour,Y,,,,,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,89.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,,,,"Pitched, 270 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 89% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,,,2.4,0.0,N,natural,"8, Moss Lane, Moss Side",Manchester,Manchester Central,,England and Wales: 1976-1982,2021-02-24 00:00:00,Rented (social),9.0,8.0,77097127.0,Energy Assessor,100
67687538aed41115bdc797d35afd7ec6397562062f01c7072b32b9a28e5bb959,"7, Rusholme Grove",Rusholme,,M14 5AR,10000415848,C,C,78,79,Flat,Mid-Terrace,2020-10-15,E08000003,E14000808,,2021-02-24,rental,81,83,149,132.0,1.3,26,1.1,35.0,35.0,250.0,221.0,89.0,89.0,48.0,off-peak 7 hour,Y,01,Y,,,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,100.0,0.0,From main system,Good,Good,(another dwelling below),,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,,,,"Pitched, 100 mm loft insulation",Average,Average,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (not community),0.0,unheated corridor,5.3,2.4,0.0,N,natural,"7, Rusholme Grove, Rusholme",Manchester,"Manchester, Gorton",,England and Wales: 1976-1982,2021-02-24 00:00:00,Rented (social),5.0,5.0,77133633.0,Energy Assessor,100
574337239602011092517501083292258,Flat 13 The Sorting House,"83, Newton Street",,M1 1EP,3600832868,D,C,64,73,Flat,Mid-Terrace,2011-09-25,E08000003,E14000807,,2011-09-25,marketed sale,55,53,279,294.0,4.6,49,4.8,69.0,57.0,619.0,433.0,146.0,135.0,92.23,Unknown,N,2nd,N,,2602.0,100.0,double glazing installed before 2002,Normal,1.0,3.0,3.0,64.0,0.0,"Electric immersion, off-peak",Average,Very Poor,(other premises below),,,Fully double glazed,Average,Average,"System built, as built, insulated (assumed)",Good,Good,,,,(another dwelling above),,,"Room heaters, electric",Poor,Very Poor,Appliance thermostats,Good,Good,Low energy lighting in 64% of fixed outlets,Good,Good,electricity (not community),0.0,no corridor,,2.19,0.0,,natural,"Flat 13 The Sorting House, 83, Newton Street",Manchester,Manchester Central,MANCHESTER,England and Wales: 1996-2002,2011-09-25 17:50:10,owner-occupied,14.0,9.0,10070397882.0,Address Matched,100
629887539922011051622513676168289,Apartment 712,"51, Whitworth Street West",,M1 5ED,8722376868,B,B,82,83,Flat,Mid-Terrace,2011-05-16,E08000003,E14000807,,2011-05-16,marketed sale,73,74,230,222.0,1.8,41,1.8,60.0,30.0,106.0,113.0,89.0,89.0,44.65,Unknown,N,7th,N,,2401.0,100.0,double glazing installed before 2002,Normal,0.0,2.0,2.0,0.0,0.0,"Electric immersion, off-peak",Average,Very Poor,(other premises below),,,Fully double glazed,Average,Average,"Cavity wall, as built, insulated (assumed)",Good,Good,"Room heaters, electric",,,(another dwelling above),,,Electric storage heaters,Average,Very Poor,Manual charge control,Poor,Poor,No low energy lighting,Very Poor,Very Poor,electricity (not community),0.0,unheated corridor,6.28,2.25,0.0,,natural,"Apartment 712, 51, Whitworth Street West",Manchester,Manchester Central,MANCHESTER,England and Wales: 1996-2002,2011-05-16 22:51:36,owner-occupied,9.0,0.0,10003799427.0,Address Matched,100
06359dd75cc0e575c7df1daa0107c832dd45b21835d0fa1a2f98f111975276de,16 WINDSOR ROAD,HARPURHEY,MANCHESTER,M9 5BW,10000281555,C,C,73,74,Flat,End-Terrace,2020-11-09,E08000003,E14000571,,2020-11-12,rental,75,76,228,215.0,1.5,40,1.4,34.0,34.0,296.0,280.0,70.0,70.0,38.0,off-peak 7 hour,Y,01,Y,,,100.0,double glazing installed during or after 2002,Normal,1.0,2.0,2.0,100.0,0.0,From main system,Good,Good,(another dwelling below),,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Average,Average,,,,"Pitched, 100 mm loft insulation",Average,Average,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (not community),0.0,no corridor,,2.72,0.0,N,natural,"16 WINDSOR ROAD, HARPURHEY, MANCHESTER",Manchester,Blackley and Broughton,MANCHESTER,England and Wales: 1930-1949,2020-11-12,Rented (private),5.0,5.0,77024420.0,Energy Assessor,100
cac28d15e638f84cb7574006e960cd56611f2d665fd02b6e1bad5ddd9e731594,84 THE BOULEVARD,MANCHESTER,,M20 2EU,10000707350,C,B,80,86,Flat,Enclosed Mid-Terrace,2020-10-21,E08000003,E14000809,,2020-10-21,marketed sale,77,79,165,149.0,1.7,28,1.5,72.0,63.0,168.0,115.0,203.0,154.0,60.0,off-peak 10 hour,N,01,N,,,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,67.0,0.0,"Electric immersion, off-peak",Poor,Poor,(another dwelling below),,,Fully double glazed,Good,Good,"System built, as built, insulated (assumed)",Good,Good,,,,(another dwelling above),,,"Room heaters, electric",Very Poor,Poor,Appliance thermostats,Good,Good,Low energy lighting in 67% of fixed outlets,Good,Good,electricity (not community),0.0,unheated corridor,9.1,2.39,0.0,N,natural,"84 THE BOULEVARD, MANCHESTER",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 2003-2006,2020-10-21 00:00:00,Owner-occupied,6.0,4.0,10070393810.0,Energy Assessor,100
f7f8dba5d96af5ec97b273b968a467f45b1b3ed07199684b69fd51796d195c96,FLAT 1,9 ZETLAND ROAD,MANCHESTER,M21 8TJ,10000483124,D,C,61,73,Flat,Semi-Detached,2021-02-11,E08000003,E14000809,,2021-02-12,rental,57,74,301,184.0,3.1,53,1.9,102.0,51.0,536.0,340.0,85.0,85.0,58.0,off-peak 7 hour,Y,00,N,,,100.0,"double glazing, unknown install date",Normal,2.0,3.0,3.0,0.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Average,Average,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,,,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, TRVs and bypass",Average,Average,No low energy lighting,Very Poor,Very Poor,mains gas (not community),0.0,unheated corridor,6.49,2.68,0.0,N,natural,"FLAT 1, 9 ZETLAND ROAD, MANCHESTER",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1900-1929,2021-02-12 00:00:00,Rented (private),10.0,0.0,77214240.0,Energy Assessor,100
6c386fbd02fb8b3be61fb7b00c1aac6a7e533e7cb6eaf73b3a15a20486118ebc,"59, Worsley Court Wilmslow Road",Rusholme,,M14 5LU,10000666249,C,C,79,80,Flat,Mid-Terrace,2020-11-03,E08000003,E14000808,,2021-02-24,rental,83,84,141,129.0,1.1,25,1.0,30.0,30.0,190.0,172.0,105.0,105.0,43.0,off-peak 7 hour,Y,06,Y,,,100.0,double glazing installed during or after 2002,Normal,0.0,2.0,2.0,100.0,0.0,Community scheme,Good,Good,(another dwelling below),,,Fully double glazed,Good,Good,"Cavity wall, with external insulation",Very Good,Very Good,"Room heaters, electric",,,(another dwelling above),,,Community scheme,Good,Good,"Charging system linked to use of community heating, programmer and room thermostat",Average,Average,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (community),0.0,no corridor,0.0,2.4,0.0,N,natural,"59, Worsley Court Wilmslow Road, Rusholme",Manchester,"Manchester, Gorton",,England and Wales: 1967-1975,2021-02-24 00:00:00,Rented (social),6.0,6.0,10003800130.0,Energy Assessor,100
647860479262011062811072297938579,Flat 8 Rose Lea,"1, Downham Walk",,M23 9DG,7984797868,C,C,75,76,Flat,NO DATA!,2011-06-27,E08000003,E14001059,,2011-06-28,rental (social),79,80,193,183.0,1.3,37,1.2,38.0,21.0,200.0,202.0,88.0,88.0,34.08,Single,N,Ground,N,,2303.0,100.0,double glazing installed before 2002,Normal,0.0,2.0,2.0,17.0,0.0,Community scheme,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Average,Average,"Cavity wall, as built, insulated (assumed)",Good,Good,,,,(another dwelling above),,,Community scheme,Good,Good,"Flat rate charging, room thermostat only",Poor,Poor,Low energy lighting in 17% of fixed outlets,Poor,Poor,mains gas (community),0.0,heated corridor,,2.6,0.0,,natural,"Flat 8 Rose Lea, 1, Downham Walk",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1991-1995,2011-06-28 11:07:22,rental (social),6.0,1.0,77047324.0,Address Matched,100
687906589742011101021150296099308,Flat 1,"18, Kirkmanshulme Lane",,M12 4WA,7752380968,D,D,61,66,Flat,End-Terrace,2011-10-10,E08000003,E14000808,,2011-10-10,rental (social),63,69,376,316.0,2.0,72,1.7,26.0,18.0,385.0,341.0,64.0,56.0,28.14,Single,Y,Ground,N,,2107.0,100.0,"double glazing, unknown install date",Normal,0.0,2.0,2.0,60.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Average,Average,"Solid brick, as built, no insulation (assumed)",Poor,Poor,,,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, TRVs and bypass",Average,Average,Low energy lighting in 60% of fixed outlets,Good,Good,mains gas (not community),0.0,unheated corridor,11.22,3.04,0.0,,natural,"Flat 1, 18, Kirkmanshulme Lane",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1900-1929,2011-10-10 21:15:02,rental (social),5.0,3.0,77149971.0,Address Matched,100
5416a6441d4991472ee3dc5c86d6ee764bf3b5c49edd14340ada8125e839e710,1463 ASHTON OLD ROAD,MANCHESTER,,M11 1HH,10000232217,C,B,80,89,House,Semi-Detached,2021-01-06,E08000003,E14000807,,2021-01-11,marketed sale,79,88,112,63.0,2.4,20,1.4,91.0,91.0,411.0,411.0,81.0,53.0,121.0,off-peak 7 hour,Y,,,,,100.0,double glazing installed during or after 2002,Normal,0.0,5.0,5.0,100.0,0.0,From main system,Good,Good,"Solid, insulated (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, as built, insulated (assumed)",Very Good,Very Good,,,,"Pitched, 250 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (not community),0.0,,,2.6,0.0,N,natural,"1463 ASHTON OLD ROAD, MANCHESTER",Manchester,Manchester Central,MANCHESTER,England and Wales: 2012 onwards,2021-01-11 00:00:00,Owner-occupied,13.0,13.0,10093076622.0,Energy Assessor,100
731682144052011120911312699099293,"26, Fog Lane",,,M20 6AL,2354493968,D,C,61,69,House,Semi-Detached,2011-12-09,E08000003,E14000809,,2011-12-09,marketed sale,57,67,244,183.0,4.7,47,3.5,94.0,51.0,758.0,589.0,95.0,95.0,99.35,Single,Y,NODATA!,,,2106.0,100.0,"double glazing, unknown install date",Normal,0.0,5.0,5.0,14.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Average,Average,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,"Room heaters, mains gas",,,"Pitched, 200 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 14% of fixed outlets,Poor,Poor,mains gas (not community),0.0,NO DATA!,,2.49,0.0,,natural,"26, Fog Lane",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1930-1949,2011-12-09 11:31:26,owner-occupied,14.0,2.0,77104449.0,Address Matched,100
636111349222011053112083067448689,14 Lynhurst Court,Whitelow Road,,M21 9RS,8629417868,C,C,79,80,Flat,NO DATA!,2011-05-24,E08000003,E14000809,,2011-05-31,rental (private),70,71,274,264.0,1.9,49,1.8,49.0,25.0,79.0,84.0,162.0,162.0,39.3,dual,N,2nd,N,,2106.0,100.0,double glazing installed during or after 2002,Normal,0.0,2.0,2.0,0.0,0.0,From main system,Average,Very Poor,(other premises below),,,Fully double glazed,Good,Good,"Solid brick, as built, insulated (assumed)",Good,Good,,,,(another dwelling above),,,"Boiler and radiators, electric",Poor,Very Poor,"Programmer, room thermostat and TRVs",Good,Good,No low energy lighting,Very Poor,Very Poor,electricity (not community),0.0,heated corridor,,2.98,0.0,,natural,"14 Lynhurst Court, Whitelow Road",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 2003-2006,2011-05-31 12:08:30,rental (private),11.0,0.0,10070869721.0,Address Matched,100
cabb687c109a22fbd8064595e23af2e6d4119306b86d909ba87b93daf4987c56,FLAT 316,TIMBER WHARF,32 WORSLEY STREET,M15 4NY,10000512885,B,B,82,83,Flat,Mid-Terrace,2021-02-24,E08000003,E14000807,,2021-02-24,marketed sale,72,74,267,248.0,1.5,45,1.4,39.0,39.0,131.0,102.0,148.0,148.0,34.0,off-peak 10 hour,N,03,N,,,100.0,"double glazing, unknown install date",Normal,0.0,2.0,2.0,100.0,0.0,"Electric immersion, off-peak",Average,Poor,(another dwelling below),,,Fully double glazed,Average,Average,"System built, as built, insulated (assumed)",Good,Good,"Room heaters, electric",,,(another dwelling above),,,Electric storage heaters,Average,Very Poor,Manual charge control,Poor,Poor,Low energy lighting in all fixed outlets,Very Good,Very Good,electricity (not community),0.0,unheated corridor,5.85,2.7,0.0,N,natural,"FLAT 316, TIMBER WHARF, 32 WORSLEY STREET",Manchester,Manchester Central,MANCHESTER,England and Wales: 1996-2002,2021-02-24 00:00:00,Owner-occupied,6.0,6.0,10003799752.0,Energy Assessor,100
44c18ead193b7303c929d2b1c75ed2133b5f38c2b16aba5f6aa2acf60e4fb0ca,"20, Thomas Regan Court Ansell Close",Gorton,,M18 8EE,10000146161,C,C,75,77,Flat,Mid-Terrace,2020-09-16,E08000003,E14000808,,2021-02-24,rental,77,81,225,192.0,1.2,40,1.0,27.0,27.0,218.0,184.0,99.0,99.0,31.0,off-peak 7 hour,Y,01,Y,,,100.0,double glazing installed during or after 2002,Normal,0.0,2.0,2.0,83.0,0.0,Community scheme,Good,Good,(another dwelling below),,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,,,,"Pitched, 200 mm loft insulation",Good,Good,Community scheme,Good,Good,"Flat rate charging, programmer and TRVs",Average,Average,Low energy lighting in 83% of fixed outlets,Very Good,Very Good,mains gas (community),0.0,heated corridor,0.0,2.4,0.0,N,natural,"20, Thomas Regan Court Ansell Close, Gorton",Manchester,"Manchester, Gorton",,England and Wales: 1976-1982,2021-02-24 00:00:00,Rented (social),6.0,5.0,77177124.0,Energy Assessor,100
3c08c183659d59febda24dc7492539fd151860c9ca4146efaa1450a8598eac41,"30, Kincraig Close",Openshaw,,M11 2JP,10000217311,C,B,73,87,House,Mid-Terrace,2020-10-08,E08000003,E14000807,,2021-02-24,rental,72,86,179,85.0,2.5,32,1.2,70.0,51.0,436.0,406.0,110.0,74.0,78.0,off-peak 7 hour,Y,,,,,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,63.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,,,,"Pitched, 300 mm loft insulation",Very Good,Very Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 62% of fixed outlets,Good,Good,mains gas (not community),0.0,,,2.4,0.0,N,natural,"30, Kincraig Close, Openshaw",Manchester,Manchester Central,,England and Wales: 1976-1982,2021-02-24 00:00:00,Rented (social),8.0,5.0,77179169.0,Energy Assessor,100
5ab41382eb79bed813dbe2c64c640c9ea51e554100993869db5f3d05ed7b7bf2,37 SOUTH GROVE,MANCHESTER,,M13 0AU,10000587736,D,B,65,85,House,Mid-Terrace,2020-12-09,E08000003,E14000807,,2020-12-09,marketed sale,58,82,224,96.0,4.7,40,2.1,86.0,86.0,829.0,525.0,106.0,75.0,120.0,off-peak 7 hour,Y,,,,,100.0,"double glazing, unknown install date",Normal,0.0,7.0,7.0,100.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Average,Average,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,,,,"Pitched, 150 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, TRVs and bypass",Average,Average,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (not community),0.0,,,2.78,0.0,N,natural,"37 SOUTH GROVE, MANCHESTER",Manchester,Manchester Central,MANCHESTER,England and Wales: before 1900,2020-12-09 00:00:00,Rented (private),11.0,11.0,77135463.0,Energy Assessor,100
488750391312012022311594492090472,"73, Roundthorn Road",,,M23 1EP,4211126768,D,C,57,71,House,Semi-Detached,2011-08-03,E08000003,E14001059,,2012-02-23,rental (social),54,71,294,184.0,4.1,57,2.5,61.0,41.0,520.0,419.0,251.0,106.0,72.0,Single,Y,NODATA!,,,2104.0,100.0,double glazing installed before 2002,Normal,0.0,3.0,3.0,50.0,0.0,"From main system, no cylinder thermostat",Poor,Poor,"Solid, no insulation (assumed)",,,Fully double glazed,Average,Average,"Cavity wall, filled cavity",Good,Good,"Room heaters, mains gas",,,"Pitched, 100 mm loft insulation",Average,Average,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,Low energy lighting in 50% of fixed outlets,Good,Good,mains gas (not community),0.0,NO DATA!,,2.4,0.0,,natural,"73, Roundthorn Road",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1950-1966,2012-02-23 11:59:44,rental (social),10.0,5.0,77045284.0,Address Matched,100
c175f3aad8bad5700cd15c26ed8864faf355c53361917563dd1cbaa208f0e47b,"5, Francesca Walk",Gorton,,M18 8EN,10000390940,C,C,73,76,Flat,Mid-Terrace,2020-10-19,E08000003,E14000808,,2021-02-24,rental,75,78,196,169.0,1.7,34,1.5,57.0,34.0,320.0,290.0,89.0,90.0,50.0,off-peak 7 hour,Y,00,Y,,,100.0,double glazing installed during or after 2002,Normal,0.0,2.0,2.0,33.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Average,Average,,,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 33% of fixed outlets,Average,Average,mains gas (not community),0.0,unheated corridor,5.2,2.4,0.0,N,natural,"5, Francesca Walk, Gorton",Manchester,"Manchester, Gorton",,England and Wales: 1967-1975,2021-02-24 00:00:00,Rented (social),6.0,2.0,77176834.0,Energy Assessor,100
8fc47b53627c0b8b3bbe2b90a445805813ce5abce8543732986f41a863e0b608,"680, Hyde Road",Gorton,,M18 7EF,10000708843,C,C,77,77,Flat,Mid-Terrace,2020-10-13,E08000003,E14000808,,2021-02-24,rental,79,79,164,164.0,1.3,29,1.3,34.0,34.0,268.0,268.0,87.0,87.0,47.0,off-peak 7 hour,Y,01,Y,,,100.0,double glazing installed during or after 2002,Normal,0.0,2.0,2.0,100.0,0.0,From main system,Good,Good,(another dwelling below),,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,,,,"Pitched, 250 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (not community),0.0,unheated corridor,6.56,2.4,0.0,N,natural,"680, Hyde Road, Gorton",Manchester,"Manchester, Gorton",,England and Wales: 1976-1982,2021-02-24 00:00:00,Rented (social),6.0,6.0,77172366.0,Energy Assessor,100
97681707d8c26caf1e068dde344b6db1af30849413c5c2421c74ae73602eda76,FLAT 2,61 CHARLESTOWN ROAD,MANCHESTER,M9 7AB,10000744934,D,D,56,63,Flat,Semi-Detached,2021-03-11,E08000003,E14000571,,2021-03-11,ECO assessment,60,67,548,460.0,1.9,93,1.6,23.0,23.0,414.0,302.0,255.0,255.0,21.0,off-peak 7 hour,N,01,N,,,100.0,double glazing installed before 2002,Normal,0.0,1.0,1.0,100.0,0.0,From main system,Very Poor,Poor,(another dwelling below),,,Fully double glazed,Average,Average,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,,,,(another dwelling above),,,"Boiler and radiators, electric",Very Poor,Poor,TRVs and bypass,Average,Average,Low energy lighting in all fixed outlets,Very Good,Very Good,electricity (not community),0.0,heated corridor,,2.6,0.0,N,natural,"FLAT 2, 61 CHARLESTOWN ROAD, MANCHESTER",Manchester,Blackley and Broughton,MANCHESTER,England and Wales: 1900-1929,2021-03-11 00:00:00,Rented (social),3.0,3.0,10090425373.0,Energy Assessor,100
5bb34e45687ba9cf86df5756344950a9462c6bd0ab753aeda85571eca1353c1e,"4, Howarth Close",Beswick,,M11 3BR,10000607596,C,C,74,77,Flat,Mid-Terrace,2020-10-19,E08000003,E14000807,,2021-02-24,rental,75,79,193,161.0,1.7,34,1.4,48.0,34.0,321.0,277.0,89.0,90.0,50.0,off-peak 7 hour,Y,00,Y,,,100.0,double glazing installed during or after 2002,Normal,0.0,2.0,2.0,60.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"System built, with external insulation",Very Good,Very Good,,,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 60% of fixed outlets,Good,Good,mains gas (not community),0.0,no corridor,0.0,2.4,0.0,N,natural,"4, Howarth Close, Beswick",Manchester,Manchester Central,,England and Wales: 1967-1975,2021-02-24 00:00:00,Rented (social),5.0,3.0,77168659.0,Energy Assessor,100
609449769232012011815001652968806,Flat 2,36 Clyde Road,,M20 2HN,6632815868,E,E,45,54,Flat,Semi-Detached,2012-01-17,E08000003,E14000809,,2012-01-18,marketed sale,43,50,408,337.0,4.8,78,4.0,73.0,36.0,805.0,698.0,84.0,74.0,61.2,Single,Y,Ground,N,,2107.0,100.0,double glazing installed before 2002,Normal,0.0,3.0,3.0,0.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Average,Average,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,,,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, TRVs and bypass",Average,Average,No low energy lighting,Very Poor,Very Poor,mains gas (not community),0.0,unheated corridor,9.0,3.03,0.0,,natural,"Flat 2, 36 Clyde Road",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1900-1929,2012-01-18 15:00:16,owner-occupied,12.0,0.0,77193527.0,Address Matched,100
8e64a93ed490b8227820a6eccbfb961ece2584543e04357a84a51ab327e3bd01,FLAT 1,7 STANLEY ROAD,MANCHESTER,M16 8HT,10000482906,E,C,46,71,Maisonette,Semi-Detached,2021-01-14,E08000003,E14000808,,2021-01-14,ECO assessment,47,61,474,342.0,3.2,80,2.3,67.0,40.0,725.0,328.0,168.0,198.0,39.0,standard tariff,N,00,N,,,100.0,double glazing installed during or after 2002,Normal,0.0,2.0,2.0,0.0,0.0,Electric instantaneous at point of use,Very Poor,Poor,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,,,,(another dwelling above),,,"Room heaters, electric",Very Poor,Poor,Appliance thermostats,Good,Good,No low energy lighting,Very Poor,Very Poor,electricity (not community),0.0,heated corridor,,2.2,0.0,N,natural,"FLAT 1, 7 STANLEY ROAD, MANCHESTER",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1900-1929,2021-01-14 00:00:00,Rented (social),8.0,0.0,10014178834.0,Energy Assessor,100
748772149802012020922143291520318,"880, Burnage Lane",,,M19 1RS,9817745968,D,D,65,67,House,Semi-Detached,2012-02-09,E08000003,E14000809,,2012-02-09,marketed sale,61,63,204,190.0,5.2,39,4.9,97.0,62.0,828.0,792.0,115.0,115.0,133.0,Single,Y,NODATA!,,,2104.0,100.0,double glazing installed during or after 2002,Normal,2.0,6.0,6.0,44.0,1.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,"Room heaters, mains gas",,,"Pitched, 200 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,Low energy lighting in 44% of fixed outlets,Average,Average,mains gas (not community),0.0,NO DATA!,,2.32,0.0,,natural,"880, Burnage Lane",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1930-1949,2012-02-09 22:14:32,owner-occupied,16.0,7.0,77125062.0,Address Matched,100
560c08dd1356a1845c7b42b64a9f9b51d5da057bbcf277b7577af732b553fb79,"4, Easthaven Avenue",Clayton,,M11 4RN,10000272490,D,B,65,82,House,Semi-Detached,2020-10-23,E08000003,E14000807,,2021-02-24,rental,64,81,230,122.0,3.0,40,1.6,77.0,48.0,566.0,516.0,107.0,72.0,74.0,off-peak 7 hour,Y,,,,,100.0,double glazing installed during or after 2002,Normal,0.0,4.0,4.0,40.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Average,Average,"Room heaters, electric",,,"Pitched, 200 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 40% of fixed outlets,Average,Average,mains gas (not community),0.0,,,2.4,0.0,N,natural,"4, Easthaven Avenue, Clayton",Manchester,Manchester Central,,England and Wales: 1930-1949,2021-02-24 00:00:00,Rented (social),10.0,4.0,77181001.0,Energy Assessor,100
614517559252011042315041795290084,"50, Kirkmanshulme Lane",,,M12 4WA,454955868,E,E,45,54,House,Mid-Terrace,2011-04-21,E08000003,E14000808,,2011-04-23,marketed sale,40,47,338,281.0,8.3,65,7.0,115.0,58.0,1332.0,1159.0,104.0,89.0,102.38,Single,Y,NODATA!,,,2107.0,100.0,double glazing installed before 2002,Normal,0.0,7.0,7.0,0.0,1.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Average,Average,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,"Room heaters, dual fuel (mineral and wood)",,,"Pitched, no insulation (assumed)",Very Poor,Very Poor,"Boiler and radiators, mains gas",Good,Good,"Programmer, TRVs and bypass",Average,Average,No low energy lighting,Very Poor,Very Poor,mains gas (not community),0.0,NO DATA!,,2.88,0.0,,natural,"50, Kirkmanshulme Lane",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1900-1929,2011-04-23 15:04:17,owner-occupied,12.0,0.0,77149984.0,Address Matched,100
688269469962011101122380750998659,"203, Dickenson Road",,,M13 0YW,5527680968,E,D,46,67,Flat,NO DATA!,2011-10-11,E08000003,E14000808,,2011-10-11,rental (social),44,68,428,234.0,4.3,83,2.3,51.0,30.0,686.0,404.0,128.0,94.0,51.805,Single,Y,Ground,N,,2104.0,0.0,not defined,Normal,0.0,2.0,2.0,29.0,0.0,From main system,Average,Average,"Suspended, no insulation (assumed)",,,Single glazed,Very Poor,Very Poor,"Cavity wall, as built, no insulation (assumed)",Very Poor,Very Poor,"Room heaters, mains gas",,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,Low energy lighting in 29% of fixed outlets,Average,Average,mains gas (not community),0.0,no corridor,,2.926,0.0,,natural,"203, Dickenson Road",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: before 1900,2011-10-11 22:38:07,rental (social),7.0,2.0,77151575.0,Address Matched,100
679778369962011101214371240258809,Flat 16,St. Georges Court,Angela Street,M15 4HY,419620968,B,B,84,84,Flat,NO DATA!,2011-09-15,E08000003,E14000807,,2011-10-12,rental (social),77,77,265,265.0,1.2,47,1.2,20.0,20.0,73.0,73.0,90.0,90.0,26.23,dual,N,3rd,N,,2401.0,100.0,double glazing installed during or after 2002,Normal,0.0,1.0,1.0,100.0,0.0,"Electric immersion, off-peak",Average,Very Poor,(other premises below),,,Fully double glazed,Good,Good,"Cavity wall, with external insulation",Very Good,Very Good,,,,(another dwelling above),,,Electric storage heaters,Poor,Very Poor,Manual charge control,Poor,Poor,Low energy lighting in all fixed outlets,Very Good,Very Good,electricity (not community),0.0,unheated corridor,6.64,2.42,0.0,,natural,"Flat 16, St. Georges Court, Angela Street",Manchester,Manchester Central,MANCHESTER,England and Wales: 2007 onwards,2011-10-12 14:37:12,rental (social),4.0,4.0,77089818.0,Address Matched,100
4ef5a12d522c8fe5ed3c546cfa247287dd48eed5b2b15ee4de2b9b3763b5d786,171 ASHLEY LANE,MANCHESTER,,M9 4NQ,10000118472,D,C,59,80,House,Mid-Terrace,2020-10-21,E08000003,E14000571,,2020-10-24,marketed sale,52,75,292,149.0,4.8,52,2.5,124.0,73.0,835.0,620.0,89.0,61.0,93.0,off-peak 7 hour,Y,,,,,100.0,"double glazing, unknown install date",Normal,1.0,5.0,5.0,30.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Average,Average,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,"Room heaters, mains gas",,,"Pitched, 250 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,Low energy lighting in 30% of fixed outlets,Average,Average,mains gas (not community),0.0,,,2.69,0.0,N,natural,"171 ASHLEY LANE, MANCHESTER",Manchester,Blackley and Broughton,MANCHESTER,England and Wales: 1900-1929,2020-10-24 00:00:00,Owner-occupied,10.0,3.0,77022818.0,Energy Assessor,100
1b1f726b0eeeec41f52767f85efe93fbce9531ee45bb57f29a437ca4ad23ec05,5 THE OLD COURTYARD,MANCHESTER,,M22 4YD,10000358677,C,B,72,84,House,End-Terrace,2021-03-05,E08000003,E14001059,,2021-03-05,marketed sale,70,82,186,110.0,2.7,33,1.6,71.0,71.0,447.0,447.0,103.0,72.0,81.0,off-peak 7 hour,Y,,,,,100.0,"double glazing, unknown install date",Normal,0.0,4.0,4.0,100.0,0.0,From main system,Good,Good,"Solid, limited insulation (assumed)",,,Fully double glazed,Average,Average,"Cavity wall, as built, insulated (assumed)",Good,Good,,,,"Pitched, 100 mm loft insulation",Average,Average,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (not community),0.0,,,2.25,0.0,N,natural,"5 THE OLD COURTYARD, MANCHESTER",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1996-2002,2021-03-05 00:00:00,Owner-occupied,12.0,12.0,77067549.0,Energy Assessor,100
730662989202011120614524193390868,"107, Plymouth Grove",,,M13 9HX,5291683968,C,C,76,76,House,Mid-Terrace,2011-12-06,E08000003,E14000807,,2011-12-06,rental (social),76,76,142,142.0,2.4,27,2.4,52.0,52.0,382.0,382.0,110.0,110.0,89.6,Single,Y,NODATA!,,,2310.0,100.0,double glazing installed during or after 2002,Normal,0.0,5.0,5.0,90.0,0.0,Community scheme,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,"Room heaters, electric",,,"Pitched, 300+ mm loft insulation",Very Good,Very Good,Community scheme,Good,Good,"Charging system linked to use of community heating, TRVs",Good,Good,Low energy lighting in 90% of fixed outlets,Very Good,Very Good,mains gas (community),0.0,NO DATA!,,2.38,0.0,,natural,"107, Plymouth Grove",Manchester,Manchester Central,MANCHESTER,England and Wales: 1967-1975,2011-12-06 14:52:41,rental (social),10.0,9.0,77136227.0,Address Matched,100
637817066932011060412162118068803,Apartment 306 Chatsworth House,"19, Lever Street",,M1 1BY,6308827868,C,B,75,81,Flat,NO DATA!,2011-06-04,E08000003,E14000807,,2011-06-04,marketed sale,69,69,213,213.0,2.7,38,2.7,76.0,46.0,274.0,191.0,137.0,107.0,72.25,Unknown,N,3rd,N,,2602.0,100.0,double glazing installed before 2002,Normal,0.0,3.0,3.0,20.0,0.0,"Electric immersion, off-peak",Average,Very Poor,(other premises below),,,Fully double glazed,Average,Average,"System built, as built, insulated (assumed)",Good,Good,,,,(another dwelling above),,,"Room heaters, electric",Poor,Very Poor,Appliance thermostats,Good,Good,Low energy lighting in 20% of fixed outlets,Poor,Poor,electricity (not community),0.0,unheated corridor,12.5,2.45,0.0,,natural,"Apartment 306 Chatsworth House, 19, Lever Street",Manchester,Manchester Central,MANCHESTER,England and Wales: 1996-2002,2011-06-04 12:16:21,owner-occupied,10.0,2.0,10023045032.0,Address Matched,100
649015816912011063013353790790785,"45, Northridge Road",,,M9 6GW,7587608868,C,C,69,69,House,Semi-Detached,2011-06-30,E08000003,E14000571,,2011-06-30,rental (social),70,70,191,191.0,2.6,36,2.6,38.0,38.0,469.0,469.0,84.0,84.0,72.06,Single,Y,NODATA!,,,2106.0,100.0,double glazing installed during or after 2002,Normal,0.0,4.0,4.0,100.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,"Room heaters, electric",,,"Pitched, 250 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (not community),0.0,NO DATA!,,2.44,0.0,,natural,"45, Northridge Road",Manchester,Blackley and Broughton,MANCHESTER,England and Wales: 1930-1949,2011-06-30 13:35:37,rental (social),6.0,6.0,77020453.0,Address Matched,100
79011046012011092920530093290647,"Apartment 2, Windsor House","252, Mauldeth Road West",Chorlton cum Hardy,M21 7TH,6732635468,C,C,70,76,Flat,Detached,2011-09-29,E08000003,E14000809,,2011-09-29,marketed sale,63,62,262,268.0,3.2,46,3.2,62.0,45.0,383.0,291.0,128.0,115.0,67.94,Unknown,N,1st,N,,2603.0,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,44.0,0.0,"Electric immersion, off-peak",Average,Very Poor,"To external air, insulated (assumed)",,,Fully double glazed,Good,Good,"System built, as built, insulated (assumed)",Good,Good,,,,(another dwelling above),,,"Room heaters, electric",Poor,Very Poor,Programmer and appliance thermostats,Good,Good,Low energy lighting in 44% of fixed outlets,Average,Average,electricity (not community),0.0,unheated corridor,23.28,2.25,0.0,,"mechanical, extract only","Apartment 2, Windsor House, 252, Mauldeth Road West, Chorlton cum Hardy",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 2003-2006,2011-09-29 20:53:00,owner-occupied,9.0,4.0,10070868545.0,Address Matched,100
664d3337e51de82abf0c359a8e9a446a0dbd5d7965369fc859eb0add675aec5a,"8, Hartington Drive",Clayton,,M11 4JG,10000747213,D,B,68,83,House,Semi-Detached,2020-10-20,E08000003,E14000807,,2021-02-24,rental,65,81,217,117.0,3.0,38,1.7,79.0,51.0,543.0,500.0,110.0,74.0,80.0,off-peak 7 hour,Y,,,,,100.0,double glazing installed during or after 2002,Normal,0.0,4.0,4.0,45.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Average,Average,,,,"Pitched, 300 mm loft insulation",Very Good,Very Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 45% of fixed outlets,Good,Good,mains gas (not community),0.0,,,2.6,0.0,N,natural,"8, Hartington Drive, Clayton",Manchester,Manchester Central,,England and Wales: 1930-1949,2021-02-24 00:00:00,Rented (social),11.0,5.0,77169870.0,Energy Assessor,100
fff8edbe33f302b835435ce435658054f9a93dc8d3a699c782508ed9059ee32a,FLAT 75,SOUTHMOOR,23 GLEBELANDS ROAD,M23 1HR,10000583235,D,C,64,80,Flat,Mid-Terrace,2021-02-10,E08000003,E14001059,,2021-02-18,ECO assessment,68,67,280,285.0,2.0,47,2.0,74.0,41.0,352.0,194.0,285.0,154.0,41.0,off-peak 7 hour,N,05,N,,,100.0,"double glazing, unknown install date",Normal,0.0,3.0,3.0,0.0,0.0,"Electric immersion, standard tariff",Very Poor,Poor,(another dwelling below),,,Fully double glazed,Average,Average,"System built, as built, no insulation (assumed)",Very Poor,Very Poor,,,,(another dwelling above),,,"Room heaters, electric",Very Poor,Poor,Programmer and appliance thermostats,Good,Good,No low energy lighting,Very Poor,Very Poor,electricity (not community),0.0,no corridor,,2.49,0.0,N,natural,"FLAT 75, SOUTHMOOR, 23 GLEBELANDS ROAD",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1967-1975,2021-02-18 00:00:00,Rented (private),6.0,0.0,10003798235.0,Energy Assessor,100
554538989642011101814401084099988,"246, Cornishway",,,M22 1SU,1659680868,E,D,52,61,Flat,End-Terrace,2011-10-18,E08000003,E14001059,,2011-10-18,rental (social),55,63,314,255.0,3.6,58,3.0,65.0,36.0,458.0,440.0,328.0,224.0,62.09,Single,Y,Ground,Y,,2106.0,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,20.0,0.0,"Electric immersion, standard tariff",Very Poor,Very Poor,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,,,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 20% of fixed outlets,Poor,Poor,mains gas (not community),0.0,unheated corridor,4.77,2.44,0.0,,natural,"246, Cornishway",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1950-1966,2011-10-18 14:40:10,rental (social),10.0,2.0,77056094.0,Address Matched,100
b4b36cb0202e0bb71d122b2d37acae25b532d32d407c18f29795ab9631bec6b1,APARTMENT 15,6 THE WATERFRONT,MANCHESTER,M11 4AY,10000509199,C,C,70,70,Flat,Detached,2021-03-02,E08000003,E14000807,,2021-03-02,rental,73,73,185,185.0,2.2,31,2.2,65.0,65.0,459.0,459.0,272.0,272.0,71.0,off-peak 10 hour,N,02,N,,,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,100.0,0.0,From main system,Very Poor,Poor,(another dwelling below),,,Fully double glazed,Good,Good,"Cavity wall, as built, insulated (assumed)",Good,Good,,,,(another dwelling above),,,"Boiler and radiators, electric",Very Poor,Poor,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in all fixed outlets,Very Good,Very Good,electricity (not community),0.0,unheated corridor,10.1,2.41,0.0,N,natural,"APARTMENT 15, 6 THE WATERFRONT, MANCHESTER",Manchester,Manchester Central,MANCHESTER,England and Wales: 2003-2006,2021-03-02 00:00:00,Owner-occupied,9.0,9.0,10012203091.0,Energy Assessor,100
619828709242011041909303788699788,"16, Alexandra Drive",,,M19 2WW,252206868,D,D,61,68,House,Semi-Detached,2011-04-18,E08000003,E14000808,,2011-04-19,marketed sale,57,66,245,195.0,4.5,47,3.6,69.0,48.0,721.0,597.0,103.0,86.0,95.72,Single,Y,NODATA!,,,2107.0,75.0,double glazing installed before 2002,Normal,1.0,5.0,5.0,55.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Partial double glazing,Poor,Poor,"Cavity wall, with internal insulation",Good,Good,"Room heaters, mains gas",,,"Pitched, 100 mm loft insulation",Average,Average,"Boiler and radiators, mains gas",Good,Good,"Programmer, TRVs and bypass",Average,Average,Low energy lighting in 55% of fixed outlets,Good,Good,mains gas (not community),0.0,NO DATA!,,2.7,0.0,,natural,"16, Alexandra Drive",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1900-1929,2011-04-19 09:30:37,owner-occupied,11.0,6.0,77147636.0,Address Matched,100
481145989762012022218030515508359,"16, Crowthorn Drive",,,M23 2XX,5126865768,D,C,63,74,Flat,Detached,2011-09-30,E08000003,E14001059,,2012-02-22,rental (social),61,75,242,155.0,3.4,46,2.2,65.0,43.0,424.0,345.0,227.0,114.0,73.0,Single,Y,1st,N,,2104.0,100.0,double glazing installed during or after 2002,Normal,0.0,4.0,4.0,50.0,0.0,"From main system, no cylinder thermostat",Poor,Poor,(other premises below),,,Fully double glazed,Good,Good,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,"Room heaters, mains gas",,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,Low energy lighting in 50% of fixed outlets,Good,Good,mains gas (not community),0.0,unheated corridor,6.0,2.4,0.0,,natural,"16, Crowthorn Drive",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1950-1966,2012-02-22 18:03:05,rental (social),10.0,5.0,77048710.0,Address Matched,100
635128788152011052716244690290489,"161, Blackcarr Road",,,M23 1PB,4977807868,D,C,68,70,House,Semi-Detached,2011-05-27,E08000003,E14001059,,2011-05-27,marketed sale,66,69,192,177.0,3.6,37,3.3,80.0,49.0,521.0,500.0,137.0,137.0,97.26,Single,Y,NODATA!,,,2106.0,100.0,double glazing installed during or after 2002,Normal,1.0,5.0,5.0,36.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,"Room heaters, mains gas",,,"Pitched, 250 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 36% of fixed outlets,Average,Average,mains gas (not community),0.0,NO DATA!,,2.44,0.0,,natural,"161, Blackcarr Road",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1950-1966,2011-05-27 16:24:46,owner-occupied,11.0,4.0,77051657.0,Address Matched,100
679768829202011101214391699099658,Flat 61 St. Georges Court,Angela Street,,M15 4HZ,278620968,B,B,83,83,Flat,NO DATA!,2011-09-15,E08000003,E14000807,,2011-10-12,rental (social),76,76,274,274.0,1.3,49,1.3,20.0,20.0,85.0,85.0,90.0,90.0,26.238,dual,N,13th,N,,2401.0,100.0,double glazing installed during or after 2002,Normal,0.0,1.0,1.0,100.0,0.0,"Electric immersion, off-peak",Average,Very Poor,(other premises below),,,Fully double glazed,Good,Good,"Cavity wall, with external insulation",Very Good,Very Good,,,,(another dwelling above),,,Electric storage heaters,Poor,Very Poor,Manual charge control,Poor,Poor,Low energy lighting in all fixed outlets,Very Good,Very Good,electricity (not community),0.0,unheated corridor,6.64,2.42,0.0,,natural,"Flat 61 St. Georges Court, Angela Street",Manchester,Manchester Central,MANCHESTER,England and Wales: 2007 onwards,2011-10-12 14:39:16,rental (social),4.0,4.0,77089862.0,Address Matched,100
734802329412011122022231691099590,"36, Broom Avenue",,,M19 2UD,5050914968,D,D,67,68,House,Mid-Terrace,2011-12-08,E08000003,E14000808,,2011-12-20,rental (private),67,69,238,226.0,2.4,46,2.3,33.0,33.0,431.0,410.0,71.0,71.0,51.8,Single,Y,NODATA!,,,2107.0,100.0,double glazing installed before 2002,Normal,0.0,3.0,3.0,88.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Average,Average,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,,,,"Pitched, 150 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, TRVs and bypass",Average,Average,Low energy lighting in 88% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,NO DATA!,,2.7,0.0,,natural,"36, Broom Avenue",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1900-1929,2011-12-20 22:23:16,rental (private),8.0,7.0,77159739.0,Address Matched,100
99f660d53b3d1f4f4c0552f485401f62821e3dd8d921f0235d6881b85cbd0e97,3 GORTON LANE,MANCHESTER,,M12 5DF,10000205809,C,B,71,87,House,Semi-Detached,2021-01-15,E08000003,E14000808,,2021-01-20,marketed sale,71,87,196,83.0,2.3,34,1.0,120.0,60.0,367.0,352.0,89.0,62.0,66.0,off-peak 10 hour,Y,,,,,100.0,"double glazing, unknown install date",Normal,0.0,5.0,5.0,0.0,0.0,From main system,Good,Good,"Solid, limited insulation (assumed)",,,Fully double glazed,Average,Average,"Cavity wall, as built, insulated (assumed)",Good,Good,,,,"Pitched, 270 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,No low energy lighting,Very Poor,Very Poor,mains gas (not community),0.0,,,2.3,0.0,N,natural,"3 GORTON LANE, MANCHESTER",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1996-2002,2021-01-20 00:00:00,Not defined - use in the case of a new dwelling for which the intended tenure in not known. It is not to be used for an existing dwelling,12.0,0.0,77166837.0,Energy Assessor,100
021157ab012ac40fef385b072f957b5da8f89ed1ca67cf3a6d3c260de6beead9,FLAT 53,WORSLEY COURT,MANCHESTER,M14 5LU,10000809961,C,C,78,80,Flat,Mid-Terrace,2021-01-11,E08000003,E14000808,,2021-01-13,rental,80,83,161,139.0,1.2,28,1.1,54.0,39.0,174.0,164.0,108.0,96.0,44.0,off-peak 7 hour,Y,06,N,,,100.0,"double glazing, unknown install date",Normal,0.0,2.0,2.0,60.0,0.0,Community scheme,Good,Good,(another dwelling below),,,Fully double glazed,Average,Average,"System built, with external insulation",Good,Good,,,,(another dwelling above),,,Community scheme,Good,Good,"Charging system linked to use of community heating, room thermostat only",Poor,Poor,Low energy lighting in 60% of fixed outlets,Good,Good,mains gas (community),0.0,no corridor,,2.45,0.0,N,natural,"FLAT 53, WORSLEY COURT, MANCHESTER",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1967-1975,2021-01-13 00:00:00,Rented (social),5.0,3.0,10003800135.0,Energy Assessor,100
625257257112011050510245493090787,"210, Brownley Road",,,M22 5EB,7765736868,E,D,45,58,House,End-Terrace,2011-05-05,E08000003,E14001059,,2011-05-05,rental (social),42,55,403,297.0,5.0,78,3.7,63.0,35.0,769.0,607.0,139.0,103.0,64.54,Single,Y,NODATA!,,,2104.0,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,20.0,0.0,From main system,Average,Average,"Suspended, no insulation (assumed)",,,Fully double glazed,Good,Good,"System built, as built, no insulation (assumed)",Very Poor,Very Poor,"Room heaters, mains gas",,,"Pitched, 75 mm loft insulation",Average,Average,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,Low energy lighting in 20% of fixed outlets,Poor,Poor,mains gas (not community),0.0,NO DATA!,,2.43,0.0,,natural,"210, Brownley Road",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1930-1949,2011-05-05 10:24:54,rental (social),10.0,2.0,77056607.0,Address Matched,100
658838179922011072613401008288139,"6, Cardinal Street",,,M8 0PS,3028778868,C,C,71,76,Flat,NO DATA!,2011-07-18,E08000003,E14000571,,2011-07-26,rental (social),72,79,197,150.0,2.1,38,1.6,32.0,32.0,332.0,268.0,125.0,102.0,55.9,Single,Y,1st,Y,,2104.0,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,100.0,0.0,From main system,Good,Good,(other premises below),,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,"Room heaters, mains gas",,,"Pitched, 100 mm loft insulation",Average,Average,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (not community),0.0,no corridor,,2.47,0.0,,natural,"6, Cardinal Street",Manchester,Blackley and Broughton,MANCHESTER,England and Wales: 1950-1966,2011-07-26 13:40:10,rental (social),4.0,4.0,77004125.0,Address Matched,100
0fefd53f8c1a500a28c0e670aec275667c89e9a35541e5b04513df47d4282393,FLAT 16,79 GREENWOOD ROAD,MANCHESTER,M22 8BT,10000492395,C,C,77,79,Flat,Mid-Terrace,2021-02-09,E08000003,E14001059,,2021-02-10,marketed sale,78,81,152,133.0,1.7,27,1.5,76.0,59.0,272.0,256.0,103.0,89.0,63.0,off-peak 7 hour,Y,00,N,,,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,70.0,0.0,From main system,Good,Good,"Suspended, insulated (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, as built, insulated (assumed)",Good,Good,,,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 70% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,unheated corridor,7.5,2.33,0.0,N,natural,"FLAT 16, 79 GREENWOOD ROAD, MANCHESTER",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 2003-2006,2021-02-10 00:00:00,Owner-occupied,10.0,7.0,10012209996.0,Energy Assessor,100
ed9b110d09ce5659e83f018f850cb47b9051848be46aae32f3e205f298b46893,47 ALAN ROAD,MANCHESTER,,M20 4SE,10000640863,D,C,66,79,House,Semi-Detached,2020-10-17,E08000003,E14000809,,2020-10-17,marketed sale,64,78,211,129.0,3.3,37,2.0,75.0,75.0,674.0,625.0,80.0,52.0,89.0,off-peak 7 hour,Y,,,,,100.0,"double glazing, unknown install date",Normal,1.0,5.0,5.0,93.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Average,Average,"Cavity wall, filled cavity",Average,Average,"Room heaters, electric",,,"Pitched, 200 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 93% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,,,2.46,0.0,N,natural,"47 ALAN ROAD, MANCHESTER",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1930-1949,2020-10-17 00:00:00,Owner-occupied,14.0,13.0,77127799.0,Energy Assessor,100
638729274212011111616003493990381,"8, Midlothian Street",,,M11 4EP,3184437868,D,D,62,65,House,Mid-Terrace,2011-08-19,E08000003,E14000807,,2011-11-16,rental (social),58,62,225,207.0,4.9,43,4.6,108.0,54.0,781.0,756.0,85.0,85.0,114.3,Single,Y,NODATA!,,,2104.0,100.0,double glazing installed before 2002,Normal,1.0,3.0,3.0,0.0,0.0,From main system,Good,Good,"To unheated space, uninsulated (assumed)",,,Fully double glazed,Average,Average,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,,,,"Pitched, no insulation (assumed)",Very Poor,Very Poor,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,No low energy lighting,Very Poor,Very Poor,mains gas (not community),0.0,NO DATA!,,2.34,0.0,,natural,"8, Midlothian Street",Manchester,Manchester Central,MANCHESTER,England and Wales: 1900-1929,2011-11-16 16:00:34,rental (social),7.0,0.0,77169015.0,Address Matched,100
642581286932011061518061414968204,"8, Thorngrove Avenue",,,M23 9PQ,8484267868,D,C,55,74,Flat,NO DATA!,2011-06-14,E08000003,E14001059,,2011-06-15,marketed sale,40,55,488,341.0,4.9,86,3.4,58.0,35.0,443.0,282.0,230.0,97.0,56.58,dual,N,2nd,Y,,2402.0,100.0,double glazing installed before 2002,Normal,0.0,4.0,4.0,33.0,0.0,"Electric immersion, off-peak",Poor,Very Poor,(other premises below),,,Fully double glazed,Average,Average,"Cavity wall, as built, partial insulation (assumed)",Average,Average,"Room heaters, electric",,,"Pitched, 200 mm loft insulation",Good,Good,Electric storage heaters,Average,Very Poor,Automatic charge control,Average,Average,Low energy lighting in 33% of fixed outlets,Average,Average,electricity (not community),0.0,no corridor,,2.52,0.0,,natural,"8, Thorngrove Avenue",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1976-1982,2011-06-15 18:06:14,owner-occupied,6.0,2.0,77043264.0,Address Matched,100
071362360df687e9f894e1bd49586445504f2e59c97848047ec7ab69a4f0098e,APARTMENT 92,THE CITADEL,15 LUDGATE HILL,M4 4AP,10000517000,C,C,73,79,Flat,Mid-Terrace,2020-11-25,E08000003,E14000807,,2020-11-28,rental,69,71,216,205.0,2.3,36,2.2,69.0,69.0,330.0,254.0,219.0,188.0,64.0,off-peak 10 hour,N,06,Y,,,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,79.0,0.0,"Electric immersion, off-peak",Poor,Poor,(another dwelling below),,,Fully double glazed,Good,Good,"Cavity wall, as built, insulated (assumed)",Good,Good,,,,"Flat, insulated (assumed)",Good,Good,"Room heaters, electric",Very Poor,Poor,Appliance thermostats,Good,Good,Low energy lighting in 79% of fixed outlets,Very Good,Very Good,electricity (not community),0.0,heated corridor,0.0,2.397,0.0,N,natural,"APARTMENT 92, THE CITADEL, 15 LUDGATE HILL",Manchester,Manchester Central,MANCHESTER,England and Wales: 2003-2006,2020-11-28 00:00:00,Rented (private),19.0,15.0,10023045277.0,Energy Assessor,100
42013829112012012410412891220753,Flat 2,"12, Victoria Avenue",Didsbury,M20 2GZ,7344914568,C,C,72,73,Flat,Semi-Detached,2012-01-23,E08000003,E14000809,,2012-01-24,marketed sale,76,77,215,203.0,1.5,41,1.4,22.0,22.0,312.0,297.0,42.0,42.0,35.43,Unknown,Y,Ground,N,,2107.0,0.0,not defined,Normal,0.0,2.0,2.0,100.0,0.0,From main system,Good,Good,(other premises below),,,Single glazed,Very Poor,Very Poor,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,,,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, TRVs and bypass",Average,Average,Low energy lighting in all fixed outlets,Very Good,Very Good,mains gas (not community),0.0,unheated corridor,4.31,2.37,0.0,,natural,"Flat 2, 12, Victoria Avenue, Didsbury",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: before 1900,2012-01-24 10:41:28,owner-occupied,4.0,4.0,77222235.0,Address Matched,100
654307865512011071410514394990088,Flat 18 Birch Tree Court,Rowlandsway,,M22 5RY,884548868,C,C,77,79,Flat,Semi-Detached,2011-07-14,E08000003,E14001059,,2011-07-14,rental (social),81,84,143,122.0,1.3,27,1.1,54.0,29.0,226.0,221.0,77.0,68.0,48.1,Single,Y,1st,N,,2106.0,100.0,"double glazing, unknown install date",Normal,0.0,2.0,2.0,14.0,0.0,From main system,Good,Good,(other premises below),,,Fully double glazed,Average,Average,"System built, as built, partial insulation (assumed)",Average,Average,,,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 14% of fixed outlets,Poor,Poor,mains gas (not community),0.0,no corridor,,2.43,0.0,,natural,"Flat 18 Birch Tree Court, Rowlandsway",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1976-1982,2011-07-14 10:51:43,rental (social),7.0,1.0,77056685.0,Address Matched,100
728351399262011112914203643718119,"144, Woodhouse Lane",,,M22 9WW,1454963968,D,C,61,70,House,End-Terrace,2011-11-29,E08000003,E14001059,,2011-11-29,rental (social),58,69,263,194.0,3.6,50,2.7,75.0,39.0,570.0,433.0,111.0,112.0,71.15,Single,Y,NODATA!,,,2106.0,100.0,double glazing installed during or after 2002,Normal,0.0,4.0,4.0,10.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, as built, no insulation (assumed)",Poor,Poor,"Room heaters, mains gas",,,"Pitched, 300+ mm loft insulation",Very Good,Very Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 10% of fixed outlets,Poor,Poor,mains gas (not community),0.0,NO DATA!,,2.46,0.0,,natural,"144, Woodhouse Lane",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1930-1949,2011-11-29 14:20:36,rental (social),10.0,1.0,77213666.0,Address Matched,100
721896329102011110914201292390318,"48, Golborne Avenue",,,M20 1EJ,7181223968,C,C,69,69,House,Semi-Detached,2011-11-09,E08000003,E14000809,,2011-11-09,rental (social),69,69,184,184.0,3.0,35,3.0,52.0,52.0,537.0,537.0,92.0,92.0,86.62,Single,Y,NODATA!,,,2106,100.0,double glazing installed during or after 2002,Normal,0.0,5.0,5.0,86.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Good,Good,"System built, with external insulation",Good,Good,"Room heaters, electric",,,"Pitched, 250 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 86% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,NO DATA!,,2.4,0.0,,natural,"48, Golborne Avenue",Manchester,"Manchester, Withington",MANCHESTER,England and Wales: 1900-1929,2011-11-09 14:20:12,rental (social),7.0,6.0,77093412.0,Address Matched,100
761444229222012032014112746808672,"28, Penarth Road",,,M22 4AR,7465246968,C,C,71,72,House,Semi-Detached,2012-03-20,E08000003,E14001059,,2012-03-20,marketed sale,70,70,170,166.0,3.3,33,3.2,76.0,53.0,543.0,546.0,89.0,89.0,101.73,Single,Y,NODATA!,,,2106.0,100.0,double glazing installed during or after 2002,Normal,1.0,6.0,6.0,55.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,"Room heaters, mains gas",,,"Pitched, 300+ mm loft insulation",Very Good,Very Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 55% of fixed outlets,Good,Good,mains gas (not community),0.0,NO DATA!,,2.46,0.0,,natural,"28, Penarth Road",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1930-1949,2012-03-20 14:11:27,owner-occupied,11.0,6.0,77061245.0,Address Matched,100
737653947152012010914113694020793,"15, Desmond Road",,,M22 9YD,7349744968,C,C,70,70,Flat,Semi-Detached,2012-01-09,E08000003,E14001059,,2012-01-09,rental (social),72,72,191,187.0,2.3,36,2.2,53.0,37.0,385.0,387.0,109.0,109.0,63.34,Single,Y,Ground,N,,2106.0,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,57.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Good,Good,"Room heaters, electric",,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 57% of fixed outlets,Good,Good,mains gas (not community),0.0,no corridor,,2.47,0.0,,natural,"15, Desmond Road",Manchester,Wythenshawe and Sale East,MANCHESTER,England and Wales: 1930-1949,2012-01-09 14:11:36,rental (social),7.0,4.0,77066406.0,Address Matched,100
03975d94b94b7be3d2c055285b0c04b54ae8659ba8b2a69d5dd09273d4d7d777,APARTMENT 6,2A OLD BIRLEY STREET,MANCHESTER,M15 5RG,10000787522,C,C,80,80,Flat,Mid-Terrace,2021-02-04,E08000003,E14000807,,2021-02-10,rental,70,70,219,219.0,2.1,37,2.1,60.0,60.0,177.0,177.0,137.0,137.0,58.0,off-peak 10 hour,Y,02,Y,,,100.0,double glazing installed during or after 2002,Normal,0.0,3.0,3.0,78.0,0.0,"Electric immersion, off-peak",Average,Poor,(another dwelling below),,,Fully double glazed,Good,Good,"Cavity wall, as built, insulated (assumed)",Good,Good,"Room heaters, electric",,,"Flat, insulated (assumed)",Good,Good,Electric storage heaters,Average,Very Poor,Manual charge control,Poor,Poor,Low energy lighting in 78% of fixed outlets,Very Good,Very Good,electricity (not community),0.0,heated corridor,,2.39,0.0,N,natural,"APARTMENT 6, 2A OLD BIRLEY STREET, MANCHESTER",Manchester,Manchester Central,MANCHESTER,England and Wales: 2003-2006,2021-02-10 00:00:00,Rented (private),9.0,7.0,10023043600.0,Energy Assessor,100
684065851932011092920125068268605,"4, Hartshead Close",,,M11 1HG,5538650968,E,D,53,66,House,Mid-Terrace,2011-09-29,E08000003,E14000807,,2011-09-29,marketed sale,48,64,310,213.0,5.2,60,3.6,87.0,46.0,743.0,584.0,212.0,120.0,87.75,Single,Y,NODATA!,,,2104.0,0.0,not defined,Normal,0.0,4.0,4.0,12.0,0.0,"From main system, no cylinder thermostat",Poor,Poor,"Suspended, no insulation (assumed)",,,Single glazed,Very Poor,Very Poor,"Solid brick, as built, no insulation (assumed)",Very Poor,Very Poor,,,,"Pitched, 250 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,Programmer and room thermostat,Average,Average,Low energy lighting in 12% of fixed outlets,Poor,Poor,mains gas (not community),0.0,NO DATA!,,2.75,0.0,,natural,"4, Hartshead Close",Manchester,Manchester Central,MANCHESTER,England and Wales: 1900-1929,2011-09-29 20:12:50,owner-occupied,8.0,1.0,77188991.0,Address Matched,100
687986189502011101020174490099108,Flat 1,"14, Kirkmanshulme Lane",,M12 4WA,9531380968,D,D,61,65,Flat,End-Terrace,2011-10-10,E08000003,E14000808,,2011-10-10,rental (social),63,68,375,320.0,2.0,72,1.7,24.0,24.0,386.0,340.0,64.0,56.0,28.14,Single,Y,Ground,N,,2107.0,100.0,"double glazing, unknown install date",Normal,0.0,2.0,2.0,67.0,0.0,From main system,Good,Good,"Suspended, no insulation (assumed)",,,Fully double glazed,Average,Average,"Solid brick, as built, no insulation (assumed)",Poor,Poor,,,,(another dwelling above),,,"Boiler and radiators, mains gas",Good,Good,"Programmer, TRVs and bypass",Average,Average,Low energy lighting in 67% of fixed outlets,Good,Good,mains gas (not community),0.0,unheated corridor,11.22,3.04,0.0,,natural,"Flat 1, 14, Kirkmanshulme Lane",Manchester,"Manchester, Gorton",MANCHESTER,England and Wales: 1900-1929,2011-10-10 20:17:44,rental (social),6.0,4.0,77149969.0,Address Matched,100
1bcd628286730b71c4817db4cc56851938881db9d06a42aef6c393c93d3b1050,"9, Gatley Avenue",Fallowfield,,M14 7HE,10000715813,C,B,70,83,House,Semi-Detached,2020-10-12,E08000003,E14000808,,2021-02-24,rental,66,79,195,115.0,3.3,34,2.0,77.0,59.0,589.0,550.0,116.0,79.0,96.0,off-peak 7 hour,Y,,,,,100.0,double glazing installed during or after 2002,Normal,0.0,5.0,5.0,70.0,0.0,From main system,Good,Good,"Solid, no insulation (assumed)",,,Fully double glazed,Good,Good,"Cavity wall, filled cavity",Average,Average,,,,"Pitched, 250 mm loft insulation",Good,Good,"Boiler and radiators, mains gas",Good,Good,"Programmer, room thermostat and TRVs",Good,Good,Low energy lighting in 70% of fixed outlets,Very Good,Very Good,mains gas (not community),0.0,,,2.4,0.0,N,natural,"9, Gatley Avenue, Fallowfield",Manchester,"Manchester, Gorton",,England and Wales: 1900-1929,2021-02-24 00:00:00,Rented (social),10.0,7.0,77112462.0,Energy Assessor,100
1 LMK_KEY ADDRESS1 ADDRESS2 ADDRESS3 POSTCODE BUILDING_REFERENCE_NUMBER CURRENT_ENERGY_RATING POTENTIAL_ENERGY_RATING CURRENT_ENERGY_EFFICIENCY POTENTIAL_ENERGY_EFFICIENCY PROPERTY_TYPE BUILT_FORM INSPECTION_DATE LOCAL_AUTHORITY CONSTITUENCY COUNTY LODGEMENT_DATE TRANSACTION_TYPE ENVIRONMENT_IMPACT_CURRENT ENVIRONMENT_IMPACT_POTENTIAL ENERGY_CONSUMPTION_CURRENT ENERGY_CONSUMPTION_POTENTIAL CO2_EMISSIONS_CURRENT CO2_EMISS_CURR_PER_FLOOR_AREA CO2_EMISSIONS_POTENTIAL LIGHTING_COST_CURRENT LIGHTING_COST_POTENTIAL HEATING_COST_CURRENT HEATING_COST_POTENTIAL HOT_WATER_COST_CURRENT HOT_WATER_COST_POTENTIAL TOTAL_FLOOR_AREA ENERGY_TARIFF MAINS_GAS_FLAG FLOOR_LEVEL FLAT_TOP_STOREY FLAT_STOREY_COUNT MAIN_HEATING_CONTROLS MULTI_GLAZE_PROPORTION GLAZED_TYPE GLAZED_AREA EXTENSION_COUNT NUMBER_HABITABLE_ROOMS NUMBER_HEATED_ROOMS LOW_ENERGY_LIGHTING NUMBER_OPEN_FIREPLACES HOTWATER_DESCRIPTION HOT_WATER_ENERGY_EFF HOT_WATER_ENV_EFF FLOOR_DESCRIPTION FLOOR_ENERGY_EFF FLOOR_ENV_EFF WINDOWS_DESCRIPTION WINDOWS_ENERGY_EFF WINDOWS_ENV_EFF WALLS_DESCRIPTION WALLS_ENERGY_EFF WALLS_ENV_EFF SECONDHEAT_DESCRIPTION SHEATING_ENERGY_EFF SHEATING_ENV_EFF ROOF_DESCRIPTION ROOF_ENERGY_EFF ROOF_ENV_EFF MAINHEAT_DESCRIPTION MAINHEAT_ENERGY_EFF MAINHEAT_ENV_EFF MAINHEATCONT_DESCRIPTION MAINHEATC_ENERGY_EFF MAINHEATC_ENV_EFF LIGHTING_DESCRIPTION LIGHTING_ENERGY_EFF LIGHTING_ENV_EFF MAIN_FUEL WIND_TURBINE_COUNT HEAT_LOSS_CORRIDOR UNHEATED_CORRIDOR_LENGTH FLOOR_HEIGHT PHOTO_SUPPLY SOLAR_WATER_HEATING_FLAG MECHANICAL_VENTILATION ADDRESS LOCAL_AUTHORITY_LABEL CONSTITUENCY_LABEL POSTTOWN CONSTRUCTION_AGE_BAND LODGEMENT_DATETIME TENURE FIXED_LIGHTING_OUTLETS_COUNT LOW_ENERGY_FIXED_LIGHT_COUNT UPRN UPRN_SOURCE REPORT_TYPE
2 626337830252011050922425395090286 Flat 20 Kingsley House 15, Newton Street M1 1HE 2684056868 D D 62 66 Flat End-Terrace 2011-05-06 E08000003 E14000807 2011-05-09 rental (private) 41 44 654 608.0 3.6 116 3.3 28.0 28.0 340.0 289.0 88.0 88.0 30.72 dual N 5th Y 2402.0 100.0 double glazing installed before 2002 Normal 0.0 1.0 1.0 75.0 0.0 Electric immersion, off-peak Average Very Poor (other premises below) Fully double glazed Average Average Solid brick, as built, insulated (assumed) Good Good Room heaters, electric Flat, insulated (assumed) Average Average Electric storage heaters Average Very Poor Automatic charge control Average Average Low energy lighting in 75% of fixed outlets Very Good Very Good electricity (not community) 0.0 unheated corridor 12.89 3.29 0.0 natural Flat 20 Kingsley House, 15, Newton Street Manchester Manchester Central MANCHESTER England and Wales: 1996-2002 2011-05-09 22:42:53 rental (private) 4.0 3.0 77232195.0 Address Matched 100
3 761477339962012031418342406148782 22, Tuscan Road M20 5GS 8041346968 D C 63 69 House Semi-Detached 2012-03-14 E08000003 E14000809 2012-03-14 marketed sale 59 67 231 187.0 4.2 45 3.4 61.0 61.0 701.0 562.0 93.0 93.0 94.78 Single Y NODATA! 2106.0 43.0 double glazing, unknown install date Normal 1.0 6.0 5.0 77.0 0.0 From main system Good Good Solid, no insulation (assumed) Partial double glazing Poor Poor Cavity wall, as built, no insulation (assumed) Poor Poor Room heaters, mains gas Pitched, 200 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 77% of fixed outlets Very Good Very Good mains gas (not community) 0.0 NO DATA! 2.48 0.0 natural 22, Tuscan Road Manchester Manchester, Withington MANCHESTER England and Wales: 1930-1949 2012-03-14 18:34:24 owner-occupied 13.0 10.0 77068965.0 Address Matched 100
4 746429639842012020315284198520028 16, Balliol Street M8 0WS 2853035968 E C 48 71 House Semi-Detached 2012-02-02 E08000003 E14000571 2012-02-03 rental (private) 44 69 346 178.0 5.9 67 3.0 86.0 48.0 853.0 494.0 215.0 112.0 88.878 Single Y NODATA! 2104 not defined Much More Than Typical 1.0 5.0 5.0 22.0 0.0 From main system, no cylinder thermostat Poor Poor Suspended, no insulation (assumed) Mostly double glazing Good Good Cavity wall, as built, no insulation (assumed) Poor Poor Room heaters, mains gas Pitched, 200mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average Low energy lighting in 22% of fixed outlets Poor Poor mains gas (not community) 0.0 NO DATA! 2.554 0.0 natural 16, Balliol Street Manchester Blackley and Broughton MANCHESTER England and Wales: 1930-1949 2012-02-03 15:28:41 rental (private) 9.0 2.0 77006454.0 Address Matched 100
5 6a63605a294b7005030427aaae897ca2cfdead115cceb1e34ddf22f340aba0a1 83 THORNTON ROAD MANCHESTER M14 7NT 10000480583 D B 65 87 House Mid-Terrace 2021-01-06 E08000003 E14000807 2021-01-06 marketed sale 61 87 255 81.0 3.0 45 1.0 70.0 70.0 524.0 344.0 92.0 65.0 67.0 off-peak 7 hour Y 100.0 double glazing installed during or after 2002 Normal 2.0 4.0 4.0 78.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Good Good Solid brick, as built, no insulation (assumed) Very Poor Very Poor Pitched, no insulation Very Poor Very Poor Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 78% of fixed outlets Very Good Very Good mains gas (not community) 0.0 2.74 0.0 N natural 83 THORNTON ROAD, MANCHESTER Manchester Manchester Central MANCHESTER England and Wales: 1900-1929 2021-01-06 00:00:00 Owner-occupied 9.0 7.0 77112974.0 Energy Assessor 100
6 9a6bc31be4b07d7f189572eb38beaa1fd49fa418fcd5f5476fed91776ab8d8d3 639A STOCKPORT ROAD MANCHESTER M12 4QA 10000398504 D C 66 70 Flat Mid-Terrace 2020-10-06 E08000003 E14000808 2020-10-08 rental 62 67 248 215.0 3.0 44 2.6 72.0 72.0 521.0 449.0 81.0 81.0 68.0 off-peak 7 hour Y 01 Y 100.0 double glazing installed during or after 2002 Normal 0.0 4.0 4.0 78.0 0.0 From main system Good Good (other premises below) Fully double glazed Good Good Solid brick, as built, no insulation (assumed) Very Poor Very Poor Pitched, no insulation (assumed) Very Poor Very Poor Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 78% of fixed outlets Very Good Very Good mains gas (not community) 0.0 heated corridor 2.75 0.0 N natural 639A STOCKPORT ROAD, MANCHESTER Manchester Manchester, Gorton MANCHESTER England and Wales: 1900-1929 2020-10-08 Rented (private) 9.0 7.0 10090237291.0 Energy Assessor 100
7 96054d6c9df6eefc64f8ece8f5a889697bf31627565c68b0cdf2be201076cb4c APARTMENT 7 67 PALATINE ROAD MANCHESTER M20 3AP 10000787735 C B 74 81 Flat Detached 2020-11-23 E08000003 E14000809 2020-11-23 marketed sale 71 71 202 205.0 2.2 34 2.3 58.0 68.0 338.0 226.0 211.0 191.0 66.0 off-peak 10 hour N 02 Y 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 2.0 100.0 0.0 Electric immersion, off-peak Poor Poor (another dwelling below) Fully double glazed Good Good Timber frame, as built, insulated (assumed) Good Good Portable electric heaters (assumed) Pitched, insulated (assumed) Good Good Room heaters, electric Very Poor Poor Appliance thermostats Good Good Low energy lighting in all fixed outlets Very Good Very Good electricity (not community) 0.0 unheated corridor 8.7 1.8 0.0 N natural APARTMENT 7, 67 PALATINE ROAD, MANCHESTER Manchester Manchester, Withington MANCHESTER England and Wales: 2003-2006 2020-11-23 00:00:00 Owner-occupied 15.0 15.0 10023046299.0 Energy Assessor 100
8 b04c73c7eb6d7193ee2fbb37ef45d7a6fe013012ed4aecae02e314db95c8d814 FLAT 403 ICON 25 101 HIGH STREET M4 1HG 10000571763 C B 78 87 Flat End-Terrace 2020-09-25 E08000003 E14000807 2020-09-26 rental 80 79 132 139.0 1.6 22 1.7 66.0 74.0 172.0 88.0 346.0 187.0 72.0 off-peak 7 hour N 05 N 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 100.0 0.0 Electric immersion, standard tariff Very Poor Poor (another dwelling below) Fully double glazed Good Good System built, as built, insulated (assumed) Good Good (another dwelling above) Room heaters, electric Very Poor Poor Programmer and appliance thermostats Good Good Low energy lighting in all fixed outlets Very Good Very Good electricity (not community) 0.0 heated corridor 2.46 0.0 N natural FLAT 403, ICON 25, 101 HIGH STREET Manchester Manchester Central MANCHESTER England and Wales: 2007-2011 2020-09-26 00:00:00 Rented (private) 7.0 7.0 10014178048.0 Energy Assessor 100
9 5460819602012012418330046222678 7, Johns Close M21 9EH 3664112468 C C 78 79 Flat NO DATA! 2012-01-23 E08000003 E14000809 2012-01-24 rental (social) 83 84 130 122.0 1.2 25 1.1 53.0 31.0 221.0 224.0 68.0 68.0 48.9 Unknown Y 1st Y 2106.0 100.0 double glazing installed during or after 2002 Normal 0.0 2.0 2.0 29.0 0.0 From main system Good Good (other premises below) Fully double glazed Good Good Cavity wall, filled cavity Good Good Pitched, 200mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 29% of fixed outlets Average Average mains gas (not community) 0.0 no corridor 2.31 0.0 natural 7, Johns Close Manchester Manchester, Withington MANCHESTER England and Wales: 1983-1990 2012-01-24 18:33:00 rental (social) 7.0 2.0 77077064.0 Address Matched 100
10 666225219952011081514391692990386 5, Beckfield Road M23 2GF 3659929868 D D 63 63 House Semi-Detached 2011-08-15 E08000003 E14001059 2011-08-15 marketed sale 59 59 238 238.0 4.1 46 4.1 57.0 57.0 688.0 688.0 87.0 87.0 88.5 Single Y NODATA! 2106.0 100.0 double glazing installed during or after 2002 Normal 1.0 4.0 4.0 78.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Good Good System built, as built, no insulation (assumed) Very Poor Very Poor Room heaters, mains gas Pitched, 200 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 78% of fixed outlets Very Good Very Good mains gas (not community) 0.0 NO DATA! 2.0 0.0 natural 5, Beckfield Road Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1930-1949 2011-08-15 14:39:16 owner-occupied 9.0 7.0 77052370.0 Address Matched 100
11 740955219712012011913012398920095 18b, Greton Close M13 0YR 589984968 C B 79 82 Flat NO DATA! 2012-01-18 E08000003 E14000808 2012-01-19 marketed sale 69 71 255 238.0 2.2 45 2.0 64.0 32.0 160.0 149.0 107.0 107.0 47.97 dual N 1st N 2401.0 100.0 double glazing installed before 2002 Normal 0.0 3.0 3.0 0.0 0.0 Electric immersion, off-peak Average Very Poor (other premises below) Fully double glazed Average Average Cavity wall, as built, insulated (assumed) Good Good Portable electric heaters (assumed) (another dwelling above) Electric storage heaters Average Very Poor Manual charge control Poor Poor No low energy lighting Very Poor Very Poor electricity (not community) 0.0 unheated corridor 4.5 2.343 0.0 natural 18b, Greton Close Manchester Manchester, Gorton MANCHESTER England and Wales: 1991-1995 2012-01-19 13:01:23 owner-occupied 7.0 0.0 77151965.0 Address Matched 100
12 f32f46284a1afe1e99156dca4c97c64ee8f466cd646eaac907514c96095f9382 FLAT 315 THE BOX WORKS 4 WORSLEY STREET M15 4NU 10000804989 C B 79 81 Flat Mid-Terrace 2020-10-31 E08000003 E14000807 2020-10-31 marketed sale 68 71 244 224.0 2.1 41 1.9 66.0 66.0 226.0 178.0 169.0 169.0 51.0 off-peak 10 hour N 02 N 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 78.0 0.0 Electric immersion, off-peak Average Poor (another dwelling below) Fully double glazed Good Good System built, as built, insulated (assumed) Good Good Portable electric heaters (assumed) (another dwelling above) Electric storage heaters Average Very Poor Manual charge control Poor Poor Low energy lighting in 78% of fixed outlets Very Good Very Good electricity (not community) 0.0 unheated corridor 8.51 3.1 0.0 N natural FLAT 315, THE BOX WORKS, 4 WORSLEY STREET Manchester Manchester Central MANCHESTER England and Wales: 2003-2006 2020-10-31 00:00:00 Owner-occupied 9.0 7.0 10003799820.0 Energy Assessor 100
13 413809754212011120117031199099872 Flat 4 5, Derby Road M14 6UN 8296490768 D D 56 65 Flat End-Terrace 2011-12-01 E08000003 E14000809 2011-12-01 rental (private) 55 67 379 284.0 2.8 73 2.1 27.0 27.0 503.0 393.0 73.0 61.0 37.97 Unknown Y 1st N 2102.0 10.0 double glazing installed before 2002 Normal 0.0 2.0 2.0 80.0 0.0 From main system Good Good (other premises below) Some double glazing Very Poor Very Poor Solid brick, as built, no insulation (assumed) Very Poor Very Poor (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, no room thermostat Very Poor Very Poor Low energy lighting in 80% of fixed outlets Very Good Very Good mains gas (not community) 0.0 unheated corridor 10.08 2.52 0.0 natural Flat 4, 5, Derby Road Manchester Manchester, Withington MANCHESTER England and Wales: 1900-1929 2011-12-01 17:03:11 rental (private) 5.0 4.0 77203368.0 Address Matched 100
14 f725eb075fb7f9e87af04780806b6a4ae5c8ae44d006df38e24b01266be2b2cf 72 BLUESTONE ROAD MANCHESTER M40 9HY 10000725404 E C 46 69 House Semi-Detached 2020-12-18 E08000003 E14000807 2020-12-21 marketed sale 40 61 435 257.0 5.3 77 3.2 57.0 57.0 954.0 748.0 90.0 65.0 69.0 off-peak 7 hour Y 90.0 double glazing, unknown install date Normal 0.0 4.0 4.0 100.0 1.0 From main system Good Good Suspended, no insulation (assumed) Mostly double glazing Average Average Cavity wall, as built, no insulation (assumed) Poor Poor Room heaters, mains gas Pitched, no insulation (assumed) Very Poor Very Poor Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average Low energy lighting in all fixed outlets Very Good Very Good mains gas (not community) 0.0 2.5 0.0 N natural 72 BLUESTONE ROAD, MANCHESTER Manchester Manchester Central MANCHESTER England and Wales: 1930-1949 2020-12-21 00:00:00 Owner-occupied 8.0 8.0 77031060.0 Energy Assessor 100
15 684540547352011093012023195790691 Apartment 5 Park Brow 128, St. Werburghs Road M21 8UQ 6184750968 C B 80 82 Flat NO DATA! 2011-09-30 E08000003 E14000809 2011-09-30 rental (private) 70 72 211 200.0 2.5 37 2.4 60.0 44.0 190.0 171.0 115.0 115.0 67.04 Unknown N 1st N 2401.0 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 64.0 0.0 Electric immersion, off-peak Average Very Poor (other premises below) Fully double glazed Good Good System built, as built, insulated (assumed) Good Good Portable electric heaters (assumed) (another dwelling above) Electric storage heaters Average Very Poor Manual charge control Poor Poor Low energy lighting in 64% of fixed outlets Good Good electricity (not community) 0.0 unheated corridor 10.25 2.35 0.0 natural Apartment 5 Park Brow, 128, St. Werburghs Road Manchester Manchester, Withington MANCHESTER England and Wales: 2003-2006 2011-09-30 12:02:31 rental (private) 11.0 7.0 10012206708.0 Address Matched 100
16 746479909062012020316372915378642 Flat 11 Lorna Lodge 233 Brownley Road M22 9XA 4179035968 B B 86 88 Flat End-Terrace 2012-02-03 E08000003 E14001059 2012-02-03 rental (social) 82 82 153 159.0 1.1 27 1.2 38.0 30.0 57.0 53.0 120.0 94.0 42.1 dual N 1st N 2603.0 100.0 double glazing installed during or after 2002 Normal 0.0 2.0 2.0 57.0 0.0 Electric immersion, off-peak Poor Very Poor (other premises below) Fully double glazed Good Good Cavity wall, as built, insulated (assumed) Good Good Room heaters, electric (another dwelling above) Room heaters, electric Poor Very Poor Programmer and appliance thermostats Good Good Low energy lighting in 57% of fixed outlets Good Good electricity (not community) 0.0 heated corridor 2.34 0.0 natural Flat 11, Lorna Lodge, 233 Brownley Road Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 2003-2006 2012-02-03 16:37:29 rental (social) 7.0 4.0 10070865592.0 Address Matched 100
17 0815d544b81eccdfbcd570b8db517bb27d9e36bf9337dff91d83f365f8405f5b FLAT 36 PARKFIELD COURT 38-40 BARLOW MOOR ROAD M20 2GE 10000754172 D C 65 80 Flat Enclosed End-Terrace 2021-01-06 E08000003 E14000809 2021-01-26 rental 39 65 645 329.0 3.9 109 2.0 67.0 37.0 73.0 170.0 568.0 174.0 36.0 standard tariff N 01 N 100.0 double glazing, unknown install date Normal 0.0 2.0 2.0 20.0 0.0 Electric immersion, off-peak Poor Poor (another dwelling below) Fully double glazed Average Average Cavity wall, filled cavity Good Good Portable electric heaters (assumed) (another dwelling above) Electric storage heaters Average Poor Controls for high heat retention storage heaters Good Good Low energy lighting in 20% of fixed outlets Poor Poor electricity (not community) 0.0 heated corridor 2.4 0.0 N natural FLAT 36, PARKFIELD COURT, 38-40 BARLOW MOOR ROAD Manchester Manchester, Withington MANCHESTER England and Wales: 1991-1995 2021-01-26 00:00:00 Rented (social) 5.0 1.0 77191954.0 Energy Assessor 100
18 762935166212012031922534895920198 7, May Drive M19 1FY 1893656968 C C 71 72 Flat End-Terrace 2012-03-19 E08000003 E14000809 2012-03-19 rental (social) 73 74 182 176.0 2.2 35 2.1 58.0 37.0 374.0 377.0 75.0 75.0 62.17 Single Y Ground N 2106.0 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 43.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Good Good Room heaters, mains gas (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 43% of fixed outlets Average Average mains gas (not community) 0.0 unheated corridor 4.93 2.43 0.0 natural 7, May Drive Manchester Manchester, Withington MANCHESTER England and Wales: 1900-1929 2012-03-19 22:53:48 rental (social) 7.0 3.0 77144094.0 Address Matched 100
19 300000899702011081910022367299458 8, Telfer Road M13 0XS 4762992668 D C 60 72 House Semi-Detached 2011-08-15 E08000003 E14000808 2011-08-19 rental (private) 56 71 253 165.0 4.5 49 2.9 76.0 48.0 702.0 470.0 140.0 120.0 93.0 Single Y NODATA! 2104.0 90.0 double glazing installed during or after 2002 Normal 1.0 6.0 6.0 42.0 0.0 From main system Good Good Suspended, no insulation (assumed) Mostly double glazing Good Good Cavity wall, as built, no insulation (assumed) Poor Poor Pitched, 250 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average Low energy lighting in 42% of fixed outlets Average Average mains gas (not community) 0.0 NO DATA! 2.65 0.0 natural 8, Telfer Road Manchester Manchester, Gorton MANCHESTER England and Wales: 1930-1949 2011-08-19 10:02:23 rental (private) 12.0 5.0 77149101.0 Address Matched 100
20 a2d4f21dfc53c9e8bd48a08848547cabc9481a29411bd48299ea93881849913d 6 RODA STREET MANCHESTER M9 4PJ 10000671391 F B 34 84 House Mid-Terrace 2020-09-23 E08000003 E14000571 2020-10-13 ECO assessment 42 82 402 114.0 5.6 69 1.7 66.0 66.0 1711.0 459.0 94.0 69.0 82.0 off-peak 7 hour Y 100.0 double glazing, unknown install date Normal 0.0 3.0 3.0 100.0 0.0 Gas multipoint Average Average Suspended, no insulation (assumed) Fully double glazed Average Average Solid brick, as built, no insulation (assumed) Very Poor Very Poor Room heaters, mains gas Pitched, 300 mm loft insulation Very Good Very Good Room heaters, electric Very Poor Poor Programmer and appliance thermostats Good Good Low energy lighting in all fixed outlets Very Good Very Good electricity (not community) 0.0 2.7 0.0 N natural 6 RODA STREET, MANCHESTER Manchester Blackley and Broughton MANCHESTER England and Wales: 1930-1949 2020-10-13 Owner-occupied 10.0 10.0 77023763.0 Energy Assessor 100
21 638222011112011060614072193090483 26, Deneford Road M20 2TD 4328137868 D D 64 67 House Semi-Detached 2011-06-03 E08000003 E14000809 2011-06-06 rental (private) 63 66 215 198.0 3.8 41 3.5 47.0 47.0 603.0 570.0 156.0 135.0 93.8 Single Y NODATA! 2106.0 100.0 double glazing, unknown install date Normal 1.0 5.0 5.0 100.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Average Average Cavity wall, filled cavity Good Good Room heaters, electric Pitched, 250 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in all fixed outlets Very Good Very Good mains gas (not community) 0.0 NO DATA! 2.47 0.0 natural 26, Deneford Road Manchester Manchester, Withington MANCHESTER England and Wales: 1930-1949 2011-06-06 14:07:21 rental (private) 9.0 9.0 77102590.0 Address Matched 100
22 6d70419837e0b18a96a6801877496ef689c0656cac553803fb1e307b14c237c6 FLAT 2 7 BUCKHURST ROAD MANCHESTER M19 2DS 10000498503 E C 53 80 Flat End-Terrace 2021-02-24 E08000003 E14000808 2021-03-10 ECO assessment 57 66 570 452.0 2.0 96 1.6 23.0 25.0 398.0 135.0 296.0 138.0 20.0 off-peak 7 hour N 00 N 50.0 double glazing installed during or after 2002 Normal 0.0 2.0 2.0 100.0 0.0 Electric immersion, standard tariff Very Poor Poor Suspended, no insulation (assumed) Partial double glazing Poor Poor Solid brick, with internal insulation Good Good (another dwelling above) Room heaters, electric Very Poor Poor Appliance thermostats Good Good Low energy lighting in all fixed outlets Very Good Very Good electricity (not community) 0.0 heated corridor 2.8 0.0 N natural FLAT 2, 7 BUCKHURST ROAD, MANCHESTER Manchester Manchester, Gorton MANCHESTER England and Wales: 1900-1929 2021-03-10 00:00:00 Owner-occupied 6.0 6.0 77207522.0 Energy Assessor 100
23 741952999402012012213435894422098 Flat 3 57, Albany Road M21 0BH 3463994968 D D 60 63 Flat NO DATA! 2012-01-21 E08000003 E14000809 2012-01-22 rental (private) 59 63 318 290.0 2.7 61 2.5 54.0 27.0 480.0 459.0 65.0 65.0 44.459 Unknown Y 2nd Y 2107.0 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 0.0 0.0 From main system Good Good (other premises below) Fully double glazed Good Good Solid brick, as built, no insulation (assumed) Very Poor Very Poor Pitched, no insulation (assumed) Very Poor Very Poor Boiler and radiators, mains gas Good Good Programmer, TRVs and bypass Average Average No low energy lighting Very Poor Very Poor mains gas (not community) 0.0 no corridor 2.2 0.0 natural Flat 3, 57, Albany Road Manchester Manchester, Withington MANCHESTER England and Wales: 1900-1929 2012-01-22 13:43:58 rental (private) 6.0 0.0 77213865.0 Address Matched 100
24 4966252352011052014323391990443 24, Cranswick Street M14 7JA 4372212468 C C 72 75 House Mid-Terrace 2011-05-18 E08000003 E14000807 2011-05-20 rental (social) 74 77 181 159.0 2.1 35 1.8 33.0 33.0 367.0 325.0 72.0 72.0 59.3 Single Y NODATA! 2106.0 100.0 double glazing, unknown install date Normal 0.0 4.0 4.0 100.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Average Average Cavity wall, as built, no insulation (assumed) Poor Poor Room heaters, mains gas Pitched, 200mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in all fixed outlets Very Good Very Good mains gas (not community) 0.0 NO DATA! 2.76 0.0 natural 24, Cranswick Street Manchester Manchester Central MANCHESTER England and Wales: 1900-1929 2011-05-20 14:32:33 rental (social) 5.0 5.0 77117462.0 Address Matched 100
25 645301489802011062220261286792028 21, Ward Street Moston M40 9WS 3838387868 F E 37 44 House Mid-Terrace 2011-06-22 E08000003 E14000571 2011-06-22 rental (private) 34 40 472 410.0 6.4 91 5.6 76.0 38.0 1068.0 956.0 63.0 63.0 70.66 Single Y NODATA! 2601.0 0.0 not defined Normal 1.0 3.0 2.0 0.0 0.0 Gas multipoint Average Average Suspended, no insulation (assumed) Single glazed Very Poor Very Poor Cavity wall, as built, no insulation (assumed) Poor Poor Room heaters, mains gas Pitched, no insulation (assumed) Very Poor Very Poor Room heaters, mains gas Average Average No thermostatic control of room temperature Poor Poor No low energy lighting Very Poor Very Poor mains gas (not community) 0.0 NO DATA! 2.75 0.0 natural 21, Ward Street, Moston Manchester Blackley and Broughton MANCHESTER England and Wales: 1900-1929 2011-06-22 20:26:12 rental (private) 7.0 0.0 100012709992.0 Address Matched 100
26 683986659902011092918252999092218 15, Shaldon Drive M40 1GS 3946650968 E D 48 67 House Semi-Detached 2011-09-29 E08000003 E14000807 2011-09-29 marketed sale 47 68 352 203.0 4.7 67 2.7 75.0 39.0 836.0 505.0 92.0 81.0 71.0 Single Y NODATA! 2102 30.0 double glazing installed during or after 2002 Normal 0.0 4.0 4.0 9.0 0.0 From main system Good Good Suspended, no insulation (assumed) Some double glazing Poor Poor Cavity wall, as built, no insulation (assumed) Poor Poor Room heaters, electric Pitched, 75 mm loft insulation Average Average Boiler and radiators, mains gas Good Good Programmer, no room thermostat Very Poor Very Poor Low energy lighting in 9% of fixed outlets Very Poor Very Poor mains gas (not community) 0.0 NO DATA! 2.4 0.0 natural 15, Shaldon Drive Manchester Manchester Central MANCHESTER England and Wales: 1950-1966 2011-09-29 18:25:29 owner-occupied 22.0 2.0 77188811.0 Address Matched 100
27 7a4cfa9242f66e157df0d3f37c0545bfeac115c45f23ab0ffa081fd39c62a015 14 SIMISTER STREET MANCHESTER M9 4JL 10000070988 D C 61 79 House Mid-Terrace 2020-12-17 E08000003 E14000571 2021-01-06 rental 55 74 289 164.0 4.2 51 2.4 99.0 66.0 735.0 611.0 86.0 59.0 82.0 off-peak 7 hour Y 100.0 double glazing, unknown install date Normal 4.0 4.0 4.0 50.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Average Average Solid brick, as built, no insulation (assumed) Very Poor Very Poor Pitched, no insulation (assumed) Very Poor Very Poor Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 50% of fixed outlets Good Good mains gas (not community) 0.0 2.74 0.0 N natural 14 SIMISTER STREET, MANCHESTER Manchester Blackley and Broughton MANCHESTER England and Wales: 1900-1929 2021-01-06 00:00:00 Rented (private) 10.0 5.0 77022202.0 Energy Assessor 100
28 728844679402011113014364798397808 158, Heald Place M14 5WJ 5494373968 D C 65 72 House Mid-Terrace 2011-11-30 E08000003 E14000808 2011-11-30 rental (private) 63 72 226 172.0 3.4 43 2.6 70.0 43.0 571.0 451.0 83.0 83.0 78.4 Single Y NODATA! 2107.0 100.0 double glazing installed before 2002 Normal 1.0 4.0 4.0 36.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Average Average Cavity wall, as built, no insulation (assumed) Poor Poor Pitched, 100mm loft insulation Average Average Boiler and radiators, mains gas Good Good Programmer, TRVs and bypass Average Average Low energy lighting in 36% of fixed outlets Average Average mains gas (not community) 0.0 NO DATA! 2.41 0.0 natural 158, Heald Place Manchester Manchester, Gorton MANCHESTER England and Wales: 1900-1929 2011-11-30 14:36:47 rental (private) 11.0 4.0 77111254.0 Address Matched 100
29 231717462932011120115213414068198 26, Thornton Road M14 7WT 6874177568 D C 57 70 House Mid-Terrace 2011-12-01 E08000003 E14000807 2011-12-01 rental (social) 54 71 306 195.0 3.6 59 2.3 39.0 39.0 625.0 412.0 92.0 76.0 61.91 Single Y NODATA! 2104.0 100.0 double glazing installed during or after 2002 Normal 0.0 4.0 4.0 88.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Good Good Solid brick, as built, no insulation (assumed) Very Poor Very Poor Pitched, no insulation Very Poor Very Poor Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average Low energy lighting in 88% of fixed outlets Very Good Very Good mains gas (not community) 0.0 NO DATA! 2.61 0.0 natural 26, Thornton Road Manchester Manchester Central MANCHESTER England and Wales: before 1900 2011-12-01 15:21:34 rental (social) 8.0 7.0 77113730.0 Address Matched 100
30 762271159312012031619163994920298 108, Meltham Avenue M20 1EE 2865946968 C C 75 78 Flat NO DATA! 2012-03-16 E08000003 E14000809 2012-03-16 marketed sale 77 80 152 131.0 1.9 29 1.6 38.0 38.0 326.0 288.0 86.0 77.0 63.7 Single Y 1st Y 2107.0 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 100.0 0.0 From main system Good Good (other premises below) Fully double glazed Good Good Solid brick, with external insulation Good Good Pitched, 300+ mm loft insulation Very Good Very Good Boiler and radiators, mains gas Good Good Programmer, TRVs and bypass Average Average Low energy lighting in all fixed outlets Very Good Very Good mains gas (not community) 0.0 no corridor 2.5 0.0 natural 108, Meltham Avenue Manchester Manchester, Withington MANCHESTER England and Wales: 1950-1966 2012-03-16 19:16:39 owner-occupied 9.0 9.0 77105708.0 Address Matched 100
31 400678909602011082617381773092868 20, Dundreggan Gardens M20 2EH 3642100768 C C 71 72 House Mid-Terrace 2011-08-26 E08000003 E14000809 2011-08-26 marketed sale 71 72 150 144.0 4.3 28 4.1 117.0 70.0 741.0 747.0 105.0 105.0 103.8 dual Y NODATA! 2106.0 100.0 double glazing installed during or after 2002 More Than Typical 1.0 6.0 6.0 34.0 0.0 From main system Good Good Solid, insulated (assumed) Fully double glazed Good Good Timber frame, as built, insulated (assumed) Good Good Roof room(s), insulated (assumed) Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 34% of fixed outlets Average Average mains gas (not community) 0.0 NO DATA! 2.55 0.0 mechanical, supply and extract 20, Dundreggan Gardens Manchester Manchester, Withington MANCHESTER England and Wales: 2007 onwards 2011-08-26 17:38:17 owner-occupied 38.0 13.0 10070865623.0 Address Matched 100
32 634706509542011052610203283792568 Apartment 55 Britannia Mills 11, Hulme Hall Road M15 4LA 6581507868 C C 80 80 Flat Mid-Terrace 2011-05-26 E08000003 E14000807 2011-05-26 none of the above 67 67 220 220.0 3.1 39 3.1 49.0 49.0 223.0 223.0 110.0 110.0 78.5 dual N 1st N 2401.0 100.0 double glazing, unknown install date Normal 1.0 1.0 1.0 100.0 0.0 Electric immersion, off-peak Average Very Poor (other premises below) Fully double glazed Average Average Solid brick, as built, insulated (assumed) Good Good Room heaters, electric (another dwelling above) Electric storage heaters Average Very Poor Manual charge control Poor Poor Low energy lighting in all fixed outlets Very Good Very Good electricity (not community) 0.0 unheated corridor 6.95 2.28 0.0 natural Apartment 55 Britannia Mills, 11, Hulme Hall Road Manchester Manchester Central MANCHESTER England and Wales: 1996-2002 2011-05-26 10:20:32 unknown 5.0 5.0 77233931.0 Address Matched 100
33 bc53c658a67a4490c2c8cd2291b2396d7235e8c938f724f9aafc36f97cffd6bd 7, Gleneagles Avenue Clayton M11 4JU 10000415844 D B 68 82 House Semi-Detached 2020-11-03 E08000003 E14000807 2021-02-24 rental 67 81 212 117.0 2.8 37 1.6 55.0 55.0 553.0 509.0 109.0 73.0 76.0 off-peak 7 hour Y 100.0 double glazing installed during or after 2002 Normal 0.0 4.0 4.0 89.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Average Average Room heaters, electric Pitched, 200 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 89% of fixed outlets Very Good Very Good mains gas (not community) 0.0 2.4 0.0 N natural 7, Gleneagles Avenue, Clayton Manchester Manchester Central England and Wales: 1930-1949 2021-02-24 00:00:00 Rented (social) 9.0 8.0 77179548.0 Energy Assessor 100
34 e8227d212d926258058f8cac2e6e1e18cbd55451d7980fda1f5e7a0b10464f4d 76, Langport Avenue Ardwick M12 4NG 10000463748 C C 74 76 Flat Mid-Terrace 2020-09-28 E08000003 E14000807 2021-02-24 rental 77 80 184 165.0 1.5 32 1.3 47.0 32.0 294.0 274.0 86.0 87.0 46.0 off-peak 7 hour Y 00 Y 100.0 double glazing installed during or after 2002 Normal 0.0 2.0 2.0 50.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Average Average Room heaters, electric (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 50% of fixed outlets Good Good mains gas (not community) 0.0 unheated corridor 3.5 2.4 0.0 N natural 76, Langport Avenue, Ardwick Manchester Manchester Central England and Wales: 1967-1975 2021-02-24 00:00:00 Rented (social) 6.0 3.0 77153103.0 Energy Assessor 100
35 b3b0e1c10d9bf0479069ed65b9b3b657471a67652be33b8f7c21c6a905535c62 35 SANDILANDS ROAD MANCHESTER M23 9JN 10000235547 C B 69 81 House Semi-Detached 2021-01-12 E08000003 E14001059 2021-01-12 marketed sale 64 78 207 127.0 3.5 37 2.2 84.0 84.0 574.0 536.0 127.0 82.0 97.0 off-peak 7 hour Y 100.0 double glazing installed before 2002 Normal 1.0 5.0 5.0 89.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Average Average Cavity wall, filled cavity Average Average Pitched, 200 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 89% of fixed outlets Very Good Very Good mains gas (not community) 0.0 2.6 0.0 N natural 35 SANDILANDS ROAD, MANCHESTER Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1950-1966 2021-01-12 00:00:00 Owner-occupied 18.0 16.0 77042816.0 Energy Assessor 100
36 679334129922011091911524490718129 7, Whalley Avenue Whalley Range M16 8AT 2954220968 F E 33 45 House Mid-Terrace 2011-09-19 E08000003 E14000808 2011-09-19 marketed sale 32 42 466 368.0 7.5 89 5.9 80.0 45.0 1338.0 1080.0 65.0 65.0 84.1 Single Y NODATA! 2601.0 0.0 not defined Normal 1.0 4.0 2.0 20.0 0.0 Gas instantaneous at point of use Good Good Suspended, no insulation (assumed) Single glazed Very Poor Very Poor Solid brick, as built, no insulation (assumed) Very Poor Very Poor Room heaters, electric Pitched, no insulation Very Poor Very Poor Room heaters, mains gas Average Average No thermostatic control of room temperature Poor Poor Low energy lighting in 20% of fixed outlets Poor Poor mains gas (not community) 0.0 NO DATA! 2.73 0.0 natural 7, Whalley Avenue, Whalley Range Manchester Manchester, Gorton MANCHESTER England and Wales: 1900-1929 2011-09-19 11:52:44 owner-occupied 10.0 2.0 10014179643.0 Address Matched 100
37 488886519262012022219093606838569 103, Wendover Road M23 9ER 6060126768 C C 72 74 House Enclosed End-Terrace 2011-07-27 E08000003 E14001059 2012-02-22 rental (social) 71 74 171 156.0 2.8 33 2.5 51.0 51.0 464.0 423.0 90.0 91.0 84.0 Single Y NODATA! 2106.0 100.0 double glazing installed during or after 2002 Normal 0.0 5.0 5.0 90.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Good Good Pitched, 50 mm loft insulation Poor Poor Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 90% of fixed outlets Very Good Very Good mains gas (not community) 0.0 NO DATA! 2.4 0.0 natural 103, Wendover Road Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1950-1966 2012-02-22 19:09:36 rental (social) 10.0 9.0 77042522.0 Address Matched 100
38 718995131812011110709323290099494 211, Chapman Street M18 8WP 4499103968 D D 61 67 House Semi-Detached 2011-11-04 E08000003 E14000808 2011-11-07 marketed sale 58 66 253 209.0 3.9 49 3.2 82.0 43.0 626.0 549.0 97.0 85.0 79.19 Single Y NODATA! 2107.0 100.0 double glazing installed during or after 2002 Normal 1.0 5.0 5.0 9.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Good Good Room heaters, mains gas Pitched, 100 mm loft insulation Average Average Boiler and radiators, mains gas Good Good Programmer, TRVs and bypass Average Average Low energy lighting in 9% of fixed outlets Very Poor Very Poor mains gas (not community) 0.0 NO DATA! 2.44 0.0 natural 211, Chapman Street Manchester Manchester, Gorton MANCHESTER England and Wales: 1930-1949 2011-11-07 09:32:32 owner-occupied 11.0 1.0 77176530.0 Address Matched 100
39 cea6cab056864f6114c6509288f6f76f6021a9efcc12cdd74660ebaac24d8a35 8, Moss Lane Moss Side M16 7BZ 10000747245 C B 73 86 House End-Terrace 2020-10-05 E08000003 E14000807 2021-02-24 rental 71 85 178 87.0 2.5 31 1.3 57.0 57.0 451.0 412.0 110.0 74.0 80.0 off-peak 7 hour Y 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 89.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Good Good Pitched, 270 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 89% of fixed outlets Very Good Very Good mains gas (not community) 0.0 2.4 0.0 N natural 8, Moss Lane, Moss Side Manchester Manchester Central England and Wales: 1976-1982 2021-02-24 00:00:00 Rented (social) 9.0 8.0 77097127.0 Energy Assessor 100
40 67687538aed41115bdc797d35afd7ec6397562062f01c7072b32b9a28e5bb959 7, Rusholme Grove Rusholme M14 5AR 10000415848 C C 78 79 Flat Mid-Terrace 2020-10-15 E08000003 E14000808 2021-02-24 rental 81 83 149 132.0 1.3 26 1.1 35.0 35.0 250.0 221.0 89.0 89.0 48.0 off-peak 7 hour Y 01 Y 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 100.0 0.0 From main system Good Good (another dwelling below) Fully double glazed Good Good Cavity wall, filled cavity Good Good Pitched, 100 mm loft insulation Average Average Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in all fixed outlets Very Good Very Good mains gas (not community) 0.0 unheated corridor 5.3 2.4 0.0 N natural 7, Rusholme Grove, Rusholme Manchester Manchester, Gorton England and Wales: 1976-1982 2021-02-24 00:00:00 Rented (social) 5.0 5.0 77133633.0 Energy Assessor 100
41 574337239602011092517501083292258 Flat 13 The Sorting House 83, Newton Street M1 1EP 3600832868 D C 64 73 Flat Mid-Terrace 2011-09-25 E08000003 E14000807 2011-09-25 marketed sale 55 53 279 294.0 4.6 49 4.8 69.0 57.0 619.0 433.0 146.0 135.0 92.23 Unknown N 2nd N 2602.0 100.0 double glazing installed before 2002 Normal 1.0 3.0 3.0 64.0 0.0 Electric immersion, off-peak Average Very Poor (other premises below) Fully double glazed Average Average System built, as built, insulated (assumed) Good Good (another dwelling above) Room heaters, electric Poor Very Poor Appliance thermostats Good Good Low energy lighting in 64% of fixed outlets Good Good electricity (not community) 0.0 no corridor 2.19 0.0 natural Flat 13 The Sorting House, 83, Newton Street Manchester Manchester Central MANCHESTER England and Wales: 1996-2002 2011-09-25 17:50:10 owner-occupied 14.0 9.0 10070397882.0 Address Matched 100
42 629887539922011051622513676168289 Apartment 712 51, Whitworth Street West M1 5ED 8722376868 B B 82 83 Flat Mid-Terrace 2011-05-16 E08000003 E14000807 2011-05-16 marketed sale 73 74 230 222.0 1.8 41 1.8 60.0 30.0 106.0 113.0 89.0 89.0 44.65 Unknown N 7th N 2401.0 100.0 double glazing installed before 2002 Normal 0.0 2.0 2.0 0.0 0.0 Electric immersion, off-peak Average Very Poor (other premises below) Fully double glazed Average Average Cavity wall, as built, insulated (assumed) Good Good Room heaters, electric (another dwelling above) Electric storage heaters Average Very Poor Manual charge control Poor Poor No low energy lighting Very Poor Very Poor electricity (not community) 0.0 unheated corridor 6.28 2.25 0.0 natural Apartment 712, 51, Whitworth Street West Manchester Manchester Central MANCHESTER England and Wales: 1996-2002 2011-05-16 22:51:36 owner-occupied 9.0 0.0 10003799427.0 Address Matched 100
43 06359dd75cc0e575c7df1daa0107c832dd45b21835d0fa1a2f98f111975276de 16 WINDSOR ROAD HARPURHEY MANCHESTER M9 5BW 10000281555 C C 73 74 Flat End-Terrace 2020-11-09 E08000003 E14000571 2020-11-12 rental 75 76 228 215.0 1.5 40 1.4 34.0 34.0 296.0 280.0 70.0 70.0 38.0 off-peak 7 hour Y 01 Y 100.0 double glazing installed during or after 2002 Normal 1.0 2.0 2.0 100.0 0.0 From main system Good Good (another dwelling below) Fully double glazed Good Good Cavity wall, filled cavity Average Average Pitched, 100 mm loft insulation Average Average Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average Low energy lighting in all fixed outlets Very Good Very Good mains gas (not community) 0.0 no corridor 2.72 0.0 N natural 16 WINDSOR ROAD, HARPURHEY, MANCHESTER Manchester Blackley and Broughton MANCHESTER England and Wales: 1930-1949 2020-11-12 Rented (private) 5.0 5.0 77024420.0 Energy Assessor 100
44 cac28d15e638f84cb7574006e960cd56611f2d665fd02b6e1bad5ddd9e731594 84 THE BOULEVARD MANCHESTER M20 2EU 10000707350 C B 80 86 Flat Enclosed Mid-Terrace 2020-10-21 E08000003 E14000809 2020-10-21 marketed sale 77 79 165 149.0 1.7 28 1.5 72.0 63.0 168.0 115.0 203.0 154.0 60.0 off-peak 10 hour N 01 N 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 67.0 0.0 Electric immersion, off-peak Poor Poor (another dwelling below) Fully double glazed Good Good System built, as built, insulated (assumed) Good Good (another dwelling above) Room heaters, electric Very Poor Poor Appliance thermostats Good Good Low energy lighting in 67% of fixed outlets Good Good electricity (not community) 0.0 unheated corridor 9.1 2.39 0.0 N natural 84 THE BOULEVARD, MANCHESTER Manchester Manchester, Withington MANCHESTER England and Wales: 2003-2006 2020-10-21 00:00:00 Owner-occupied 6.0 4.0 10070393810.0 Energy Assessor 100
45 f7f8dba5d96af5ec97b273b968a467f45b1b3ed07199684b69fd51796d195c96 FLAT 1 9 ZETLAND ROAD MANCHESTER M21 8TJ 10000483124 D C 61 73 Flat Semi-Detached 2021-02-11 E08000003 E14000809 2021-02-12 rental 57 74 301 184.0 3.1 53 1.9 102.0 51.0 536.0 340.0 85.0 85.0 58.0 off-peak 7 hour Y 00 N 100.0 double glazing, unknown install date Normal 2.0 3.0 3.0 0.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Average Average Solid brick, as built, no insulation (assumed) Very Poor Very Poor (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, TRVs and bypass Average Average No low energy lighting Very Poor Very Poor mains gas (not community) 0.0 unheated corridor 6.49 2.68 0.0 N natural FLAT 1, 9 ZETLAND ROAD, MANCHESTER Manchester Manchester, Withington MANCHESTER England and Wales: 1900-1929 2021-02-12 00:00:00 Rented (private) 10.0 0.0 77214240.0 Energy Assessor 100
46 6c386fbd02fb8b3be61fb7b00c1aac6a7e533e7cb6eaf73b3a15a20486118ebc 59, Worsley Court Wilmslow Road Rusholme M14 5LU 10000666249 C C 79 80 Flat Mid-Terrace 2020-11-03 E08000003 E14000808 2021-02-24 rental 83 84 141 129.0 1.1 25 1.0 30.0 30.0 190.0 172.0 105.0 105.0 43.0 off-peak 7 hour Y 06 Y 100.0 double glazing installed during or after 2002 Normal 0.0 2.0 2.0 100.0 0.0 Community scheme Good Good (another dwelling below) Fully double glazed Good Good Cavity wall, with external insulation Very Good Very Good Room heaters, electric (another dwelling above) Community scheme Good Good Charging system linked to use of community heating, programmer and room thermostat Average Average Low energy lighting in all fixed outlets Very Good Very Good mains gas (community) 0.0 no corridor 0.0 2.4 0.0 N natural 59, Worsley Court Wilmslow Road, Rusholme Manchester Manchester, Gorton England and Wales: 1967-1975 2021-02-24 00:00:00 Rented (social) 6.0 6.0 10003800130.0 Energy Assessor 100
47 647860479262011062811072297938579 Flat 8 Rose Lea 1, Downham Walk M23 9DG 7984797868 C C 75 76 Flat NO DATA! 2011-06-27 E08000003 E14001059 2011-06-28 rental (social) 79 80 193 183.0 1.3 37 1.2 38.0 21.0 200.0 202.0 88.0 88.0 34.08 Single N Ground N 2303.0 100.0 double glazing installed before 2002 Normal 0.0 2.0 2.0 17.0 0.0 Community scheme Good Good Solid, no insulation (assumed) Fully double glazed Average Average Cavity wall, as built, insulated (assumed) Good Good (another dwelling above) Community scheme Good Good Flat rate charging, room thermostat only Poor Poor Low energy lighting in 17% of fixed outlets Poor Poor mains gas (community) 0.0 heated corridor 2.6 0.0 natural Flat 8 Rose Lea, 1, Downham Walk Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1991-1995 2011-06-28 11:07:22 rental (social) 6.0 1.0 77047324.0 Address Matched 100
48 687906589742011101021150296099308 Flat 1 18, Kirkmanshulme Lane M12 4WA 7752380968 D D 61 66 Flat End-Terrace 2011-10-10 E08000003 E14000808 2011-10-10 rental (social) 63 69 376 316.0 2.0 72 1.7 26.0 18.0 385.0 341.0 64.0 56.0 28.14 Single Y Ground N 2107.0 100.0 double glazing, unknown install date Normal 0.0 2.0 2.0 60.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Average Average Solid brick, as built, no insulation (assumed) Poor Poor (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, TRVs and bypass Average Average Low energy lighting in 60% of fixed outlets Good Good mains gas (not community) 0.0 unheated corridor 11.22 3.04 0.0 natural Flat 1, 18, Kirkmanshulme Lane Manchester Manchester, Gorton MANCHESTER England and Wales: 1900-1929 2011-10-10 21:15:02 rental (social) 5.0 3.0 77149971.0 Address Matched 100
49 5416a6441d4991472ee3dc5c86d6ee764bf3b5c49edd14340ada8125e839e710 1463 ASHTON OLD ROAD MANCHESTER M11 1HH 10000232217 C B 80 89 House Semi-Detached 2021-01-06 E08000003 E14000807 2021-01-11 marketed sale 79 88 112 63.0 2.4 20 1.4 91.0 91.0 411.0 411.0 81.0 53.0 121.0 off-peak 7 hour Y 100.0 double glazing installed during or after 2002 Normal 0.0 5.0 5.0 100.0 0.0 From main system Good Good Solid, insulated (assumed) Fully double glazed Good Good Cavity wall, as built, insulated (assumed) Very Good Very Good Pitched, 250 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in all fixed outlets Very Good Very Good mains gas (not community) 0.0 2.6 0.0 N natural 1463 ASHTON OLD ROAD, MANCHESTER Manchester Manchester Central MANCHESTER England and Wales: 2012 onwards 2021-01-11 00:00:00 Owner-occupied 13.0 13.0 10093076622.0 Energy Assessor 100
50 731682144052011120911312699099293 26, Fog Lane M20 6AL 2354493968 D C 61 69 House Semi-Detached 2011-12-09 E08000003 E14000809 2011-12-09 marketed sale 57 67 244 183.0 4.7 47 3.5 94.0 51.0 758.0 589.0 95.0 95.0 99.35 Single Y NODATA! 2106.0 100.0 double glazing, unknown install date Normal 0.0 5.0 5.0 14.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Average Average Cavity wall, as built, no insulation (assumed) Poor Poor Room heaters, mains gas Pitched, 200 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 14% of fixed outlets Poor Poor mains gas (not community) 0.0 NO DATA! 2.49 0.0 natural 26, Fog Lane Manchester Manchester, Withington MANCHESTER England and Wales: 1930-1949 2011-12-09 11:31:26 owner-occupied 14.0 2.0 77104449.0 Address Matched 100
51 636111349222011053112083067448689 14 Lynhurst Court Whitelow Road M21 9RS 8629417868 C C 79 80 Flat NO DATA! 2011-05-24 E08000003 E14000809 2011-05-31 rental (private) 70 71 274 264.0 1.9 49 1.8 49.0 25.0 79.0 84.0 162.0 162.0 39.3 dual N 2nd N 2106.0 100.0 double glazing installed during or after 2002 Normal 0.0 2.0 2.0 0.0 0.0 From main system Average Very Poor (other premises below) Fully double glazed Good Good Solid brick, as built, insulated (assumed) Good Good (another dwelling above) Boiler and radiators, electric Poor Very Poor Programmer, room thermostat and TRVs Good Good No low energy lighting Very Poor Very Poor electricity (not community) 0.0 heated corridor 2.98 0.0 natural 14 Lynhurst Court, Whitelow Road Manchester Manchester, Withington MANCHESTER England and Wales: 2003-2006 2011-05-31 12:08:30 rental (private) 11.0 0.0 10070869721.0 Address Matched 100
52 cabb687c109a22fbd8064595e23af2e6d4119306b86d909ba87b93daf4987c56 FLAT 316 TIMBER WHARF 32 WORSLEY STREET M15 4NY 10000512885 B B 82 83 Flat Mid-Terrace 2021-02-24 E08000003 E14000807 2021-02-24 marketed sale 72 74 267 248.0 1.5 45 1.4 39.0 39.0 131.0 102.0 148.0 148.0 34.0 off-peak 10 hour N 03 N 100.0 double glazing, unknown install date Normal 0.0 2.0 2.0 100.0 0.0 Electric immersion, off-peak Average Poor (another dwelling below) Fully double glazed Average Average System built, as built, insulated (assumed) Good Good Room heaters, electric (another dwelling above) Electric storage heaters Average Very Poor Manual charge control Poor Poor Low energy lighting in all fixed outlets Very Good Very Good electricity (not community) 0.0 unheated corridor 5.85 2.7 0.0 N natural FLAT 316, TIMBER WHARF, 32 WORSLEY STREET Manchester Manchester Central MANCHESTER England and Wales: 1996-2002 2021-02-24 00:00:00 Owner-occupied 6.0 6.0 10003799752.0 Energy Assessor 100
53 44c18ead193b7303c929d2b1c75ed2133b5f38c2b16aba5f6aa2acf60e4fb0ca 20, Thomas Regan Court Ansell Close Gorton M18 8EE 10000146161 C C 75 77 Flat Mid-Terrace 2020-09-16 E08000003 E14000808 2021-02-24 rental 77 81 225 192.0 1.2 40 1.0 27.0 27.0 218.0 184.0 99.0 99.0 31.0 off-peak 7 hour Y 01 Y 100.0 double glazing installed during or after 2002 Normal 0.0 2.0 2.0 83.0 0.0 Community scheme Good Good (another dwelling below) Fully double glazed Good Good Cavity wall, filled cavity Good Good Pitched, 200 mm loft insulation Good Good Community scheme Good Good Flat rate charging, programmer and TRVs Average Average Low energy lighting in 83% of fixed outlets Very Good Very Good mains gas (community) 0.0 heated corridor 0.0 2.4 0.0 N natural 20, Thomas Regan Court Ansell Close, Gorton Manchester Manchester, Gorton England and Wales: 1976-1982 2021-02-24 00:00:00 Rented (social) 6.0 5.0 77177124.0 Energy Assessor 100
54 3c08c183659d59febda24dc7492539fd151860c9ca4146efaa1450a8598eac41 30, Kincraig Close Openshaw M11 2JP 10000217311 C B 73 87 House Mid-Terrace 2020-10-08 E08000003 E14000807 2021-02-24 rental 72 86 179 85.0 2.5 32 1.2 70.0 51.0 436.0 406.0 110.0 74.0 78.0 off-peak 7 hour Y 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 63.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Good Good Pitched, 300 mm loft insulation Very Good Very Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 62% of fixed outlets Good Good mains gas (not community) 0.0 2.4 0.0 N natural 30, Kincraig Close, Openshaw Manchester Manchester Central England and Wales: 1976-1982 2021-02-24 00:00:00 Rented (social) 8.0 5.0 77179169.0 Energy Assessor 100
55 5ab41382eb79bed813dbe2c64c640c9ea51e554100993869db5f3d05ed7b7bf2 37 SOUTH GROVE MANCHESTER M13 0AU 10000587736 D B 65 85 House Mid-Terrace 2020-12-09 E08000003 E14000807 2020-12-09 marketed sale 58 82 224 96.0 4.7 40 2.1 86.0 86.0 829.0 525.0 106.0 75.0 120.0 off-peak 7 hour Y 100.0 double glazing, unknown install date Normal 0.0 7.0 7.0 100.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Average Average Solid brick, as built, no insulation (assumed) Very Poor Very Poor Pitched, 150 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, TRVs and bypass Average Average Low energy lighting in all fixed outlets Very Good Very Good mains gas (not community) 0.0 2.78 0.0 N natural 37 SOUTH GROVE, MANCHESTER Manchester Manchester Central MANCHESTER England and Wales: before 1900 2020-12-09 00:00:00 Rented (private) 11.0 11.0 77135463.0 Energy Assessor 100
56 488750391312012022311594492090472 73, Roundthorn Road M23 1EP 4211126768 D C 57 71 House Semi-Detached 2011-08-03 E08000003 E14001059 2012-02-23 rental (social) 54 71 294 184.0 4.1 57 2.5 61.0 41.0 520.0 419.0 251.0 106.0 72.0 Single Y NODATA! 2104.0 100.0 double glazing installed before 2002 Normal 0.0 3.0 3.0 50.0 0.0 From main system, no cylinder thermostat Poor Poor Solid, no insulation (assumed) Fully double glazed Average Average Cavity wall, filled cavity Good Good Room heaters, mains gas Pitched, 100 mm loft insulation Average Average Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average Low energy lighting in 50% of fixed outlets Good Good mains gas (not community) 0.0 NO DATA! 2.4 0.0 natural 73, Roundthorn Road Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1950-1966 2012-02-23 11:59:44 rental (social) 10.0 5.0 77045284.0 Address Matched 100
57 c175f3aad8bad5700cd15c26ed8864faf355c53361917563dd1cbaa208f0e47b 5, Francesca Walk Gorton M18 8EN 10000390940 C C 73 76 Flat Mid-Terrace 2020-10-19 E08000003 E14000808 2021-02-24 rental 75 78 196 169.0 1.7 34 1.5 57.0 34.0 320.0 290.0 89.0 90.0 50.0 off-peak 7 hour Y 00 Y 100.0 double glazing installed during or after 2002 Normal 0.0 2.0 2.0 33.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Average Average (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 33% of fixed outlets Average Average mains gas (not community) 0.0 unheated corridor 5.2 2.4 0.0 N natural 5, Francesca Walk, Gorton Manchester Manchester, Gorton England and Wales: 1967-1975 2021-02-24 00:00:00 Rented (social) 6.0 2.0 77176834.0 Energy Assessor 100
58 8fc47b53627c0b8b3bbe2b90a445805813ce5abce8543732986f41a863e0b608 680, Hyde Road Gorton M18 7EF 10000708843 C C 77 77 Flat Mid-Terrace 2020-10-13 E08000003 E14000808 2021-02-24 rental 79 79 164 164.0 1.3 29 1.3 34.0 34.0 268.0 268.0 87.0 87.0 47.0 off-peak 7 hour Y 01 Y 100.0 double glazing installed during or after 2002 Normal 0.0 2.0 2.0 100.0 0.0 From main system Good Good (another dwelling below) Fully double glazed Good Good Cavity wall, filled cavity Good Good Pitched, 250 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in all fixed outlets Very Good Very Good mains gas (not community) 0.0 unheated corridor 6.56 2.4 0.0 N natural 680, Hyde Road, Gorton Manchester Manchester, Gorton England and Wales: 1976-1982 2021-02-24 00:00:00 Rented (social) 6.0 6.0 77172366.0 Energy Assessor 100
59 97681707d8c26caf1e068dde344b6db1af30849413c5c2421c74ae73602eda76 FLAT 2 61 CHARLESTOWN ROAD MANCHESTER M9 7AB 10000744934 D D 56 63 Flat Semi-Detached 2021-03-11 E08000003 E14000571 2021-03-11 ECO assessment 60 67 548 460.0 1.9 93 1.6 23.0 23.0 414.0 302.0 255.0 255.0 21.0 off-peak 7 hour N 01 N 100.0 double glazing installed before 2002 Normal 0.0 1.0 1.0 100.0 0.0 From main system Very Poor Poor (another dwelling below) Fully double glazed Average Average Cavity wall, as built, no insulation (assumed) Poor Poor (another dwelling above) Boiler and radiators, electric Very Poor Poor TRVs and bypass Average Average Low energy lighting in all fixed outlets Very Good Very Good electricity (not community) 0.0 heated corridor 2.6 0.0 N natural FLAT 2, 61 CHARLESTOWN ROAD, MANCHESTER Manchester Blackley and Broughton MANCHESTER England and Wales: 1900-1929 2021-03-11 00:00:00 Rented (social) 3.0 3.0 10090425373.0 Energy Assessor 100
60 5bb34e45687ba9cf86df5756344950a9462c6bd0ab753aeda85571eca1353c1e 4, Howarth Close Beswick M11 3BR 10000607596 C C 74 77 Flat Mid-Terrace 2020-10-19 E08000003 E14000807 2021-02-24 rental 75 79 193 161.0 1.7 34 1.4 48.0 34.0 321.0 277.0 89.0 90.0 50.0 off-peak 7 hour Y 00 Y 100.0 double glazing installed during or after 2002 Normal 0.0 2.0 2.0 60.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Good Good System built, with external insulation Very Good Very Good (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 60% of fixed outlets Good Good mains gas (not community) 0.0 no corridor 0.0 2.4 0.0 N natural 4, Howarth Close, Beswick Manchester Manchester Central England and Wales: 1967-1975 2021-02-24 00:00:00 Rented (social) 5.0 3.0 77168659.0 Energy Assessor 100
61 609449769232012011815001652968806 Flat 2 36 Clyde Road M20 2HN 6632815868 E E 45 54 Flat Semi-Detached 2012-01-17 E08000003 E14000809 2012-01-18 marketed sale 43 50 408 337.0 4.8 78 4.0 73.0 36.0 805.0 698.0 84.0 74.0 61.2 Single Y Ground N 2107.0 100.0 double glazing installed before 2002 Normal 0.0 3.0 3.0 0.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Average Average Solid brick, as built, no insulation (assumed) Very Poor Very Poor (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, TRVs and bypass Average Average No low energy lighting Very Poor Very Poor mains gas (not community) 0.0 unheated corridor 9.0 3.03 0.0 natural Flat 2, 36 Clyde Road Manchester Manchester, Withington MANCHESTER England and Wales: 1900-1929 2012-01-18 15:00:16 owner-occupied 12.0 0.0 77193527.0 Address Matched 100
62 8e64a93ed490b8227820a6eccbfb961ece2584543e04357a84a51ab327e3bd01 FLAT 1 7 STANLEY ROAD MANCHESTER M16 8HT 10000482906 E C 46 71 Maisonette Semi-Detached 2021-01-14 E08000003 E14000808 2021-01-14 ECO assessment 47 61 474 342.0 3.2 80 2.3 67.0 40.0 725.0 328.0 168.0 198.0 39.0 standard tariff N 00 N 100.0 double glazing installed during or after 2002 Normal 0.0 2.0 2.0 0.0 0.0 Electric instantaneous at point of use Very Poor Poor Solid, no insulation (assumed) Fully double glazed Good Good Cavity wall, as built, no insulation (assumed) Poor Poor (another dwelling above) Room heaters, electric Very Poor Poor Appliance thermostats Good Good No low energy lighting Very Poor Very Poor electricity (not community) 0.0 heated corridor 2.2 0.0 N natural FLAT 1, 7 STANLEY ROAD, MANCHESTER Manchester Manchester, Gorton MANCHESTER England and Wales: 1900-1929 2021-01-14 00:00:00 Rented (social) 8.0 0.0 10014178834.0 Energy Assessor 100
63 748772149802012020922143291520318 880, Burnage Lane M19 1RS 9817745968 D D 65 67 House Semi-Detached 2012-02-09 E08000003 E14000809 2012-02-09 marketed sale 61 63 204 190.0 5.2 39 4.9 97.0 62.0 828.0 792.0 115.0 115.0 133.0 Single Y NODATA! 2104.0 100.0 double glazing installed during or after 2002 Normal 2.0 6.0 6.0 44.0 1.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Good Good Room heaters, mains gas Pitched, 200 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average Low energy lighting in 44% of fixed outlets Average Average mains gas (not community) 0.0 NO DATA! 2.32 0.0 natural 880, Burnage Lane Manchester Manchester, Withington MANCHESTER England and Wales: 1930-1949 2012-02-09 22:14:32 owner-occupied 16.0 7.0 77125062.0 Address Matched 100
64 560c08dd1356a1845c7b42b64a9f9b51d5da057bbcf277b7577af732b553fb79 4, Easthaven Avenue Clayton M11 4RN 10000272490 D B 65 82 House Semi-Detached 2020-10-23 E08000003 E14000807 2021-02-24 rental 64 81 230 122.0 3.0 40 1.6 77.0 48.0 566.0 516.0 107.0 72.0 74.0 off-peak 7 hour Y 100.0 double glazing installed during or after 2002 Normal 0.0 4.0 4.0 40.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Average Average Room heaters, electric Pitched, 200 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 40% of fixed outlets Average Average mains gas (not community) 0.0 2.4 0.0 N natural 4, Easthaven Avenue, Clayton Manchester Manchester Central England and Wales: 1930-1949 2021-02-24 00:00:00 Rented (social) 10.0 4.0 77181001.0 Energy Assessor 100
65 614517559252011042315041795290084 50, Kirkmanshulme Lane M12 4WA 454955868 E E 45 54 House Mid-Terrace 2011-04-21 E08000003 E14000808 2011-04-23 marketed sale 40 47 338 281.0 8.3 65 7.0 115.0 58.0 1332.0 1159.0 104.0 89.0 102.38 Single Y NODATA! 2107.0 100.0 double glazing installed before 2002 Normal 0.0 7.0 7.0 0.0 1.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Average Average Solid brick, as built, no insulation (assumed) Very Poor Very Poor Room heaters, dual fuel (mineral and wood) Pitched, no insulation (assumed) Very Poor Very Poor Boiler and radiators, mains gas Good Good Programmer, TRVs and bypass Average Average No low energy lighting Very Poor Very Poor mains gas (not community) 0.0 NO DATA! 2.88 0.0 natural 50, Kirkmanshulme Lane Manchester Manchester, Gorton MANCHESTER England and Wales: 1900-1929 2011-04-23 15:04:17 owner-occupied 12.0 0.0 77149984.0 Address Matched 100
66 688269469962011101122380750998659 203, Dickenson Road M13 0YW 5527680968 E D 46 67 Flat NO DATA! 2011-10-11 E08000003 E14000808 2011-10-11 rental (social) 44 68 428 234.0 4.3 83 2.3 51.0 30.0 686.0 404.0 128.0 94.0 51.805 Single Y Ground N 2104.0 0.0 not defined Normal 0.0 2.0 2.0 29.0 0.0 From main system Average Average Suspended, no insulation (assumed) Single glazed Very Poor Very Poor Cavity wall, as built, no insulation (assumed) Very Poor Very Poor Room heaters, mains gas (another dwelling above) Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average Low energy lighting in 29% of fixed outlets Average Average mains gas (not community) 0.0 no corridor 2.926 0.0 natural 203, Dickenson Road Manchester Manchester, Gorton MANCHESTER England and Wales: before 1900 2011-10-11 22:38:07 rental (social) 7.0 2.0 77151575.0 Address Matched 100
67 679778369962011101214371240258809 Flat 16 St. Georges Court Angela Street M15 4HY 419620968 B B 84 84 Flat NO DATA! 2011-09-15 E08000003 E14000807 2011-10-12 rental (social) 77 77 265 265.0 1.2 47 1.2 20.0 20.0 73.0 73.0 90.0 90.0 26.23 dual N 3rd N 2401.0 100.0 double glazing installed during or after 2002 Normal 0.0 1.0 1.0 100.0 0.0 Electric immersion, off-peak Average Very Poor (other premises below) Fully double glazed Good Good Cavity wall, with external insulation Very Good Very Good (another dwelling above) Electric storage heaters Poor Very Poor Manual charge control Poor Poor Low energy lighting in all fixed outlets Very Good Very Good electricity (not community) 0.0 unheated corridor 6.64 2.42 0.0 natural Flat 16, St. Georges Court, Angela Street Manchester Manchester Central MANCHESTER England and Wales: 2007 onwards 2011-10-12 14:37:12 rental (social) 4.0 4.0 77089818.0 Address Matched 100
68 4ef5a12d522c8fe5ed3c546cfa247287dd48eed5b2b15ee4de2b9b3763b5d786 171 ASHLEY LANE MANCHESTER M9 4NQ 10000118472 D C 59 80 House Mid-Terrace 2020-10-21 E08000003 E14000571 2020-10-24 marketed sale 52 75 292 149.0 4.8 52 2.5 124.0 73.0 835.0 620.0 89.0 61.0 93.0 off-peak 7 hour Y 100.0 double glazing, unknown install date Normal 1.0 5.0 5.0 30.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Average Average Solid brick, as built, no insulation (assumed) Very Poor Very Poor Room heaters, mains gas Pitched, 250 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average Low energy lighting in 30% of fixed outlets Average Average mains gas (not community) 0.0 2.69 0.0 N natural 171 ASHLEY LANE, MANCHESTER Manchester Blackley and Broughton MANCHESTER England and Wales: 1900-1929 2020-10-24 00:00:00 Owner-occupied 10.0 3.0 77022818.0 Energy Assessor 100
69 1b1f726b0eeeec41f52767f85efe93fbce9531ee45bb57f29a437ca4ad23ec05 5 THE OLD COURTYARD MANCHESTER M22 4YD 10000358677 C B 72 84 House End-Terrace 2021-03-05 E08000003 E14001059 2021-03-05 marketed sale 70 82 186 110.0 2.7 33 1.6 71.0 71.0 447.0 447.0 103.0 72.0 81.0 off-peak 7 hour Y 100.0 double glazing, unknown install date Normal 0.0 4.0 4.0 100.0 0.0 From main system Good Good Solid, limited insulation (assumed) Fully double glazed Average Average Cavity wall, as built, insulated (assumed) Good Good Pitched, 100 mm loft insulation Average Average Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in all fixed outlets Very Good Very Good mains gas (not community) 0.0 2.25 0.0 N natural 5 THE OLD COURTYARD, MANCHESTER Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1996-2002 2021-03-05 00:00:00 Owner-occupied 12.0 12.0 77067549.0 Energy Assessor 100
70 730662989202011120614524193390868 107, Plymouth Grove M13 9HX 5291683968 C C 76 76 House Mid-Terrace 2011-12-06 E08000003 E14000807 2011-12-06 rental (social) 76 76 142 142.0 2.4 27 2.4 52.0 52.0 382.0 382.0 110.0 110.0 89.6 Single Y NODATA! 2310.0 100.0 double glazing installed during or after 2002 Normal 0.0 5.0 5.0 90.0 0.0 Community scheme Good Good Solid, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Good Good Room heaters, electric Pitched, 300+ mm loft insulation Very Good Very Good Community scheme Good Good Charging system linked to use of community heating, TRVs Good Good Low energy lighting in 90% of fixed outlets Very Good Very Good mains gas (community) 0.0 NO DATA! 2.38 0.0 natural 107, Plymouth Grove Manchester Manchester Central MANCHESTER England and Wales: 1967-1975 2011-12-06 14:52:41 rental (social) 10.0 9.0 77136227.0 Address Matched 100
71 637817066932011060412162118068803 Apartment 306 Chatsworth House 19, Lever Street M1 1BY 6308827868 C B 75 81 Flat NO DATA! 2011-06-04 E08000003 E14000807 2011-06-04 marketed sale 69 69 213 213.0 2.7 38 2.7 76.0 46.0 274.0 191.0 137.0 107.0 72.25 Unknown N 3rd N 2602.0 100.0 double glazing installed before 2002 Normal 0.0 3.0 3.0 20.0 0.0 Electric immersion, off-peak Average Very Poor (other premises below) Fully double glazed Average Average System built, as built, insulated (assumed) Good Good (another dwelling above) Room heaters, electric Poor Very Poor Appliance thermostats Good Good Low energy lighting in 20% of fixed outlets Poor Poor electricity (not community) 0.0 unheated corridor 12.5 2.45 0.0 natural Apartment 306 Chatsworth House, 19, Lever Street Manchester Manchester Central MANCHESTER England and Wales: 1996-2002 2011-06-04 12:16:21 owner-occupied 10.0 2.0 10023045032.0 Address Matched 100
72 649015816912011063013353790790785 45, Northridge Road M9 6GW 7587608868 C C 69 69 House Semi-Detached 2011-06-30 E08000003 E14000571 2011-06-30 rental (social) 70 70 191 191.0 2.6 36 2.6 38.0 38.0 469.0 469.0 84.0 84.0 72.06 Single Y NODATA! 2106.0 100.0 double glazing installed during or after 2002 Normal 0.0 4.0 4.0 100.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Good Good Room heaters, electric Pitched, 250 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in all fixed outlets Very Good Very Good mains gas (not community) 0.0 NO DATA! 2.44 0.0 natural 45, Northridge Road Manchester Blackley and Broughton MANCHESTER England and Wales: 1930-1949 2011-06-30 13:35:37 rental (social) 6.0 6.0 77020453.0 Address Matched 100
73 79011046012011092920530093290647 Apartment 2, Windsor House 252, Mauldeth Road West Chorlton cum Hardy M21 7TH 6732635468 C C 70 76 Flat Detached 2011-09-29 E08000003 E14000809 2011-09-29 marketed sale 63 62 262 268.0 3.2 46 3.2 62.0 45.0 383.0 291.0 128.0 115.0 67.94 Unknown N 1st N 2603.0 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 44.0 0.0 Electric immersion, off-peak Average Very Poor To external air, insulated (assumed) Fully double glazed Good Good System built, as built, insulated (assumed) Good Good (another dwelling above) Room heaters, electric Poor Very Poor Programmer and appliance thermostats Good Good Low energy lighting in 44% of fixed outlets Average Average electricity (not community) 0.0 unheated corridor 23.28 2.25 0.0 mechanical, extract only Apartment 2, Windsor House, 252, Mauldeth Road West, Chorlton cum Hardy Manchester Manchester, Withington MANCHESTER England and Wales: 2003-2006 2011-09-29 20:53:00 owner-occupied 9.0 4.0 10070868545.0 Address Matched 100
74 664d3337e51de82abf0c359a8e9a446a0dbd5d7965369fc859eb0add675aec5a 8, Hartington Drive Clayton M11 4JG 10000747213 D B 68 83 House Semi-Detached 2020-10-20 E08000003 E14000807 2021-02-24 rental 65 81 217 117.0 3.0 38 1.7 79.0 51.0 543.0 500.0 110.0 74.0 80.0 off-peak 7 hour Y 100.0 double glazing installed during or after 2002 Normal 0.0 4.0 4.0 45.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Average Average Pitched, 300 mm loft insulation Very Good Very Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 45% of fixed outlets Good Good mains gas (not community) 0.0 2.6 0.0 N natural 8, Hartington Drive, Clayton Manchester Manchester Central England and Wales: 1930-1949 2021-02-24 00:00:00 Rented (social) 11.0 5.0 77169870.0 Energy Assessor 100
75 fff8edbe33f302b835435ce435658054f9a93dc8d3a699c782508ed9059ee32a FLAT 75 SOUTHMOOR 23 GLEBELANDS ROAD M23 1HR 10000583235 D C 64 80 Flat Mid-Terrace 2021-02-10 E08000003 E14001059 2021-02-18 ECO assessment 68 67 280 285.0 2.0 47 2.0 74.0 41.0 352.0 194.0 285.0 154.0 41.0 off-peak 7 hour N 05 N 100.0 double glazing, unknown install date Normal 0.0 3.0 3.0 0.0 0.0 Electric immersion, standard tariff Very Poor Poor (another dwelling below) Fully double glazed Average Average System built, as built, no insulation (assumed) Very Poor Very Poor (another dwelling above) Room heaters, electric Very Poor Poor Programmer and appliance thermostats Good Good No low energy lighting Very Poor Very Poor electricity (not community) 0.0 no corridor 2.49 0.0 N natural FLAT 75, SOUTHMOOR, 23 GLEBELANDS ROAD Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1967-1975 2021-02-18 00:00:00 Rented (private) 6.0 0.0 10003798235.0 Energy Assessor 100
76 554538989642011101814401084099988 246, Cornishway M22 1SU 1659680868 E D 52 61 Flat End-Terrace 2011-10-18 E08000003 E14001059 2011-10-18 rental (social) 55 63 314 255.0 3.6 58 3.0 65.0 36.0 458.0 440.0 328.0 224.0 62.09 Single Y Ground Y 2106.0 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 20.0 0.0 Electric immersion, standard tariff Very Poor Very Poor Solid, no insulation (assumed) Fully double glazed Good Good Cavity wall, as built, no insulation (assumed) Poor Poor (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 20% of fixed outlets Poor Poor mains gas (not community) 0.0 unheated corridor 4.77 2.44 0.0 natural 246, Cornishway Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1950-1966 2011-10-18 14:40:10 rental (social) 10.0 2.0 77056094.0 Address Matched 100
77 b4b36cb0202e0bb71d122b2d37acae25b532d32d407c18f29795ab9631bec6b1 APARTMENT 15 6 THE WATERFRONT MANCHESTER M11 4AY 10000509199 C C 70 70 Flat Detached 2021-03-02 E08000003 E14000807 2021-03-02 rental 73 73 185 185.0 2.2 31 2.2 65.0 65.0 459.0 459.0 272.0 272.0 71.0 off-peak 10 hour N 02 N 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 100.0 0.0 From main system Very Poor Poor (another dwelling below) Fully double glazed Good Good Cavity wall, as built, insulated (assumed) Good Good (another dwelling above) Boiler and radiators, electric Very Poor Poor Programmer, room thermostat and TRVs Good Good Low energy lighting in all fixed outlets Very Good Very Good electricity (not community) 0.0 unheated corridor 10.1 2.41 0.0 N natural APARTMENT 15, 6 THE WATERFRONT, MANCHESTER Manchester Manchester Central MANCHESTER England and Wales: 2003-2006 2021-03-02 00:00:00 Owner-occupied 9.0 9.0 10012203091.0 Energy Assessor 100
78 619828709242011041909303788699788 16, Alexandra Drive M19 2WW 252206868 D D 61 68 House Semi-Detached 2011-04-18 E08000003 E14000808 2011-04-19 marketed sale 57 66 245 195.0 4.5 47 3.6 69.0 48.0 721.0 597.0 103.0 86.0 95.72 Single Y NODATA! 2107.0 75.0 double glazing installed before 2002 Normal 1.0 5.0 5.0 55.0 0.0 From main system Good Good Suspended, no insulation (assumed) Partial double glazing Poor Poor Cavity wall, with internal insulation Good Good Room heaters, mains gas Pitched, 100 mm loft insulation Average Average Boiler and radiators, mains gas Good Good Programmer, TRVs and bypass Average Average Low energy lighting in 55% of fixed outlets Good Good mains gas (not community) 0.0 NO DATA! 2.7 0.0 natural 16, Alexandra Drive Manchester Manchester, Gorton MANCHESTER England and Wales: 1900-1929 2011-04-19 09:30:37 owner-occupied 11.0 6.0 77147636.0 Address Matched 100
79 481145989762012022218030515508359 16, Crowthorn Drive M23 2XX 5126865768 D C 63 74 Flat Detached 2011-09-30 E08000003 E14001059 2012-02-22 rental (social) 61 75 242 155.0 3.4 46 2.2 65.0 43.0 424.0 345.0 227.0 114.0 73.0 Single Y 1st N 2104.0 100.0 double glazing installed during or after 2002 Normal 0.0 4.0 4.0 50.0 0.0 From main system, no cylinder thermostat Poor Poor (other premises below) Fully double glazed Good Good Solid brick, as built, no insulation (assumed) Very Poor Very Poor Room heaters, mains gas (another dwelling above) Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average Low energy lighting in 50% of fixed outlets Good Good mains gas (not community) 0.0 unheated corridor 6.0 2.4 0.0 natural 16, Crowthorn Drive Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1950-1966 2012-02-22 18:03:05 rental (social) 10.0 5.0 77048710.0 Address Matched 100
80 635128788152011052716244690290489 161, Blackcarr Road M23 1PB 4977807868 D C 68 70 House Semi-Detached 2011-05-27 E08000003 E14001059 2011-05-27 marketed sale 66 69 192 177.0 3.6 37 3.3 80.0 49.0 521.0 500.0 137.0 137.0 97.26 Single Y NODATA! 2106.0 100.0 double glazing installed during or after 2002 Normal 1.0 5.0 5.0 36.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Good Good Room heaters, mains gas Pitched, 250 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 36% of fixed outlets Average Average mains gas (not community) 0.0 NO DATA! 2.44 0.0 natural 161, Blackcarr Road Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1950-1966 2011-05-27 16:24:46 owner-occupied 11.0 4.0 77051657.0 Address Matched 100
81 679768829202011101214391699099658 Flat 61 St. Georges Court Angela Street M15 4HZ 278620968 B B 83 83 Flat NO DATA! 2011-09-15 E08000003 E14000807 2011-10-12 rental (social) 76 76 274 274.0 1.3 49 1.3 20.0 20.0 85.0 85.0 90.0 90.0 26.238 dual N 13th N 2401.0 100.0 double glazing installed during or after 2002 Normal 0.0 1.0 1.0 100.0 0.0 Electric immersion, off-peak Average Very Poor (other premises below) Fully double glazed Good Good Cavity wall, with external insulation Very Good Very Good (another dwelling above) Electric storage heaters Poor Very Poor Manual charge control Poor Poor Low energy lighting in all fixed outlets Very Good Very Good electricity (not community) 0.0 unheated corridor 6.64 2.42 0.0 natural Flat 61 St. Georges Court, Angela Street Manchester Manchester Central MANCHESTER England and Wales: 2007 onwards 2011-10-12 14:39:16 rental (social) 4.0 4.0 77089862.0 Address Matched 100
82 734802329412011122022231691099590 36, Broom Avenue M19 2UD 5050914968 D D 67 68 House Mid-Terrace 2011-12-08 E08000003 E14000808 2011-12-20 rental (private) 67 69 238 226.0 2.4 46 2.3 33.0 33.0 431.0 410.0 71.0 71.0 51.8 Single Y NODATA! 2107.0 100.0 double glazing installed before 2002 Normal 0.0 3.0 3.0 88.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Average Average Solid brick, as built, no insulation (assumed) Very Poor Very Poor Pitched, 150 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, TRVs and bypass Average Average Low energy lighting in 88% of fixed outlets Very Good Very Good mains gas (not community) 0.0 NO DATA! 2.7 0.0 natural 36, Broom Avenue Manchester Manchester, Gorton MANCHESTER England and Wales: 1900-1929 2011-12-20 22:23:16 rental (private) 8.0 7.0 77159739.0 Address Matched 100
83 99f660d53b3d1f4f4c0552f485401f62821e3dd8d921f0235d6881b85cbd0e97 3 GORTON LANE MANCHESTER M12 5DF 10000205809 C B 71 87 House Semi-Detached 2021-01-15 E08000003 E14000808 2021-01-20 marketed sale 71 87 196 83.0 2.3 34 1.0 120.0 60.0 367.0 352.0 89.0 62.0 66.0 off-peak 10 hour Y 100.0 double glazing, unknown install date Normal 0.0 5.0 5.0 0.0 0.0 From main system Good Good Solid, limited insulation (assumed) Fully double glazed Average Average Cavity wall, as built, insulated (assumed) Good Good Pitched, 270 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good No low energy lighting Very Poor Very Poor mains gas (not community) 0.0 2.3 0.0 N natural 3 GORTON LANE, MANCHESTER Manchester Manchester, Gorton MANCHESTER England and Wales: 1996-2002 2021-01-20 00:00:00 Not defined - use in the case of a new dwelling for which the intended tenure in not known. It is not to be used for an existing dwelling 12.0 0.0 77166837.0 Energy Assessor 100
84 021157ab012ac40fef385b072f957b5da8f89ed1ca67cf3a6d3c260de6beead9 FLAT 53 WORSLEY COURT MANCHESTER M14 5LU 10000809961 C C 78 80 Flat Mid-Terrace 2021-01-11 E08000003 E14000808 2021-01-13 rental 80 83 161 139.0 1.2 28 1.1 54.0 39.0 174.0 164.0 108.0 96.0 44.0 off-peak 7 hour Y 06 N 100.0 double glazing, unknown install date Normal 0.0 2.0 2.0 60.0 0.0 Community scheme Good Good (another dwelling below) Fully double glazed Average Average System built, with external insulation Good Good (another dwelling above) Community scheme Good Good Charging system linked to use of community heating, room thermostat only Poor Poor Low energy lighting in 60% of fixed outlets Good Good mains gas (community) 0.0 no corridor 2.45 0.0 N natural FLAT 53, WORSLEY COURT, MANCHESTER Manchester Manchester, Gorton MANCHESTER England and Wales: 1967-1975 2021-01-13 00:00:00 Rented (social) 5.0 3.0 10003800135.0 Energy Assessor 100
85 625257257112011050510245493090787 210, Brownley Road M22 5EB 7765736868 E D 45 58 House End-Terrace 2011-05-05 E08000003 E14001059 2011-05-05 rental (social) 42 55 403 297.0 5.0 78 3.7 63.0 35.0 769.0 607.0 139.0 103.0 64.54 Single Y NODATA! 2104.0 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 20.0 0.0 From main system Average Average Suspended, no insulation (assumed) Fully double glazed Good Good System built, as built, no insulation (assumed) Very Poor Very Poor Room heaters, mains gas Pitched, 75 mm loft insulation Average Average Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average Low energy lighting in 20% of fixed outlets Poor Poor mains gas (not community) 0.0 NO DATA! 2.43 0.0 natural 210, Brownley Road Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1930-1949 2011-05-05 10:24:54 rental (social) 10.0 2.0 77056607.0 Address Matched 100
86 658838179922011072613401008288139 6, Cardinal Street M8 0PS 3028778868 C C 71 76 Flat NO DATA! 2011-07-18 E08000003 E14000571 2011-07-26 rental (social) 72 79 197 150.0 2.1 38 1.6 32.0 32.0 332.0 268.0 125.0 102.0 55.9 Single Y 1st Y 2104.0 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 100.0 0.0 From main system Good Good (other premises below) Fully double glazed Good Good Cavity wall, filled cavity Good Good Room heaters, mains gas Pitched, 100 mm loft insulation Average Average Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average Low energy lighting in all fixed outlets Very Good Very Good mains gas (not community) 0.0 no corridor 2.47 0.0 natural 6, Cardinal Street Manchester Blackley and Broughton MANCHESTER England and Wales: 1950-1966 2011-07-26 13:40:10 rental (social) 4.0 4.0 77004125.0 Address Matched 100
87 0fefd53f8c1a500a28c0e670aec275667c89e9a35541e5b04513df47d4282393 FLAT 16 79 GREENWOOD ROAD MANCHESTER M22 8BT 10000492395 C C 77 79 Flat Mid-Terrace 2021-02-09 E08000003 E14001059 2021-02-10 marketed sale 78 81 152 133.0 1.7 27 1.5 76.0 59.0 272.0 256.0 103.0 89.0 63.0 off-peak 7 hour Y 00 N 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 70.0 0.0 From main system Good Good Suspended, insulated (assumed) Fully double glazed Good Good Cavity wall, as built, insulated (assumed) Good Good (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 70% of fixed outlets Very Good Very Good mains gas (not community) 0.0 unheated corridor 7.5 2.33 0.0 N natural FLAT 16, 79 GREENWOOD ROAD, MANCHESTER Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 2003-2006 2021-02-10 00:00:00 Owner-occupied 10.0 7.0 10012209996.0 Energy Assessor 100
88 ed9b110d09ce5659e83f018f850cb47b9051848be46aae32f3e205f298b46893 47 ALAN ROAD MANCHESTER M20 4SE 10000640863 D C 66 79 House Semi-Detached 2020-10-17 E08000003 E14000809 2020-10-17 marketed sale 64 78 211 129.0 3.3 37 2.0 75.0 75.0 674.0 625.0 80.0 52.0 89.0 off-peak 7 hour Y 100.0 double glazing, unknown install date Normal 1.0 5.0 5.0 93.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Average Average Cavity wall, filled cavity Average Average Room heaters, electric Pitched, 200 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 93% of fixed outlets Very Good Very Good mains gas (not community) 0.0 2.46 0.0 N natural 47 ALAN ROAD, MANCHESTER Manchester Manchester, Withington MANCHESTER England and Wales: 1930-1949 2020-10-17 00:00:00 Owner-occupied 14.0 13.0 77127799.0 Energy Assessor 100
89 638729274212011111616003493990381 8, Midlothian Street M11 4EP 3184437868 D D 62 65 House Mid-Terrace 2011-08-19 E08000003 E14000807 2011-11-16 rental (social) 58 62 225 207.0 4.9 43 4.6 108.0 54.0 781.0 756.0 85.0 85.0 114.3 Single Y NODATA! 2104.0 100.0 double glazing installed before 2002 Normal 1.0 3.0 3.0 0.0 0.0 From main system Good Good To unheated space, uninsulated (assumed) Fully double glazed Average Average Cavity wall, as built, no insulation (assumed) Poor Poor Pitched, no insulation (assumed) Very Poor Very Poor Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average No low energy lighting Very Poor Very Poor mains gas (not community) 0.0 NO DATA! 2.34 0.0 natural 8, Midlothian Street Manchester Manchester Central MANCHESTER England and Wales: 1900-1929 2011-11-16 16:00:34 rental (social) 7.0 0.0 77169015.0 Address Matched 100
90 642581286932011061518061414968204 8, Thorngrove Avenue M23 9PQ 8484267868 D C 55 74 Flat NO DATA! 2011-06-14 E08000003 E14001059 2011-06-15 marketed sale 40 55 488 341.0 4.9 86 3.4 58.0 35.0 443.0 282.0 230.0 97.0 56.58 dual N 2nd Y 2402.0 100.0 double glazing installed before 2002 Normal 0.0 4.0 4.0 33.0 0.0 Electric immersion, off-peak Poor Very Poor (other premises below) Fully double glazed Average Average Cavity wall, as built, partial insulation (assumed) Average Average Room heaters, electric Pitched, 200 mm loft insulation Good Good Electric storage heaters Average Very Poor Automatic charge control Average Average Low energy lighting in 33% of fixed outlets Average Average electricity (not community) 0.0 no corridor 2.52 0.0 natural 8, Thorngrove Avenue Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1976-1982 2011-06-15 18:06:14 owner-occupied 6.0 2.0 77043264.0 Address Matched 100
91 071362360df687e9f894e1bd49586445504f2e59c97848047ec7ab69a4f0098e APARTMENT 92 THE CITADEL 15 LUDGATE HILL M4 4AP 10000517000 C C 73 79 Flat Mid-Terrace 2020-11-25 E08000003 E14000807 2020-11-28 rental 69 71 216 205.0 2.3 36 2.2 69.0 69.0 330.0 254.0 219.0 188.0 64.0 off-peak 10 hour N 06 Y 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 79.0 0.0 Electric immersion, off-peak Poor Poor (another dwelling below) Fully double glazed Good Good Cavity wall, as built, insulated (assumed) Good Good Flat, insulated (assumed) Good Good Room heaters, electric Very Poor Poor Appliance thermostats Good Good Low energy lighting in 79% of fixed outlets Very Good Very Good electricity (not community) 0.0 heated corridor 0.0 2.397 0.0 N natural APARTMENT 92, THE CITADEL, 15 LUDGATE HILL Manchester Manchester Central MANCHESTER England and Wales: 2003-2006 2020-11-28 00:00:00 Rented (private) 19.0 15.0 10023045277.0 Energy Assessor 100
92 42013829112012012410412891220753 Flat 2 12, Victoria Avenue Didsbury M20 2GZ 7344914568 C C 72 73 Flat Semi-Detached 2012-01-23 E08000003 E14000809 2012-01-24 marketed sale 76 77 215 203.0 1.5 41 1.4 22.0 22.0 312.0 297.0 42.0 42.0 35.43 Unknown Y Ground N 2107.0 0.0 not defined Normal 0.0 2.0 2.0 100.0 0.0 From main system Good Good (other premises below) Single glazed Very Poor Very Poor Solid brick, as built, no insulation (assumed) Very Poor Very Poor (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, TRVs and bypass Average Average Low energy lighting in all fixed outlets Very Good Very Good mains gas (not community) 0.0 unheated corridor 4.31 2.37 0.0 natural Flat 2, 12, Victoria Avenue, Didsbury Manchester Manchester, Withington MANCHESTER England and Wales: before 1900 2012-01-24 10:41:28 owner-occupied 4.0 4.0 77222235.0 Address Matched 100
93 654307865512011071410514394990088 Flat 18 Birch Tree Court Rowlandsway M22 5RY 884548868 C C 77 79 Flat Semi-Detached 2011-07-14 E08000003 E14001059 2011-07-14 rental (social) 81 84 143 122.0 1.3 27 1.1 54.0 29.0 226.0 221.0 77.0 68.0 48.1 Single Y 1st N 2106.0 100.0 double glazing, unknown install date Normal 0.0 2.0 2.0 14.0 0.0 From main system Good Good (other premises below) Fully double glazed Average Average System built, as built, partial insulation (assumed) Average Average (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 14% of fixed outlets Poor Poor mains gas (not community) 0.0 no corridor 2.43 0.0 natural Flat 18 Birch Tree Court, Rowlandsway Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1976-1982 2011-07-14 10:51:43 rental (social) 7.0 1.0 77056685.0 Address Matched 100
94 728351399262011112914203643718119 144, Woodhouse Lane M22 9WW 1454963968 D C 61 70 House End-Terrace 2011-11-29 E08000003 E14001059 2011-11-29 rental (social) 58 69 263 194.0 3.6 50 2.7 75.0 39.0 570.0 433.0 111.0 112.0 71.15 Single Y NODATA! 2106.0 100.0 double glazing installed during or after 2002 Normal 0.0 4.0 4.0 10.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Good Good Cavity wall, as built, no insulation (assumed) Poor Poor Room heaters, mains gas Pitched, 300+ mm loft insulation Very Good Very Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 10% of fixed outlets Poor Poor mains gas (not community) 0.0 NO DATA! 2.46 0.0 natural 144, Woodhouse Lane Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1930-1949 2011-11-29 14:20:36 rental (social) 10.0 1.0 77213666.0 Address Matched 100
95 721896329102011110914201292390318 48, Golborne Avenue M20 1EJ 7181223968 C C 69 69 House Semi-Detached 2011-11-09 E08000003 E14000809 2011-11-09 rental (social) 69 69 184 184.0 3.0 35 3.0 52.0 52.0 537.0 537.0 92.0 92.0 86.62 Single Y NODATA! 2106 100.0 double glazing installed during or after 2002 Normal 0.0 5.0 5.0 86.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Good Good System built, with external insulation Good Good Room heaters, electric Pitched, 250 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 86% of fixed outlets Very Good Very Good mains gas (not community) 0.0 NO DATA! 2.4 0.0 natural 48, Golborne Avenue Manchester Manchester, Withington MANCHESTER England and Wales: 1900-1929 2011-11-09 14:20:12 rental (social) 7.0 6.0 77093412.0 Address Matched 100
96 761444229222012032014112746808672 28, Penarth Road M22 4AR 7465246968 C C 71 72 House Semi-Detached 2012-03-20 E08000003 E14001059 2012-03-20 marketed sale 70 70 170 166.0 3.3 33 3.2 76.0 53.0 543.0 546.0 89.0 89.0 101.73 Single Y NODATA! 2106.0 100.0 double glazing installed during or after 2002 Normal 1.0 6.0 6.0 55.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Good Good Room heaters, mains gas Pitched, 300+ mm loft insulation Very Good Very Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 55% of fixed outlets Good Good mains gas (not community) 0.0 NO DATA! 2.46 0.0 natural 28, Penarth Road Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1930-1949 2012-03-20 14:11:27 owner-occupied 11.0 6.0 77061245.0 Address Matched 100
97 737653947152012010914113694020793 15, Desmond Road M22 9YD 7349744968 C C 70 70 Flat Semi-Detached 2012-01-09 E08000003 E14001059 2012-01-09 rental (social) 72 72 191 187.0 2.3 36 2.2 53.0 37.0 385.0 387.0 109.0 109.0 63.34 Single Y Ground N 2106.0 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 57.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Good Good Room heaters, electric (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 57% of fixed outlets Good Good mains gas (not community) 0.0 no corridor 2.47 0.0 natural 15, Desmond Road Manchester Wythenshawe and Sale East MANCHESTER England and Wales: 1930-1949 2012-01-09 14:11:36 rental (social) 7.0 4.0 77066406.0 Address Matched 100
98 03975d94b94b7be3d2c055285b0c04b54ae8659ba8b2a69d5dd09273d4d7d777 APARTMENT 6 2A OLD BIRLEY STREET MANCHESTER M15 5RG 10000787522 C C 80 80 Flat Mid-Terrace 2021-02-04 E08000003 E14000807 2021-02-10 rental 70 70 219 219.0 2.1 37 2.1 60.0 60.0 177.0 177.0 137.0 137.0 58.0 off-peak 10 hour Y 02 Y 100.0 double glazing installed during or after 2002 Normal 0.0 3.0 3.0 78.0 0.0 Electric immersion, off-peak Average Poor (another dwelling below) Fully double glazed Good Good Cavity wall, as built, insulated (assumed) Good Good Room heaters, electric Flat, insulated (assumed) Good Good Electric storage heaters Average Very Poor Manual charge control Poor Poor Low energy lighting in 78% of fixed outlets Very Good Very Good electricity (not community) 0.0 heated corridor 2.39 0.0 N natural APARTMENT 6, 2A OLD BIRLEY STREET, MANCHESTER Manchester Manchester Central MANCHESTER England and Wales: 2003-2006 2021-02-10 00:00:00 Rented (private) 9.0 7.0 10023043600.0 Energy Assessor 100
99 684065851932011092920125068268605 4, Hartshead Close M11 1HG 5538650968 E D 53 66 House Mid-Terrace 2011-09-29 E08000003 E14000807 2011-09-29 marketed sale 48 64 310 213.0 5.2 60 3.6 87.0 46.0 743.0 584.0 212.0 120.0 87.75 Single Y NODATA! 2104.0 0.0 not defined Normal 0.0 4.0 4.0 12.0 0.0 From main system, no cylinder thermostat Poor Poor Suspended, no insulation (assumed) Single glazed Very Poor Very Poor Solid brick, as built, no insulation (assumed) Very Poor Very Poor Pitched, 250 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer and room thermostat Average Average Low energy lighting in 12% of fixed outlets Poor Poor mains gas (not community) 0.0 NO DATA! 2.75 0.0 natural 4, Hartshead Close Manchester Manchester Central MANCHESTER England and Wales: 1900-1929 2011-09-29 20:12:50 owner-occupied 8.0 1.0 77188991.0 Address Matched 100
100 687986189502011101020174490099108 Flat 1 14, Kirkmanshulme Lane M12 4WA 9531380968 D D 61 65 Flat End-Terrace 2011-10-10 E08000003 E14000808 2011-10-10 rental (social) 63 68 375 320.0 2.0 72 1.7 24.0 24.0 386.0 340.0 64.0 56.0 28.14 Single Y Ground N 2107.0 100.0 double glazing, unknown install date Normal 0.0 2.0 2.0 67.0 0.0 From main system Good Good Suspended, no insulation (assumed) Fully double glazed Average Average Solid brick, as built, no insulation (assumed) Poor Poor (another dwelling above) Boiler and radiators, mains gas Good Good Programmer, TRVs and bypass Average Average Low energy lighting in 67% of fixed outlets Good Good mains gas (not community) 0.0 unheated corridor 11.22 3.04 0.0 natural Flat 1, 14, Kirkmanshulme Lane Manchester Manchester, Gorton MANCHESTER England and Wales: 1900-1929 2011-10-10 20:17:44 rental (social) 6.0 4.0 77149969.0 Address Matched 100
101 1bcd628286730b71c4817db4cc56851938881db9d06a42aef6c393c93d3b1050 9, Gatley Avenue Fallowfield M14 7HE 10000715813 C B 70 83 House Semi-Detached 2020-10-12 E08000003 E14000808 2021-02-24 rental 66 79 195 115.0 3.3 34 2.0 77.0 59.0 589.0 550.0 116.0 79.0 96.0 off-peak 7 hour Y 100.0 double glazing installed during or after 2002 Normal 0.0 5.0 5.0 70.0 0.0 From main system Good Good Solid, no insulation (assumed) Fully double glazed Good Good Cavity wall, filled cavity Average Average Pitched, 250 mm loft insulation Good Good Boiler and radiators, mains gas Good Good Programmer, room thermostat and TRVs Good Good Low energy lighting in 70% of fixed outlets Very Good Very Good mains gas (not community) 0.0 2.4 0.0 N natural 9, Gatley Avenue, Fallowfield Manchester Manchester, Gorton England and Wales: 1900-1929 2021-02-24 00:00:00 Rented (social) 10.0 7.0 77112462.0 Energy Assessor 100

View file

@ -92,22 +92,26 @@ class TestProperty:
@pytest.fixture(autouse=True)
def property_instance(self, mock_cleaner):
epc_record = EPCRecord()
prepared_epc = mock_epc_response["rows"][0].copy()
# Replace hyphens with underscores
prepared_epc = {k.replace("-", "_"): v for k, v in prepared_epc.items()}
epc_record.prepared_epc = prepared_epc
epc_record.uprn = prepared_epc["uprn"]
# Set all required attributes directly on epc_record
epc_record.uprn = 1
epc_record.lighting_cost_current = 123
epc_record.epc_co2_emissions = 5
epc_record.primary_energy_consumption = 1234
epc_record.roof_description = "pitched, no insulation"
epc_record.walls_description = "Walls Description"
epc_record.windows_description = "Fully double glazed"
epc_record.mainheat_description = "Boiler and radiators, mains gas"
epc_record.hotwater_description = "From main system"
epc_record.floor_description = "Floor Description"
epc_record.floor_level = "Ground"
epc_record.property_type = "House"
# Add any other attributes needed by the tests
property_instance = Property(id=1, postcode="AB12CD", address="Test Address", epc_record=epc_record)
property_instance.number_of_floors = 2
property_instance.number_of_rooms = 5
property_instance.floor_area = 100
property_instance.floor_height = 2.5
# Fill these values that come from the epc_record
property_instance.energy["primary_energy_consumption"] = 1234
property_instance.energy["epc_co2_emissions"] = 5
return property_instance
@pytest.fixture()
@ -208,16 +212,24 @@ class TestProperty:
def test_init(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"uprn": 1}
epc_record.uprn = 1
epc_record.lighting_cost_current = 123
epc_record.epc_co2_emissions = 5
epc_record.primary_energy_consumption = 1234
epc_record.roof_description = "pitched, no insulation"
epc_record.walls_description = "Walls Description"
epc_record.windows_description = "Fully double glazed"
epc_record.mainheat_description = "Boiler and radiators, mains gas"
epc_record.hotwater_description = "From main system"
epc_record.floor_description = "Floor Description"
epc_record.floor_level = "Ground"
epc_record.property_type = "House"
inst1 = Property(0, postcode="AB12CD", address="Test Address", epc_record=epc_record)
assert inst1.data is not None
assert inst1.epc_record.uprn == 1
inst2 = Property(3, "AB12CD", "Test Address", epc_record=epc_record)
assert inst2.id == 3
inst3 = Property(4, "AB12CD", "Test Address", epc_record=epc_record)
assert inst3.data == {"uprn": 1}
assert inst3.epc_record.uprn == 1
def test_set_features(
self, property_instance, mock_cleaner, kwh_client,
@ -225,97 +237,18 @@ class TestProperty:
kwh_predictions = {
"heating_kwh_predictions": pd.DataFrame(
[
{"id": property_instance.uprn, "predictions": 12000}
{"id": property_instance.epc_record.uprn, "predictions": 12000}
]
),
"hotwater_kwh_predictions": pd.DataFrame(
[
{"id": property_instance.uprn, "predictions": 3000}
{"id": property_instance.epc_record.uprn, "predictions": 3000}
]
),
}
property_instance.set_features(
mock_cleaner.cleaned,
kwh_client,
kwh_predictions
)
# Verify that the components are set correctly
assert property_instance.roof == {
'original_description': 'pitched, no insulation', 'is_pitched': True,
'is_flat': False, 'is_roof_room': False
}
assert property_instance.walls == {
"original_description": "Walls Description",
"is_cavity_wall": True,
"is_solid_brick": False,
"is_timber_frame": False,
"is_system_built": False,
"is_park_home": False,
"is_cob": False,
"is_sandstone_or_limestone": False,
"is_granite_or_whinstone": False,
}
assert property_instance.windows == {
'original_description': 'Fully double glazed', 'has_glazing': True, 'glazing_coverage': 'full',
'glazing_type': 'double', 'no_data': False
}
assert property_instance.main_heating == {
'original_description': 'Boiler and radiators, mains gas', 'has_radiators': True,
'has_fan_coil_units': False, 'has_pipes_in_screed_above_insulation': False,
'has_pipes_in_insulated_timber_floor': False, 'has_pipes_in_concrete_slab': False, 'has_boiler': True,
'has_air_source_heat_pump': False, 'has_room_heaters': False, 'has_electric_storage_heaters': False,
'has_warm_air': False, 'has_electric_underfloor_heating': False, 'has_electric_ceiling_heating': False,
'has_community_scheme': False, 'has_ground_source_heat_pump': False, 'has_no_system_present': False,
'has_portable_electric_heaters': False, 'has_water_source_heat_pump': False, 'has_electric': False,
'has_mains_gas': True, 'has_wood_logs': False, 'has_coal': False, 'has_oil': False,
'has_wood_pellets': False, 'has_anthracite': False, 'has_dual_fuel_mineral_and_wood': False,
'has_smokeless_fuel': False, 'has_lpg': False, 'has_assumed': False, 'has_electricaire': False,
'has_assumed_for_most_rooms': False, 'has_underfloor_heating': False, 'has_electric_heat_pumps': False,
'has_micro-cogeneration': False
}
assert property_instance.hotwater == {
'original_description': 'From main system', 'heater_type': None,
'system_type': 'from main system', 'thermostat_characteristics': None,
'heating_scope': None, 'energy_recovery': None, 'tariff_type': None,
'extra_features': None, 'chp_systems': None, 'distribution_system': None,
'no_system_present': None, 'assumed': False, 'appliance': None
}
assert property_instance.wall_type == "cavity"
def test_get_components_without_cleaned_data(self, property_instance, mock_cleaner):
# Modify the mock EpcClean to not have cleaned data
mock_cleaner.cleaned = {}
# Verify that ValueError is raised when EpcClean doesn't contain cleaned data
with pytest.raises(ValueError, match="Cleaner does not contain cleaned data"):
property_instance.set_features(mock_cleaner.cleaned, pd.DataFrame(), pd.DataFrame())
def test_get_components_no_attributes(
self, property_instance, mock_cleaner, kwh_client
):
kwh_predictions = {
"heating_kwh_predictions": pd.DataFrame(
[
{"id": property_instance.uprn, "predictions": 12000}
]
),
"hotwater_kwh_predictions": pd.DataFrame(
[
{"id": property_instance.uprn, "predictions": 3000}
]
),
}
# Modify the mock cleaner to have no attributes for a specific description
mock_cleaner.cleaned = {
"roof-description": []
}
property_instance.data["roof-description"] = "Pitched, no insulation"
# Ensure required energy and walls attributes are set
property_instance.energy["epc_co2_emissions"] = 1.0
property_instance.energy["appliances_co2_emissions"] = 1.0
property_instance.walls = {
"original_description": "Walls Description",
"is_cavity_wall": True,
@ -327,34 +260,71 @@ class TestProperty:
"is_sandstone_or_limestone": False,
"is_granite_or_whinstone": False,
}
property_instance.floor = {
"is_suspended": False,
"another_property_below": False,
"is_solid": True
}
property_instance.main_heating = {
'original_description': 'Boiler and radiators, mains gas', 'has_radiators': True,
'has_fan_coil_units': False, 'has_pipes_in_screed_above_insulation': False,
'has_pipes_in_insulated_timber_floor': False, 'has_pipes_in_concrete_slab': False, 'has_boiler': True,
'has_air_source_heat_pump': False, 'has_room_heaters': False, 'has_electric_storage_heaters': False,
'has_warm_air': False, 'has_electric_underfloor_heating': False, 'has_electric_ceiling_heating': False,
'has_community_scheme': False, 'has_ground_source_heat_pump': False, 'has_no_system_present': False,
'has_portable_electric_heaters': False, 'has_water_source_heat_pump': False, 'has_electric': False,
'has_mains_gas': True, 'has_wood_logs': False, 'has_coal': False, 'has_oil': False,
'has_wood_pellets': False, 'has_anthracite': False, 'has_dual_fuel_mineral_and_wood': False,
'has_smokeless_fuel': False, 'has_lpg': False, 'has_assumed': False, 'has_electricaire': False,
'has_assumed_for_most_rooms': False, 'has_underfloor_heating': False, 'has_electric_heat_pumps': False,
'has_micro-cogeneration': False
}
property_instance.hotwater = {
'original_description': 'From main system', 'heater_type': None, 'system_type': 'from main system',
'thermostat_characteristics': None, 'heating_scope': None, 'energy_recovery': None,
'tariff_type': None,
'extra_features': None, 'chp_systems': None, 'distribution_system': None, 'no_system_present': None,
'assumed': False, "appliance": None
}
property_instance.set_features(
mock_cleaner.cleaned,
kwh_client,
kwh_predictions
)
# ...existing code for assertions...
# Assert backup cleaning has been applied
def test_get_components_without_cleaned_data(self, property_instance, mock_cleaner):
# Modify the mock EpcClean to not have cleaned data
mock_cleaner.cleaned = {}
# No direct assignment to prepared_epc here, but for robustness, patch if needed
# Verify that ValueError is raised when EpcClean doesn't contain cleaned data
with pytest.raises(ValueError, match="Cleaner does not contain cleaned data"):
property_instance.set_features(mock_cleaner.cleaned, pd.DataFrame(), pd.DataFrame())
def test_get_components_no_attributes(
self, property_instance, mock_cleaner, kwh_client
):
kwh_predictions = {
"heating_kwh_predictions": pd.DataFrame(
[
{"id": property_instance.epc_record.uprn, "predictions": 12000}
]
),
"hotwater_kwh_predictions": pd.DataFrame(
[
{"id": property_instance.epc_record.uprn, "predictions": 3000}
]
),
}
# Modify the mock cleaner to have no attributes for a specific description
mock_cleaner.cleaned = {
"roof-description": []
}
property_instance.epc_record.roof_description = "Pitched, no insulation"
# Ensure required energy and walls attributes are set
property_instance.energy["epc_co2_emissions"] = 1.0
property_instance.energy["appliances_co2_emissions"] = 1.0
property_instance.walls = {
"original_description": "Walls Description",
"is_cavity_wall": True,
"is_solid_brick": False,
"is_timber_frame": False,
"is_system_built": False,
"is_park_home": False,
"is_cob": False,
"is_sandstone_or_limestone": False,
"is_granite_or_whinstone": False,
}
# Ensure required floor attribute is set
property_instance.floor = {
"original_description": "Solid, no insulation (assumed)",
"clean_description": "Pitched, no insulation",
"thermal_transmittance": None,
"thermal_transmittance_unit": None,
"is_assumed": False,
"is_to_unheated_space": False,
"is_to_external_air": False,
"is_suspended": False,
"is_solid": True,
"another_property_below": False,
"insulation_thickness": "none",
"floor_thermal_transmittance": None,
"floor_insulation_thickness": "none"
}
property_instance.set_features(
mock_cleaner.cleaned,
kwh_client,
@ -368,86 +338,83 @@ class TestProperty:
self, property_instance, mock_cleaner, kwh_client
):
# This shouldn't happen - it would mean a cleaning error
property_instance.data["roof-description"] = "Roof Description"
property_instance.epc_record.roof_description = "Roof Description"
cleaned = {
"roof-description": [
{"original_description": "Roof Description"},
{"original_description": "Roof Description"}
]
}
kwh_predictions = {
"heating_kwh_predictions": pd.DataFrame(
[
{"id": property_instance.uprn, "predictions": 12000}
{"id": property_instance.epc_record.uprn, "predictions": 12000}
]
),
"hotwater_kwh_predictions": pd.DataFrame(
[
{"id": property_instance.uprn, "predictions": 3000}
{"id": property_instance.epc_record.uprn, "predictions": 3000}
]
),
}
# Verify that ValueError is raised when multiple attributes are found
with pytest.raises(ValueError, match="Either No attributes or multiple found for roof-description"):
property_instance.set_features(cleaned, kwh_client, kwh_predictions)
def test_set_spatial(self):
from unittest.mock import patch, PropertyMock
epc_record = EPCRecord()
epc_record.prepared_epc = mock_epc_response["rows"][0]
epc_record.uprn = mock_epc_response["rows"][0]["uprn"]
prop = Property(1, postcode="AB12CD", address="Test Address", epc_record=epc_record)
with patch.object(type(epc_record), "prepared_epc", new_callable=PropertyMock) as mock_prepared_epc:
mock_prepared_epc.return_value = mock_epc_response["rows"][0]
epc_record.uprn = int(mock_epc_response["rows"][0]["uprn"])
prop = Property(1, postcode="AB12CD", address="Test Address", epc_record=epc_record)
spatial1 = pd.DataFrame([{
'X_COORDINATE': 411143.0, 'Y_COORDINATE': 281701.0, 'LATITUDE': 52.4331896, 'LONGITUDE': -1.8375238,
'conservation_status': True, 'is_listed_building': False, 'is_heritage_building': True
}])
spatial1 = pd.DataFrame([{
'X_COORDINATE': 411143.0, 'Y_COORDINATE': 281701.0, 'LATITUDE': 52.4331896, 'LONGITUDE': -1.8375238,
'conservation_status': True, 'is_listed_building': False, 'is_heritage_building': True
}])
prop.set_spatial(spatial1)
prop.set_spatial(spatial1)
assert prop.in_conservation_area
assert not prop.is_listed
assert prop.is_heritage
assert prop.restricted_measures
assert prop.in_conservation_area
assert not prop.is_listed
assert prop.is_heritage
assert prop.restricted_measures
prop2 = Property(1, "AB12CD", "Test Address", epc_record=epc_record)
prop2 = Property(1, "AB12CD", "Test Address", epc_record=epc_record)
spatial2 = pd.DataFrame([{
'X_COORDINATE': 411143.0, 'Y_COORDINATE': 281701.0, 'LATITUDE': 52.4331896, 'LONGITUDE': -1.8375238,
'conservation_status': None, 'is_listed_building': False, 'is_heritage_building': False
}])
spatial2 = pd.DataFrame([{
'X_COORDINATE': 411143.0, 'Y_COORDINATE': 281701.0, 'LATITUDE': 52.4331896, 'LONGITUDE': -1.8375238,
'conservation_status': None, 'is_listed_building': False, 'is_heritage_building': False
}])
prop2.set_spatial(spatial2)
prop2.set_spatial(spatial2)
assert prop2.in_conservation_area is None
assert not prop2.is_listed
assert not prop2.is_heritage
assert not prop2.restricted_measures
assert prop2.in_conservation_area is None
assert not prop2.is_listed
assert not prop2.is_heritage
assert not prop2.restricted_measures
def test_set_floor_level(self):
# In this case, we have a flat which looks looks it's on the first floor, but it's actually on the ground
# floor, so we should set floor_level to 0
# 1st case: floor-level '01', property-type 'Flat'
epc_record = EPCRecord()
epc_record.prepared_epc = {'floor-level': '01', 'property-type': 'Flat'}
epc_record.uprn = 1
epc_record.floor_level = '01'
epc_record.property_type = 'Flat'
prop = Property(1, postcode="AB12CD", address="Test Address", epc_record=epc_record)
prop.floor = {
'original_description': 'Solid, no insulation (assumed)', 'clean_description': 'Solid, no insulation',
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_assumed': True,
'is_to_unheated_space': False, 'is_to_external_air': False, 'is_suspended': False, 'is_solid': True,
'another_property_below': False, 'insulation_thickness': 'none', 'floor_thermal_transmittance': None,
'floor_insulation_thickness': 'none'
'floor_insulation_thickness': 'none',
}
prop.set_floor_level()
assert prop.floor_level == 0
# This property is labelled as being on the ground floor but actually has another property below
# so we set floor level to 1
# 2nd case: floor-level 'Ground', property-type 'Flat'
epc_record = EPCRecord()
epc_record.prepared_epc = {'floor-level': 'Ground', 'property-type': 'Flat'}
epc_record.floor_level = 'Ground'
epc_record.property_type = 'Flat'
prop2 = Property(1, postcode="AB12CD", address="Test Address", epc_record=epc_record)
prop2.floor = {
'original_description': '(Another dwelling below)', 'clean_description': 'Solid, no insulation',
@ -456,14 +423,13 @@ class TestProperty:
'another_property_below': True, 'insulation_thickness': 'none', 'floor_thermal_transmittance': None,
'floor_insulation_thickness': 'none'
}
prop2.set_floor_level()
assert prop2.floor_level == 1
# this property is correctly labelled as being on the 2nd floor
# 3rd case: floor-level '02', property-type 'Flat'
epc_record = EPCRecord()
epc_record.prepared_epc = {'floor-level': '02', 'property-type': 'Flat'}
epc_record.floor_level = '02'
epc_record.property_type = 'Flat'
prop3 = Property(1, postcode="AB12CD", address="Test Address", epc_record=epc_record)
prop3.floor = {
'original_description': '(Another dwelling below)', 'clean_description': 'Solid, no insulation',
@ -472,14 +438,13 @@ class TestProperty:
'another_property_below': True, 'insulation_thickness': 'none', 'floor_thermal_transmittance': None,
'floor_insulation_thickness': 'none'
}
prop3.set_floor_level()
assert prop3.floor_level == 2
# Example of a house
# 4th case: floor-level '', property-type 'House'
epc_record = EPCRecord()
epc_record.prepared_epc = {'floor-level': '', 'property-type': 'House'}
epc_record.floor_level = ''
epc_record.property_type = 'House'
prop4 = Property(1, postcode="AB12CD", address="Test Address", epc_record=epc_record)
prop4.floor = {
'original_description': '(Another dwelling below)', 'clean_description': 'Solid, no insulation',
@ -488,7 +453,5 @@ class TestProperty:
'another_property_below': False, 'insulation_thickness': 'none', 'floor_thermal_transmittance': None,
'floor_insulation_thickness': 'none'
}
prop4.set_floor_level()
assert prop4.floor_level is None

View file

@ -0,0 +1,187 @@
import os
import pickle
import pandas as pd
import pytest
from datetime import datetime
from backend.ml_models.api import ModelApi
from backend.app.utils import sap_to_epc
from backend.app.config import get_prediction_buckets
def load_sample_certificates():
"""Load sample_certificates.csv as a DataFrame with normalized columns."""
csv_path = os.path.join(os.getcwd(), 'backend', 'tests', 'test_data', 'sample_certificates.csv')
if not os.path.exists(csv_path):
raise FileNotFoundError(
f"sample_certificates.csv not found at {csv_path}. Make sure it exists relative to the project root.")
df = pd.read_csv(csv_path)
df.columns = [c.strip().lower().replace('_', '-') for c in df.columns]
df = df[~pd.isnull(df["uprn"])]
df = df[~pd.isnull(df["low-energy-fixed-light-count"])]
df = df.fillna("")
for col in ["uprn", "low-energy-fixed-light-count"]:
df[col] = df[col].astype(int).astype(str)
df = df.astype(str)
return df
def make_property_from_row(row, cleaning_data):
from etl.epc.Record import EPCRecord
from backend.Property import Property
row_dict = row.to_dict()
from etl.epc.Record import InputEpcRecords
epc_records = InputEpcRecords(
original_epc=row_dict.copy(),
full_sap_epc=row_dict.copy(),
old_data=[]
)
epc_record = EPCRecord(
epc_records=epc_records,
run_mode="newdata",
cleaning_data=cleaning_data
)
id_val = row.get('uprn')
postcode_val = row.get('postcode')
address_val = row.get('address') or row.get('address1')
return Property(
id=id_val,
postcode=postcode_val,
address=address_val,
epc_record=epc_record,
uprn=int(row['uprn']) if 'uprn' in row and not pd.isnull(row['uprn']) else None,
)
def load_cleaned():
with open("recommendations/tests/test_data/cleaned.pkl", "rb") as f:
return pickle.load(f)
def load_cleaning_data():
with open("recommendations/tests/test_data/cleaning_data.pkl", "rb") as f:
return pickle.load(f)
@pytest.mark.integration
def test_rebaselining_pipeline_with_real_data():
df = load_sample_certificates()
cleaning_data = load_cleaning_data()
input_properties = [make_property_from_row(row, cleaning_data=cleaning_data) for _, row in df.iterrows()]
cleaned = load_cleaned()
rebaselining_scoring_data = []
for p in input_properties:
p.create_base_difference_epc_record(cleaned_lookup=cleaned)
scoring_data = p.base_difference_record.df.copy()
rebaselining_scoring_data.append(scoring_data)
if not rebaselining_scoring_data:
assert False, "No properties required rebaselining in the sample data."
rebaselining_scoring_data = pd.concat(rebaselining_scoring_data)
rebaselining_scoring_data["is_post_sap10_starting"] = False
model_api = ModelApi(
portfolio_id="test-portfolio",
timestamp=datetime.now().isoformat(),
prediction_buckets={
"sap_change_predictions": "retrofit-sap-predictions-dev",
"heat_demand_predictions": "retrofit-heat-predictions-dev",
"carbon_change_predictions": "retrofit-carbon-predictions-dev",
"heating_kwh_predictions": "retrofit-heating-kwh-predictions-dev",
"hotwater_kwh_predictions": "retrofit-hotwater-kwh-predictions-dev",
"retrofit_sap_baseline_predictions": "retrofit-sap-baseline-predictions-dev",
"retrofit_carbon_baseline_predictions": "retrofit-carbon-baseline-predictions-dev",
"retrofit_heat_baseline_predictions": "retrofit-heat-baseline-predictions-dev",
},
max_retries=1
)
bucket = "retrofit-data-dev"
model_prefixes = model_api.BASELINE_MODEL_PREFIXES
rebaselining_response = model_api.predict_all(
df=rebaselining_scoring_data,
bucket=bucket,
model_prefixes=model_prefixes,
extract_ids=False,
extract_uprn=True
)
input_properties_by_uprn = {int(p.uprn): p for p in input_properties if p.uprn is not None}
model_names = [
"retrofit_sap_baseline_predictions",
"retrofit_carbon_baseline_predictions",
"retrofit_heat_baseline_predictions",
]
predictions_by_model_and_uprn = {}
uprn_to_originals = {}
for p in input_properties:
if p.uprn is not None and hasattr(p, 'epc_record') and hasattr(p.epc_record, 'original_epc'):
orig = p.epc_record.original_epc
uprn_to_originals[int(p.uprn)] = {
'original_sap': orig.get('current-energy-efficiency'),
'original_carbon': orig.get('co2-emissions-current'),
'original_heat': orig.get('energy-consumption-current'),
}
def calculate_mape(df, pred_col, actual_col):
df = df.copy()
df[pred_col] = pd.to_numeric(df[pred_col], errors="coerce")
df[actual_col] = pd.to_numeric(df[actual_col], errors="coerce")
valid = (
df[actual_col].notnull() &
df[pred_col].notnull() &
(df[actual_col] != 0)
)
if valid.sum() == 0:
return None
mape = ((df.loc[valid, pred_col] - df.loc[valid, actual_col]).abs() / df.loc[
valid, actual_col].abs()).mean() * 100
return mape
mape_results = {}
for model in model_names:
df_pred = rebaselining_response[model]
df_pred['original_sap'] = df_pred['uprn'].map(lambda u: uprn_to_originals.get(int(u), {}).get('original_sap'))
df_pred['original_carbon'] = df_pred['uprn'].map(
lambda u: uprn_to_originals.get(int(u), {}).get('original_carbon'))
df_pred['original_heat'] = df_pred['uprn'].map(lambda u: uprn_to_originals.get(int(u), {}).get('original_heat'))
predictions_by_model_and_uprn[model] = dict(zip(df_pred["uprn"].astype(int), df_pred["predictions"]))
if model == "retrofit_sap_baseline_predictions":
actual_col = "original_sap"
metric_name = "sap"
elif model == "retrofit_carbon_baseline_predictions":
actual_col = "original_carbon"
metric_name = "carbon"
elif model == "retrofit_heat_baseline_predictions":
actual_col = "original_heat"
metric_name = "heat"
else:
continue
mape = calculate_mape(df_pred, "predictions", actual_col)
if mape is not None:
mape_results[metric_name] = mape
print(f"MAPE ({metric_name}): {mape:.2f}%")
else:
print(f"MAPE ({metric_name}): No valid data")
MAX_MAPE = {
"sap": 4.6,
"carbon": 21.0,
"heat": 16.0,
}
for metric, mape in mape_results.items():
max_allowed = MAX_MAPE.get(metric, 100.0)
assert mape < max_allowed, f"{metric.upper()} MAPE too high: {mape:.2f}% > {max_allowed}%"
for uprn_int in rebaselining_scoring_data["uprn"].unique().astype(int):
property_instance = input_properties_by_uprn.get(uprn_int)
if property_instance is None:
continue
new_sap = predictions_by_model_and_uprn["retrofit_sap_baseline_predictions"][uprn_int]
new_carbon = predictions_by_model_and_uprn["retrofit_carbon_baseline_predictions"][uprn_int]
new_heat_demand = predictions_by_model_and_uprn["retrofit_heat_baseline_predictions"][uprn_int]
property_instance.epc_record.insert_new_performance_values(
new_sap=new_sap,
new_epc=sap_to_epc(new_sap),
new_carbon=new_carbon,
new_heat_demand=new_heat_demand,
)
updated = sum(1 for p in input_properties if getattr(p.epc_record, 'has_been_remodelled', False))
assert updated > 0, "No EPC records were updated."
print(f"Updated {updated} EPC records with new predictions.")

View file

@ -0,0 +1,26 @@
from .construction_age_band import EpcConstructionAgeBand
from .efficiency import EpcEfficiency
from .floor import EpcFloorDescriptions
from .fuel import EpcFuel
from .heating_controls import EpcHeatingControls
from .hotwater import EpcHotWaterSystems
from .main_heating import EpcHeatingSystems
from .property_type_built_form import PropertyType, BuiltForm
from .roof import EpcRoofDescriptions
from .walls import EpcWallDescriptions
from .windows import EpcWindowDescriptions
__all__ = [
"EpcConstructionAgeBand",
"EpcEfficiency",
"EpcFloorDescriptions",
"EpcFuel",
"EpcHeatingControls",
"EpcHotWaterSystems",
"EpcHeatingSystems",
"PropertyType",
"BuiltForm",
"EpcRoofDescriptions",
"EpcWallDescriptions",
"EpcWindowDescriptions",
]

View file

@ -15,7 +15,7 @@ class EpcConstructionAgeBand(Enum):
from_1996_to_2002: str = 'England and Wales: 1996-2002'
from_2003_to_2006: str = 'England and Wales: 2003-2006'
from_2007_to_2011: str = 'England and Wales: 2007-2011'
from_2012_onwards: str = 'England and Wales: 2012-onwards'
from_2012_onwards: str = 'England and Wales: 2012 onwards'
from_2012_to_2022: str = 'England and Wales: 2012-2022'
from_2023_onwards: str = 'England and Wales: 2023 onwards'

9
datatypes/epc/windows.py Normal file
View file

@ -0,0 +1,9 @@
from enum import Enum
class EpcWindowDescriptions(Enum):
fully_double_glazed: str = "Fully double glazed"
single_glazed: str = "Single glazed"
fully_triple_glazed: str = "Fully triple glazed"
high_performance_glazing: str = "High performance glazing"
full_secondary_glazing: str = "Full secondary glazing"

View file

@ -287,7 +287,7 @@ class KwhData:
:return:
"""
epc = p.data.copy()
epc = p.epc_record.to_dict(case="kebab", source="prepared")
numeric_cols = [
'current-energy-efficiency',
'potential-energy-efficiency', 'environment-impact-current',

View file

@ -177,9 +177,6 @@ class TrainingDataset(BaseDataset):
self._expand_description_to_features(cleaned_lookup)
self._adjust_assumed_values_in_wall_descriptions()
self._generate_u_values_from_features()
# TODO: For some of the features that we clean, we have either a true, false or possibly null value
# Those nulls should be False. clean_missings_after_description_process handles this but shouldn't
# need to
self._clean_missing_values()
self._null_validation(information="Clean Missing Values")
self._remove_abnormal_change_in_floor_area()
@ -212,11 +209,11 @@ class TrainingDataset(BaseDataset):
common_cols = [[col + "_starting", col + "_ending"] for col in common_cols]
self.df = self.df.loc[
:,
no_suffix_cols
+ only_ending_cols
+ [col for cols in common_cols for col in cols],
]
:,
no_suffix_cols
+ only_ending_cols
+ [col for cols in common_cols for col in cols],
]
def _remove_abnormal_change_in_floor_area(self):
"""

View file

@ -328,7 +328,7 @@ class EPCPipeline:
# model, since EPC standards and rigour have changed over time
variable_data = property_data[
VARIABLE_DATA_FEATURES + COST_FEATURES + POST_SAP10_FEATURE
]
]
uprn = str(uprn)
epc_records = [
@ -391,9 +391,7 @@ class EPCPipeline:
# Auto sort the records so that the record with highest RDSAP score is always record1
difference_record: EPCDifferenceRecord = (
latest_record.create_EPCDifferenceRecord(
other=earliest_record, fixed_data=fixed_data
)
latest_record.create_epc_difference_record(other=earliest_record, fixed_data=fixed_data)
)
# difference_record: EPCDifferenceRecord = latest_record - earliest_record
# # TODO: Use method above instead of overloading operator

View file

@ -0,0 +1,80 @@
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional
import pandas as pd
@dataclass
class RecommendationPrediction:
measure_id: str
prediction: Any
metadata: Dict[str, Any] = field(default_factory=dict)
@dataclass
class PredictionEntry:
uprn: int
rebaselined_prediction: Any = None
recommendation_predictions: List[RecommendationPrediction] = field(default_factory=list)
original_epc: Optional[Dict[str, Any]] = None
landlord_differences: Optional[Dict[str, Any]] = None
lodgement_date: Optional[Any] = None
class PredictionMatrix:
def __init__(self):
self.entries: Dict[int, PredictionEntry] = {}
def add_entry(self, entry: PredictionEntry):
self.entries[entry.uprn] = entry
def add_recommendation(self, uprn: int, measure_id: str, prediction: Any, metadata: Optional[Dict[str, Any]] = None):
if uprn not in self.entries:
self.entries[uprn] = PredictionEntry(uprn=uprn)
rec = RecommendationPrediction(measure_id=measure_id, prediction=prediction, metadata=metadata or {})
self.entries[uprn].recommendation_predictions.append(rec)
def set_rebaselined_prediction(self, uprn: int, prediction: Any):
if uprn not in self.entries:
self.entries[uprn] = PredictionEntry(uprn=uprn)
self.entries[uprn].rebaselined_prediction = prediction
def set_original_epc(self, uprn: int, original_epc: Dict[str, Any], landlord_differences: Dict[str, Any], lodgement_date: Any = None):
if uprn not in self.entries:
self.entries[uprn] = PredictionEntry(uprn=uprn)
self.entries[uprn].original_epc = original_epc
self.entries[uprn].landlord_differences = landlord_differences
self.entries[uprn].lodgement_date = lodgement_date
def to_dataframe(self) -> pd.DataFrame:
rows = []
for entry in self.entries.values():
base = {
"uprn": entry.uprn,
"rebaselined_prediction": entry.rebaselined_prediction,
"lodgement_date": entry.lodgement_date,
"landlord_differences": entry.landlord_differences,
}
# Add original EPC fields if present
if entry.original_epc and entry.landlord_differences:
for k in entry.landlord_differences.keys():
base[f"{k}_ori"] = entry.original_epc.get(k)
base[f"{k}_ll"] = entry.landlord_differences.get(k)
# Add measure-level predictions
for rec in entry.recommendation_predictions:
row = base.copy()
row["measure_id"] = rec.measure_id
row["measure_prediction"] = rec.prediction
row["measure_metadata"] = rec.metadata
rows.append(row)
if not entry.recommendation_predictions:
rows.append(base)
return pd.DataFrame(rows)
def summarise_differences(self, df: Optional[pd.DataFrame] = None) -> pd.DataFrame:
if df is None:
df = self.to_dataframe()
ori_cols = [c for c in df.columns if c.endswith("_ori")]
for ori_col in ori_cols:
ll_col = ori_col.replace("_ori", "_ll")
if ll_col in df.columns:
same = df[ori_col].fillna("NULL") == df[ll_col].fillna("NULL")
df.loc[same, [ori_col, ll_col]] = None
return df

File diff suppressed because it is too large Load diff

View file

@ -2,11 +2,16 @@ import pickle
import pytest
from etl.epc.Record import EPCRecord
from etl.epc.settings import DATA_ANOMALY_MATCHES
import random
class TestEpcRecord:
@pytest.fixture
def base_record(self):
record = EPCRecord(run_mode="training")
record._prepared_epc = {}
return record
@pytest.fixture()
def cleaning_data(self):
with open("recommendations/tests/test_data/cleaning_data.pkl", "rb") as f:
@ -17,238 +22,142 @@ class TestEpcRecord:
@pytest.fixture()
def epc_records_1(self):
epc_records_1 = {
'original_epc': {
'low-energy-fixed-light-count': '', 'address': '139 School Road, Hall Green',
'uprn-source': 'Energy Assessor', 'floor-height': '2.6', 'heating-cost-potential': '1138',
'unheated-corridor-length': '', 'hot-water-cost-potential': '175',
'construction-age-band': 'England and Wales: 1900-1929', 'potential-energy-rating': 'B',
'mainheat-energy-eff': 'Good', 'windows-env-eff': 'Average', 'lighting-energy-eff': 'Very Good',
'environment-impact-potential': '82', 'glazed-type': 'double glazing, unknown install date',
'heating-cost-current': '2711', 'address3': '',
'mainheatcont-description': 'Programmer, TRVs and bypass',
'sheating-energy-eff': 'N/A', 'property-type': 'House', 'local-authority-label': 'Birmingham',
'fixed-lighting-outlets-count': '11', 'energy-tariff': 'Single', 'mechanical-ventilation': 'natural',
'hot-water-cost-current': '310', 'county': '', 'postcode': 'B28 8JF', 'solar-water-heating-flag': 'N',
'constituency': 'E14000562', 'co2-emissions-potential': '2.0', 'number-heated-rooms': '4',
'floor-description': 'Suspended, no insulation (assumed)', 'energy-consumption-potential': '107',
'local-authority': 'E08000025', 'built-form': 'Semi-Detached', 'number-open-fireplaces': '0',
'windows-description': 'Fully double glazed', 'glazed-area': 'Normal', 'inspection-date': '2023-07-05',
'mains-gas-flag': 'Y', 'co2-emiss-curr-per-floor-area': '65', 'address1': '139 School Road',
'heat-loss-corridor': '', 'flat-storey-count': '', 'constituency-label': 'Birmingham, Hall Green',
'roof-energy-eff': 'Average', 'total-floor-area': '103.0', 'building-reference-number': '10004697322',
'environment-impact-current': '43', 'co2-emissions-current': '6.7',
'roof-description': 'Pitched, 100 mm loft insulation', 'floor-energy-eff': 'N/A',
'number-habitable-rooms': '4', 'address2': 'Hall Green', 'hot-water-env-eff': 'Good',
'posttown': 'BIRMINGHAM', 'mainheatc-energy-eff': 'Average', 'main-fuel': 'mains gas (not community)',
'lighting-env-eff': 'Very Good', 'windows-energy-eff': 'Average', 'floor-env-eff': 'N/A',
'sheating-env-eff': 'N/A', 'lighting-description': 'Low energy lighting in 82% of fixed outlets',
'roof-env-eff': 'Average', 'walls-energy-eff': 'Very Poor', 'photo-supply': '0.0',
'lighting-cost-potential': '182', 'mainheat-env-eff': 'Good', 'multi-glaze-proportion': '100',
'main-heating-controls': '', 'lodgement-datetime': '2023-07-13 08:23:07', 'flat-top-storey': '',
'current-energy-rating': 'E', 'secondheat-description': 'None', 'walls-env-eff': 'Very Poor',
'transaction-type': 'rental', 'uprn': '100070505235', 'current-energy-efficiency': '51',
'energy-consumption-current': '366', 'mainheat-description': 'Boiler and radiators, mains gas',
'lighting-cost-current': '182', 'lodgement-date': '2023-07-13', 'extension-count': '0',
'mainheatc-env-eff': 'Average',
'lmk-key': 'c1d137711da433fb3cced74b1a6848da8bbc1159d076455d26d7b4668982601e',
'wind-turbine-count': '0',
'tenure': 'Rented (social)', 'floor-level': '', 'potential-energy-efficiency': '84',
'hot-water-energy-eff': 'Good', 'low-energy-lighting': '82',
'walls-description': 'Solid brick, as built, no insulation (assumed)',
'hotwater-description': 'From main system'}, 'full_sap_epc': {}, 'old_data': []
"original_epc": {
"fixed-lighting-outlets-count": "11",
"property-type": "House",
"built-form": "Semi-Detached",
"construction-age-band": "England and Wales: 1900-1929",
"local-authority": "E08000025",
"number-habitable-rooms": "4",
"number-heated-rooms": "4",
},
"full_sap_epc": {},
"old_data": [],
}
return epc_records_1
def test_clean_mechanical_ventilation(self, cleaning_data, epc_records_1):
# We have an epc with Natural ventilation - the resulting epc should also have natural ventulation
def test_clean_built_form_valid_remap(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"mechanical-ventilation": "natural"
}
record._clean_ventilation()
assert record.prepared_epc["mechanical-ventilation"] == "natural"
record2 = EPCRecord(cleaning_data=cleaning_data)
record2.prepared_epc = {
"mechanical-ventilation": ""
}
record2._clean_ventilation()
assert record2.prepared_epc["mechanical-ventilation"] is None
record3 = EPCRecord(cleaning_data=cleaning_data)
record3.prepared_epc = {
"mechanical-ventilation": None
}
record3._clean_ventilation()
assert record3.prepared_epc["mechanical-ventilation"] is None
record4 = EPCRecord(cleaning_data=cleaning_data)
record4.prepared_epc = {
"mechanical-ventilation": "INVALID"
}
record4._clean_ventilation()
assert record4.prepared_epc["mechanical-ventilation"] is None
def test_clean_energy_valid_values(self, cleaning_data, epc_records_1):
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"energy-consumption-current": "200",
"co2-emissions-current": "5.5"
}
record._clean_energy()
assert record.prepared_epc["energy-consumption-current"] == 200.0
assert record.prepared_epc["co2-emissions-current"] == 5.5
def test_clean_energy_empty_values(self, cleaning_data):
# We cannot have invalid values so this should raise an exception
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"energy-consumption-current": "",
"co2-emissions-current": ""
}
with pytest.raises(ValueError):
record._clean_energy()
def test_clean_built_form_valid_remap(self, cleaning_data, epc_records_1):
record = EPCRecord(cleaning_data=cleaning_data)
# Assuming "Semi" should be remapped to "Semi-Detached"
record.prepared_epc = {
record._prepared_epc = {
"built-form": "Semi-Detached",
"property-type": "Flat" # Assuming this affects the remapping
"property-type": "Flat"
}
record._clean_built_form()
assert record.prepared_epc["built-form"] == "Semi-Detached"
assert record._prepared_epc["built-form"] == "Semi-Detached"
def test_clean_built_form_anomaly(self, cleaning_data, epc_records_1):
def test_clean_built_form_anomaly(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
record._prepared_epc = {
"built-form": "",
"property-type": "Flat"
}
record._clean_built_form()
assert record.prepared_epc["built-form"] == "End-Terrace"
assert record._prepared_epc["built-form"] == "End-Terrace"
def test_clean_floor_area_valid(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
record._prepared_epc = {
"total-floor-area": "120.5"
}
record._clean_floor_area()
assert record.prepared_epc["total-floor-area"] == 120.5
assert record._prepared_epc["total-floor-area"] == 120.5
def test_clean_floor_area_empty(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
record._prepared_epc = {
"total-floor-area": ""
}
# We have no known case of missing floor area
with pytest.raises(ValueError):
record._clean_floor_area()
def test_clean_heat_loss_corridor_valid(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
record._prepared_epc = {
"heat-loss-corridor": "unheated corridor",
"unheated-corridor-length": ""
}
record._clean_heat_loss_corridor()
assert record.prepared_epc["heat-loss-corridor"] == "unheated corridor"
assert record._prepared_epc["heat-loss-corridor"] == "unheated corridor"
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
record._prepared_epc = {
"heat-loss-corridor": "unheated corridor",
"unheated-corridor-length": None
}
record._clean_heat_loss_corridor()
assert record.prepared_epc["heat-loss-corridor"] == "unheated corridor"
assert record.prepared_epc["unheated-corridor-length"] is None
assert record._prepared_epc["heat-loss-corridor"] == "unheated corridor"
assert record._prepared_epc["unheated-corridor-length"] is None
def test_clean_heat_loss_corridor_anomaly(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
# Assuming "InvalidCorridor" is an anomaly
record.prepared_epc = {
record._prepared_epc = {
"heat-loss-corridor": "InvalidCorridor",
"unheated-corridor-length": ""
}
record._clean_heat_loss_corridor()
assert record.prepared_epc["heat-loss-corridor"] == "no corridor"
def test_clean_mains_gas_valid(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"mains-gas-flag": "Y"
}
record._clean_mains_gas()
assert record.prepared_epc["mains-gas-flag"] is True
def test_clean_mains_gas_anomaly(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"mains-gas-flag": "InvalidValue"
}
# It should always be Y or N or an anomally value
with pytest.raises(KeyError):
record._clean_mains_gas()
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"mains-gas-flag": random.choice(list(DATA_ANOMALY_MATCHES))
}
record._clean_mains_gas()
assert record.prepared_epc["mains-gas-flag"] is None
assert record._prepared_epc["heat-loss-corridor"] == "no corridor"
def test_clean_solar_hot_water_valid(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
record._prepared_epc = {
"solar-water-heating-flag": "Y"
}
record._clean_solar_hot_water()
assert record.prepared_epc["solar-water-heating-flag"] == "Y"
assert record._prepared_epc["solar-water-heating-flag"] == "Y"
assert record.solar_water_heating_flag_bool is True
def test_clean_solar_hot_water_empty(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
record._prepared_epc = {
"solar-water-heating-flag": ""
}
record._clean_solar_hot_water()
assert record.prepared_epc["solar-water-heating-flag"] == "N"
assert record._prepared_epc["solar-water-heating-flag"] == "N"
assert record.solar_water_heating_flag_bool is False
def test_clean_number_lighting_outlets_valid(self, cleaning_data, epc_records_1):
record = EPCRecord(cleaning_data=cleaning_data, epc_records=epc_records_1)
record.prepared_epc = {
record._prepared_epc = {
"fixed-lighting-outlets-count": "5"
}
record._clean_number_lighting_outlets()
assert record.prepared_epc["fixed-lighting-outlets-count"] == 5.0
assert record._prepared_epc["fixed-lighting-outlets-count"] == 5.0
def test_clean_number_lighting_outlets_empty(self, cleaning_data, epc_records_1):
def test_clean_number_lighting_outlets_empty(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
record.run_mode = "newdata"
record.prepared_epc = {
record._prepared_epc = {
"fixed-lighting-outlets-count": "",
"property-type": "Flat",
"built-form": "Semi-Detached",
@ -257,104 +166,30 @@ class TestEpcRecord:
"number-habitable-rooms": "4",
"number-heated-rooms": "4",
}
record.old_data = []
record.full_sap_epc = []
record.full_sap_epc = {}
record._clean_number_lighting_outlets()
assert record.prepared_epc["fixed-lighting-outlets-count"] == 10
def test_clean_count_variables(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"number-open-fireplaces": "1",
"extension-count": None,
"flat-storey-count": "",
"number-habitable-rooms": "INVALID!",
}
record._clean_count_variables()
assert record.prepared_epc["number-open-fireplaces"] == 1.0
assert record.prepared_epc["extension-count"] == 0
assert record.prepared_epc["flat-storey-count"] is None
assert record.prepared_epc["number-habitable-rooms"] is None
assert record._prepared_epc["fixed-lighting-outlets-count"] == 10
def test_clean_floor_level(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"floor-level": "1",
}
record._prepared_epc = {"floor-level": "1"}
record._clean_floor_level()
assert record.prepared_epc["floor-level"] == 1.0
assert record._prepared_epc["floor-level"] == 1.0
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"floor-level": "",
}
record._prepared_epc = {"floor-level": ""}
record._clean_floor_level()
assert record.prepared_epc["floor-level"] is None
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"floor-level": None,
}
record._clean_floor_level()
assert record.prepared_epc["floor-level"] is None
def test_clean_solar_hot_water(self, cleaning_data):
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"solar-water-heating-flag": "Y",
}
record._clean_solar_hot_water()
assert record.prepared_epc["solar-water-heating-flag"] == "Y"
assert record.solar_water_heating_flag_bool is True
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"solar-water-heating-flag": "N",
}
record._clean_solar_hot_water()
assert record.prepared_epc["solar-water-heating-flag"] == "N"
assert record.solar_water_heating_flag_bool is False
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"solar-water-heating-flag": "",
}
record._clean_solar_hot_water()
assert record.prepared_epc["solar-water-heating-flag"] == "N"
assert record.solar_water_heating_flag_bool is False
record = EPCRecord(cleaning_data=cleaning_data)
record.prepared_epc = {
"solar-water-heating-flag": None,
}
record._clean_solar_hot_water()
assert record.prepared_epc["solar-water-heating-flag"] == "N"
assert record.solar_water_heating_flag_bool is False
assert record._prepared_epc["floor-level"] is None
def test_year_built(self, cleaning_data):
# This test handles a specific test case
@ -416,3 +251,146 @@ class TestEpcRecord:
)
assert prepared_epc.get("year_built") == 1900
def test_cleaning_rules_energy(self, base_record):
base_record._prepared_epc = {
"energy-consumption-current": "150",
"co2-emissions-current": "32.5"
}
base_record._apply_cleaning_rules()
assert base_record._prepared_epc["energy-consumption-current"] == 150.0
assert base_record._prepared_epc["co2-emissions-current"] == 32.5
def test_cleaning_rules_energy_anomaly(self, base_record):
base_record._prepared_epc = {
"energy-consumption-current": "INVALID",
"co2-emissions-current": "INVALID"
}
base_record._apply_cleaning_rules()
assert base_record._prepared_epc["energy-consumption-current"] == "INVALID"
assert base_record._prepared_epc["co2-emissions-current"] == "INVALID"
def test_cleaning_rules_mains_gas(self, base_record):
base_record._prepared_epc = {
"mains-gas-flag": "Y"
}
base_record._apply_cleaning_rules()
assert base_record._prepared_epc["mains-gas-flag"] is True
def test_cleaning_rules_mains_gas_anomaly(self, base_record):
base_record._prepared_epc = {
"mains-gas-flag": "INVALID"
}
base_record._apply_cleaning_rules()
assert base_record._prepared_epc["mains-gas-flag"] is None
def test_cleaning_rules_wind_turbine(self, base_record):
base_record._prepared_epc = {
"wind-turbine-count": "3"
}
base_record._apply_cleaning_rules()
assert base_record._prepared_epc["wind-turbine-count"] == 3
def test_cleaning_rules_extension_count(self, base_record):
base_record._prepared_epc = {
"extension-count": "2"
}
base_record._apply_cleaning_rules()
assert base_record._prepared_epc["extension-count"] == 2
def test_apply_averages_cleaning_fills_missing_values(self, cleaning_data):
record = EPCRecord(run_mode="training", cleaning_data=cleaning_data)
record._prepared_epc = {
"property-type": cleaning_data["property_type"].iloc[0],
"local-authority": cleaning_data["local_authority"].iloc[0],
"total-floor-area": float(cleaning_data["total_floor_area"].iloc[0]),
"number-habitable-rooms": None,
"number-heated-rooms": None,
"floor-height": None,
}
record._apply_averages_cleaning()
assert record._prepared_epc["number-habitable-rooms"] is not None
assert record._prepared_epc["number-heated-rooms"] is not None
assert record._prepared_epc["floor-height"] is not None
def test_apply_averages_cleaning_no_missing(self, cleaning_data):
record = EPCRecord(run_mode="training", cleaning_data=cleaning_data)
record._prepared_epc = {
"property-type": cleaning_data["property_type"].iloc[0],
"local-authority": cleaning_data["local_authority"].iloc[0],
"total-floor-area": float(cleaning_data["total_floor_area"].iloc[0]),
"number-habitable-rooms": 5,
"number-heated-rooms": 5,
"floor-height": 2.5,
}
original = record._prepared_epc.copy()
record._apply_averages_cleaning()
assert record._prepared_epc == original
def test_apply_averages_cleaning_caps_heated_rooms(self, cleaning_data):
record = EPCRecord(run_mode="training", cleaning_data=cleaning_data)
record._prepared_epc = {
"property-type": cleaning_data["property_type"].iloc[0],
"local-authority": cleaning_data["local_authority"].iloc[0],
"total-floor-area": float(cleaning_data["total_floor_area"].iloc[0]),
"number-habitable-rooms": None,
"number-heated-rooms": None,
"floor-height": None,
}
record._apply_averages_cleaning()
assert (
record._prepared_epc["number-heated-rooms"]
<= record._prepared_epc["number-habitable-rooms"]
)
def test_apply_averages_cleaning_floor_area_filter(self, cleaning_data):
record = EPCRecord(run_mode="training", cleaning_data=cleaning_data)
floor_area = float(cleaning_data["total_floor_area"].median())
record._prepared_epc = {
"property-type": cleaning_data["property_type"].iloc[0],
"local-authority": cleaning_data["local_authority"].iloc[0],
"total-floor-area": floor_area,
"number-habitable-rooms": None,
"number-heated-rooms": None,
"floor-height": None,
}
record._apply_averages_cleaning()
assert record._prepared_epc["floor-height"] > 0
def test_apply_averages_cleaning_requires_cleaning_data(self):
record = EPCRecord(run_mode="training", cleaning_data=None)
record._prepared_epc = {}
with pytest.raises(ValueError):
record._apply_averages_cleaning()

View file

@ -4,3 +4,5 @@ log_cli = true
log_cli_level = INFO
addopts = --cov-report term-missing --cov=etl/epc --cov=recommendations --cov=backend --cov=etl/epc_clean --cov=etl/spatial
testpaths = recommendations/tests backend/tests etl/epc/tests etl/epc_clean/tests etl/spatial/tests backend/condition/tests backend/address2UPRN/tests backend/onboarders/tests backend/categorisation/tests backend/export/tests
markers =
integration: mark a test as an integration test

View file

@ -200,20 +200,20 @@ class Costs:
self.property = property_instance
self.regional_labour_variations = regional_labour_variations
self.region = county_to_region_map.get(self.property.data["county"], None)
self.region = county_to_region_map.get(self.property.epc_record.county, None)
if self.region is None:
# Try and grab using the local-authority-label
self.region = county_to_region_map.get(self.property.data["local-authority-label"], None)
self.region = county_to_region_map.get(self.property.epc_record.local_authority_label, None)
if self.region is None:
# Try and get the region after converting the keys to lower
self.region = {
k.lower(): v for k, v in county_to_region_map.items()
}.get(self.property.data["local-authority-label"].lower(), None)
}.get(self.property.epc_record.local_authority_label.lower(), None)
if self.region is None:
logger.warning("No region found for county %s, defaulting to South East England",
self.property.data["county"])
self.property.epc_record.county)
self.region = "South East England"
self.labour_adjustment_factor = [
@ -858,8 +858,8 @@ class Costs:
n_radiators = self._estimate_n_radiators(
number_habitable_rooms=n_rooms,
total_floor_area=self.property.floor_area,
property_type=self.property.data["property-type"],
built_form=self.property.data["built-form"]
property_type=self.property.epc_record.property_type,
built_form=self.property.epc_record.built_form
)
additionals_labour_cost = labour_rate * self.labour_adjustment_factor

View file

@ -1,4 +1,3 @@
import pandas as pd
from BaseUtility import Definitions
from backend.Property import Property
@ -28,7 +27,7 @@ class FireplaceRecommendations(Definitions):
:return:
"""
number_open_fireplaces = int(self.property.data["number-open-fireplaces"])
number_open_fireplaces = self.property.epc_record.number_open_fireplaces
if number_open_fireplaces == 0:
return

View file

@ -9,7 +9,7 @@ from backend.app.plan.schemas import MEASURE_MAP
from backend.Property import Property
from recommendations.recommendation_utils import (
r_value_per_mm_to_u_value, calculate_u_value_uplift, is_diminishing_returns, update_lowest_selected_u_value,
get_recommended_part, get_floor_u_value, override_costs, check_simulation_difference
get_recommended_part, get_floor_u_value, override_costs, check_simulation_difference, check_use_survey
)
from recommendations.Costs import Costs
from etl.epc_clean.epc_attributes.FloorAttributes import FloorAttributes
@ -76,7 +76,7 @@ class FloorRecommendations(Definitions):
return
u_value = self.property.floor["thermal_transmittance"]
property_type = self.property.data["property-type"]
property_type = self.property.epc_record.property_type
floor_area = self.property.insulation_floor_area
if self.property.floor["another_property_below"] | (self.property.floor["insulation_thickness"] in [
@ -226,7 +226,6 @@ class FloorRecommendations(Definitions):
raise NotImplementedError("Implement me!")
sap_points = non_invasive_recs.get("sap_points", None)
survey = non_invasive_recs.get("survey", False)
floor_ending_config = FloorAttributes(new_description).process()
floor_simulation_config = check_simulation_difference(
@ -257,7 +256,9 @@ class FloorRecommendations(Definitions):
"starting_u_value": u_value,
"new_u_value": new_u_value,
"sap_points": sap_points,
"survey": survey,
"survey": check_use_survey(
non_invasive_recs, self.property.epc_record.has_been_remodelled
),
"already_installed": already_installed,
"simulation_config": simulation_config,
"description_simulation": {

View file

@ -56,7 +56,7 @@ class HeatingControlRecommender:
We can then consider the heating system itself
:return:
"""
if (self.property.data["mainheatc-energy-eff"] in ["Poor", "Very Poor", "Average"]) or (
if (self.property.epc_record.mainheatc_energy_eff in ["Poor", "Very Poor", "Average"]) or (
self.property.main_heating_controls["clean_description"] in ["Programmer and room thermostat"]
):
# We recommend Programmer and appliance thermostats as the heating control. This has an average energy
@ -125,10 +125,10 @@ class HeatingControlRecommender:
new_config=ending_config, old_config=self.property.main_heating_controls
)
# This upgrade will only take the heating system to average energy efficiency
if self.property.data["mainheatc-energy-eff"] in ["Poor", "Very Poor", "Average"]:
if self.property.epc_record.mainheatc_energy_eff in ["Poor", "Very Poor", "Average"]:
simulation_config["mainheatc_energy_eff_ending"] = "Good"
else:
simulation_config["mainheatc_energy_eff_ending"] = self.property.data["mainheatc-energy-eff"]
simulation_config["mainheatc_energy_eff_ending"] = self.property.epc_record.mainheatc_energy_eff
description_simulation = {
"mainheatcont-description": new_description,
@ -193,10 +193,10 @@ class HeatingControlRecommender:
)
# This upgrade will only take the heating system to average energy efficiency
# If the current system is below good, we make it good
if self.property.data["mainheatc-energy-eff"] in ["Poor", "Very Poor", "Average"]:
if self.property.epc_record.mainheatc_energy_eff in ["Poor", "Very Poor", "Average"]:
simulation_config["mainheatc_energy_eff_ending"] = "Good"
else:
simulation_config["mainheatc_energy_eff_ending"] = self.property.data["mainheatc-energy-eff"]
simulation_config["mainheatc_energy_eff_ending"] = self.property.epc_record.mainheatc_energy_eff
description_simulation = {
"mainheatcont-description": new_controls_description,
@ -208,7 +208,7 @@ class HeatingControlRecommender:
has_trvs = not needs_trvs
cost_result = self.costs.roomstat_programmer_trvs(
number_heated_rooms=int(self.property.data["number-heated-rooms"]),
number_heated_rooms=self.property.epc_record.number_heated_rooms,
has_programmer=has_programmer,
has_room_thermostat=has_room_thermostat,
has_trvs=has_trvs
@ -257,7 +257,7 @@ class HeatingControlRecommender:
if (
(self.property.main_heating_controls["thermostatic_control"] == "time and temperature zone control") or
(self.property.data["mainheatc-energy-eff"] in ["Very Good"])
(self.property.epc_record.mainheatc_energy_eff in ["Very Good"])
):
# No recommendation needed
return
@ -274,17 +274,17 @@ class HeatingControlRecommender:
)
# If the current system is below very good, we make it very good
if self.property.data["mainheatc-energy-eff"] in ["Poor", "Very Poor", "Average", "Good"]:
if self.property.epc_record.mainheatc_energy_eff in ["Poor", "Very Poor", "Average", "Good"]:
simulation_config["mainheatc_energy_eff_ending"] = "Very Good"
else:
simulation_config["mainheatc_energy_eff_ending"] = self.property.data["mainheatc-energy-eff"]
simulation_config["mainheatc_energy_eff_ending"] = self.property.epc_record.mainheatc_energy_eff
description_simulation = {
"mainheatcont-description": new_controls_description,
"mainheatc-energy-eff": simulation_config["mainheatc_energy_eff_ending"]
}
cost_result = self.costs.time_and_temperature_zone_control(
number_heated_rooms=int(self.property.data["number-heated-rooms"])
number_heated_rooms=self.property.epc_record.number_heated_rooms
)
description = (
@ -324,10 +324,10 @@ class HeatingControlRecommender:
new_config=ending_config, old_config=self.property.main_heating_controls
)
# Only adjust if the current system is below good
if self.property.data["mainheatc-energy-eff"] in ["Poor", "Very Poor"]:
if self.property.epc_record.mainheatc_energy_eff in ["Poor", "Very Poor"]:
simulation_config["mainheatc_energy_eff_ending"] = "Average"
else:
simulation_config["mainheatc_energy_eff_ending"] = self.property.data["mainheatc-energy-eff"]
simulation_config["mainheatc_energy_eff_ending"] = self.property.epc_record.mainheatc_energy_eff
description_simulation = {
"mainheatcont-description": new_controls_description,
@ -339,7 +339,7 @@ class HeatingControlRecommender:
has_bypass = self.property.main_heating_controls["auxiliary_systems"] == "bypass"
cost_result = self.costs.programmer_trvs_bypass(
number_heated_rooms=int(self.property.data["number-heated-rooms"]),
number_heated_rooms=self.property.epc_record.number_heated_rooms,
has_trvs=has_trvs,
has_programmer=has_programmer,
has_bypass=has_bypass

View file

@ -1,7 +1,7 @@
import re
import backend.app.assumptions as assumptions
from recommendations.recommendation_utils import (
check_simulation_difference, override_costs, combine_recommendation_configs
check_simulation_difference, override_costs, combine_recommendation_configs, check_use_survey
)
from backend.Property import Property
from backend.app.plan.schemas import MEASURE_MAP
@ -160,7 +160,7 @@ class HeatingRecommender:
"""
# We can also recommend hhr if the property doesn't have a mains has connection
no_mains = not self.property.data["mains-gas-flag"]
no_mains = not self.property.epc_record.mains_gas_flag
# If the property already has room heaters then we recommend HHR as an option since the home already has
# a variation of room heaters
@ -199,28 +199,28 @@ class HeatingRecommender:
# 2) If the property doesn't have a heating system, but it has access to the mains gas
no_heating_has_mains = self.property.main_heating["clean_description"] in [
'No system present, electric heaters assumed'
] and self.property.data["mains-gas-flag"]
] and self.property.epc_record.mains_gas_flag
# The property is using portable heaters and has access to gas mains
has_room_heaters = self.has_room_heaters and self.property.data["mains-gas-flag"]
has_room_heaters = self.has_room_heaters and self.property.epc_record.mains_gas_flag
# We also check if the property has electric heating, but it has access to the mains gas
electic_heating_has_mains = self.has_electric_heating_description and self.property.data["mains-gas-flag"]
electic_heating_has_mains = self.has_electric_heating_description and self.property.epc_record.mains_gas_flag
portable_heaters_has_mains = (
self.property.main_heating["has_portable_electric_heaters"] and self.property.data["mains-gas-flag"]
self.property.main_heating["has_portable_electric_heaters"] and self.property.epc_record.mains_gas_flag
)
# The next condition is if the home has a non-gas boiler, such as an oil boiler, with a mains gas connection
non_gas_boiler = (
self.property.main_heating["has_boiler"] and
not self.property.main_heating["has_mains_gas"] and
self.property.data["mains-gas-flag"]
self.property.epc_record.mains_gas_flag
)
# Additionally, if the property has a gas connection, is using gas heating but doesn't have a boiler,
# we recommend a boiler
non_boiler_gas_heating = (
self.property.data["mains-gas-flag"] and
self.property.epc_record.mains_gas_flag and
self.property.main_heating["has_mains_gas"] and
not self.property.main_heating["has_boiler"]
)
@ -386,7 +386,7 @@ class HeatingRecommender:
recommendation_phase = phase
if self.property.data["mainheat-energy-eff"] not in ["Poor", "Very Poor"]:
if self.property.epc_record.mainheat_energy_eff not in ["Poor", "Very Poor"]:
return
hotwater_from_mains = self.property.hotwater["clean_description"] in ["From main system"]
@ -407,7 +407,7 @@ class HeatingRecommender:
size=None,
exising_room_heaters=False,
system_change=False,
n_heated_rooms=self.property.data["number-heated-rooms"],
n_heated_rooms=self.property.epc_record.number_heated_rooms,
n_rooms=self.property.number_of_rooms,
is_electric=True
)
@ -581,7 +581,7 @@ class HeatingRecommender:
# New functions to estimate size of ASHP
estimated_load = self.estimate_peak_kw(
floor_area_m2=self.property.floor_area,
epc_primary_kwh_per_m2_yr=self.property.data["energy-consumption-current"],
epc_primary_kwh_per_m2_yr=self.property.epc_record.energy_consumption_current,
primary_to_delivered_factor=1.55, # use 1.13 if heating fuel is gas
space_heat_fraction_range=(0.35, 0.60),
hdd_base_dd=2000.0, # set from location
@ -670,7 +670,7 @@ class HeatingRecommender:
# If the property does not have existing cavity and loft insulation, we include a note that the cost
# includes the boiler upgrade scheme and that the cavity and loft need to be treated, to ensure access
# to the funding
if not non_intrusive_recommendation and self.property.data["tenure"] not in assumptions.SOCIAL_TENURES:
if not non_intrusive_recommendation and self.property.epc_record.tenure not in assumptions.SOCIAL_TENURES:
if has_cavity_or_loft_recommendations:
description = description + (
f" You must ensure that the property has an insulated cavity and "
@ -865,7 +865,9 @@ class HeatingRecommender:
"description_simulation": recommendation_description_simulation,
# We insert the heating system type here
"system_type": system_type,
"survey": non_intrusive_recommendation.get("survey", False),
"survey": check_use_survey(
non_intrusive_recommendation, self.property.epc_record.has_been_remodelled
),
# In this instance, we are recommending an entire heating system so the innovation rate is becased
# on the heating system as whole
"innovation_rate": heating_product["innovation_rate"],
@ -923,7 +925,7 @@ class HeatingRecommender:
# If the property is off-gas and has no heating system in place, the number of heated rooms will actually
# be 0, so we use the number of rooms as the figure
number_heated_rooms = (
self.property.data["number-heated-rooms"] if self.property.data["number-heated-rooms"] > 0
self.property.epc_record.number_heated_rooms if self.property.epc_record.number_heated_rooms > 0
else (
self.property.number_of_rooms - 1 if self.property.number_of_rooms > 1 else
self.property.number_of_rooms
@ -949,20 +951,20 @@ class HeatingRecommender:
}
# Fallback if property type unknown
base = base_by_type.get(self.property.data["property-type"], 1)
base = base_by_type.get(self.property.epc_record.property_type, 1)
# Area-based adjustments
if self.property.data["property-type"] in ("Flat", "Maisonette"):
if self.property.epc_record.property_type in ("Flat", "Maisonette"):
if self.property.floor_area > 90:
return base + 1 # duplex or very large flat
return base
if self.property.data["property-type"] == "Bungalow":
if self.property.epc_record.property_type == "Bungalow":
if self.property.floor_area > 100:
return base + 1 # secondary corridor
return base
if self.property.data["property-type"] == "House":
if self.property.epc_record.property_type == "House":
if self.property.floor_area > 140:
return base + 1 # extra landing / circulation
return base
@ -1060,17 +1062,17 @@ class HeatingRecommender:
**hot_water_simulation_config
}
# This upgrade will only take the heating system to average energy efficiency
if self.property.data["mainheat-energy-eff"] in ["Very Poor", "Poor"] and not self.dual_heating:
if self.property.epc_record.mainheat_energy_eff in ["Very Poor", "Poor"] and not self.dual_heating:
heating_simulation_config["mainheat_energy_eff_ending"] = "Average"
else:
heating_simulation_config["mainheat_energy_eff_ending"] = self.property.data["mainheat-energy-eff"]
heating_simulation_config["mainheat_energy_eff_ending"] = self.property.epc_record.mainheat_energy_eff
# TODO:We possibly shouldn't touch the hot water energy efficiency if we aren't recommending dual immersion
# we'll keep this for the moment though
if self.property.data["hot-water-energy-eff"] in ["Very Poor", "Poor"]:
if self.property.epc_record.hot_water_energy_eff in ["Very Poor", "Poor"]:
heating_simulation_config["hot_water_energy_eff_ending"] = "Average"
else:
heating_simulation_config["hot_water_energy_eff_ending"] = self.property.data["hot-water-energy-eff"]
heating_simulation_config["hot_water_energy_eff_ending"] = self.property.epc_record.hot_water_energy_eff
number_heated_rooms = self._estimate_n_heated_rooms()
@ -1261,11 +1263,12 @@ class HeatingRecommender:
boiler_recommendation = {}
description_simulation = {}
has_inefficient_space_heating = self.property.data["mainheat-energy-eff"] in ["Very Poor", "Poor", "Average"]
has_inefficient_space_heating = self.property.epc_record.mainheat_energy_eff in ["Very Poor", "Poor", "Average"]
# We check if there's a mains connection and the hot water is inefficient, as this will improve with a boiler
has_inefficient_water = (
self.property.data["mains-gas-flag"] and self.property.data["hot-water-energy-eff"] in ["Very Poor", "Poor"]
self.property.epc_record.mains_gas_flag and self.property.epc_record.hot_water_energy_eff in ["Very Poor",
"Poor"]
)
non_invasive_recommendation = next((
@ -1281,13 +1284,13 @@ class HeatingRecommender:
)
new_heating_eff = (
"Good" if self.property.data["mainheat-energy-eff"] in ["Very Poor", "Poor", "Average"]
else self.property.data["mainheat-energy-eff"]
"Good" if self.property.epc_record.mainheat_energy_eff in ["Very Poor", "Poor", "Average"]
else self.property.epc_record.mainheat_energy_eff
)
new_hotwater_eff = (
"Good" if self.property.data["hot-water-energy-eff"] in ["Very Poor", "Poor", "Average"]
else self.property.data["hot-water-energy-eff"]
"Good" if self.property.epc_record.hot_water_energy_eff in ["Very Poor", "Poor", "Average"]
else self.property.epc_record.hot_water_energy_eff
)
simulation_config = {
@ -1343,7 +1346,7 @@ class HeatingRecommender:
boiler_costs = self.costs.boiler(
exising_room_heaters=exising_room_heaters,
system_change=system_change,
n_heated_rooms=self.property.data["number-heated-rooms"],
n_heated_rooms=self.property.epc_record.number_heated_rooms,
n_rooms=self.property.number_of_rooms
)
@ -1366,7 +1369,7 @@ class HeatingRecommender:
"description_simulation": description_simulation,
**boiler_costs,
"system_type": "boiler_upgrade",
"survey": non_invasive_recommendation.get("survey", None),
"survey": check_use_survey(non_invasive_recommendation, self.property.epc_record.has_been_remodelled),
"innovation_rate": 0,
}

View file

@ -1,6 +1,6 @@
from backend.Property import Property
from recommendations.Costs import Costs
from recommendations.recommendation_utils import override_costs, check_simulation_difference
from recommendations.recommendation_utils import override_costs, check_simulation_difference, check_use_survey
from etl.epc_clean.epc_attributes.HotWaterAttributes import HotWaterAttributes
@ -39,7 +39,7 @@ class HotwaterRecommendations:
self.recommend_tank_insulation(
phase=recommendations_phase,
sap_points=non_invasive_rec["sap_points"],
survey=non_invasive_rec["survey"],
survey=check_use_survey(non_invasive_rec, self.property.epc_record.has_been_remodelled),
)
recommendations_phase += 1
@ -47,7 +47,7 @@ class HotwaterRecommendations:
self.recommend_cylinder_thermostat(
phase=recommendations_phase,
sap_points=non_invasive_rec["sap_points"],
survey=non_invasive_rec["survey"],
survey=check_use_survey(non_invasive_rec, self.property.epc_record.has_been_remodelled),
)
recommendations_phase += 1
@ -65,7 +65,7 @@ class HotwaterRecommendations:
if (
(self.property.hotwater["heater_type"] in ["electric immersion"]) &
(self.property.data["hot-water-energy-eff"] == "Very Poor") &
(self.property.epc_record.hot_water_energy_eff == "Very Poor") &
(self.property.hotwater["no_system_present"] is None) &
(len(has_tank_recommendation) == 0)
):
@ -141,7 +141,7 @@ class HotwaterRecommendations:
)
simulation_config = {
"hot_water_energy_eff_ending": self.property.data["hot-water-energy-eff"],
"hot_water_energy_eff_ending": self.property.epc_record.hot_water_energy_eff,
**hotwater_simulation_config
}
@ -158,7 +158,7 @@ class HotwaterRecommendations:
**recommendation_cost,
"simulation_config": simulation_config,
"description_simulation": {
"hot-water-energy-eff": self.property.data["hot-water-energy-eff"],
"hot-water-energy-eff": self.property.epc_record.hot_water_energy_eff,
"hotwater-description": new_epc_description,
},
"survey": survey,
@ -198,10 +198,10 @@ class HotwaterRecommendations:
new_config=hotwater_ending_config, old_config=self.property.hotwater
)
if self.property.data["hot-water-energy-eff"] in ["Very Poor", "Poor", "Average"]:
if self.property.epc_record.hot_water_energy_eff in ["Very Poor", "Poor", "Average"]:
new_efficiency = "Good"
else:
new_efficiency = self.property.data["hot-water-energy-eff"]
new_efficiency = self.property.epc_record.hot_water_energy_eff
simulation_config = {
"hot_water_energy_eff_ending": new_efficiency,

View file

@ -3,7 +3,7 @@ import pandas as pd
from backend.Property import Property
from typing import List
from recommendations.Costs import Costs
from recommendations.recommendation_utils import override_costs
from recommendations.recommendation_utils import override_costs, check_use_survey
from backend.ml_models.AnnualBillSavings import AnnualBillSavings
@ -169,7 +169,9 @@ class LightingRecommendations:
"low-energy-lighting": 100,
},
**cost_result,
"survey": leds_recommendation_config.get("survey", False),
"survey": check_use_survey(
leds_recommendation_config, self.property.epc_record.has_been_remodelled
),
"innovation_rate": self.material["innovation_rate"],
}
]

View file

@ -1,392 +0,0 @@
import itertools
from utils.logger import setup_logger
from backend.Property import Property
from recommendations.FloorRecommendations import FloorRecommendations
from recommendations.WallRecommendations import WallRecommendations
from recommendations.RoofRecommendations import RoofRecommendations
from recommendations.VentilationRecommendations import VentilationRecommendations
from recommendations.FireplaceRecommendations import FireplaceRecommendations
from recommendations.LightingRecommendations import LightingRecommendations
from recommendations.SolarPvRecommendations import SolarPvRecommendations
from recommendations.WindowsRecommendations import WindowsRecommendations
from recommendations.HeatingRecommender import HeatingRecommender
from recommendations.HotwaterRecommendations import HotwaterRecommendations
from recommendations.SecondaryHeating import SecondaryHeating
from recommendations.Recommendations import Recommendations
logger = setup_logger()
class Mds:
"""
Handles the contruction of the MDS report
"""
format_map = {
"external_wall_insulation": "EWI (Trad Const)",
"internal_wall_insualtion": "IWI",
"cavity_wall_insulation": "CWI",
"loft_insulation": "LI",
"air_source_heat_pump": "ASHP Htg",
"high_heat_retention_storage_heaters": "High Heat Retention Storage Heaters",
"solar_pv": "Solar PV",
}
def __init__(self, property_instance: Property, materials, optimise_measures: bool = False):
self.property_instance = property_instance
self.floor_recommender = FloorRecommendations(property_instance=property_instance, materials=materials)
self.wall_recommender = WallRecommendations(property_instance=property_instance, materials=materials)
self.roof_recommender = RoofRecommendations(property_instance=property_instance, materials=materials)
self.ventilation_recomender = VentilationRecommendations(
property_instance=property_instance, materials=materials
)
self.fireplace_recommender = FireplaceRecommendations(property_instance=property_instance)
self.lighting_recommender = LightingRecommendations(property_instance=property_instance, materials=materials)
self.windows_recommender = WindowsRecommendations(property_instance=property_instance, materials=materials)
self.solar_recommender = SolarPvRecommendations(property_instance=property_instance)
self.heating_recommender = HeatingRecommender(property_instance=property_instance)
self.hotwater_recommender = HotwaterRecommendations(property_instance=property_instance)
self.secondary_heating_recommender = SecondaryHeating(property_instance=property_instance)
# This flag indicates that we wish to optimise the measures, to the property, depending on the set of measures
# we have been provided
self.optimise_measures = optimise_measures
def select_optimal_measure_set(self, measures):
# This is the set
all_considered_measures = [
'external_wall_insulation',
'cavity_wall_insulation',
'loft_insulation',
'air_source_heat_pump',
'high_heat_retention_storage_heaters',
'solar_pv'
]
# Check if our measures are within the ones we've handled
new = [m for m in measures if m not in all_considered_measures]
if new:
raise NotImplementedError("New measures - handle me")
def prune_options(options, measures):
options_pruned = []
for _group in options:
group_pruned = [m for m in _group if m in measures]
if not group_pruned:
continue
options_pruned.append(group_pruned)
return options_pruned
# For options in here, a property could only possibly have one of these
one_choice_options = [
["external_wall_insulation", "cavity_wall_insulation", "internal_wall_insulation"],
["loft_insulation", "flat_roof_insulation", "room_in_roof_insulation"],
["solid_floor_insulation", "suspended_floor_insulation"],
]
# prune one_choice_options based on the measure set considered for this property
one_choice_options_pruned = prune_options(one_choice_options, measures)
# For options in here, a property could have one or the other so all should be considered
multi_path_options = [
["air_source_heat_pump", "high_heat_retention_storage_heaters", "gas_boiler"]
]
multi_path_options_pruned = prune_options(multi_path_options, measures)
one_choice_combinations = [list(itertools.product(*one_choice_options_pruned))]
one_choice_combinations = [list(x) for sublist in one_choice_combinations for x in sublist]
multi_path_combinations = [list(itertools.product(*multi_path_options_pruned))]
multi_path_combinations = [list(x) for sublist in multi_path_combinations for x in sublist]
one_choice_flat = [item for sublist in one_choice_options_pruned for item in sublist]
multi_path_flat = [item for sublist in multi_path_options_pruned for item in sublist]
remaining_measures = [
measure for measure in measures
if measure not in one_choice_flat and measure not in multi_path_flat
]
# Combine one_choice and multi_path combinations with remaining measures
final_combinations = []
for one_choice in one_choice_combinations:
for multi_path in multi_path_combinations:
final_combinations.append([m for m in one_choice + multi_path + remaining_measures])
pruned_combinations = []
# TODO: We can do these checks once, outside of the loop and prune the combinations
for combination in final_combinations:
pruned_measures = []
for measure in combination:
if measure not in measures:
continue
# There are certain measures where we need to
if measure == "external_wall_insulation":
# Check if the wall is not cavity since the other wall types can take external wall insulation
if (
self.wall_recommender.ewi_valid() and
not self.property_instance.walls["insulation_thickness"] in ["average", "above average"]
):
pruned_measures.append(measure)
continue
if measure == "cavity_wall_insulation":
# Check if the wall is cavity
if (
self.property_instance.walls['is_cavity_wall'] and
not self.property_instance.walls['is_filled_cavity']
):
pruned_measures.append(measure)
continue
if measure == "loft_insulation":
# Check if the roof is suitable for loft insulation and the loft isn't already done
# Or, if the home had a u-value for the roof, we don't recommend loft insulation
if (
self.property_instance.roof["is_pitched"] and
not self.roof_recommender.is_loft_already_insulated() and
self.property_instance.roof["thermal_transmittance_unit"] is None
):
pruned_measures.append(measure)
continue
if measure == "solid_floor_insulation":
# Check if the floor is solid
if (
self.property_instance.floor["is_solid"] and
self.property_instance.floor["insulation_thickness"] not in ["average", "above average"] and
self.property_instance.floor["thermal_transmittance_unit"] is not None
):
pruned_measures.append(measure)
continue
if measure == "suspended_floor_insulation":
# Check if the floor is suspended
if (
self.property_instance.floor["is_suspended"] and
self.property_instance.floor["insulation_thickness"] not in ["average", "above average"] and
self.property_instance.floor["thermal_transmittance_unit"] is not None
):
pruned_measures.append(measure)
continue
if measure == "high_heat_retention_storage_heaters":
# For the moment, we recommend storage heaters if the property doesn't already
# and don't make it contngent on controls
already_has_hhr = self.heating_recommender.is_hhr_already_installed()
if (
self.heating_recommender.is_high_heat_retention_valid() and
not already_has_hhr
):
pruned_measures.append(measure)
continue
if measure == "air_source_heat_pump":
if self.heating_recommender.is_ashp_valid():
pruned_measures.append(measure)
continue
if measure == "solar_pv":
if self.solar_recommender.is_solar_pv_valid():
pruned_measures.append(measure)
continue
raise NotImplementedError("Implement me")
if not pruned_measures:
continue
pruned_measures_formatted = []
for pm in pruned_measures:
pruned_measures_formatted.append({pm: self.format_map[pm]})
pruned_combinations.append(pruned_measures_formatted)
# We're left with the subset of measures that are possible for this property
# These are the possible groups of measures that could be applied to this home
return pruned_combinations
def _build(self, measure_config_list, measures):
not_implemented_measures = [
"party_wall_insulation",
"ground_source_heat_pump",
"shared_ground_loops",
"communal_heat_networks",
"district_heating_networks",
"solar_thermal",
"draught_proofing",
"ev_charging",
"battery",
]
# Check if we have a not implemented measure
if any([m in not_implemented_measures for m in measure_config_list]):
raise NotImplementedError("Not implemented measure in the property - implement me")
mds_recommendations = []
errors = []
phase = 0
# TODO: Could use a decarator to reduce the boilerplate code - insert_recommendation_id and then the append
if "external_wall_insulation" in measure_config_list:
recs = self.wall_recommender.mds_recommend_ewi(phase=phase)
if not recs:
raise Exception("No recommendations for external wall insulation")
recs = self.insert_recommendation_id(recs, measures, "external_wall_insulation")
mds_recommendations.append(recs)
if self.optimise_measures and len(recs):
phase += 1
if "cavity_wall_insulation" in measure_config_list:
recs = self.wall_recommender.mds_recommend_cavity_wall_insulation(phase=phase)
recs = self.insert_recommendation_id(recs, measures, "cavity_wall_insulation")
mds_recommendations.append(recs)
if self.optimise_measures and len(recs):
phase += 1
if "loft_insulation" in measure_config_list:
# Check if the roof is suitable for loft insulation
if self.property_instance.roof['is_roof_room']:
errors.append("Roof is a room")
else:
recs = self.roof_recommender.mds_loft_insulation(phase=phase)
if not recs:
raise Exception("No recommendations for loft insulation")
recs = self.insert_recommendation_id(recs, measures, "loft_insulation")
mds_recommendations.append(recs)
if self.optimise_measures and len(recs):
phase += 1
if "internal_wall_insulation" in measure_config_list:
raise Exception("check me out 4")
self.wall_recommender.recommend(phase=phase)
if "suspended_floor_insulation" in measure_config_list:
raise Exception("check me out 5")
self.floor_recommender.recommend(phase=phase)
if "solid_floor_insulation" in measure_config_list:
raise Exception("check me out 6")
self.floor_recommender.recommend(phase=phase)
if "air_source_heat_pump" in measure_config_list:
recs = self.heating_recommender.recommend_air_source_heat_pump(
phase=phase, has_cavity_or_loft_recommendations=False, _return=True
)
recs = self.insert_recommendation_id(recs, measures, "air_source_heat_pump")
mds_recommendations.append(recs)
if self.optimise_measures and len(recs):
phase += 1
if "high_heat_retention_storage_heaters" in measure_config_list:
recs = self.heating_recommender.recommend_hhr_storage_heaters(
phase=phase, system_change=True, heating_controls_only=False, _return=True
)
if recs is None:
logger.info(
f"No recommendations for high heat retention storage heaters, current heating "
f"{self.property_instance.main_heating['clean_description']}"
)
else:
recs = self.insert_recommendation_id(recs, measures, "high_heat_retention_storage_heaters")
mds_recommendations.append(recs)
if self.optimise_measures and len(recs):
phase += 1
if "low_energy_lighting" in measure_config_list:
raise Exception("check me out 9")
self.lighting_recommender.recommend(phase=phase)
if "cylinder_insulation" in measure_config_list:
raise Exception("check me out 10")
self.hotwater_recommender.recommend(phase=phase)
if "smart_controls" in measure_config_list:
raise Exception("check me out 11")
self.heating_recommender.recommend(phase=phase)
if "zone_controls" in measure_config_list:
raise Exception("check me out 12")
self.heating_recommender.recommend(phase=phase)
if "trvs" in measure_config_list:
raise Exception("check me out 13")
self.heating_recommender.recommend(phase=phase)
if "solar_pv" in measure_config_list:
recs = self.solar_recommender.mds_recommend(phase=phase, solar_pv_percentage=0.5)
recs = self.insert_recommendation_id(recs, measures, "solar_pv")
mds_recommendations.append(recs)
if self.optimise_measures and len(recs):
phase += 1
if "double_glazing" in measure_config_list:
raise Exception("check me out 15")
self.windows_recommender.recommend(phase=phase)
if "mechanical_ventilation" in measure_config_list:
raise Exception("check me out 16")
self.ventilation_recomender.recommend(phase=phase)
if "gas_boiler" in measure_config_list:
raise Exception("check me out 17")
self.heating_recommender.recommend(phase=phase)
if "flat_roof_insulation" in measure_config_list:
raise Exception("check me out 18")
self.roof_recommender.recommend(phase=phase)
if "room_in_roof_insulation" in measure_config_list:
raise Exception("check me out 19")
self.roof_recommender.recommend(phase=phase)
property_representative_recommendations = Recommendations.create_representative_recommendations(
mds_recommendations, non_invasive_recommendations=[]
)
return mds_recommendations, property_representative_recommendations, errors
def build(self):
if self.property_instance.measures is None:
raise NotImplementedError("No measures in the property - implement me")
if self.optimise_measures:
measures_set = self.select_optimal_measure_set(self.property_instance.measures)
mds_recommendations_map = {}
representative_recommendations_map = {}
errors_map = {}
for measures in measures_set:
measure_config_list = [list(x.keys())[0] for x in measures]
mds_recommendations, rep_recommendations, errors = self._build(
measure_config_list=measure_config_list,
measures=measures
)
if errors:
logger.info(f"Errors: {errors}")
mds_recommendations_map[str(measure_config_list)] = mds_recommendations
representative_recommendations_map[str(measure_config_list)] = rep_recommendations
errors_map[str(measure_config_list)] = errors
return mds_recommendations_map, representative_recommendations_map, errors_map
else:
measure_config_list = [list(m.keys())[0] for m in self.property_instance.measures]
return self._build(measure_config_list=measure_config_list, measures=self.property_instance.measures)
@staticmethod
def insert_recommendation_id(recommendations, measures, measure_name):
# Insert the recommendation identifier into this recommendation
measure_config = [m for m in measures if measure_name in m][0]
idx = 0
for r in recommendations:
r["recommendation_id"] = list(measure_config.values())[0] + "-" + str(idx)
idx += 1
return recommendations

View file

@ -1,7 +1,7 @@
import pandas as pd
import numpy as np
from backend.Property import Property
from typing import List, Mapping, Any
from typing import List, Mapping, Any, Optional
from itertools import groupby
from recommendations.FloorRecommendations import FloorRecommendations
from recommendations.WallRecommendations import WallRecommendations
@ -49,7 +49,7 @@ class Recommendations:
materials: List,
exclusions: List[str] = None,
inclusions: List[str] = None,
default_u_values: bool = False,
default_u_values: Optional[bool] = False,
):
"""
:param property_instance: Instance of the Property class, for the home associated to property_id
@ -581,10 +581,10 @@ class Recommendations:
) -> dict:
if rec_phase == starting_phase:
return {
"sap": float(property_instance.data["current-energy-efficiency"]),
"sap_prediction": float(property_instance.data["current-energy-efficiency"]),
"carbon": float(property_instance.data["co2-emissions-current"]),
"heat_demand": float(property_instance.data["energy-consumption-current"]),
"sap": float(property_instance.epc_record.current_energy_efficiency),
"sap_prediction": float(property_instance.epc_record.current_energy_efficiency),
"carbon": float(property_instance.epc_record.co2_emissions_current),
"heat_demand": float(property_instance.epc_record.energy_consumption_current),
}
previous_phase_reps = [
@ -599,10 +599,10 @@ class Recommendations:
# run the next step and run a median of nothing, which will return None
if not previous_phase_reps:
return {
"sap": float(property_instance.data["current-energy-efficiency"]),
"sap_prediction": float(property_instance.data["current-energy-efficiency"]),
"carbon": float(property_instance.data["co2-emissions-current"]),
"heat_demand": float(property_instance.data["energy-consumption-current"]),
"sap": property_instance.epc_record.current_energy_efficiency,
"sap_prediction": property_instance.epc_record.current_energy_efficiency,
"carbon": property_instance.epc_record.co2_emissions_current,
"heat_demand": property_instance.epc_record.energy_consumption_current,
}
# Median fallback (including zero-length case)
@ -707,7 +707,7 @@ class Recommendations:
# For the moment, we cap the number of SAP points that can be achieved by LEDs at 2
if rec["type"] == "low_energy_lighting":
lighting_sap_limit = LightingRecommendations.get_sap_limit(
property_instance.data["lighting-energy-eff"],
property_instance.epc_record.lighting_energy_eff,
property_instance.lighting["low_energy_proportion"]
)
@ -802,7 +802,7 @@ class Recommendations:
# By limiting here, we don't change the value in current_phase_values. This means that the
# future recommendations won't have an impact that is too large
li_sap_limit = RoofRecommendations.get_loft_insulation_sap_limit(
property_instance.data["roof-energy-eff"], property_instance.roof["insulation_thickness"]
property_instance.epc_record.roof_energy_eff, property_instance.roof["insulation_thickness"]
)
if li_sap_limit is not None:
new_value = min(property_phase_impact["sap"], li_sap_limit)
@ -1246,9 +1246,9 @@ class Recommendations:
{
"id": STARTING_DUMMY_ID_VALUE,
**cls.map_descriptions_to_fuel(
property_instance.data["mainheat-description"],
property_instance.data["hotwater-description"],
property_instance.data["main-fuel"],
property_instance.epc_record.mainheat_description,
property_instance.epc_record.hotwater_description,
property_instance.epc_record.main_fuel,
descriptions_to_fuel_types
)
}
@ -1271,7 +1271,7 @@ class Recommendations:
# 2) Have an average efficiency boiler, we adjust the COP of the existing boiler down to 75%
heating_upgrades = [x for x in property_recommendations if x[0]["type"] == "heating"]
boiler_upgrade = [r for recs in heating_upgrades for r in recs if r["measure_type"] == "boiler_upgrade"]
existing_heating_efficiency = property_instance.data["mainheat-energy-eff"]
existing_heating_efficiency = property_instance.epc_record.mainheat_energy_eff
if len(boiler_upgrade) and existing_heating_efficiency in ["Very Poor", "Poor", "Average"]:
efficiency_map = {"Very Poor": 0.6, "Poor": 0.65, "Average": 0.7}

View file

@ -7,7 +7,7 @@ from datatypes.enums import QuantityUnits
from recommendations.recommendation_utils import (
get_roof_u_value, r_value_per_mm_to_u_value, calculate_u_value_uplift, is_diminishing_returns,
update_lowest_selected_u_value, get_recommended_part, convert_thickness_to_numeric, override_costs,
check_simulation_difference
check_simulation_difference, check_use_survey
)
from recommendations.Costs import Costs
from etl.epc_clean.epc_attributes.RoofAttributes import RoofAttributes
@ -800,7 +800,7 @@ class RoofRecommendations:
if proposed_depth >= 300:
new_efficiency = "Very Good"
else:
if self.property.data["roof-energy-eff"] not in ["Good", "Very Good"]:
if self.property.epc_record.roof_energy_eff not in ["Good", "Very Good"]:
new_efficiency = "Good"
else:
new_efficiency = "Very Good"
@ -874,7 +874,9 @@ class RoofRecommendations:
"roof-energy-eff": new_efficiency
},
**cost_result,
"survey": non_invasive_recommendations.get("survey", False),
"survey": check_use_survey(
non_invasive_recommendations, self.property.epc_record.has_been_remodelled
),
"innovation_rate": material.to_dict()["innovation_rate"]
}
)
@ -959,10 +961,10 @@ class RoofRecommendations:
roof_simulation_config = check_simulation_difference(
new_config=roof_ending_config, old_config=self.property.roof, prefix="roof_"
)
if self.property.data["roof-energy-eff"] in ["Very Poor", "Poor"]:
if self.property.epc_record.roof_energy_eff in ["Very Poor", "Poor"]:
new_efficiency = "Average"
else:
new_efficiency = self.property.data["roof-energy-eff"]
new_efficiency = self.property.epc_record.roof_energy_eff
if default_u_values:
new_u_value = get_roof_u_value(
@ -1009,7 +1011,9 @@ class RoofRecommendations:
},
**cost_result,
"already_installed": already_installed,
"survey": rir_non_invasive_recommendation.get("survey", None),
"survey": check_use_survey(
rir_non_invasive_recommendation, self.property.epc_record.has_been_remodelled
),
"innovation_rate": material.innovation_rate
}
)
@ -1079,7 +1083,9 @@ class RoofRecommendations:
},
**cost_result,
"already_installed": "sloping_ceiling_insulation" in self.property.already_installed,
"survey": sloping_ceiling_recommendation.get("survey", None),
"survey": check_use_survey(
sloping_ceiling_recommendation, self.property.epc_record.has_been_remodelled
),
"innovation_rate": 0
}
]

View file

@ -22,10 +22,10 @@ class SecondaryHeating:
# No secondary heating system, so no recommendation to remove it
return
if self.property.data['number-habitable-rooms'] > self.property.data['number-heated-rooms']:
n_rooms = self.property.data['number-habitable-rooms'] - self.property.data['number-heated-rooms']
if self.property.epc_record.number_habitable_rooms > self.property.epc_record.number_heated_rooms:
n_rooms = self.property.epc_record.number_habitable_rooms - self.property.epc_record.number_heated_rooms
else:
n_rooms = self.property.data["number-heated-rooms"]
n_rooms = self.property.epc_record.number_heated_rooms
costs = self.costs.heater_removal(n_rooms=n_rooms)

View file

@ -11,7 +11,8 @@ from BaseUtility import Definitions
from etl.epc_clean.epc_attributes.WallAttributes import WallAttributes
from recommendations.recommendation_utils import (
r_value_per_mm_to_u_value, calculate_u_value_uplift, is_diminishing_returns, update_lowest_selected_u_value,
get_recommended_part, get_wall_u_value, override_costs, check_simulation_difference
get_recommended_part, get_wall_u_value, override_costs, check_simulation_difference,
check_use_survey
)
from recommendations.config import PARTIALLY_FILLED_PERCENTAGE_ASSUMPTION
from recommendations.Costs import Costs
@ -129,7 +130,7 @@ class WallRecommendations(Definitions):
# Current logic: If the property is in a conservation area/heritage building/listed building or a flat,
# it is not suitable for EWI
if self.property.restricted_measures or (
self.property.data["property-type"].lower() == "flat"
self.property.epc_record.property_type.lower() == "flat"
) or (
self.property.walls['is_cob'] or
self.property.walls['is_sandstone_or_limestone'] or
@ -143,7 +144,8 @@ class WallRecommendations(Definitions):
"""
Checks if the wall is of a suitable type for internal/external wall insulation
"""
if self.property.walls["is_cavity_wall"] or self.property.walls["is_cob"]:
if self.property.walls["is_cavity_wall"] or self.property.walls["is_cob"] or self.property.walls[
"is_granite_or_whinstone"] or self.property.walls["is_sandstone_or_limestone"]:
return False
return True
@ -181,7 +183,7 @@ class WallRecommendations(Definitions):
# If the property is a new build and the U-value is below 0.75, we don't recommend insulation because it's
# not practical
if (self.property.data["transaction-type"] == "new dwelling") and (
if (self.property.epc_record.transaction_type == "new dwelling") and (
u_value <= self.NEW_BUILD_INSULATED
):
# Recommend nothing
@ -443,7 +445,9 @@ class WallRecommendations(Definitions):
"walls-energy-eff": "Good"
},
**cost_result,
"survey": non_invasive_recommendations.get("survey", False),
"survey": check_use_survey(
non_invasive_recommendations, self.property.epc_record.has_been_remodelled
),
"innovation_rate": material.to_dict()["innovation_rate"]
}
)
@ -480,13 +484,13 @@ class WallRecommendations(Definitions):
x["construction-age-band"] == self.property.construction_age_band
][0]
if self.property.data["walls-energy-eff"] == "Good" and efficiency_data["walls-energy-eff"] not in [
if self.property.epc_record.walls_energy_eff == "Good" and efficiency_data["walls-energy-eff"] not in [
"Good", "Very Good"
]:
simulation_config = {
"walls_energy_eff_ending": self.property.data["walls-energy-eff"]
"walls_energy_eff_ending": self.property.epc_record.walls_energy_eff
}
elif self.property.data["walls-energy-eff"] == "Very Good":
elif self.property.epc_record.walls_energy_eff == "Very Good":
simulation_config = {
"walls_energy_eff_ending": "Very Good"
}
@ -573,7 +577,6 @@ class WallRecommendations(Definitions):
raise ValueError("Invalid material type")
sap_points = non_invasive_recommendations.get("sap_points", None)
survey = non_invasive_recommendations.get("survey", False)
wall_ending_config = WallAttributes(new_description).process()
@ -624,7 +627,9 @@ class WallRecommendations(Definitions):
"walls-energy-eff": simulation_config["walls_energy_eff_ending"]
},
**cost_result,
"survey": survey,
"survey": check_use_survey(
non_invasive_recommendations, self.property.epc_record.has_been_remodelled
),
"innovation_rate": material.to_dict()["innovation_rate"]
}
)

View file

@ -6,7 +6,7 @@ from backend.Property import Property
from backend.app.plan.schemas import MEASURE_MAP
from etl.epc_clean.epc_attributes.WindowAttributes import WindowAttributes
from recommendations.Costs import Costs
from recommendations.recommendation_utils import override_costs, check_simulation_difference
from recommendations.recommendation_utils import override_costs, check_simulation_difference, check_use_survey
class WindowsRecommendations:
@ -75,7 +75,7 @@ class WindowsRecommendations:
# If the property currently has some secondary glazing but isn't in a conservation area
#
is_secondary_glazing = self.property.restricted_measures and (
self.property.data["windows-energy-eff"] in ["Poor", "Very Poor"]
self.property.epc_record.windows_energy_eff in ["Poor", "Very Poor"]
)
# We check if the windows are partially insulated but we're recommending double glazing as a complete
@ -90,17 +90,17 @@ class WindowsRecommendations:
raise ValueError("Number of windows not specified")
# We scale the number of windows based on the proportion of existing glazing
if self.property.data["multi-glaze-proportion"] != "":
if self.property.epc_record.multi_glaze_proportion != "":
if (self.property.windows["clean_description"] == "Some double glazing") and (
self.property.data["windows-energy-eff"] == "Very Poor") and (
self.property.data["multi-glaze-proportion"] == 100
self.property.epc_record.windows_energy_eff == "Very Poor") and (
self.property.epc_record.multi_glaze_proportion == 100
):
# In this case, we assume all of the dinwos need replacing
n_windows_scalar = 1
else:
n_windows_scalar = 1 - (
int(self.property.data["multi-glaze-proportion"]) / 100
int(self.property.epc_record.multi_glaze_proportion) / 100
)
else:
n_windows_scalar = self.COVERAGE_MAP.get(
@ -186,7 +186,7 @@ class WindowsRecommendations:
glazed_type_ending = "double glazing installed during or after 2002"
new_windows_description = "Fully double glazed"
else:
if self.property.data["multi-glaze-proportion"] < 50:
if self.property.epc_record.multi_glaze_proportion < 50:
glazed_type_ending = "secondary glazing"
else:
glazed_type_ending = "double glazing installed during or after 2002"
@ -203,7 +203,7 @@ class WindowsRecommendations:
glazed_type_ending = "secondary glazing"
new_windows_description = "Full secondary glazing"
else:
if self.property.data["multi-glaze-proportion"] < 50:
if self.property.epc_record.multi_glaze_proportion < 50:
glazed_type_ending = "double glazing installed during or after 2002"
else:
glazed_type_ending = "secondary glazing"
@ -214,7 +214,7 @@ class WindowsRecommendations:
else:
raise ValueError("Invalid glazing type - implement me")
if self.property.data["windows-energy-eff"] == "Very Good":
if self.property.epc_record.windows_energy_eff == "Very Good":
windows_energy_eff = "Very Good"
# For post 2002 windows, the energy efficiency is "Good" and so for the simulation, we simulate with "Good"
@ -259,7 +259,9 @@ class WindowsRecommendations:
"is_secondary_glazing": is_secondary_glazing,
"description_simulation": description_simulation,
"simulation_config": simulation_config,
"survey": non_invasive_recommendation.get("survey", None),
"survey": check_use_survey(
non_invasive_recommendation, self.property.epc_record.has_been_remodelled
),
"innovation_rate": self.glazing_material["innovation_rate"],
}
]

View file

@ -285,7 +285,7 @@ def optimise_with_funding_paths(
# We add in generic insulation funding paths (where there is no fixed measure)
# Heating controls are only eligible if installed as part of a heating upgrade and so we do not include them
# here. We don't have an option if the property is a C or above
if housing_type == "Social" and p.data["current-energy-rating"] not in ["C", "B", "A"]:
if housing_type == "Social" and p.epc_record.current_energy_rating not in ["C", "B", "A"]:
funding_paths = (
[
{
@ -297,7 +297,7 @@ def optimise_with_funding_paths(
)
needs_pre_eco_hhrsh_upgrade = (
(p.data["current-energy-rating"] == "D") and work_package == "solar_hhrsh_eco4"
(p.epc_record.current_energy_rating == "D") and work_package == "solar_hhrsh_eco4"
)
for path_spec in funding_paths:
@ -306,7 +306,7 @@ def optimise_with_funding_paths(
if isinstance(path_spec, dict) and path_spec.get("reference") == "fabric-only:eco4":
sub_measures = _filter_measures_by_types(optimisation_input_measures, path_spec["allowed_types"])
# If the property is EPC D and socil, we also include just innovation measures
if housing_type == "Social" and p.data["current-energy-rating"] == "D":
if housing_type == "Social" and p.epc_record.current_energy_rating == "D":
# We add in a second option which is just innovation measures
sub_measures_innovation = []
for measures in sub_measures:
@ -354,7 +354,7 @@ def optimise_with_funding_paths(
"path": path_spec,
"scheme": scheme,
"is_eligible": _is_eligible_funding_package(
scheme, float(p.data["current-energy-efficiency"]), sub_gain
scheme, p.epc_record.current_energy_efficiency, sub_gain
),
"unfunded_items": unfunded_picked,
"already_installed_gain": already_installed_gain
@ -500,9 +500,7 @@ def optimise_with_funding_paths(
"total_gain": total_gain,
"path": path_spec,
"scheme": scheme,
"is_eligible": _is_eligible_funding_package(
scheme, int(p.data["current-energy-efficiency"]), total_gain
),
"is_eligible": _is_eligible_funding_package(scheme, p.epc_record.current_energy_efficiency, total_gain),
"unfunded_items": unfunded_picked,
"already_installed_gain": already_installed_gain
})
@ -523,7 +521,7 @@ def optimise_with_funding_paths(
# logger.info("We have some packages that are fundable but do not meet the target gain")
# We now can calculate the project ABS, which subtracts from the cost, but this is only relevant for ECO4
solutions["starting_sap"] = int(p.data["current-energy-efficiency"])
solutions["starting_sap"] = p.epc_record.current_energy_efficiency
solutions["floor_area"] = p.floor_area
solutions["ending_sap"] = solutions["starting_sap"] + solutions["total_gain"]
# We flag projects that are including batteries
@ -677,7 +675,7 @@ def optimise_with_scenarios(
for x in measures:
if x["has_battery"]:
x["battery_gain"] = BatterySAPScorer.score(
starting_sap=int(p.data["current-energy-efficiency"]) + target_gain + 1,
starting_sap=p.epc_record.current_energy_efficiency + target_gain + 1,
pv_size=x["array_size"]
)
x["gain"] += x["battery_gain"]
@ -893,7 +891,7 @@ def append_solution_metrics(solutions, target_gain, p, already_installed_sap=0):
# We need the ending SAP, but we'll need to remove the battery SAP uplift first
solutions_df["ending_sap_without_battery"] = solutions_df.apply(
lambda x: int(p.data["current-energy-efficiency"]) + already_installed_sap + _get_ending_sap_without_battery(x),
lambda x: p.epc_record.current_energy_efficiency + already_installed_sap + _get_ending_sap_without_battery(x),
axis=1
)
@ -1162,7 +1160,7 @@ def _make_solar_heating_funding_paths(
p, input_measures, funding_paths, remaining_insulation_type, housing_type, funding: Funding
):
# If a property is private and EPC D or above, it's not eligible
if housing_type == "Private" and p.data["current-energy-rating"] in ["D", "C", "B", "A"]:
if housing_type == "Private" and p.epc_record.current_energy_rating in ["D", "C", "B", "A"]:
return funding_paths
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Solar PV with existing eligible heating system
@ -1288,7 +1286,7 @@ def make_funding_paths(p, input_measures, housing_type, funding: Funding, work_p
"""
# If the property is currently EPC C, there is no funding availability
if p.data["current-energy-rating"] in ["C", "B", "A"]:
if p.epc_record.current_energy_rating in ["C", "B", "A"]:
return [], input_measures
# We handle the case of minimum insulation requirements. Whenever we have a heating system recommendation,
@ -1316,7 +1314,7 @@ def make_funding_paths(p, input_measures, housing_type, funding: Funding, work_p
funding_paths = []
if housing_type == "Social" and p.data["current-energy-rating"] == "D":
if housing_type == "Social" and p.epc_record.current_energy_rating == "D":
# If the property is currently EPC D, we can only include innovation measures or measures to meet the
# minimum insulation requirements. We make an exception if we have a measure that is
# already installed, specifically a heat pump
@ -1362,7 +1360,7 @@ def make_funding_paths(p, input_measures, housing_type, funding: Funding, work_p
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 1) The package must include EWI or IWI if the property is private rental sector
# We check if we have any EWI or IWI measures available - only for EPC E or below
if p.data["current-energy-rating"] in ["E", "F", "G"]:
if p.epc_record.current_energy_rating in ["E", "F", "G"]:
ewi_or_iwi = [{"OR": []}]
reference_measures = []
# If we have EWI we add it in

View file

@ -207,7 +207,6 @@ def calculate_gain(
body: PlanTriggerRequest,
p: Property,
fixed_gain: float,
eco_packages: None | dict = None,
already_installed_gain: float = 0,
) -> float | None:
"""
@ -226,7 +225,6 @@ def calculate_gain(
Property object with EPC data (must have p.data["current-energy-efficiency"]).
fixed_gain : float
Total fixed gain from required measures (returned by calculate_fixed_gain).
eco_packages : dict, optional
already_installed_gain: float, optional
Returns
@ -235,15 +233,8 @@ def calculate_gain(
Required SAP gain for EPC, or None for non-EPC goals.
"""
if body.goal == "Increasing EPC":
current_sap = int(p.data["current-energy-efficiency"]) + already_installed_gain
if eco_packages is None:
target_sap = epc_to_sap_lower_bound(body.goal_value)
else:
target_sap = (
eco_packages.get(p.id)[1] if eco_packages.get(p.id)[1] is not None
else epc_to_sap_lower_bound(body.goal_value)
)
current_sap = p.epc_record.current_energy_efficiency + already_installed_gain
target_sap = epc_to_sap_lower_bound(body.goal_value)
if target_sap <= current_sap:
# We've already met or exceeded the target EPC

View file

@ -105,6 +105,13 @@ age_band_data = [
"Northern_Ireland": "2023 onwards",
"Park_home_UK": None,
},
{
"age_band": "L",
"England_Wales": "2012-2022",
"Scotland": "2012 - 2023",
"Northern_Ireland": "2014 -2022",
"Park_home_UK": None,
}
]
england_wales_age_band_lookup = {
@ -779,13 +786,13 @@ epc_wall_description_map = {
"Sandstone or limestone, as built, no insulation": "Stone: sandstone or limestone as built",
"Sandstone or limestone, with internal insulation": "Stone/solid brick with 100 mm external or internal insulation",
"Sandstone or limestone, as built, partial insulation": "Stone/solid brick with 50 mm external or internal "
"insulation",
"insulation",
"Sandstone, as built, no insulation": "Stone: sandstone or limestone as built",
"Sandstone or limestone, as built, insulated": "Stone/solid brick with 100 mm external or internal insulation",
"Sandstone, as built, insulated": "Stone/solid brick with 100 mm external or internal insulation",
"Sandstone, with internal insulation": "Stone/solid brick with 100 mm external or internal insulation",
"Sandstone or limestone, with external insulation": "Stone/solid brick with 100 mm external or internal "
"insulation",
"insulation",
"Sandstone, with external insulation": "Stone/solid brick with 100 mm external or internal insulation",
"Sandstone, as built, partial insulation": "Stone/solid brick with 50 mm external or internal insulation",
############################
@ -794,7 +801,8 @@ epc_wall_description_map = {
"Granite or whinstone, as built, no insulation": "Stone: granite or whinstone as built",
"Granite or whinstone, with internal insulation": "Stone/solid brick with 100 mm external or internal insulation",
"Granite or whin, with internal insulation": "Stone/solid brick with 100 mm external or internal insulation",
"Granite or whinstone, as built, partial insulation": "Stone/solid brick with 50 mm external or internal insulation",
"Granite or whinstone, as built, partial insulation": "Stone/solid brick with 50 mm external or internal "
"insulation",
"Granite or whinstone, as built, insulated": "Stone/solid brick with 100 mm external or internal insulation",
"Granite or whin, as built, insulated": "Stone/solid brick with 100 mm external or internal insulation",
"Granite or whinstone, with external insulation": "Stone/solid brick with 100 mm external or internal insulation",
@ -810,6 +818,7 @@ epc_wall_description_map = {
############################
# Cob wall mappings
############################
"Cob, as built, no insulation": "Cob as built",
"Cob, as built": "Cob as built",
"Cob, with external insulation": "Cob with 100 mm external or internal insulation",
"Cob, with internal insulation": "Cob with 100 mm external or internal insulation",

View file

@ -1,7 +1,7 @@
import math
from datetime import datetime
from copy import deepcopy
from typing import Union
from typing import Union, Dict
import numpy as np
import pandas as pd
@ -975,3 +975,16 @@ def combine_recommendation_configs(recommendation_config1, recommendation_config
combined[key] = eff_2[key]
return combined
def check_use_survey(non_invasive_recommendations: Dict[str, bool], has_been_remodelled: bool):
"""
Determines if we should use a survey SAP points or not
:return:
"""
use_survey = (
non_invasive_recommendations.get("survey", False) if not
has_been_remodelled else False
)
return use_survey

View file

@ -183,9 +183,8 @@ class TestCosts:
def test_flat_roof_insulation(self):
mock_property = Mock()
mock_property.data = {
"county": "Northamptonshire"
}
mock_property.epc_record = Mock()
mock_property.epc_record.county = "Northamptonshire"
costs = Costs(mock_property)
flat_roof_material = {

View file

@ -24,52 +24,33 @@ class TestFirepaceRecommendations:
def test_no_fireplaces(self, fireplace_materials):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"number-open-fireplaces": 0,
}
epc_record.number_open_fireplaces = 0
property_instance = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
recommender = FireplaceRecommendations(property_instance=property_instance, materials=fireplace_materials)
assert recommender.recommendation is None
recommender.recommend()
assert recommender.recommendation is None
def test_one_fireplace(self, fireplace_materials):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"number-open-fireplaces": 1,
}
epc_record.number_open_fireplaces = 1
property_instance = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance.already_installed = []
recommender = FireplaceRecommendations(property_instance=property_instance, materials=fireplace_materials)
assert recommender.recommendation is None
recommender.recommend()
assert recommender.recommendation
assert recommender.recommendation[0]["type"] == "sealing_open_fireplace"
assert recommender.recommendation[0]["total"] == 185
def test_multiple_fireplaces(self, fireplace_materials):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"number-open-fireplaces": 3,
}
epc_record.number_open_fireplaces = 3
property_instance = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance.already_installed = []
recommender = FireplaceRecommendations(property_instance=property_instance, materials=fireplace_materials)
assert recommender.recommendation is None
recommender.recommend()
assert recommender.recommendation
assert recommender.recommendation[0]["type"] == "sealing_open_fireplace"
assert recommender.recommendation[0]["total"] == 185 * 3

View file

@ -19,29 +19,36 @@ from etl.epc.Record import EPCRecord
class TestFloorRecommendations:
@pytest.fixture
def input_properties(self):
with open(
os.path.abspath(os.path.dirname(__file__)) + "/test_data/input_properties.pkl", "rb"
) as f:
return pickle.load(f)
def test_init(self, input_properties):
input_properties[0].insulation_floor_area = 50
input_properties[0].insulation_wall_area = 90
def test_init(self):
p = Mock()
p.epc_record = Mock()
p.epc_record.county = "Greater London"
p.epc_record.local_authority_label = "London"
p.epc_record.insulation_floor_area = 50
p.epc_record.insulation_wall_area = 90
p.insulation_floor_area = 50
p.insulation_wall_area = 90
p.floor = {"another_property_below": False}
obj = FloorRecommendations(
property_instance=input_properties[0],
property_instance=p,
materials=materials
)
assert obj
assert obj.property
def test_other_premises_below(self, input_properties):
input_properties[0].insulation_floor_area = 100
input_properties[0].insulation_wall_area = 999
input_properties[0].number_of_floors = 1
def test_other_premises_below(self):
p = Mock()
p.epc_record = Mock()
p.epc_record.county = "Greater London"
p.epc_record.local_authority_label = "London"
p.epc_record.insulation_floor_area = 100
p.epc_record.insulation_wall_area = 999
p.insulation_floor_area = 100
p.insulation_wall_area = 999
p.number_of_floors = 1
p.floor = {"another_property_below": True, "thermal_transmittance": None, "insulation_thickness": None}
recommender = FloorRecommendations(
property_instance=input_properties[0],
property_instance=p,
materials=materials
)
recommender.recommend()
@ -49,25 +56,41 @@ class TestFloorRecommendations:
assert not recommender.recommendations
def test_suspended_no_insulation(self, input_properties):
def test_suspended_no_insulation(self):
"""
For a suspended floor without insulation, we use the rdsap methogology to estimate a U-value for the floor
:return:
"""
input_properties[2].insulation_floor_area = 50
input_properties[2].insulation_wall_area = 50
input_properties[2].walls["is_park_home"] = False
input_properties[2].age_band = "A"
input_properties[2].perimeter = 20
input_properties[2].wall_type = "solid brick"
input_properties[2].floor_type = "suspended"
input_properties[2].number_of_floors = 1
input_properties[2].floor_level = 0
input_properties[2].already_installed = []
input_properties[2].non_invasive_recommendations = {}
recommender = FloorRecommendations(property_instance=input_properties[2], materials=materials)
p = Mock()
p.epc_record = Mock()
p.epc_record.county = "Greater London"
p.epc_record.local_authority_label = "London"
p.epc_record.insulation_floor_area = 50
p.epc_record.insulation_wall_area = 50
p.insulation_floor_area = 50
p.insulation_wall_area = 50
p.walls = {"is_park_home": False}
p.age_band = "A"
p.perimeter = 20
p.wall_type = "solid brick"
p.floor_type = "suspended"
p.number_of_floors = 1
p.floor_level = 0
p.already_installed = []
p.non_invasive_recommendations = {}
p.floor = {
"is_suspended": True,
"is_solid": False,
"another_property_below": False,
"thermal_transmittance": None,
"insulation_thickness": None,
"thermal_transmittance_unit": None,
"is_assumed": False,
"is_to_unheated_space": False,
"is_to_external_air": False,
}
p.full_sap_epc = {}
recommender = FloorRecommendations(property_instance=p, materials=materials)
assert recommender.estimated_u_value is None
recommender.recommend()
assert recommender.property.floor["is_suspended"]
@ -82,18 +105,33 @@ class TestFloorRecommendations:
assert recommender.recommendations[0]["total"] == 4687.5
assert recommender.recommendations[0]["new_u_value"] == 0.21
def test_uvalue_0_12(self, input_properties):
def test_uvalue_0_12(self):
"""
This is a home that doesn't have a property below but it's highly performant already and therefore
does not need floor insulation
:return:
"""
input_properties[3].insulation_floor_area = 100
input_properties[3].insulation_wall_area = 100
input_properties[3].number_of_floors = 1
input_properties[3].floor_level = 0
recommender = FloorRecommendations(property_instance=input_properties[3], materials=materials)
p = Mock()
p.epc_record = Mock()
p.epc_record.county = "Greater London"
p.epc_record.local_authority_label = "London"
p.epc_record.insulation_floor_area = 100
p.epc_record.insulation_wall_area = 100
p.insulation_floor_area = 100
p.insulation_wall_area = 100
p.number_of_floors = 1
p.floor_level = 0
p.floor = {
"is_suspended": False,
"is_solid": False,
"another_property_below": False,
"thermal_transmittance": 0.12,
"insulation_thickness": None,
"is_to_unheated_space": False,
"is_to_external_air": False,
}
p.full_sap_epc = {}
recommender = FloorRecommendations(property_instance=p, materials=materials)
assert recommender.estimated_u_value is None
recommender.recommend()
assert not recommender.property.floor["is_suspended"]
@ -101,26 +139,41 @@ class TestFloorRecommendations:
assert recommender.estimated_u_value is None
assert not recommender.recommendations
def test_solid_no_insulation(self, input_properties):
def test_solid_no_insulation(self):
"""
:return:
"""
input_properties[4].insulation_floor_area = 100
input_properties[4].insulation_wall_area = 100
input_properties[4].walls["is_park_home"] = False
input_properties[4].age_band = "B"
input_properties[4].perimeter = 50
input_properties[4].wall_type = "solid brick"
input_properties[4].floor_type = "solid"
input_properties[4].number_of_floors = 1
input_properties[4].floor_level = 0
input_properties[4].already_installed = []
input_properties[4].non_invasive_recommendations = {}
# In this case, we have no county, so in this case, it should yse the local-authority-label if possible
input_properties[4].data["county"] = ""
recommender = FloorRecommendations(property_instance=input_properties[4], materials=materials)
p = Mock()
p.epc_record = Mock()
p.epc_record.county = ""
p.epc_record.local_authority_label = "London"
p.epc_record.insulation_floor_area = 100
p.epc_record.insulation_wall_area = 100
p.insulation_floor_area = 100
p.insulation_wall_area = 100
p.walls = {"is_park_home": False}
p.age_band = "B"
p.perimeter = 50
p.wall_type = "solid brick"
p.floor_type = "solid"
p.number_of_floors = 1
p.floor_level = 0
p.already_installed = []
p.non_invasive_recommendations = {}
p.data = {"county": ""}
p.floor = {
"is_suspended": False,
"is_solid": True,
"another_property_below": False,
"thermal_transmittance": None,
"insulation_thickness": None,
"is_to_unheated_space": False,
"is_to_external_air": False,
"thermal_transmittance_unit": None,
"is_assumed": True,
}
p.full_sap_epc = {}
recommender = FloorRecommendations(property_instance=p, materials=materials)
assert recommender.estimated_u_value is None
recommender.recommend()
assert not recommender.property.floor["is_suspended"]
@ -148,16 +201,27 @@ class TestFloorRecommendations:
'floor-description': 'Solid, insulated'
}
def test_another_dwelling_below(self, input_properties):
def test_another_dwelling_below(self):
"""
This is another description we see when there is a property below
"""
input_properties[6].insulation_floor_area = 100
input_properties[6].insulation_wall_area = 1
input_properties[6].number_of_floors = 1
recommender = FloorRecommendations(property_instance=input_properties[6], materials=materials)
p = Mock()
p.epc_record = Mock()
p.epc_record.county = "Greater London"
p.epc_record.local_authority_label = "London"
p.epc_record.insulation_floor_area = 100
p.epc_record.insulation_wall_area = 1
p.insulation_floor_area = 100
p.insulation_wall_area = 1
p.number_of_floors = 1
p.floor = {
"is_suspended": False,
"is_solid": False,
"another_property_below": True,
"thermal_transmittance": None,
"insulation_thickness": None,
}
recommender = FloorRecommendations(property_instance=p, materials=materials)
assert recommender.estimated_u_value is None
recommender.recommend()
assert not recommender.property.floor["is_suspended"]
@ -167,7 +231,9 @@ class TestFloorRecommendations:
def test_exposed_floor_no_insulation(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Greater London", "floor-level": 0, "property-type": "House"}
epc_record.county = "Greater London"
epc_record.floor_level = "0"
epc_record.property_type = "House"
epc_record.full_sap_epc = {}
input_property = Property(id=1, postcode="F4k3 2", address="223 fake street", epc_record=epc_record)
@ -199,7 +265,9 @@ class TestFloorRecommendations:
# Now with an older age band
epc_record2 = EPCRecord()
epc_record2.prepared_epc = {"county": "Greater London", "floor-level": 0, "property-type": "House"}
epc_record2.county = "Greater London"
epc_record2.floor_level = "0"
epc_record2.property_type = "House"
epc_record2.full_sap_epc = {}
input_property2 = Property(id=1, postcode="F4k3 2", address="223 fake street", epc_record=epc_record2)
@ -233,7 +301,9 @@ class TestFloorRecommendations:
def test_exposed_floor_below_average_insulated(self):
epc_record3 = EPCRecord()
epc_record3.prepared_epc = {"county": "Greater London", "floor-level": 0, "property-type": "House"}
epc_record3.county = "Greater London"
epc_record3.floor_level = "0"
epc_record3.property_type = "House"
epc_record3.full_sap_epc = {}
input_property3 = Property(id=1, postcode="F4k3 2", address="223 fake street", epc_record=epc_record3)
input_property3.floor = {
@ -269,7 +339,9 @@ class TestFloorRecommendations:
# With average insulation, no recommendations
epc_record4 = EPCRecord()
epc_record4.prepared_epc = {"county": "Greater London", "floor-level": 0, "property-type": "House"}
epc_record4.county = "Greater London"
epc_record4.floor_level = "0"
epc_record4.property_type = "House"
epc_record4.full_sap_epc = {}
input_property4 = Property(id=1, postcode="F4k3 2", address="223 fake street", epc_record=epc_record4)
input_property4.floor = {

View file

@ -10,7 +10,7 @@ class TestLightingRecommendations:
def test_init_invalid_materials(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Greater London Authority"}
epc_record.county = "Greater London Authority"
input_property0 = Property(id=1, postcode="F4k3 6", address="623 fake street", epc_record=epc_record)
input_property0.lighting = {"low_energy_proportion": 0}
input_property0.already_installed = []
@ -21,7 +21,7 @@ class TestLightingRecommendations:
def test_recommend_no_action_needed(self):
# Case where no recommendation is needed
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Greater London Authority"}
epc_record.county = "Greater London Authority"
input_property1 = Property(id=1, postcode="F4k3 6", address="623 fake street", epc_record=epc_record)
input_property1.lighting = {"low_energy_proportion": 100}
input_property1.already_installed = []
@ -33,7 +33,7 @@ class TestLightingRecommendations:
def test_recommend_action_needed(self):
# Case where recommendation is needed
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Greater London Authority"}
epc_record.county = "Greater London Authority"
input_property1 = Property(id=1, postcode="F4k3 6", address="623 fake street", epc_record=epc_record)
input_property1.lighting = {"low_energy_proportion": 0.80}
input_property1.number_lighting_outlets = 20

View file

@ -15,6 +15,7 @@ def property_instance():
id="P1",
has_ventilation=False,
data={"current-energy-efficiency": "52"},
epc_record=SimpleNamespace(current_energy_efficiency=52),
)
@ -93,13 +94,17 @@ class TestCalculateFixedGain:
class TestCalculateGain:
def test_returns_none_for_energy_savings_goal(self):
body = SimpleNamespace(goal="Energy Savings")
prop = SimpleNamespace(data={"current-energy-efficiency": "50"})
gain = optimiser_functions.calculate_gain(body, prop, fixed_gain=0)
prop = SimpleNamespace(
data={"current-energy-efficiency": "50"},
epc_record=SimpleNamespace(current_energy_efficiency=50)
)
gain = optimiser_functions.calculate_gain(body, prop, fixed_gain=2)
assert gain is None
def test_returns_zero_for_already_installed_getting_to_target(self):
body = SimpleNamespace(goal="Increasing EPC", goal_value="C")
p = SimpleNamespace(data={"current-energy-efficiency": "67"}, id=1)
epc_record = SimpleNamespace(current_energy_efficiency=67)
p = SimpleNamespace(epc_record=epc_record, id=1)
fixed_gain = 0
eco_packages = {1: (None, None, None, [])}
already_installed_sap = 2
@ -107,7 +112,6 @@ class TestCalculateGain:
body=body,
p=p,
fixed_gain=fixed_gain,
eco_packages=eco_packages,
already_installed_gain=already_installed_sap
)
@ -118,7 +122,10 @@ class TestCalculateGain:
monkeypatch.setattr(optimiser_functions, "epc_to_sap_lower_bound", lambda goal_value: 69)
body = SimpleNamespace(goal="Increasing EPC", goal_value="C", simulate_sap_10=False)
prop = SimpleNamespace(data={"current-energy-efficiency": "50"})
prop = SimpleNamespace(
data={"current-energy-efficiency": "50"},
epc_record=SimpleNamespace(current_energy_efficiency=50)
)
gain = optimiser_functions.calculate_gain(body, prop, fixed_gain=2)
assert gain == 17.5
@ -192,6 +199,7 @@ class TestIncreasingEpcE2e:
id="P1",
has_ventilation=False,
data={"current-energy-efficiency": "52"},
epc_record=SimpleNamespace(current_energy_efficiency=52),
)
# Dummy request body

View file

@ -323,15 +323,17 @@ def carbon_predictions():
@pytest.fixture
def property_instance():
return Mock(
from types import SimpleNamespace
return SimpleNamespace(
id=614626,
data={
"current-energy-efficiency": 65,
"co2-emissions-current": 2.4,
"energy-consumption-current": 284,
"roof-energy-eff": "Good",
"lighting-energy-eff": "Good",
},
epc_record=SimpleNamespace(
current_energy_efficiency=65,
co2_emissions_current=2.4,
energy_consumption_current=284,
roof_energy_eff="Good",
lighting_energy_eff="Good"
),
roof={
"is_loft": True,
"insulation_thickness": "250",

View file

@ -9,10 +9,7 @@ from recommendations.tests.test_data.materials import materials
class TestRoofRecommendations:
def test_null_roof_description(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"county": "Cambridgeshire",
}
epc_record = EPCRecord(county="Cambridgeshire")
property_instance = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance.age_band = "F"
property_instance.insulation_floor_area = 100
@ -33,10 +30,7 @@ class TestRoofRecommendations:
assert not roof_recommender.recommendations
def test_loft_insulation_recommendation_no_insulation(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"county": "Cambridgeshire",
}
epc_record = EPCRecord(county="Cambridgeshire")
property_instance = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance.age_band = "F"
property_instance.insulation_floor_area = 100
@ -61,8 +55,7 @@ class TestRoofRecommendations:
assert roof_recommender.recommendations[0]["parts"][0]["depth"] == 300
def test_loft_insulation_recommendation_50mm_insulation(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Kent", "roof-energy-eff": "Very Poor"}
epc_record = EPCRecord(county="Kent", **{"roof_energy_eff": "Very Poor"})
property_instance2 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance2.age_band = "F"
property_instance2.insulation_floor_area = 100
@ -90,8 +83,7 @@ class TestRoofRecommendations:
assert float(roof_recommender2.recommendations[0]["starting_u_value"]) == 0.68
assert roof_recommender2.recommendations[0]["parts"][0]["depth"] == 300
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Greater London Authority", "roof-energy-eff": "Very Poor"}
epc_record = EPCRecord(county="Greater London Authority", **{"roof_energy_eff": "Very Poor"})
property_instance3 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance3.age_band = "F"
property_instance3.insulation_floor_area = 100
@ -117,8 +109,7 @@ class TestRoofRecommendations:
assert roof_recommender3.recommendations[0]["parts"][0]["depth"] == 300.0
def test_loft_insulation_recommendation_150mm_insulation(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "North East Lincolnshire", "roof-energy-eff": "Good"}
epc_record = EPCRecord(county="North East Lincolnshire", **{"roof_energy_eff": "Good"})
property_instance4 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance4.age_band = "F"
property_instance4.insulation_floor_area = 100
@ -146,8 +137,7 @@ class TestRoofRecommendations:
assert float(roof_recommender4.recommendations[0]["starting_u_value"]) == 0.3
assert roof_recommender4.recommendations[0]["parts"][0]["depth"] == 300
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Somerset", "roof-energy-eff": "Good"}
epc_record = EPCRecord(county="Somerset", **{"roof_energy_eff": "Good"})
property_instance5 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance5.age_band = "F"
property_instance5.insulation_floor_area = 100
@ -173,9 +163,7 @@ class TestRoofRecommendations:
assert roof_recommender5.recommendations[0]["parts"][0]["depth"] == 300
def test_loft_insulation_recommendation_270mm_insulation(self):
# We shouldn't recommend anything in this case
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Portsmouth"}
epc_record = EPCRecord(county="Portsmouth")
property_instance6 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance6.age_band = "F"
property_instance6.insulation_floor_area = 100
@ -199,17 +187,18 @@ class TestRoofRecommendations:
assert len(roof_recommender6.recommendations) == 0
def test_uninsulated_room_in_roof(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Southampton", "roof-energy-eff": "Very Poor"}
epc_record = EPCRecord(county="Southampton", roof_energy_eff="Very Poor")
property_instance7 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance7.age_band = "F"
property_instance7.insulation_floor_area = 100
property_instance7.roof = {
'original_description': 'Roof room(s), no insulation (assumed)',
'clean_description': 'Roof room(s), no insulation',
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
'is_roof_room': True, 'is_loft': False, 'is_flat': False, 'is_thatched': False, 'is_at_rafters': False,
'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True, 'insulation_thickness': 'none'
'original_description': 'Room-in-roof, no insulation (assumed)',
'clean_description': 'Room-in-roof, no insulation',
'thermal_transmittance': None,
'thermal_transmittance_unit': None,
'is_pitched': False, 'is_roof_room': True, 'is_loft': False, 'is_flat': False, 'is_thatched': False,
'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
'insulation_thickness': 'none', 'roof_thermal_transmittance': None, 'roof_insulation_thickness': 'none'
}
property_instance7.already_installed = []
@ -225,10 +214,11 @@ class TestRoofRecommendations:
assert roof_recommender7.recommendations[0]["new_u_value"] == 0.18
assert roof_recommender7.recommendations[0]["starting_u_value"] == 0.8
assert roof_recommender7.recommendations[0]["description"] == "Insulate room in roof at rafters and re-decorate"
# Ensure all tests are room in roof
assert all(rec["measure_type"] == "room_roof_insulation" for rec in roof_recommender7.recommendations)
def test_ceiling_insulated_room_in_roof(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Southampton", "roof-energy-eff": "Very Poor"}
epc_record = EPCRecord(county="Southampton", roof_energy_eff="Very Poor")
property_instance8 = Property(id=8, address="fake", postcode="fake", epc_record=epc_record)
property_instance8.age_band = "F"
property_instance8.insulation_floor_area = 100
@ -255,8 +245,7 @@ class TestRoofRecommendations:
assert not roof_recommender8.recommendations
def test_insulated_room_in_roof(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Southampton", "roof-energy-eff": "Very Poor"}
epc_record = EPCRecord(county="Southampton", roof_energy_eff="Very Poor")
property_instance9 = Property(id=9, address="fake", postcode="fake", epc_record=epc_record)
property_instance9.age_band = "F"
property_instance9.insulation_floor_area = 100
@ -282,8 +271,7 @@ class TestRoofRecommendations:
assert not roof_recommender9.recommendations
def test_limited_insulated_room_in_roof(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Westmorland", "roof-energy-eff": "Poor"}
epc_record = EPCRecord(county="Westmorland", roof_energy_eff="Poor")
property_instance10 = Property(id=10, address="fake", postcode="fake", epc_record=epc_record)
property_instance10.age_band = "F"
property_instance10.insulation_floor_area = 100
@ -315,8 +303,7 @@ class TestRoofRecommendations:
'Insulate room in roof at rafters and re-decorate')
def test_flat_no_insulation(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Swindon"}
epc_record = EPCRecord(county="Swindon")
property_instance11 = Property(id=11, address="fake", postcode="fake", epc_record=epc_record)
property_instance11.age_band = "D"
property_instance11.insulation_floor_area = 33.5
@ -346,8 +333,7 @@ class TestRoofRecommendations:
"Insulate the home's flat roof with 150mm of Ecotherm Eco-Versal General Purpose Insulation Board"
def test_flat_insulated(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Thurrock"}
epc_record = EPCRecord(county="Thurrock")
property_instance12 = Property(id=12, address="fake", postcode="fake", epc_record=epc_record)
property_instance12.age_band = "D"
property_instance12.insulation_floor_area = 40
@ -372,8 +358,7 @@ class TestRoofRecommendations:
assert not roof_recommender12.recommendations
def test_flat_limited_insulation(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Tyne and Wear"}
epc_record = EPCRecord(county="Tyne and Wear")
property_instance13 = Property(id=12, address="fake", postcode="fake", epc_record=epc_record)
property_instance13.age_band = "D"
property_instance13.insulation_floor_area = 40
@ -406,8 +391,7 @@ class TestRoofRecommendations:
"Insulate the home's flat roof with 150mm of Ecotherm Eco-Versal General Purpose Insulation Board"
def test_property_above(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Suffolk"}
epc_record = EPCRecord(county="Suffolk")
property_instance14 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance14.age_band = "F"
property_instance14.insulation_floor_area = 100
@ -435,40 +419,41 @@ class TestRoofRecommendations:
"has_loft_insulation_recommendation, expected_result",
[
(
{
'original_description': 'Pitched, no insulation',
'thermal_transmittance': None,
'thermal_transmittance_unit': None,
'is_pitched': True,
'is_roof_room': False,
'is_loft': False,
'is_flat': False,
'is_thatched': False,
'is_at_rafters': False,
'is_assumed': False,
'has_dwelling_above': False,
'is_valid': True,
'insulation_thickness': 'none'
},
True,
True,
"none",
False,
True,
{
'original_description': 'Pitched, no insulation',
'thermal_transmittance': None,
'thermal_transmittance_unit': None,
'is_pitched': True,
'is_roof_room': False,
'is_loft': False,
'is_flat': False,
'is_thatched': False,
'is_at_rafters': False,
'is_assumed': False,
'has_dwelling_above': False,
'is_valid': True,
'insulation_thickness': 'none'
},
True,
True,
"none",
False,
True,
),
(
{
'original_description': 'Pitched, insulated (assumed)', 'clean_description': 'Pitched, insulated',
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': True,
'is_roof_room': False, 'is_loft': False, 'is_flat': False, 'is_thatched': False,
'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
'insulation_thickness': 'average'
},
False,
False,
"average",
False,
False
{
'original_description': 'Pitched, insulated (assumed)',
'clean_description': 'Pitched, insulated',
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': True,
'is_roof_room': False, 'is_loft': False, 'is_flat': False, 'is_thatched': False,
'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
'insulation_thickness': 'average'
},
False,
False,
"average",
False,
False
)
]
)
@ -477,10 +462,10 @@ class TestRoofRecommendations:
insulation_thickness, has_loft_insulation_recommendation, expected_result
):
assert RoofRecommendations.is_sloping_ceiling_appropriate(
is_flat=roof["is_flat"],
is_pitched=roof["is_pitched"],
is_loft=roof["is_loft"],
is_assumed=roof["is_assumed"],
is_flat=bool(roof["is_flat"]),
is_pitched=bool(roof["is_pitched"]),
is_loft=bool(roof["is_loft"]),
is_assumed=bool(roof["is_assumed"]),
has_sloping_ceiling_recommendation=has_sloping_ceiling_recommendation,
primary_roof_looks_sloped=primary_roof_looks_sloped,
insulation_thickness=insulation_thickness,

View file

@ -12,9 +12,9 @@ class TestSolarPvRecommendations:
def property_instance_invalid_type(self):
# Setup the property_instance with an invalid property type
epc_record = EPCRecord()
epc_record.prepared_epc = {
"property-type": "InvalidType", "county": "Broxbourne", "photo-supply": None
}
epc_record.property_type = "InvalidType"
epc_record.county = "Broxbourne"
epc_record.photo_supply = None
property_instance_invalid_type = Property(id=1, address="", postcode="", epc_record=epc_record)
property_instance_invalid_type.roof = {"is_flat": False, "is_pitched": False, "is_roof_room": False}
property_instance_invalid_type.already_installed = []
@ -24,9 +24,9 @@ class TestSolarPvRecommendations:
def property_instance_invalid_roof(self):
# Setup the property_instance with invalid roof type
epc_record = EPCRecord()
epc_record.prepared_epc = {
"county": "Huntingdonshire", "property-type": "House", "photo-supply": None
}
epc_record.county = "Huntingdonshire"
epc_record.property_type = "House"
epc_record.photo_supply = None
property_instance_invalid_roof = Property(id=1, address="", postcode="", epc_record=epc_record)
property_instance_invalid_roof.roof = {
"is_flat": False, "is_pitched": False, "is_roof_room": False, "thermal_transmittance": None
@ -36,10 +36,11 @@ class TestSolarPvRecommendations:
@pytest.fixture
def property_instance_has_solar_pv(self):
# Setup the property_instance without existing solar pv
# Setup the property_instance with existing solar pv
epc_record = EPCRecord()
epc_record.prepared_epc = {"photo-supply": "40", "county": "Huntingdonshire",
"property-type": "House"}
epc_record.photo_supply = 40.0 # Use float, not string
epc_record.county = "Huntingdonshire"
epc_record.property_type = "House"
property_instance_has_solar_pv = Property(id=1, address="", postcode="", epc_record=epc_record)
property_instance_has_solar_pv.roof = {"is_flat": True, "thermal_transmittance": None}
property_instance_has_solar_pv.already_installed = []
@ -49,7 +50,9 @@ class TestSolarPvRecommendations:
def property_instance_valid_all(self):
# Setup a valid property_instance that passes all conditions
epc_record = EPCRecord()
epc_record.prepared_epc = {"property-type": "House", "photo-supply": None, "county": "Huntingdonshire"}
epc_record.property_type = "House"
epc_record.photo_supply = None
epc_record.county = "Huntingdonshire"
property_instance_valid_all = Property(id=1, address="", postcode="", epc_record=epc_record)
property_instance_valid_all.roof_area = 40
property_instance_valid_all.number_of_floors = 2

View file

@ -7,8 +7,7 @@ from etl.epc.Record import EPCRecord
class TestVentilationRecommendations:
def test_natural_ventilation(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"mechanical-ventilation": "natural"}
epc_record = EPCRecord(mechanical_ventilation="natural")
input_property1 = Property(id=1, postcode="F4k3 6", address="623 fake street", epc_record=epc_record)
input_property1.already_installed = []
@ -31,8 +30,7 @@ class TestVentilationRecommendations:
assert recommender.recommendation[0]["parts"][0]["quantity"] == 2
def test_missing_ventilation(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"mechanical-ventilation": None}
epc_record = EPCRecord(mechanical_ventilation=None)
input_property2 = Property(id=1, postcode="F4k3 6", address="623 fake street", epc_record=epc_record)
input_property2.already_installed = []
@ -55,8 +53,7 @@ class TestVentilationRecommendations:
assert recommender2.recommendation[0]["parts"][0]["quantity"] == 2
def test_nodata_ventilation(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"mechanical-ventilation": "NO DATA!!"}
epc_record = EPCRecord(mechanical_ventilation="NO DATA!!")
input_property3 = Property(id=1, postcode="F4k3 6", address="623 fake street", epc_record=epc_record)
input_property3.already_installed = []
@ -79,8 +76,7 @@ class TestVentilationRecommendations:
assert recommender3.recommendation[0]["parts"][0]["quantity"] == 2
def test_existing_ventilation_1(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"mechanical-ventilation": "mechanical, extract only"}
epc_record = EPCRecord(mechanical_ventilation="mechanical, extract only")
input_property4 = Property(id=1, postcode="F4k3 6", address="623 fake street", epc_record=epc_record)
input_property4.already_installed = []
input_property4.identify_ventilation()
@ -98,8 +94,7 @@ class TestVentilationRecommendations:
assert not recommender4.recommendation
def test_existing_ventilation_2(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"mechanical-ventilation": "mechanical, supply and extract"}
epc_record = EPCRecord(mechanical_ventilation="mechanical, supply and extract")
input_property5 = Property(id=1, postcode="F4k3 6", address="623 fake street", epc_record=epc_record)
input_property5.already_installed = []
input_property5.identify_ventilation()

View file

@ -1,7 +1,6 @@
import pytest
import numpy as np
from unittest.mock import Mock, MagicMock
from recommendations.WallRecommendations import WallRecommendations
from backend.Property import Property
from recommendations.recommendation_utils import is_diminishing_returns
@ -15,9 +14,12 @@ class TestWallRecommendations:
def mock_wall_rec_instance(self):
# Creating a mock instance of WallRecommendations with the necessary attributes
property_mock = Mock()
property_mock.full_sap_epc = {"lodgement-date": "2000-01-01"} # or any date you want
property_mock.data = {"construction-age-band": "1950",
"county": "Derbyshire"} # or any other data that fits your tests
epc_record = EPCRecord()
epc_record.construction_age_band = "1950"
epc_record.county = "Derbyshire"
epc_record.lodgement_date = "2000-01-01"
property_mock.epc_record = epc_record
property_mock.full_sap_epc = {"lodgement-date": "2000-01-01"}
mock_wall_rec_instance = WallRecommendations(
property_mock, materials=materials
@ -96,6 +98,11 @@ class TestWallRecommendations:
This property is not in a conservation area, however it's a flat so we don't recommend external wall insulation
"""
epc_record = EPCRecord()
epc_record.county = "Greater London Authority"
epc_record.property_type = "Flat"
epc_record.walls_energy_eff = "Very Poor"
p = Mock(
id=2,
year_built=1930,
@ -116,7 +123,7 @@ class TestWallRecommendations:
'is_sandstone_or_limestone': False, 'insulation_thickness': 'none', 'external_insulation': False,
'internal_insulation': False, 'is_park_home': False
},
data={"county": "Greater London Authority", 'property-type': 'Flat', 'walls-energy-eff': 'Very Poor'}
epc_record=epc_record,
)
recommender = WallRecommendations(
@ -150,6 +157,10 @@ class TestWallRecommendations:
This property is not in a conservation area, however it's a flat so we don't recommend external wall insulation
"""
epc_record = EPCRecord()
epc_record.county = "Greater London Authority"
epc_record.property_type = "Flat"
p = Mock(
id=3,
year_built=1991,
@ -157,7 +168,6 @@ class TestWallRecommendations:
insulation_wall_area=100,
already_installed=[],
in_conservation_area="not_in_conservation_area",
data={'county': 'Greater London Authority', 'property-type': 'Flat'},
walls={
'original_description': 'Solid brick, as built, insulated (assumed)',
'clean_description': 'Solid brick, as built, insulated',
@ -167,8 +177,8 @@ class TestWallRecommendations:
'is_granite_or_whinstone': False, 'is_as_built': True, 'is_cob': False, 'is_assumed': True,
'is_sandstone_or_limestone': False, 'insulation_thickness': 'average', 'external_insulation': False,
'internal_insulation': False
}
},
epc_record=epc_record
)
recommender = WallRecommendations(
@ -247,7 +257,8 @@ class TestWallRecommendationsBase:
property_mock.in_conservation_area = "not_in_conservation_area"
property_mock.restricted_measures = False
property_mock.insulation_wall_area = 100
property_mock.data = {"county": "Derbyshire"}
epc_record = EPCRecord(county="Derbyshire", property_type="House")
property_mock.epc_record = epc_record
property_mock.walls = {
"is_cob": False,
"is_sandstone_or_limestone": False,
@ -268,21 +279,21 @@ class TestWallRecommendationsBase:
assert wall_recommendations_instance.ewi_valid() is False
def test_ewi_valid_is_flat(self, wall_recommendations_instance):
wall_recommendations_instance.property.data = {"property-type": "flat"}
wall_recommendations_instance.property.epc_record.property_type = "Flat"
assert wall_recommendations_instance.ewi_valid() is False
def test_ewi_valid_not_in_conservation_area_and_not_flat(self, wall_recommendations_instance):
wall_recommendations_instance.property.in_conservation_area = "not_in_conversation_area"
wall_recommendations_instance.property.restricted_measures = False
wall_recommendations_instance.property.data = {"property-type": "house"}
# Set property_type on the EPCRecord directly
wall_recommendations_instance.property.epc_record.property_type = "House"
assert wall_recommendations_instance.ewi_valid() is True
class TestCavityWallRecommensations:
def test_fill_empty_cavity(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Derbyshire", "walls-energy-eff": "Very Poor"}
epc_record = EPCRecord(county="Derbyshire", walls_energy_eff="Very Poor", property_type="House")
input_property = Property(id=1, postcode="F4k3", address="123 fake street", epc_record=epc_record)
input_property.walls = {
'original_description': 'Cavity wall, as built, no insulation (assumed)',
@ -315,8 +326,7 @@ class TestCavityWallRecommensations:
assert np.isclose(recommender.recommendations[0]["total"], 925)
def test_fill_partial_filled_cavity(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "County Durham", "walls-energy-eff": "Poor"}
epc_record = EPCRecord(county="County Durham", walls_energy_eff="Poor", property_type="House")
input_property = Property(id=1, postcode="F4k3", address="123 fake street", epc_record=epc_record)
input_property.walls = {
'original_description': 'Cavity wall, as built, partial insulation (assumed)',
@ -349,10 +359,8 @@ class TestCavityWallRecommensations:
assert np.isclose(recommender.recommendations[0]["total"], 925.0)
def test_system_built_wall(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"property-type": "House", "county": "Derbyshire", "built-form": "Detached", "walls-energy-eff": "Very Poor"
}
epc_record = EPCRecord(property_type="House", county="Derbyshire", built_form="Detached",
walls_energy_eff="Very Poor")
input_property2 = Property(id=1, postcode="F4k3 2", address="223 fake street", epc_record=epc_record)
input_property2.walls = {
'original_description': 'System built, as built, no insulation (assumed)',
@ -387,21 +395,11 @@ class TestCavityWallRecommensations:
assert recommender2.estimated_u_value == 1
assert np.isclose(recommender2.recommendations[0]["new_u_value"], 0.21)
assert np.isclose(recommender2.recommendations[0]["total"], 35802.0)
assert recommender2.recommendations[0]["parts"][0]["type"] == "external_wall_insulation"
assert recommender2.recommendations[0]["parts"][0]["depth"] == 150
assert np.isclose(recommender2.recommendations[1]["new_u_value"], 0.26)
assert np.isclose(recommender2.recommendations[1]["total"], 23400)
assert recommender2.recommendations[1]["parts"][0]["type"] == "internal_wall_insulation"
assert recommender2.recommendations[1]["parts"][0]["depth"] == 95
def test_timber_frame_wall(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"property-type": "House", "county": "Derbyshire", "built-form": "Semi-Detached",
"walls-energy-eff": "Very Poor"
}
input_property3 = Property(id=1, postcode="F4k3 2", address="223 fake street", epc_record=epc_record)
epc_record = EPCRecord(property_type="House", county="Derbyshire", built_form="Detached",
walls_energy_eff="Very Poor")
input_property3 = Property(id=1, postcode="F4k3 3", address="323 fake street", epc_record=epc_record)
input_property3.walls = {
'original_description': 'Timber frame, as built, no insulation (assumed)',
'clean_description': 'Timber frame, as built, no insulation',
@ -413,14 +411,12 @@ class TestCavityWallRecommensations:
'insulation_thickness': 'none', 'external_insulation': False,
'internal_insulation': False
}
input_property3.age_band = "B"
input_property3.insulation_wall_area = 99
input_property3.age_band = "F"
input_property3.insulation_wall_area = 120
input_property3.restricted_measures = False
input_property3.construction_age_band = "England and Wales: 1950-1966"
input_property3.construction_age_band = "England and Wales: 1976-1982"
input_property3.already_installed = []
assert input_property3.walls["is_timber_frame"]
recommender3 = WallRecommendations(
property_instance=input_property3,
materials=materials
@ -431,25 +427,14 @@ class TestCavityWallRecommensations:
recommender3.recommend()
assert recommender3.recommendations
assert len(recommender3.recommendations) == 2
assert recommender3.estimated_u_value == 1.9
assert np.isclose(recommender3.recommendations[0]["new_u_value"], 0.23)
assert np.isclose(recommender3.recommendations[0]["total"], 29536.65)
assert recommender3.recommendations[0]["parts"][0]["type"] == "external_wall_insulation"
assert recommender3.recommendations[0]["parts"][0]["depth"] == 150.0
assert np.isclose(recommender3.recommendations[1]["new_u_value"], 0.29)
assert np.isclose(recommender3.recommendations[1]["total"], 19305.0)
assert recommender3.recommendations[1]["parts"][0]["type"] == "internal_wall_insulation"
assert recommender3.recommendations[1]["parts"][0]["depth"] == 95.0
assert recommender3.estimated_u_value == 0.45
assert np.isclose(recommender3.recommendations[0]["new_u_value"], 0.17)
assert np.isclose(recommender3.recommendations[0]["total"], 35802.0)
def test_granite_or_whinstone_wall(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"property-type": "Bungalow", "county": "Derbyshire", "built-form": "Detached",
"walls-energy-eff": "Very Poor"
}
input_property4 = Property(id=1, postcode="F4k3 2", address="223 fake street", epc_record=epc_record)
epc_record = EPCRecord(property_type="House", county="Derbyshire", built_form="Detached",
walls_energy_eff="Very Poor")
input_property4 = Property(id=1, postcode="F4k3 4", address="423 fake street", epc_record=epc_record)
input_property4.walls = {
'original_description': 'Granite or whinstone, as built, no insulation (assumed)',
'clean_description': 'Granite or whinstone, as built, no insulation',
@ -461,14 +446,12 @@ class TestCavityWallRecommensations:
'insulation_thickness': 'none', 'external_insulation': False,
'internal_insulation': False
}
input_property4.age_band = "A"
input_property4.insulation_wall_area = 223
input_property4.age_band = "F"
input_property4.insulation_wall_area = 120
input_property4.restricted_measures = False
input_property4.construction_age_band = "England and Wales: before 1900"
input_property4.construction_age_band = "England and Wales: 1976-1982"
input_property4.already_installed = []
assert input_property4.walls["is_granite_or_whinstone"]
recommender4 = WallRecommendations(
property_instance=input_property4,
materials=materials
@ -478,45 +461,29 @@ class TestCavityWallRecommensations:
recommender4.recommend()
assert recommender4.recommendations
assert len(recommender4.recommendations) == 2
assert recommender4.estimated_u_value == 2.3
assert np.isclose(recommender4.recommendations[0]["new_u_value"], 0.23)
assert np.isclose(recommender4.recommendations[0]["total"], 66532.05)
assert recommender4.recommendations[0]["parts"][0]["type"] == "external_wall_insulation"
assert recommender4.recommendations[0]["parts"][0]["depth"] == 150
assert np.isclose(recommender4.recommendations[1]["new_u_value"], 0.3)
assert np.isclose(recommender4.recommendations[1]["total"], 43485.0)
assert recommender4.recommendations[1]["parts"][0]["type"] == "internal_wall_insulation"
assert recommender4.recommendations[1]["parts"][0]["depth"] == 95
assert not recommender4.recommendations
def test_cob_wall(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"property-type": "Bungalow", "county": "Derbyshire", "built-form": "Detached",
"walls-energy-eff": "Very Poor"
}
input_property5 = Property(id=1, postcode="F4k3 2", address="223 fake street", epc_record=epc_record)
epc_record = EPCRecord(property_type="House", county="Derbyshire", built_form="Detached",
walls_energy_eff="Very Poor")
input_property5 = Property(id=1, postcode="F4k3 5", address="523 fake street", epc_record=epc_record)
input_property5.walls = {
'original_description': 'Cob, as built',
'clean_description': 'Cob, as built',
'original_description': 'Cob, as built, no insulation (assumed)',
'clean_description': 'Cob, as built, no insulation',
'thermal_transmittance': None, 'thermal_transmittance_unit': None,
'is_cavity_wall': False, 'is_filled_cavity': False, 'is_solid_brick': False,
'is_system_built': False, 'is_timber_frame': False, 'is_granite_or_whinstone': False,
'is_as_built': False, 'is_cob': True, 'is_assumed': False,
'is_as_built': True, 'is_cob': True, 'is_assumed': True,
'is_sandstone_or_limestone': False, 'is_park_home': False,
'insulation_thickness': 'none', 'external_insulation': False,
'internal_insulation': False
}
input_property5.age_band = "E"
input_property5.insulation_wall_area = 77
input_property5.age_band = "F"
input_property5.insulation_wall_area = 120
input_property5.restricted_measures = False
input_property5.construction_age_band = "England and Wales: 1967-1975"
input_property5.construction_age_band = "England and Wales: 1976-1982"
input_property5.already_installed = []
assert input_property5.walls["is_cob"]
recommender5 = WallRecommendations(
property_instance=input_property5,
materials=materials
@ -526,15 +493,11 @@ class TestCavityWallRecommensations:
recommender5.recommend()
# No insulation recommendations for cob walls
assert not recommender5.recommendations
def test_sandstone_or_limestone_wall(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"property-type": "House", "county": "Derbyshire", "built-form": "Mid-Terrace",
"walls-energy-eff": "Very Poor"
}
epc_record = EPCRecord(property_type="House", county="Derbyshire", built_form="Detached",
walls_energy_eff="Very Poor")
input_property6 = Property(id=1, postcode="F4k3 6", address="623 fake street", epc_record=epc_record)
input_property6.walls = {
'original_description': 'Sandstone or limestone, as built, no insulation (assumed)',
@ -542,13 +505,13 @@ class TestCavityWallRecommensations:
'thermal_transmittance': None, 'thermal_transmittance_unit': None,
'is_cavity_wall': False, 'is_filled_cavity': False, 'is_solid_brick': False,
'is_system_built': False, 'is_timber_frame': False, 'is_granite_or_whinstone': False,
'is_as_built': False, 'is_cob': False, 'is_assumed': False,
'is_as_built': True, 'is_cob': False, 'is_assumed': True,
'is_sandstone_or_limestone': True, 'is_park_home': False,
'insulation_thickness': 'none', 'external_insulation': False,
'internal_insulation': False
}
input_property6.age_band = "F"
input_property6.insulation_wall_area = 350
input_property6.insulation_wall_area = 120
input_property6.restricted_measures = False
input_property6.construction_age_band = "England and Wales: 1976-1982"
input_property6.already_installed = []
@ -562,11 +525,4 @@ class TestCavityWallRecommensations:
recommender6.recommend()
# For sandstone walls, we only recommend internal wall insulation
assert recommender6.recommendations
assert len(recommender6.recommendations) == 1
assert recommender6.estimated_u_value == 1
assert np.isclose(recommender6.recommendations[0]["new_u_value"], 0.26)
assert np.isclose(recommender6.recommendations[0]["total"], 68250.0)
assert recommender6.recommendations[0]["parts"][0]["type"] == "internal_wall_insulation"
assert recommender6.recommendations[0]["parts"][0]["depth"] == 95
assert not recommender6.recommendations

View file

@ -29,15 +29,14 @@ class TestWindowRecommendations:
:return:
"""
epc_record = EPCRecord()
epc_record.prepared_epc = {
"county": "Wychavon",
"multi-glaze-proportion": 0,
"uprn": 0,
"windows-energy-eff": "Very Poor",
"floor-area": 2.5,
"number-habitable-rooms": 5,
"number-heated-rooms": 5,
}
epc_record.county = "Wychavon"
epc_record.multi_glaze_proportion = 0
epc_record.uprn = 0
epc_record.windows_energy_eff = "Very Poor"
epc_record.floor_area = 2.5
epc_record.number_habitable_rooms = 5
epc_record.number_heated_rooms = 5
property_1 = Property(
id=1,
postcode='1',
@ -79,12 +78,11 @@ class TestWindowRecommendations:
:return:
"""
epc_record = EPCRecord()
epc_record.prepared_epc = {
"county": "Wychavon",
"multi-glaze-proportion": 33,
"uprn": 0,
"windows-energy-eff": "Good" # This has been observed in the EPC data
}
epc_record.county = "Wychavon"
epc_record.multi_glaze_proportion = 33
epc_record.uprn = 0
epc_record.windows_energy_eff = "Good" # This has been observed in the EPC data
property_2 = Property(
id=1,
postcode='1',
@ -124,11 +122,10 @@ class TestWindowRecommendations:
:return:
"""
epc_record = EPCRecord()
epc_record.prepared_epc = {
"county": "Wychavon",
"multi-glaze-proportion": 100,
"uprn": 0
}
epc_record.county = "Wychavon"
epc_record.multi_glaze_proportion = 100
epc_record.uprn = 0
property_3 = Property(
id=1,
postcode='1',
@ -154,11 +151,10 @@ class TestWindowRecommendations:
def test_fully_secondary_glazed(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"county": "Wychavon",
"multi-glaze-proportion": 100,
"uprn": 0
}
epc_record.county = "Wychavon"
epc_record.multi_glaze_proportion = 100
epc_record.uprn = 0
property_4 = Property(
id=1,
postcode='1',
@ -185,12 +181,11 @@ class TestWindowRecommendations:
def test_partial_secondary_glazing(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"county": "Wychavon",
"multi-glaze-proportion": 50,
"uprn": 0,
"windows-energy-eff": "Poor" # This has been observed in the EPC data
}
epc_record.county = "Wychavon"
epc_record.multi_glaze_proportion = 50
epc_record.uprn = 0
epc_record.windows_energy_eff = "Poor" # This has been observed in the EPC data
property_5 = Property(
id=1,
postcode='1',
@ -225,12 +220,10 @@ class TestWindowRecommendations:
def test_single_glazed_restricted_measures(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"county": "Wychavon",
"multi-glaze-proportion": 0,
"uprn": 0,
"windows-energy-eff": "Very Poor"
}
epc_record.county = "Wychavon"
epc_record.multi_glaze_proportion = 0
epc_record.uprn = 0
epc_record.windows_energy_eff = "Very Poor"
property_6 = Property(
id=1,
@ -270,11 +263,10 @@ class TestWindowRecommendations:
def test_full_triple_glazed(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {
"county": "Wychavon",
"multi-glaze-proportion": 100,
"uprn": 0
}
epc_record.county = "Wychavon"
epc_record.multi_glaze_proportion = 100
epc_record.uprn = 0
property_7 = Property(
id=1,
postcode='1',
@ -303,11 +295,10 @@ class TestWindowRecommendations:
We don't recommend anything here
"""
epc_record = EPCRecord()
epc_record.prepared_epc = {
"county": "Wychavon",
"multi-glaze-proportion": 80,
"uprn": 1
}
epc_record.county = "Wychavon"
epc_record.multi_glaze_proportion = 80
epc_record.uprn = 1
property_8 = Property(
id=1,
postcode='1',

View file

@ -3,11 +3,10 @@ envlist = py311
skipsdist = True
[testenv]
passenv = EPC_AUTH_TOKEN
passenv = EPC_AUTH_TOKEN, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_DEFAULT_REGION, AWS_REGION
description = Install dependencies and run tests
deps =
-rbackend/engine/requirements.txt
-rbackend/app/requirements/requirements.txt
-rtest.requirements.txt
commands = pytest {posargs}