mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
223 lines
5.8 KiB
Python
223 lines
5.8 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import openpyxl
|
|
import pytest
|
|
|
|
from domain.magicplan.models import (
|
|
Door,
|
|
DoorVentilation,
|
|
Floor,
|
|
Plan,
|
|
Room,
|
|
Window,
|
|
WindowVentilation,
|
|
)
|
|
from domain.magicplan.ventilation_audit import populate_sheet
|
|
|
|
|
|
def _make_window(with_ventilation: bool = True) -> Window:
|
|
vent = (
|
|
WindowVentilation(
|
|
opening_type="Hinged",
|
|
num_openings=1,
|
|
pct_openable=50,
|
|
trickle_vent_area_mm2=1000,
|
|
num_trickle_vents=2,
|
|
)
|
|
if with_ventilation
|
|
else None
|
|
)
|
|
return Window(width_m=1.0, height_m=1.2, area_m2=1.2, ventilation=vent)
|
|
|
|
|
|
def _make_door(with_ventilation: bool = True) -> Door:
|
|
vent = DoorVentilation(undercut_mm=10.0) if with_ventilation else None
|
|
return Door(width_mm=800.0, height_mm=2000.0, ventilation=vent)
|
|
|
|
|
|
def _make_plan(
|
|
num_rooms: int = 1,
|
|
num_windows_per_room: int = 1,
|
|
num_doors_per_room: int = 1,
|
|
) -> Plan:
|
|
rooms = [
|
|
Room(
|
|
name=f"Room {i}",
|
|
width_m=3.0,
|
|
length_m=4.0,
|
|
area_m2=12.0,
|
|
windows=[_make_window() for _ in range(num_windows_per_room)],
|
|
doors=[_make_door() for _ in range(num_doors_per_room)],
|
|
)
|
|
for i in range(num_rooms)
|
|
]
|
|
return Plan(
|
|
uid="test-uid",
|
|
name="Test Plan",
|
|
address="1 Test St",
|
|
postcode="TE1 1ST",
|
|
floors=[Floor(level=0, name="Ground", rooms=rooms)],
|
|
)
|
|
|
|
|
|
def _blank_sheet() -> object:
|
|
return openpyxl.Workbook().active
|
|
|
|
|
|
def test_raises_when_rooms_exceed_50() -> None:
|
|
# Arrange
|
|
plan = _make_plan(num_rooms=51, num_windows_per_room=0, num_doors_per_room=0)
|
|
sheet = _blank_sheet()
|
|
|
|
# Act / Assert
|
|
with pytest.raises(ValueError, match="50"):
|
|
populate_sheet(sheet, plan)
|
|
|
|
|
|
def test_raises_when_windows_exceed_50() -> None:
|
|
# Arrange
|
|
plan = _make_plan(num_rooms=1, num_windows_per_room=51, num_doors_per_room=0)
|
|
sheet = _blank_sheet()
|
|
|
|
# Act / Assert
|
|
with pytest.raises(ValueError, match="50"):
|
|
populate_sheet(sheet, plan)
|
|
|
|
|
|
def test_raises_when_doors_exceed_50() -> None:
|
|
# Arrange
|
|
plan = _make_plan(num_rooms=1, num_windows_per_room=0, num_doors_per_room=51)
|
|
sheet = _blank_sheet()
|
|
|
|
# Act / Assert
|
|
with pytest.raises(ValueError, match="50"):
|
|
populate_sheet(sheet, plan)
|
|
|
|
|
|
def test_writes_window_room_name_to_column_F() -> None:
|
|
# Arrange
|
|
plan = _make_plan(num_rooms=1, num_windows_per_room=1, num_doors_per_room=0)
|
|
sheet = _blank_sheet()
|
|
|
|
# Act
|
|
populate_sheet(sheet, plan)
|
|
|
|
# Assert
|
|
assert sheet["F6"].value == "Room 0"
|
|
|
|
|
|
def test_writes_window_dimensions_to_columns_G_and_H() -> None:
|
|
# Arrange
|
|
plan = _make_plan(num_rooms=1, num_windows_per_room=1, num_doors_per_room=0)
|
|
sheet = _blank_sheet()
|
|
|
|
# Act
|
|
populate_sheet(sheet, plan)
|
|
|
|
# Assert
|
|
assert sheet["G6"].value == 1.0
|
|
assert sheet["H6"].value == 1.2
|
|
|
|
|
|
def test_writes_window_opening_data_to_columns_J_K_L() -> None:
|
|
# Arrange
|
|
plan = _make_plan(num_rooms=1, num_windows_per_room=1, num_doors_per_room=0)
|
|
sheet = _blank_sheet()
|
|
|
|
# Act
|
|
populate_sheet(sheet, plan)
|
|
|
|
# Assert
|
|
assert sheet["J6"].value == "Hinged"
|
|
assert sheet["K6"].value == 1
|
|
assert sheet["L6"].value == pytest.approx(0.5)
|
|
|
|
|
|
def test_writes_trickle_vent_count_to_N_and_total_area_to_O() -> None:
|
|
# Arrange
|
|
plan = _make_plan(num_rooms=1, num_windows_per_room=1, num_doors_per_room=0)
|
|
sheet = _blank_sheet()
|
|
|
|
# Act
|
|
populate_sheet(sheet, plan)
|
|
|
|
# Assert
|
|
assert sheet["N6"].value == 2
|
|
assert sheet["O6"].value == 1000
|
|
|
|
|
|
def test_writes_door_room_name_to_column_Q() -> None:
|
|
# Arrange
|
|
plan = _make_plan(num_rooms=1, num_windows_per_room=0, num_doors_per_room=1)
|
|
sheet = _blank_sheet()
|
|
|
|
# Act
|
|
populate_sheet(sheet, plan)
|
|
|
|
# Assert
|
|
assert sheet["Q6"].value == "Room 0"
|
|
|
|
|
|
def test_writes_door_dimensions_to_columns_R_and_S() -> None:
|
|
# Arrange
|
|
plan = _make_plan(num_rooms=1, num_windows_per_room=0, num_doors_per_room=1)
|
|
sheet = _blank_sheet()
|
|
|
|
# Act
|
|
populate_sheet(sheet, plan)
|
|
|
|
# Assert
|
|
assert sheet["R6"].value == 800.0
|
|
assert sheet["S6"].value == 10.0
|
|
|
|
|
|
def test_writes_zeros_when_window_has_no_ventilation() -> None:
|
|
# Arrange
|
|
rooms = [Room(name="Room 0", width_m=3.0, length_m=4.0, area_m2=12.0, windows=[_make_window(with_ventilation=False)], doors=[])]
|
|
plan = Plan(uid="u", name="n", address="a", postcode="p", floors=[Floor(level=0, name="G", rooms=rooms)])
|
|
sheet = _blank_sheet()
|
|
|
|
# Act
|
|
populate_sheet(sheet, plan)
|
|
|
|
# Assert
|
|
assert sheet["J6"].value == 0
|
|
assert sheet["K6"].value == 0
|
|
assert sheet["L6"].value == 0
|
|
assert sheet["N6"].value == 0 # count
|
|
assert sheet["O6"].value == 0 # total area
|
|
|
|
|
|
def test_writes_zeros_when_door_has_no_ventilation() -> None:
|
|
# Arrange
|
|
rooms = [Room(name="Room 0", width_m=3.0, length_m=4.0, area_m2=12.0, windows=[], doors=[_make_door(with_ventilation=False)])]
|
|
plan = Plan(uid="u", name="n", address="a", postcode="p", floors=[Floor(level=0, name="G", rooms=rooms)])
|
|
sheet = _blank_sheet()
|
|
|
|
# Act
|
|
populate_sheet(sheet, plan)
|
|
|
|
# Assert
|
|
assert sheet["S6"].value == 0
|
|
|
|
|
|
_TEMPLATE_PATH = (
|
|
Path(__file__).parent.parent.parent.parent
|
|
/ "applications"
|
|
/ "audit_generator"
|
|
/ "Master Sero Template - Data Extraction.xlsx"
|
|
)
|
|
|
|
|
|
def test_real_template_survives_18_doors() -> None:
|
|
# Row 23 = DATA_START_ROW(6) + 17 — previously a merged separator that caused
|
|
# AttributeError: 'MergedCell' object attribute 'value' is read-only
|
|
wb = openpyxl.load_workbook(_TEMPLATE_PATH)
|
|
sheet = wb["D1 Ventilation"]
|
|
plan = _make_plan(num_rooms=18, num_windows_per_room=0, num_doors_per_room=1)
|
|
|
|
populate_sheet(sheet, plan)
|
|
|
|
assert sheet["Q23"].value == "Room 17"
|