From 326ed20015a45fbfba09fe2f3f299453c7215b56 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 16 Apr 2026 14:30:46 +0000 Subject: [PATCH] =?UTF-8?q?Load=20Conservatories,=20Renewables,=20RoomCoun?= =?UTF-8?q?tElements,=20WaterUse,=20CustomerReponse,=20SurveyAddendum=20fr?= =?UTF-8?q?om=20SiteNotes=20JSON=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/documents_parser/extractor.py | 128 ++++++++++++++++++++++++-- 1 file changed, 122 insertions(+), 6 deletions(-) diff --git a/backend/documents_parser/extractor.py b/backend/documents_parser/extractor.py index a4d9bcc9..280494fb 100644 --- a/backend/documents_parser/extractor.py +++ b/backend/documents_parser/extractor.py @@ -322,22 +322,138 @@ class PasHubRdSapSiteNotesExtractor: ) def extract_conservatories(self) -> Conservatories: - raise NotImplementedError + c_section = self._section("Conservatories", "Renewables") + val = self._get_in(c_section, "Is there conservatory?") + return Conservatories( + has_conservatory=val is not None and val.lower() != "no conservatory" + ) def extract_renewables(self) -> Renewables: - raise NotImplementedError + r_section = self._section("Renewables", "Room Count Elements") + batteries_raw = self._get_in(r_section, "Number of PV batteries:") + batteries = ( + 0 + if batteries_raw is None or batteries_raw.lower() == "none" + else int(batteries_raw) + ) + return Renewables( + wind_turbines=self._bool_in(r_section, "Has wind turbines?"), + solar_hot_water=self._bool_in(r_section, "Has solar hot water?"), + photovoltaic_array=self._bool_in(r_section, "Has photovoltaic array?"), + number_of_pv_batteries=batteries, + hydro=self._bool_in(r_section, "Is the dwelling connected to Hydro?"), + ) def extract_room_count_elements(self) -> RoomCountElements: - raise NotImplementedError + rce_section = self._section("Room Count Elements", "Customer Response") + heated_rooms_raw = self._get_in(rce_section, "Number of heated rooms?") + return RoomCountElements( + number_of_habitable_rooms=int( + self._get_in(rce_section, "Number of habitable rooms?") or 0 + ), + any_unheated_rooms=self._bool_in( + rce_section, "Are any of these rooms unheated?" + ), + number_of_heated_rooms=int(heated_rooms_raw) if heated_rooms_raw else None, + number_of_external_doors=int( + self._get_in(rce_section, "Number of external doors?") or 0 + ), + number_of_insulated_external_doors=int( + self._get_in(rce_section, "Number of insulated external doors?") or 0 + ), + number_of_draughtproofed_external_doors=int( + self._get_in(rce_section, "Number of draughtproofed external doors?") or 0 + ), + number_of_open_chimneys=int( + self._get_in(rce_section, "Number of open chimneys?") or 0 + ), + number_of_blocked_chimneys=int( + self._get_in(rce_section, "Number of blocked chimneys?") or 0 + ), + number_of_fixed_incandescent_bulbs=int( + self._get_in(rce_section, "Number of fixed incandescent bulbs:") or 0 + ), + exact_led_cfl_count_known=self._bool_in( + rce_section, "Is the exact number of LED and CFL bulbs known?" + ), + number_of_fixed_led_bulbs=int( + self._get_in(rce_section, "Number of fixed LED bulbs:") or 0 + ), + number_of_fixed_cfl_bulbs=int( + self._get_in(rce_section, "Number of fixed CFL bulbs:") or 0 + ), + waste_water_heat_recovery=self._get_in( + rce_section, "Are there any waste water heat recovery systems?" + ) or "", + ) def extract_water_use(self) -> WaterUse: - raise NotImplementedError + wu_section = self._section("Room Count Elements", "Customer Response") + baths_raw = self._get_in(wu_section, "Number of baths:") or "0" + special_raw = self._get_in( + wu_section, "How many special features are there at the", offset=2 + ) or "0" + + showers = [] + n = 1 + while f"Shower {n}" in wu_section: + start = wu_section.index(f"Shower {n}") + end = ( + wu_section.index(f"Shower {n + 1}") + if f"Shower {n + 1}" in wu_section + else len(wu_section) + ) + shower_data = wu_section[start:end] + showers.append( + Shower( + id=n, + outlet_type=self._get_in(shower_data, "Shower outlet type:") or "", + ) + ) + n += 1 + + return WaterUse( + number_of_baths=int(baths_raw), + number_of_special_features=int(special_raw), + showers=showers, + ) def extract_customer_response(self) -> CustomerResponse: - raise NotImplementedError + cr_section = self._section( + "Customer Response", "Addendum + Related Party Disclosure" + ) + return CustomerResponse( + customer_present=self._bool_in(cr_section, "Customer present?"), + willing_to_answer_satisfaction_survey=self._bool_in( + cr_section, "Customer willing to answer satisfaction survey?" + ), + ) def extract_addendum(self) -> SurveyAddendum: - raise NotImplementedError + a_section = self._section( + "Addendum + Related Party Disclosure", "Photographs Required" + ) + return SurveyAddendum( + addendum=self._get_in(a_section, "Addendum") or "", + related_party_disclosure=self._get_in( + a_section, "Related party disclosure" + ) or "", + hard_to_treat_cavity_access_issues=self._bool_in( + a_section, + "Hard to treat cavity walls: Property has access", + offset=2, + ), + hard_to_treat_cavity_high_exposure=self._bool_in( + a_section, + "Hard to treat cavity walls: Property has high", + offset=2, + ), + hard_to_treat_cavity_narrow_cavities=self._bool_in( + a_section, + "Hard to treat cavity walls: Property has narrow", + offset=2, + ), + ) def _parse_main_heating(self, data: List[str]) -> MainHeating: return MainHeating(