import os from datetime import date import pytest from backend.documents_parser.extractor import PasHubRdSapSiteNotesExtractor from backend.documents_parser.pdf import pdf_to_text_list from datatypes.epc.domain.epc_property_data import ( EpcPropertyData, InstantaneousWwhrs, MainHeatingDetail, SapBuildingPart, SapEnergySource, SapFloorDimension, SapHeating, SapWindow, ShowerOutlet, ShowerOutlets, ) from datatypes.epc.domain.mapper import EpcPropertyDataMapper PDF_PATH = os.path.join(os.path.dirname(__file__), "fixtures", "ExampleSiteNotes.pdf") class TestPdfToEpcPropertyData: @pytest.fixture def result(self) -> EpcPropertyData: with open(PDF_PATH, "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_full_epc_property_data(self, result: EpcPropertyData) -> None: assert result == EpcPropertyData( dwelling_type="Mid-terrace house", inspection_date=date(2025, 9, 25), tenure="Rented Social", transaction_type="Grant-Scheme (ECO, RHI, etc.)", roofs=[], walls=[], floors=[], main_heating=[], door_count=2, sap_heating=SapHeating( instantaneous_wwhrs=InstantaneousWwhrs(), main_heating_details=[ MainHeatingDetail( has_fghrs=False, main_fuel_type="Mains gas", heat_emitter_type="Radiators", emitter_temperature="Unknown", main_heating_control="Programmer, room thermostat and TRVs", fan_flue_present=True, ) ], has_fixed_air_conditioning=False, shower_outlets=ShowerOutlets( shower_outlet=ShowerOutlet(shower_outlet_type="Non-Electric Shower"), ), ), sap_windows=[ SapWindow( pvc_frame="Wooden or PVC", glazing_gap="16 mm or more", orientation="North West", window_type="Window", glazing_type="Double glazing, Unknown install date", window_width=2.3, window_height=1.2, draught_proofed=True, window_location="Main Building", window_wall_type="External wall", permanent_shutters_present=False, ), SapWindow( pvc_frame="Wooden or PVC", glazing_gap="16 mm or more", orientation="North West", window_type="Window", glazing_type="Double glazing, Unknown install date", window_width=1.0, window_height=1.2, draught_proofed=True, window_location="Main Building", window_wall_type="External wall", permanent_shutters_present=False, ), SapWindow( pvc_frame="Wooden or PVC", glazing_gap="16 mm or more", orientation="North East", window_type="Window", glazing_type="Double glazing, Unknown install date", window_width=1.0, window_height=0.9, draught_proofed=True, window_location="Main Building", window_wall_type="External wall", permanent_shutters_present=False, ), SapWindow( pvc_frame="Wooden or PVC", glazing_gap="16 mm or more", orientation="North", window_type="Window", glazing_type="Double glazing, Unknown install date", window_width=1.0, window_height=0.9, draught_proofed=True, window_location="Extension 1", window_wall_type="External wall", permanent_shutters_present=False, ), SapWindow( pvc_frame="Wooden or PVC", glazing_gap="16 mm or more", orientation="North East", window_type="Window", glazing_type="Double glazing, Unknown install date", window_width=1.7, window_height=0.9, draught_proofed=True, window_location="Extension 1", window_wall_type="External wall", permanent_shutters_present=False, ), SapWindow( pvc_frame="Wooden or PVC", glazing_gap="16 mm or more", orientation="North West", window_type="Window", glazing_type="Double glazing, Unknown install date", window_width=2.3, window_height=0.9, draught_proofed=True, window_location="Extension 1", window_wall_type="External wall", permanent_shutters_present=False, ), SapWindow( pvc_frame="Wooden or PVC", glazing_gap="16 mm or more", orientation="North West", window_type="Window", glazing_type="Double glazing, Unknown install date", window_width=1.2, window_height=1.0, draught_proofed=True, window_location="Extension 1", window_wall_type="External wall", permanent_shutters_present=False, ), SapWindow( pvc_frame="Wooden or PVC", glazing_gap="16 mm or more", orientation="North East", window_type="Window", glazing_type="Double glazing, Unknown install date", window_width=1.0, window_height=0.9, draught_proofed=True, window_location="Extension 1", window_wall_type="External wall", permanent_shutters_present=False, ), ], sap_energy_source=SapEnergySource( mains_gas=True, meter_type="Single", pv_battery_count=0, wind_turbines_count=0, gas_smart_meter_present=True, is_dwelling_export_capable=True, wind_turbines_terrain_type="Suburban", electricity_smart_meter_present=True, ), sap_building_parts=[ SapBuildingPart( identifier="main", construction_age_band="1950-1966", wall_construction="Cavity", wall_insulation_type="Filled Cavity", wall_thickness_measured=True, party_wall_construction="Cavity Masonry, Filled", sap_floor_dimensions=[ SapFloorDimension( room_height_m=2.19, total_floor_area_m2=35.68, party_wall_length_m=10.62, heat_loss_perimeter_m=13.44, floor=1, ), SapFloorDimension( room_height_m=2.17, total_floor_area_m2=35.68, party_wall_length_m=10.62, heat_loss_perimeter_m=11.0, floor=0, ), ], wall_thickness_mm=310, roof_insulation_location="Joists", roof_insulation_thickness=100, ), SapBuildingPart( identifier="extension_1", construction_age_band="2003-2006", wall_construction="Cavity", wall_insulation_type="As built", wall_thickness_measured=True, party_wall_construction="Cavity Masonry, Filled", sap_floor_dimensions=[ SapFloorDimension( room_height_m=2.0, total_floor_area_m2=3.8, party_wall_length_m=0.0, heat_loss_perimeter_m=5.7, floor=0, ), ], wall_thickness_mm=310, roof_insulation_location="Sloping ceiling insulation", roof_insulation_thickness="As built", ), ], solar_water_heating=False, has_hot_water_cylinder=False, has_fixed_air_conditioning=False, wet_rooms_count=0, extensions_count=1, heated_rooms_count=0, open_chimneys_count=0, habitable_rooms_count=3, insulated_door_count=0, cfl_fixed_lighting_bulbs_count=1, led_fixed_lighting_bulbs_count=0, incandescent_fixed_lighting_bulbs_count=4, total_floor_area_m2=75.16, built_form="Mid-terrace", property_type="House", has_conservatory=False, blocked_chimneys_count=0, draughtproofed_door_count=2, address_line_1="40, Abbey Place", post_town="Crewe", postcode="CW1 4JR", report_reference="6EA2A86D-94CE-4792-8D49-AB495C744EDD", )