- 공용 mark_stage — save = 그 단계 진행 중 · 뒤 완료 · 진행 중 → 낡음 / next = 그 단계 완료 · 다음 미시작 · 낡음 → 진행 중 - B05 · B06 한 본문 [저장] = 단계 2 · 3 save(빈 본문 · [>] 확정 제외) · B06 [>] = 2 완료 · 3 next - B07 장 [저장] = 4 save · B07 [>] = 4 next - B08 [저장] 넷(옵션 · 자재 · 수문 · 이정) = 5 save · 새 POST quantity/complete = 5 next - B09 [저장] = 6 save · 새 POST estimation/complete = 6 next - 자동설계 체인(mark_stage_complete=False) 그대로 - 새 시험 test_298_2_stage_state · 이웃 시험 셋 기대값 맞춤 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
104 lines
3.7 KiB
Python
104 lines
3.7 KiB
Python
"""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, "mark_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"}
|