From 55d7b91171b860af71405e6877f05f331bef86e3 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Tue, 5 May 2026 15:46:13 +0000 Subject: [PATCH] =?UTF-8?q?map=20magicplan=20base=20models=20to=20data=20c?= =?UTF-8?q?lasses=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- datatypes/magicplan/api/response.py | 1 + datatypes/magicplan/domain/__init__.py | 0 datatypes/magicplan/domain/mapper.py | 52 ++++++++++++++++++++ datatypes/magicplan/domain/models.py | 38 ++++++++++++++ datatypes/magicplan/domain/tests/__init__.py | 0 pytest.ini | 2 +- 6 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 datatypes/magicplan/domain/__init__.py create mode 100644 datatypes/magicplan/domain/mapper.py create mode 100644 datatypes/magicplan/domain/models.py create mode 100644 datatypes/magicplan/domain/tests/__init__.py diff --git a/datatypes/magicplan/api/response.py b/datatypes/magicplan/api/response.py index b81e02d5..8e704c65 100644 --- a/datatypes/magicplan/api/response.py +++ b/datatypes/magicplan/api/response.py @@ -170,6 +170,7 @@ class Room(BaseModel): walls_surface: Optional[float] = None walls_surface_without_openings: Optional[float] = None windows_surface: Optional[float] = None + dimensions: Optional[str] = None room_type: Optional[str] = None furniture_count: Optional[int] = None image: Optional[str] = None diff --git a/datatypes/magicplan/domain/__init__.py b/datatypes/magicplan/domain/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/datatypes/magicplan/domain/mapper.py b/datatypes/magicplan/domain/mapper.py new file mode 100644 index 00000000..00efba3d --- /dev/null +++ b/datatypes/magicplan/domain/mapper.py @@ -0,0 +1,52 @@ +from datatypes.magicplan.api.response import MagicPlan +from datatypes.magicplan.domain.models import Plan, Floor, Room, Window, Door + + +def map_plan(mp: MagicPlan) -> Plan: + return Plan( + uid=mp.plan.id, + name=mp.plan.name, + floors=[_map_floor(f) for f in mp.plan_detail.plan.floors], + ) + + +def _map_floor(f) -> Floor: + return Floor( + level=f.level, + name=f.name, + rooms=[_map_room(r) for r in f.rooms], + ) + + +def _map_room(r) -> Room: + width, length = _parse_dimensions(r.dimensions) + return Room( + name=r.name, + width=width, + length=length, + area=r.area, + windows=[_map_window(wi) for wi in r.wall_items if wi.symbol.id.startswith("window")], + doors=[_map_door(wi) for wi in r.wall_items if wi.symbol.id.startswith("door")], + ) + + +def _parse_dimensions(dimensions: str | None) -> tuple[float, float]: + if not dimensions: + return 0.0, 0.0 + parts = dimensions.split(" x ") + width = float(parts[0].split(" m")[0]) + length = float(parts[1].split(" m")[0]) + return width, length + + +def _map_window(wi) -> Window: + return Window( + width=wi.size.x, + height=wi.size.z, + area=wi.size.x * wi.size.z, + opening_type=wi.symbol.id.removeprefix("window"), + ) + + +def _map_door(wi) -> Door: + return Door(width=wi.size.x) diff --git a/datatypes/magicplan/domain/models.py b/datatypes/magicplan/domain/models.py new file mode 100644 index 00000000..4f488001 --- /dev/null +++ b/datatypes/magicplan/domain/models.py @@ -0,0 +1,38 @@ +from dataclasses import dataclass, field + + +@dataclass +class Window: + width: float + height: float + area: float + opening_type: str + + +@dataclass +class Door: + width: float + + +@dataclass +class Room: + name: str + width: float + length: float + area: float + windows: list[Window] = field(default_factory=list) + doors: list[Door] = field(default_factory=list) + + +@dataclass +class Floor: + level: int | None + name: str | None + rooms: list[Room] = field(default_factory=list) + + +@dataclass +class Plan: + uid: str + name: str | None + floors: list[Floor] = field(default_factory=list) diff --git a/datatypes/magicplan/domain/tests/__init__.py b/datatypes/magicplan/domain/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pytest.ini b/pytest.ini index 2032ba6c..761dfbed 100644 --- a/pytest.ini +++ b/pytest.ini @@ -3,6 +3,6 @@ pythonpath = . log_cli = true log_cli_level = INFO addopts = --cov-report term-missing --cov=etl/epc --cov=recommendations --cov=backend --cov=etl/epc_clean --cov=etl/spatial -testpaths = recommendations/tests backend/tests etl/epc/tests etl/epc_clean/tests etl/spatial/tests backend/condition/tests backend/address2UPRN/tests backend/onboarders/tests backend/categorisation/tests backend/export/tests etl/hubspot/tests backend/hubspot_trigger_orchestrator/tests datatypes/epc/schema/tests datatypes/epc/surveys/tests datatypes/epc/domain/tests backend/ecmk_fetcher/tests/ backend/pashub_fetcher/tests backend/documents_parser/tests backend/magic_plan/tests datatypes/magicplan/api/tests +testpaths = recommendations/tests backend/tests etl/epc/tests etl/epc_clean/tests etl/spatial/tests backend/condition/tests backend/address2UPRN/tests backend/onboarders/tests backend/categorisation/tests backend/export/tests etl/hubspot/tests backend/hubspot_trigger_orchestrator/tests datatypes/epc/schema/tests datatypes/epc/surveys/tests datatypes/epc/domain/tests backend/ecmk_fetcher/tests/ backend/pashub_fetcher/tests backend/documents_parser/tests backend/magic_plan/tests datatypes/magicplan/api/tests datatypes/magicplan/domain/tests markers = integration: mark a test as an integration test