"""B07 횡단도 [확정]은 설계 **상태만** 올린다 — 정본 설계값을 덮지 않는다 (2026-09-14 브레인 ②). 실측(936be972 · 읽기만): 옛 [확정]은 입력 셋(지반·단면·측구 쪽)만으로 단면적을 다시 계산해 설계를 통째로 덮었다 — 62측점 전부 단면적이 바뀌고(절토 −20.8% · 성토 +5.8%) 암선·절토경사· 표준 횡단·구조물 트림이 빠졌으며, 종점 1078.01 은 **사용자가 끈 측구가 켜졌다**. B07 CAD 에는 설계를 고치는 자리가 없으므로 덮을 값이 없다 — 「반만 계산할 거면 반만 덮는다」. """ from __future__ import annotations import asyncio from pathlib import Path from types import SimpleNamespace from uuid import UUID import B07_DesignDetail.B07_DesignDetail_Router as router from B07_DesignDetail.B07_DesignDetail_Schema import DesignDrawingConfirmRequest STORED = { "status": "provisional", "ground_type": "ripping_rock", "section_mode": "left_cut", "ditch_side": "left", "ditch_enabled": False, "rock_boundary_offset_m": 0.8, "cut_slope_ratio": 0.5, "cut_area_m2": 48.894, "fill_area_m2": 54.84, } class _Cursor: async def __aenter__(self) -> _Cursor: return self async def __aexit__(self, *_: object) -> bool: return False class _Connection: async def begin(self) -> None: ... async def commit(self) -> None: ... async def rollback(self) -> None: ... def cursor(self) -> _Cursor: return _Cursor() class _Acquire: async def __aenter__(self) -> _Connection: return _Connection() async def __aexit__(self, *_: object) -> bool: return False def test_확정은_상태만_올리고_설계값을_안_덮는다(monkeypatch, tmp_path: Path) -> None: patches: list[dict] = [] async def source(_project_id: UUID) -> tuple[int, Path, Path, bool]: return 182, tmp_path, tmp_path / "longitudinal.json", False async def designs(_route_id: int) -> dict[int, dict]: return {700: dict(STORED)} async def merge(_connection: object, **kwargs: object) -> bool: patches.append(dict(kwargs["patch"])) # type: ignore[arg-type] return True async def stage(*_: object) -> None: ... monkeypatch.setattr(router, "_confirmed_source", source) monkeypatch.setattr(router, "_designs_by_chainage", designs) monkeypatch.setattr( router, "_drawing_list", lambda *_: [SimpleNamespace(id="cross_00700m", kind="cross")] ) monkeypatch.setattr(router, "extract_quantity_table", lambda *_: None) monkeypatch.setattr(router, "_store_confirmed_drawing", lambda *_: False) monkeypatch.setattr(router, "get_db_pool", lambda: SimpleNamespace(acquire=_Acquire)) monkeypatch.setattr(router, "merge_cross_section_design_by_round", merge) monkeypatch.setattr(router, "start_stage", stage) monkeypatch.setattr(router, "complete_stage", stage) # 옛 길 — 입력 셋으로 다시 계산한 값(암 절토경사가 빠져 절토가 줄어든 모양)을 흉내 낸다. monkeypatch.setattr( router, "_recompute_confirmed_design", lambda *_: {**STORED, "ditch_enabled": True, "cut_area_m2": 7.527, "status": "confirmed"}, raising=False, ) response = asyncio.run( router.confirm_design_drawing( UUID("936be972-11bc-46c2-8bf3-b15d8de7df0d"), "cross_00700m", DesignDrawingConfirmRequest(drawing={}), ) ) # 덮는 것은 상태 하나뿐 — 단면적·사용자 입력(측구 끔)은 그대로. assert patches == [{"status": "confirmed"}] # 화면 정보 패널이 받는 설계도 저장값 그대로(상태만 확정). assert response.design == {**STORED, "status": "confirmed"}