diff --git a/backend/documents_parser/tests/fixtures/ExampleSiteNotes_6.pdf b/backend/documents_parser/tests/fixtures/ExampleSiteNotes_6.pdf new file mode 100644 index 00000000..f19446bd Binary files /dev/null and b/backend/documents_parser/tests/fixtures/ExampleSiteNotes_6.pdf differ diff --git a/backend/documents_parser/tests/fixtures/site_notes_example_6_text.json b/backend/documents_parser/tests/fixtures/site_notes_example_6_text.json new file mode 100644 index 00000000..ef7258de --- /dev/null +++ b/backend/documents_parser/tests/fixtures/site_notes_example_6_text.json @@ -0,0 +1 @@ +["SMART EPC: Record of", "Inspection & Site Notes", "Inspection Surveyor:", "Robert Rhodes", "E-Mail Address:", "rods30@live.co.uk", "Report Reference:", "2B688EF1-FE12-4F7E-860A-E63ABA4FEA47", "Created On:", "8 November 2025", "Date of Inspection:", "01 October 2025", "Property Address:", "34,", "Acton Road,", "Crewe,", "Cheshire,", "CW2 8TN", "Property Photo", "Page 1", "", "Photo of electricity meter:", "Photo of Gas 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:", "01/10/2025", "Transaction Type:", "Grant-Scheme (ECO, RHI, etc.)", "Tenure:", "Rented Social", "Type of Property:", "House", "Detachment Type:", "Semi-Detached", "Number of storeys:", "2 Storeys", "Terrain Type:", "Suburban", "Number of Extensions:", "No Extensions", "Is an electricity smart meter present?", "Yes", "Electric meter type:", "Single", "Is the dwelling export-capable?", "Yes", "Is mains gas available?", "Yes", "Is there a gas smart meter?", "Yes", "Is the gas meter accessible?", "Yes", "Page 2", "", "External indicators of Cavity Wall Construction:", "External indicators of Cavity Wall Construction:", "External indicators of Cavity Wall Construction:", "External indicators of Cavity Wall Construction:", "Select Measurements Location:", "Internal", "Building Construction", "Main Building", "Age Range:", "1950-1966", "Record indicators of property age:", "local knowledge, enquiries of owner", "Walls - Construction Type:", "Cavity", "Record external indicators of Cavity Construction:", "stretcher bond, wall thickness over 270 mm, evidence of cavity fill drill holes,", "Drilled and boroscoped", "Page 3", "", "Photo indicators of filled cavity insulation:", "Photo indicators of filled cavity insulation:", "Photo indicators of filled cavity insulation:", "Photo indicators of filled cavity insulation:", "Walls - Insulation Type:", "Filled Cavity", "Record indicators of filled cavity:", "evidence of cavity fill drill holes, Drilled and boroscoped wall", "Page 4", "", "Photo indicators of filled cavity insulation:", "Photo indicators of filled cavity insulation:", "Photo indicators of filled cavity insulation:", "Photo indicators of filled cavity insulation:", "Page 5", "", "Photo indicators of filled cavity insulation:", "Photo wall thickness:", "Thermal conductivity of wall insulation:", "Unknown", "Wall U-Value known?", "Not Known", "Wall thickness:", "280 mm", "Party wall construction type:", "Solid Masonry, Timber Frame, or System Built", "Floor type:", "Ground Floor", "Floor Construction:", "Solid", "Floor Insulation Type:", "As Built", "Floor U-Value known?", "Not Known", "Building Measurements", "Area (m2)", "Height (m)", "Heat Loss Perimeter (m)", "PWL (m)", "Main Building", "Floor 1", "41.33", "2.25", "18.63", "7.29", "Floor 0", "41.33", "2.46", "18.63", "7.29", "Page 6", "", "Loft insulation:", "Record indicators of party wall construction in roof space:", "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:", "300 mm", "Record indicators of Cavity Wall Construction in roof", "space:", "No indicator of construction visible", "Are there rooms in the roof?", "No", "Page 7", "", "Photo of glazing type:", "All Windows the same", "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?", "12 mm", "Is the window draught proofed?", "Yes", "Are there permanent shutters present?", "No", "Window height:", "0.88 m", "Window width:", "0.95 m", "Orientation:", "East", "Window 2", "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?", "12 mm", "Is the window draught proofed?", "Yes", "Are there permanent shutters present?", "No", "Window height:", "1.17 m", "Window width:", "0.82 m", "Orientation:", "South", "Window 3", "Window location:", "Main Building", "Page 8", "", "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?", "12 mm", "Is the window draught proofed?", "Yes", "Are there permanent shutters present?", "No", "Window height:", "1.24 m", "Window width:", "2.06 m", "Orientation:", "West", "Window 4", "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?", "12 mm", "Is the window draught proofed?", "Yes", "Are there permanent shutters present?", "No", "Window height:", "0.88 m", "Window width:", "1.45 m", "Orientation:", "East", "Window 5", "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?", "12 mm", "Is the window draught proofed?", "Yes", "Are there permanent shutters present?", "No", "Window height:", "0.88 m", "Window width:", "0.95 m", "Orientation:", "East", "Window 6", "Window location:", "Main Building", "Page 9", "", "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?", "12 mm", "Is the window draught proofed?", "Yes", "Are there permanent shutters present?", "No", "Window height:", "1.18 m", "Window width:", "0.48 m", "Orientation:", "South", "Window 7", "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?", "12 mm", "Is the window draught proofed?", "Yes", "Are there permanent shutters present?", "No", "Window height:", "0.88 m", "Window width:", "0.95 m", "Orientation:", "West", "Window 8", "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?", "12 mm", "Is the window draught proofed?", "Yes", "Are there permanent shutters present?", "No", "Window height:", "0.88 m", "Window width:", "1.45 m", "Orientation:", "West", "Page 10", "", "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", "18119", "Manufacturer", "Vaillant", "Model", "ecoTEC sustain 28", "Orig Manuf", "Vaillant", "Fuel", "Mains gas", "S. Efficiency", "0", "Type", "Combi", "Condensing", "Yes", "Year", "2017 - current", "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", "Page 11", "", "Photo of heating system:", "Photo of heating controls:", "Photo of heating controls:", "Photo of heating controls:", "Photo of heating controls:", "Page 12", "", "Photo of heating controls:", "Photo of heating controls:", "Photo of heating controls:", "Photo of secondary heating system", "Secondary Heating System", "Secondary Fuel", "Electricity", "Secondary System:", "Panel, convector or radiant heaters", "Water Heating & Cylinder", "Water Heating Type:", "Regular", "Water Heating System:", "From main heating 1", "Cylinder Size:", "No Cylinder", "Page 13", "", "Ventilation", "Ventilation type:", "Mechanical Extract - Decentralised", "Has fixed air conditioning?", "No", "Is the ventilation in the PCDF database?", "No", "Number of open flues:", "0", "Number of closed flues:", "0", "Number of boiler flues:", "0", "Number of other flues:", "0", "Number of extract fans:", "0", "Number of passive vents:", "0", "Number of flueless gas fires:", "0", "Pressure test:", "No test", "Is there a draught lobby?", "No", "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?", "4", "Are any of these rooms unheated?", "No", "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", "Is the exact number of LED and CFL bulbs known?", "Yes", "Page 14", "", "Photo of LED bulbs:", "Photo of LED bulbs:", "Photo of LED bulbs:", "Photo of LED bulbs:", "Photo of LED bulbs:", "Number of fixed LED bulbs:", "5", "Number of fixed CFL bulbs:", "2", "Page 15", "", "Photo of CFL bulbs:", "Photo of CFL bulbs:", "Photo of shower:", "Are there any waste water heat recovery systems?", "None", "Number of baths:", "1", "How many special features are there at the", "property?", "0", "Showers", "Shower 1", "Shower outlet type:", "Electric Shower", "Customer Response", "Customer present?", "Yes", "Customer willing to answer satisfaction survey?", "No", "Addendum + Related Party Disclosure", "Addendum", "PV Recommended", "Related party disclosure", "No related party", "Hard to treat cavity walls: Property has access", "issues?", "No", "Hard to treat cavity walls: Property has high", "exposure?", "No", "Hard to treat cavity walls: Property has narrow", "cavities?", "No", "Page 16", "", "General Photos:", "General Photos:", "General Photos:", "Photographs Required", "Page 17", "", "External Elevations:", "Front elavation", "External Elevations:", "Front elavation", "External Elevations:", "Front elavation", "External Elevations:", "Right Side elavation", "Page 18", "", "External Elevations:", "Right Side elavation", "External Elevations:", "Rear elavation", "External Elevations:", "Rear elavation", "External Elevations:", "Rear elavation", "Page 19", "", "Floor plan", "Page 20", ""] \ No newline at end of file diff --git a/backend/documents_parser/tests/test_end_to_end.py b/backend/documents_parser/tests/test_end_to_end.py index 7b4c7fe9..5d7597c5 100644 --- a/backend/documents_parser/tests/test_end_to_end.py +++ b/backend/documents_parser/tests/test_end_to_end.py @@ -372,3 +372,25 @@ class TestPdfToEpcPropertyDataFixture5: result.sap_heating.shower_outlets.shower_outlet.shower_outlet_type == "Electric Shower" ) + + +PDF_PATH_6 = os.path.join( + os.path.dirname(__file__), "fixtures", "ExampleSiteNotes_6.pdf" +) + + +class TestPdfToEpcPropertyDataFixture6: + @pytest.fixture + def result(self) -> EpcPropertyData: + with open(PDF_PATH_6, "rb") as f: + pdf_bytes = f.read() + site_notes = PasHubRdSapSiteNotesExtractor( + pdf_to_text_list(pdf_bytes) + ).extract() + return EpcPropertyDataMapper.from_site_notes(site_notes) + + def test_party_wall_construction(self, result: EpcPropertyData) -> None: + assert ( + result.sap_building_parts[0].party_wall_construction + == "Solid Masonry, Timber Frame, or System Built" + ) diff --git a/backend/documents_parser/tests/test_extractor.py b/backend/documents_parser/tests/test_extractor.py index 406e9234..66cc4271 100644 --- a/backend/documents_parser/tests/test_extractor.py +++ b/backend/documents_parser/tests/test_extractor.py @@ -61,6 +61,11 @@ def load_text_fixture_5() -> list[str]: return json.load(f) +def load_text_fixture_6() -> list[str]: + with open(os.path.join(FIXTURES, "site_notes_example_6_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() @@ -778,3 +783,17 @@ class TestElectricShowerExtraction: def test_shower_outlet_type(self, wu: WaterUse) -> None: assert wu.showers[0].outlet_type == "Electric Shower" + + +class TestSolidMasonryPartyWall: + @pytest.fixture + def bc(self) -> BuildingConstruction: + return PasHubRdSapSiteNotesExtractor( + load_text_fixture_6() + ).extract_building_construction() + + def test_party_wall_construction_type(self, bc: BuildingConstruction) -> None: + assert ( + bc.main_building.party_wall_construction_type + == "Solid Masonry, Timber Frame, or System Built" + )