Merge pull request #1041 from Hestia-Homes/bug/handle-missing-property-photo-in-pashub-site-notes

Fix bugs in pashub site notes extractor
This commit is contained in:
Daniel Roth 2026-04-30 17:51:16 +01:00 committed by GitHub
commit d79131cec6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 934 additions and 10 deletions

View file

@ -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 = ""

Binary file not shown.

View file

@ -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",
""
]

View file

@ -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:

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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
}
}