diff --git a/backend/documents_parser/extractor.py b/backend/documents_parser/extractor.py index 822f7907..47022c55 100644 --- a/backend/documents_parser/extractor.py +++ b/backend/documents_parser/extractor.py @@ -66,9 +66,11 @@ class PasHubRdSapSiteNotesExtractor: val = self._get_in(list_to_process, key) return val is not None and val.lower() != "not known" - def _wall_thickness_in(self, list_to_process: List[str]) -> int: + def _wall_thickness_in(self, list_to_process: List[str]) -> Optional[int]: val = self._get_in(list_to_process, "Wall thickness:") - return int(val.split()[0]) if val else 0 + if not val or val.split()[0].lower() == "unmeasurable": + return None + return int(val.split()[0]) def _section(self, start: str, end: str) -> List[str]: try: @@ -83,10 +85,17 @@ class PasHubRdSapSiteNotesExtractor: def extract_inspection_metadata(self) -> InspectionMetadata: try: addr_start = self.text_list.index("Property Address:") + 1 - addr_end = self.text_list.index("Property Photo", addr_start) - property_address = ", ".join( - t.rstrip(",") for t in self.text_list[addr_start:addr_end] - ) + try: + addr_end = self.text_list.index("Property Photo", addr_start) + address_tokens = self.text_list[addr_start:addr_end] + except ValueError: + addr_end = self.text_list.index("RdSAP Assessment", addr_start) + address_tokens = [] + for t in self.text_list[addr_start:addr_end]: + if not t or t.startswith("Page "): + break + address_tokens.append(t) + property_address = ", ".join(t.rstrip(",") for t in address_tokens) except ValueError: property_address = "" diff --git a/backend/documents_parser/tests/fixtures/PasHubSiteNotes_7.pdf b/backend/documents_parser/tests/fixtures/PasHubSiteNotes_7.pdf new file mode 100644 index 00000000..29d083c6 Binary files /dev/null and b/backend/documents_parser/tests/fixtures/PasHubSiteNotes_7.pdf differ diff --git a/backend/documents_parser/tests/fixtures/pashub_site_notes_7_text.json b/backend/documents_parser/tests/fixtures/pashub_site_notes_7_text.json new file mode 100644 index 00000000..933535cf --- /dev/null +++ b/backend/documents_parser/tests/fixtures/pashub_site_notes_7_text.json @@ -0,0 +1,670 @@ +[ + "SMART EPC: Record of", + "Inspection & Site Notes", + "Inspection Surveyor:", + "Dave Elliott", + "E-Mail Address:", + "davejohns36@icloud.com", + "Report Reference:", + "Not Applicable", + "Created On:", + "12 September 2025", + "Date of Inspection:", + "08 September 2025", + "Property Address:", + "Flat 3,", + "29 Watcombe Circus,", + "NOTTINGHAM,", + "NG5 2DU", + "Page 1", + "", + "Photo of electricity meter:", + "Single Smart Meter", + "RdSAP Assessment", + "General", + "Confirm you have checked for the existence of an", + "EPC before carrying out another energy assessment.", + "Yes", + "Does an EPC exist at the point of carrying out this", + "energy assessment?", + "No", + "Inspection Date:", + "08/09/2025", + "Transaction Type:", + "None of the Above", + "Tenure:", + "Rented Social", + "Type of Property:", + "Maisonette", + "Detachment Type:", + "Semi-Detached", + "Flat Type:", + "Mid-floor", + "Flat Location:", + "3", + "Corridor Type:", + "Unheated Corridor", + "Unheated corridor wall length:", + "6.59 m", + "Number of storeys:", + "2 Storeys", + "Terrain Type:", + "Suburban", + "Number of Extensions:", + "2 Extensions", + "Is an electricity smart meter present?", + "Yes", + "Electric meter type:", + "Single", + "Is the dwelling export-capable?", + "No", + "Is mains gas available?", + "Yes", + "Is there a gas smart meter?", + "No", + "Is the gas meter accessible?", + "Yes", + "Page 2", + "", + "Photo of Gas Meter:", + "Gas Meter", + "External indicators of Solid Brick construction:", + "Brick Pattern", + "Select Measurements Location:", + "Internal", + "Building Construction", + "Main Building", + "Age Range:", + "1900-1929", + "Record indicators of property age:", + "Property checker", + "Walls - Construction Type:", + "Solid brick", + "Record external indicators of Solid Brick", + "Construction:", + "consistent with build age", + "Walls - Insulation Type:", + "As built", + "Thermal conductivity of wall insulation:", + "Unknown", + "Wall U-Value known?", + "Not Known", + "Wall thickness:", + "280 mm", + "Page 3", + "", + "Photo wall thickness:", + "Wall Measurements", + "Wall Dry-Lined?", + "No", + "Party wall construction type:", + "Solid Masonry, Timber Frame, or System Built", + "Floor type:", + "Other dwelling below", + "Extension 1", + "Age Range:", + "1900-1929", + "Record indicators of property age:", + "Property checker", + "Walls - Construction Type:", + "Solid brick", + "Record external indicators of Solid Brick", + "Construction:", + "headers and stretchers in brick bond", + "Walls - Insulation Type:", + "As built", + "Thermal conductivity of wall insulation:", + "Unknown", + "Wall U-Value known?", + "Not Known", + "Wall thickness:", + "280 mm", + "Wall Dry-Lined?", + "Yes", + "Party wall construction type:", + "Solid Masonry, Timber Frame, or System Built", + "Floor type:", + "Other dwelling below", + "Extension 2", + "Age Range:", + "1900-1929", + "Record indicators of property age:", + "Property checker", + "Walls - Construction Type:", + "Solid brick", + "Record external indicators of Solid Brick", + "Construction:", + "headers and stretchers in brick bond", + "Walls - Insulation Type:", + "As built", + "Thermal conductivity of wall insulation:", + "Unknown", + "Page 4", + "", + "Loft insulation:", + "Loft", + "Loft insulation:", + "Loft", + "Wall U-Value known?", + "Not Known", + "Wall thickness:", + "280 mm", + "Wall Dry-Lined?", + "Yes", + "Party wall construction type:", + "Solid Masonry, Timber Frame, or System Built", + "Floor type:", + "Other dwelling below", + "Building Measurements", + "Area (m2)", + "Height (m)", + "Heat Loss Perimeter (m)", + "PWL (m)", + "Main Building", + "Floor 1", + "39.5", + "3.58", + "11.02", + "15.21", + "Floor 0", + "23.06", + "2.87", + "11.72", + "10.8", + "Extension 1", + "Floor 1", + "3.43", + "3.58", + "4.97", + "1", + "Floor 0", + "3.43", + "2.87", + "4.97", + "1", + "Extension 2", + "Floor 0", + "1.81", + "3.58", + "4.96", + "1", + "Roof Space", + "Main Building", + "Roofs - Construction Type:", + "Pitched roof (Slates or tiles), Access to loft", + "Roofs - Insulation At:", + "Joists", + "Roof U-Value:", + "Not Known", + "Roofs - Insulation Thickness:", + "225 mm", + "Page 5", + "", + "Loft insulation:", + "Loft", + "Loft insulation:", + "Loft", + "Loft insulation:", + "Loft", + "Loft insulation:", + "Loft", + "Loft insulation:", + "Loft", + "Loft insulation:", + "Loft", + "Loft insulation:", + "Loft", + "Loft insulation:", + "Loft", + "Page 6", + "", + "Loft insulation:", + "Loft", + "Indicators of Solid Brick Wall Construction in roof space:", + "solid wall construction visible to gables", + "Record indicators of Solid Brick Wall Construction in", + "roof space:", + "solid wall construction visible to gables", + "Extension 1", + "Roofs - Construction Type:", + "Flat", + "Roofs - Insulation At:", + "Unknown", + "Record indicators of Solid Brick Wall Construction in", + "roof space:", + "solid wall construction visible at eaves", + "Extension 2", + "Roofs - Construction Type:", + "Flat", + "Roofs - Insulation At:", + "Unknown", + "Record indicators of Solid Brick Wall Construction in", + "roof space:", + "Couldn\u2019t enter", + "Page 7", + "", + "Alternative Wall", + "Main Building", + "Alternative Wall 1", + "Construction type:", + "Solid brick", + "Record external indicators of Solid Brick", + "Construction:", + "consistent with building age, no visible cavity trays", + "Insulation Type:", + "As Built", + "Sheltered wall?", + "Yes", + "Thermal conductivity of wall insulation:", + "Unknown", + "Wall thickness:", + "280 mm", + "Wall Dry-Lined?", + "Yes", + "Windows", + "Window 1", + "Window location:", + "Main Building", + "Window wall type:", + "External wall", + "Glazing Type:", + "Double glazing, Unknown install date", + "Window type:", + "Window", + "Window frame type:", + "Wooden or PVC", + "What size is the glazing gap?", + "16 mm or more", + "Is the window draught proofed?", + "Yes", + "Are there permanent shutters present?", + "No", + "Window height:", + "1.2 m", + "Window width:", + "0.8 m", + "Orientation:", + "South West", + "Window 2", + "Window location:", + "Extension 1", + "Window wall type:", + "External wall", + "Glazing Type:", + "Double glazing, Unknown install date", + "Window type:", + "Window", + "Window frame type:", + "Wooden or PVC", + "What size is the glazing gap?", + "16 mm or more", + "Is the window draught proofed?", + "Yes", + "Are there permanent shutters present?", + "No", + "Window height:", + "1.65 m", + "Window width:", + "0.52 m", + "Orientation:", + "East", + "Page 8", + "", + "Window 3", + "Window location:", + "Extension 1", + "Window wall type:", + "External wall", + "Glazing Type:", + "Double glazing, Unknown install date", + "Window type:", + "Window", + "Window frame type:", + "Wooden or PVC", + "What size is the glazing gap?", + "16 mm or more", + "Is the window draught proofed?", + "Yes", + "Are there permanent shutters present?", + "No", + "Window height:", + "1.95 m", + "Window width:", + "0.86 m", + "Orientation:", + "East", + "Window 4", + "Window location:", + "Extension 1", + "Window wall type:", + "External wall", + "Glazing Type:", + "Double glazing, Unknown install date", + "Window type:", + "Window", + "Window frame type:", + "Wooden or PVC", + "What size is the glazing gap?", + "16 mm or more", + "Is the window draught proofed?", + "Yes", + "Are there permanent shutters present?", + "No", + "Window height:", + "1.76 m", + "Window width:", + "0.65 m", + "Orientation:", + "North", + "Window 5", + "Window location:", + "Extension 1", + "Window wall type:", + "External wall", + "Glazing Type:", + "Double glazing, Unknown install date", + "Window type:", + "Window", + "Window frame type:", + "Wooden or PVC", + "What size is the glazing gap?", + "16 mm or more", + "Is the window draught proofed?", + "Yes", + "Are there permanent shutters present?", + "No", + "Window height:", + "1.68 m", + "Window width:", + "0.68 m", + "Orientation:", + "East", + "Page 9", + "", + "Window 6", + "Window location:", + "Extension 1", + "Window wall type:", + "External wall", + "Glazing Type:", + "Double glazing, Unknown install date", + "Window type:", + "Window", + "Window frame type:", + "Wooden or PVC", + "What size is the glazing gap?", + "16 mm or more", + "Is the window draught proofed?", + "Yes", + "Are there permanent shutters present?", + "No", + "Window height:", + "1.84 m", + "Window width:", + "1.18 m", + "Orientation:", + "North East", + "Window 7", + "Window location:", + "Extension 1", + "Window wall type:", + "External wall", + "Glazing Type:", + "Double glazing, Unknown install date", + "Window type:", + "Window", + "Window frame type:", + "Wooden or PVC", + "What size is the glazing gap?", + "16 mm or more", + "Is the window draught proofed?", + "Yes", + "Are there permanent shutters present?", + "No", + "Window height:", + "1.76 m", + "Window width:", + "0.65 m", + "Orientation:", + "North", + "Window 8", + "Window location:", + "Extension 2", + "Window wall type:", + "External wall", + "Glazing Type:", + "Double glazing, Unknown install date", + "Window type:", + "Window", + "Window frame type:", + "Wooden or PVC", + "What size is the glazing gap?", + "16 mm or more", + "Is the window draught proofed?", + "Yes", + "Are there permanent shutters present?", + "No", + "Window height:", + "1.82 m", + "Window width:", + "0.84 m", + "Orientation:", + "South East", + "Page 10", + "", + "Window 9", + "Window location:", + "Extension 2", + "Window wall type:", + "External wall", + "Glazing Type:", + "Double glazing, Unknown install date", + "Window type:", + "Window", + "Window frame type:", + "Wooden or PVC", + "What size is the glazing gap?", + "16 mm or more", + "Is the window draught proofed?", + "Yes", + "Are there permanent shutters present?", + "No", + "Window height:", + "1.65 m", + "Window width:", + "0.5 m", + "Orientation:", + "South", + "Window 10", + "Window location:", + "Extension 2", + "Window wall type:", + "External wall", + "Glazing Type:", + "Double glazing, Unknown install date", + "Window type:", + "Window", + "Window frame type:", + "Wooden or PVC", + "What size is the glazing gap?", + "16 mm or more", + "Is the window draught proofed?", + "Yes", + "Are there permanent shutters present?", + "No", + "Window height:", + "1.71 m", + "Window width:", + "0.47 m", + "Orientation:", + "East", + "Window 11", + "Window location:", + "Extension 2", + "Window wall type:", + "External wall", + "Glazing Type:", + "Double glazing, Unknown install date", + "Window type:", + "Window", + "Window frame type:", + "Wooden or PVC", + "What size is the glazing gap?", + "16 mm or more", + "Is the window draught proofed?", + "Yes", + "Are there permanent shutters present?", + "No", + "Window height:", + "1.2 m", + "Window width:", + "0.8 m", + "Orientation:", + "South West", + "Page 11", + "", + "Heating & Hot Water", + "Main Heating Systems", + "Main Heating 1", + "How would you like to select the Heating System?", + "PCDF Search", + "System type:", + "Boiler with radiators or underfloor heating", + "Product Id", + "15030", + "Manufacturer", + "Baxi", + "Model", + "Duo-tec Combi", + "Orig Manuf", + "Baxi Heating", + "Fuel", + "Mains gas", + "S. Efficiency", + "0", + "Type", + "Combi", + "Condensing", + "Yes", + "Year", + "2006 - 2008", + "Mount", + "Wall", + "Open Flue", + "Room-sealed", + "Fan Assist", + "Yes", + "Status", + "Normal status for an actual product", + "Central heating pump age:", + "Unknown", + "Controls:", + "Programmer, room thermostat and TRVs", + "Does the boiler have a Flue Gas Heat Recover", + "System (FGHRS)?", + "No", + "Is there a weather compensator?", + "No", + "Emitter:", + "Radiators", + "Emitter Temperature:", + "Unknown", + "Secondary Heating System", + "Secondary Fuel", + "No Secondary Heating", + "Water Heating & Cylinder", + "Water Heating Type:", + "Regular", + "Water Heating System:", + "From main heating 1", + "Cylinder Size:", + "No Cylinder", + "Ventilation", + "Ventilation type:", + "Natural", + "Has fixed air conditioning?", + "No", + "Number of open flues:", + "0", + "Number of closed flues:", + "0", + "Number of boiler flues:", + "1", + "Page 12", + "", + "Number of other flues:", + "0", + "Number of extract fans:", + "2", + "Number of passive vents:", + "1", + "Number of flueless gas fires:", + "0", + "Pressure test:", + "No test", + "Is there a draught lobby?", + "Yes", + "Conservatories", + "Is there conservatory?", + "No conservatory", + "Renewables", + "Wind Turbines", + "Has wind turbines?", + "No", + "Solar hot water", + "Has solar hot water?", + "No", + "Photovoltaics", + "Has photovoltaic array?", + "No", + "Number of PV batteries:", + "None", + "Hydro", + "Is the dwelling connected to Hydro?", + "No", + "Room Count Elements", + "Number of habitable rooms?", + "3", + "Are any of these rooms unheated?", + "No", + "Number of external doors?", + "1", + "Number of insulated external doors?", + "0", + "Number of draughtproofed external doors?", + "1", + "Number of open chimneys?", + "0", + "Number of blocked chimneys?", + "0", + "Number of fixed incandescent bulbs:", + "7", + "Is the exact number of LED and CFL bulbs known?", + "Yes", + "Number of fixed LED bulbs:", + "7", + "Number of fixed CFL bulbs:", + "0", + "Are there any waste water heat recovery systems?", + "None", + "Number of baths:", + "1", + "How many special features are there at the", + "property?", + "0", + "Customer Response", + "Customer present?", + "Yes", + "Page 13", + "", + "Customer willing to answer satisfaction survey?", + "No", + "Addendum + Related Party Disclosure", + "Addendum", + "None", + "Related party disclosure", + "No related party", + "Photographs Required", + "Page 14", + "" +] \ No newline at end of file diff --git a/backend/documents_parser/tests/test_extractor.py b/backend/documents_parser/tests/test_extractor.py index 65ec8c23..be577f1b 100644 --- a/backend/documents_parser/tests/test_extractor.py +++ b/backend/documents_parser/tests/test_extractor.py @@ -66,6 +66,11 @@ def load_text_fixture_6() -> list[str]: return json.load(f) +def load_text_fixture_7() -> list[str]: + with open(os.path.join(FIXTURES, "pashub_site_notes_7_text.json")) as f: + return json.load(f) + + class TestInspectionMetadata: def test_full_inspection_metadata(self) -> None: result = PasHubRdSapSiteNotesExtractor(load_text_fixture()).extract_inspection_metadata() @@ -785,6 +790,38 @@ class TestElectricShowerExtraction: assert wu.showers[0].outlet_type == "Electric Shower" +# --- fixture 7: maisonette, 2 extensions, no property photo --- + + +class TestExtractNoPropertyPhoto: + def test_address_extracted_when_no_property_photo(self) -> None: + result = PasHubRdSapSiteNotesExtractor(load_text_fixture_7()).extract() + assert result.inspection_metadata.property_address == "Flat 3, 29 Watcombe Circus, NOTTINGHAM, NG5 2DU" + assert result.inspection_metadata.property_photo is False + assert result.general.property_type == "Maisonette" + assert result.general.number_of_extensions == 2 + + +class TestWallThicknessExtraction: + def _extractor(self) -> PasHubRdSapSiteNotesExtractor: + return PasHubRdSapSiteNotesExtractor([]) + + def test_numeric_value_returns_int(self) -> None: + assert self._extractor()._wall_thickness_in(["Wall thickness:", "310 mm"]) == 310 + + def test_unmeasurable_returns_none(self) -> None: + assert self._extractor()._wall_thickness_in(["Wall thickness:", "Unmeasurable"]) is None + + def test_unmeasurable_lowercase_returns_none(self) -> None: + assert self._extractor()._wall_thickness_in(["Wall thickness:", "unmeasurable"]) is None + + def test_unmeasurable_uppercase_returns_none(self) -> None: + assert self._extractor()._wall_thickness_in(["Wall thickness:", "UNMEASURABLE"]) is None + + def test_missing_field_returns_none(self) -> None: + assert self._extractor()._wall_thickness_in([]) is None + + class TestSolidMasonryPartyWall: @pytest.fixture def bc(self) -> BuildingConstruction: diff --git a/datatypes/epc/domain/mapper.py b/datatypes/epc/domain/mapper.py index 1ce4c73c..054b951f 100644 --- a/datatypes/epc/domain/mapper.py +++ b/datatypes/epc/domain/mapper.py @@ -1581,7 +1581,7 @@ def _map_main_building_part( construction_age_band=_extract_age_band(main.age_range), wall_construction=main.walls_construction_type, wall_insulation_type=main.walls_insulation_type, - wall_thickness_measured=main.wall_thickness_mm > 0, + wall_thickness_measured=main.wall_thickness_mm is not None, party_wall_construction=main.party_wall_construction_type, sap_floor_dimensions=_map_floor_dimensions(measurements.main_building.floors), wall_thickness_mm=main.wall_thickness_mm, @@ -1605,7 +1605,7 @@ def _map_extension_building_part( construction_age_band=_extract_age_band(ext_c.age_range), wall_construction=ext_c.walls_construction_type, wall_insulation_type=ext_c.walls_insulation_type, - wall_thickness_measured=ext_c.wall_thickness_mm > 0, + wall_thickness_measured=ext_c.wall_thickness_mm is not None, party_wall_construction=ext_c.party_wall_construction_type, sap_floor_dimensions=_map_floor_dimensions(ext_m.floors), wall_thickness_mm=ext_c.wall_thickness_mm, diff --git a/datatypes/epc/domain/tests/test_from_site_notes.py b/datatypes/epc/domain/tests/test_from_site_notes.py index ff25933c..ae1dbb3b 100644 --- a/datatypes/epc/domain/tests/test_from_site_notes.py +++ b/datatypes/epc/domain/tests/test_from_site_notes.py @@ -694,3 +694,21 @@ class TestFromSiteNotesMiscTopLevel: def test_photovoltaic_array(self, result: EpcPropertyData) -> None: # renewables.photovoltaic_array: false assert result.photovoltaic_array is False + + +class TestUnmeasurableWallThickness: + """wall_thickness_mm=None in site notes → wall_thickness_measured=False in domain.""" + + @pytest.fixture + def result(self) -> EpcPropertyData: + survey = from_dict( + PasHubRdSapSiteNotes, + load("pashub_rdsap_site_notes_example_unmeasurable_wall.json"), + ) + return EpcPropertyDataMapper.from_site_notes(survey) + + def test_wall_thickness_measured_is_false(self, result: EpcPropertyData) -> None: + assert result.sap_building_parts[0].wall_thickness_measured is False + + def test_wall_thickness_mm_is_none(self, result: EpcPropertyData) -> None: + assert result.sap_building_parts[0].wall_thickness_mm is None diff --git a/datatypes/epc/surveys/pashub_rdsap_site_notes.py b/datatypes/epc/surveys/pashub_rdsap_site_notes.py index 73a58aa6..583eb228 100644 --- a/datatypes/epc/surveys/pashub_rdsap_site_notes.py +++ b/datatypes/epc/surveys/pashub_rdsap_site_notes.py @@ -44,7 +44,7 @@ class MainBuildingConstruction: walls_insulation_type: str thermal_conductivity_of_wall_insulation: str wall_u_value_known: bool - wall_thickness_mm: int + wall_thickness_mm: Optional[int] party_wall_construction_type: str filled_cavity_indicators: Optional[str] = None @@ -59,7 +59,7 @@ class ExtensionConstruction: walls_insulation_type: str thermal_conductivity_of_wall_insulation: str wall_u_value_known: bool - wall_thickness_mm: int + wall_thickness_mm: Optional[int] party_wall_construction_type: str filled_cavity_indicators: Optional[str] = None diff --git a/datatypes/epc/surveys/tests/fixtures/pashub_rdsap_site_notes_example_unmeasurable_wall.json b/datatypes/epc/surveys/tests/fixtures/pashub_rdsap_site_notes_example_unmeasurable_wall.json new file mode 100644 index 00000000..261160f4 --- /dev/null +++ b/datatypes/epc/surveys/tests/fixtures/pashub_rdsap_site_notes_example_unmeasurable_wall.json @@ -0,0 +1,190 @@ +{ + "inspection_metadata": { + "inspection_surveyor": "test", + "email_address": "test@test.com", + "report_reference": "49D422A9-0779-44DD-9665-464D35DFF1A8", + "created_on": "2026-03-31", + "date_of_inspection": "2026-03-31", + "property_address": "1, Test Street, Test Town, Test County, TE1 1ST" + }, + "general": { + "epc_checked_before_assessment": true, + "epc_exists_at_point_of_assessment": false, + "inspection_date": "2026-03-31", + "transaction_type": "None of the Above", + "tenure": "Rented Social", + "property_type": "House", + "detachment_type": "Mid-terrace", + "number_of_storeys": 2, + "terrain_type": "Suburban", + "number_of_extensions": 0, + "electricity_smart_meter": true, + "electric_meter_type": "Single", + "dwelling_export_capable": true, + "mains_gas_available": true, + "gas_smart_meter": true, + "gas_meter_accessible": true, + "measurements_location": "Internal" + }, + "building_construction": { + "main_building": { + "age_range": "I: 1996 - 2002", + "age_indicators": "local knowledge", + "walls_construction_type": "Cavity", + "cavity_construction_indicators": "stretcher bond", + "walls_insulation_type": "As built", + "thermal_conductivity_of_wall_insulation": "Unknown", + "wall_u_value_known": false, + "wall_thickness_mm": null, + "party_wall_construction_type": "Cavity Masonry, Unfilled" + }, + "floor": { + "floor_type": "Ground Floor", + "floor_construction": "Suspended, not timber", + "floor_insulation_type": "As Built", + "floor_u_value_known": false + } + }, + "building_measurements": { + "main_building": { + "floors": [ + { + "name": "Floor 1", + "area_m2": 24.78, + "height_m": 2.37, + "heat_loss_perimeter_m": 14.21, + "pwl_m": 6.15 + }, + { + "name": "Floor 0", + "area_m2": 24.78, + "height_m": 2.35, + "heat_loss_perimeter_m": 14.21, + "pwl_m": 6.15 + } + ] + } + }, + "roof_space": { + "main_building": { + "construction_type": "Pitched roof (Slates or tiles), Access to loft", + "insulation_at": "Joists", + "roof_u_value_known": false, + "insulation_thickness_mm": 100, + "cavity_wall_construction_indicators": "No indicator of construction visible", + "rooms_in_roof": false + } + }, + "windows": [ + { + "id": 1, + "location": "Main Building", + "wall_type": "External wall", + "glazing_type": "Double glazing, Unknown install date", + "window_type": "Window", + "frame_type": "Wooden or PVC", + "glazing_gap": "16 mm or more", + "draught_proofed": true, + "permanent_shutters": false, + "height_m": 1.36, + "width_m": 1.0, + "orientation": "South East" + } + ], + "heating_and_hot_water": { + "main_heating": { + "selection_method": "PCDF Search", + "system_type": "Boiler with radiators or underfloor heating", + "product_id": 18400, + "manufacturer": "Vaillant", + "model": "ecoFIT sustain 415", + "orig_manufacturer": "Vaillant", + "fuel": "Mains gas", + "summer_efficiency": 0, + "type": "Regular", + "condensing": true, + "year": "2018 - current", + "mount": "Wall", + "open_flue": "Room-sealed", + "fan_assist": true, + "status": "Normal status for an actual product", + "central_heating_pump_age": "Unknown", + "controls": "Programmer, room thermostat and TRVs", + "flue_gas_heat_recovery_system": false, + "weather_compensator": false, + "emitter": "Radiators", + "emitter_temperature": "Unknown" + }, + "secondary_heating": { + "secondary_fuel": "No Secondary Heating" + }, + "water_heating": { + "type": "Regular", + "system": "From main heating 1", + "cylinder_size": "Normal (90-130 litres)", + "cylinder_measured_heat_loss": "Not known", + "insulation_type": "Factory fitted", + "insulation_thickness_mm": 12, + "has_thermostat": true + } + }, + "ventilation": { + "ventilation_type": "Natural", + "has_fixed_air_conditioning": false, + "number_of_open_flues": 0, + "number_of_closed_flues": 0, + "number_of_boiler_flues": 0, + "number_of_other_flues": 0, + "number_of_extract_fans": 2, + "number_of_passive_vents": 0, + "number_of_flueless_gas_fires": 0, + "pressure_test": "No test", + "draught_lobby": false + }, + "conservatories": { + "has_conservatory": false + }, + "renewables": { + "wind_turbines": false, + "solar_hot_water": false, + "photovoltaic_array": false, + "number_of_pv_batteries": 0, + "hydro": false + }, + "room_count_elements": { + "number_of_habitable_rooms": 2, + "any_unheated_rooms": true, + "number_of_heated_rooms": 0, + "number_of_external_doors": 2, + "number_of_insulated_external_doors": 0, + "number_of_draughtproofed_external_doors": 2, + "number_of_open_chimneys": 0, + "number_of_blocked_chimneys": 0, + "number_of_fixed_incandescent_bulbs": 0, + "exact_led_cfl_count_known": true, + "number_of_fixed_led_bulbs": 5, + "number_of_fixed_cfl_bulbs": 4, + "waste_water_heat_recovery": "None" + }, + "water_use": { + "number_of_baths": 1, + "number_of_special_features": 0, + "showers": [ + { + "id": 1, + "outlet_type": "Non-Electric Shower" + } + ] + }, + "customer_response": { + "customer_present": true, + "willing_to_answer_satisfaction_survey": false + }, + "addendum": { + "addendum": "None", + "related_party_disclosure": "No related party", + "hard_to_treat_cavity_access_issues": false, + "hard_to_treat_cavity_high_exposure": false, + "hard_to_treat_cavity_narrow_cavities": false + } +}