diff --git a/.idea/Model.iml b/.idea/Model.iml index b0f9c00d..4413bb06 100644 --- a/.idea/Model.iml +++ b/.idea/Model.iml @@ -7,7 +7,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index 1122b380..6f308057 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,7 +3,7 @@ - + diff --git a/backend/Property.py b/backend/Property.py index 0f5e7e77..882e450c 100644 --- a/backend/Property.py +++ b/backend/Property.py @@ -60,7 +60,7 @@ class Property: n_bedrooms = None def __init__( - self, id, postcode, address, epc_record, **kwargs + self, id, postcode, address, epc_record, overrides=None, **kwargs ): self.epc_record = epc_record @@ -74,6 +74,10 @@ class Property: } self.old_data = epc_record.get("old_data") self.property_dimensions = None + # 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 + self.overrides = overrides self.uprn = epc_record.get("uprn") self.full_sap_epc = epc_record.get("full_sap_epc") diff --git a/backend/app/plan/router.py b/backend/app/plan/router.py index 4b91566e..8d39c97f 100644 --- a/backend/app/plan/router.py +++ b/backend/app/plan/router.py @@ -44,20 +44,15 @@ BATCH_SIZE = 5 SCORING_BATCH_SIZE = 400 -def patch_epc(config, epc_records): +def patch_epc(patch, epc_records): """ This utility function is useful to patch the epc data if we have data from the customer :return: """ - number_habitable_rooms = config.get("number-habitable-rooms", None) - number_heated_rooms = config.get("number-heated-rooms", None) - - if number_habitable_rooms is not None: - epc_records["original_epc"]["number-habitable-rooms"] = int(number_habitable_rooms) - - if number_heated_rooms is not None: - epc_records["original_epc"]["number-heated-rooms"] = int(number_heated_rooms) + for patch_variable, patch_value in patch.items(): + if patch_variable in epc_records["original_epc"]: + epc_records["original_epc"][patch_variable] = patch_value return epc_records @@ -85,6 +80,17 @@ async def trigger_plan(body: PlanTriggerRequest): session.begin() logger.info("Getting the inputs") plan_input = read_csv_from_s3(bucket_name=get_settings().PLAN_TRIGGER_BUCKET, filepath=body.trigger_file_path) + # If we have patches or overrides, we should read them in here + patches = [] + if body.patches_file_path: + patches = read_csv_from_s3(bucket_name=get_settings().PLAN_TRIGGER_BUCKET, filepath=body.patches_file_path) + + overrides = [] + if body.overrides_file_path: + overrides = read_csv_from_s3( + bucket_name=get_settings().PLAN_TRIGGER_BUCKET, filepath=body.overrides_file_path + ) + cleaning_data = read_dataframe_from_s3_parquet( bucket_name=get_settings().DATA_BUCKET, file_key="sap_change_model/cleaning_dataset.parquet", ) @@ -124,7 +130,11 @@ async def trigger_plan(body: PlanTriggerRequest): 'full_sap_epc': epc_searcher.full_sap_epc.copy(), 'old_data': epc_searcher.older_epcs.copy(), } - epc_records = patch_epc(config, epc_records) + + patch = next(( + x for x in patches if (x["address"] == config["address"]) and (x["postcode"] == config["postcode"]) + ), None) + epc_records = patch_epc(patch, epc_records) prepared_epc = EPCRecord( epc_records=epc_records, @@ -132,12 +142,16 @@ async def trigger_plan(body: PlanTriggerRequest): cleaning_data=cleaning_data ) + overrides = next(( + x for x in overrides if (x["address"] == config["address"]) and (x["postcode"] == config["postcode"]) + ), None) input_properties.append( Property( id=property_id, address=epc_searcher.address_clean, postcode=epc_searcher.postcode_clean, epc_record=prepared_epc, + overrides=overrides, **Property.extract_kwargs(config) ) ) diff --git a/backend/app/plan/schemas.py b/backend/app/plan/schemas.py index b8a99704..ec49e41e 100644 --- a/backend/app/plan/schemas.py +++ b/backend/app/plan/schemas.py @@ -9,6 +9,8 @@ class PlanTriggerRequest(BaseModel): goal_value: str portfolio_id: int trigger_file_path: str + overrides_file_path: Optional[str] = None + patches_file_path: Optional[str] = None exclusions: Optional[conlist(str, min_items=1)] = None # Pre-defined list of possibilities for exclusions diff --git a/etl/customers/immo/pilot/asset_list.py b/etl/customers/immo/pilot/asset_list.py index 0da8f885..15681d42 100644 --- a/etl/customers/immo/pilot/asset_list.py +++ b/etl/customers/immo/pilot/asset_list.py @@ -24,7 +24,7 @@ council_tax_bands = pd.DataFrame(council_tax_bands) patches = [ { 'address': '6 Beech Road', 'postcode': 'DY1 4BP', - 'walls-description': 'Mixed: Filled cavity and external insulated solid brick', + 'walls-description': 'Cavity wall, filled cavity', 'walls-energy-eff': 'Good', 'roof-description': 'Pitched, 12 mm loft insulation', 'roof-energy-eff': 'Very Poor', @@ -36,7 +36,7 @@ patches = [ 'mainheatc-energy-eff': 'Good', 'lighting-description': 'Low energy lighting in 25% of fixed outlets', 'lighting-energy-eff': 'Good', - 'floor-description': 'Mixed: Solid no insulation and suspended no insulation', + 'floor-description': 'Solid, no insulation (assumed)', 'secondheat-description': 'None', 'current-energy-efficiency': '32', }