- 624-3 도구줄 = 공용 표 「b05」 · 아래 줄 = 공용 겹 줄(띠 · 올린 임도망도 숨김 · 처음 = 등고선 · 하천) · 범례 = 공용 legendRows(상태 글판 위) - 노선 띠 300 m 자르기 = B05 자기 칸(등고선 · 하천 · 1 m)만 · 그 밖 겹 = 안 자르는 둘째 GL 칸(맨 밑 · 켠 겹 있을 때만 · GL 만) · 등고선 끔 = 등고 글도 숨김 - 626-1 추천 보기 = 도구줄 아이콘 + 아래 판(영선 · 토공 최소 · 기울기 최소 · 비중 계산 · 끔) — route_recommend 저장본(지금 설계 지형) 선만 · 다시 셈 · 쓰기 없음 - 지형 칩 → 확인창 → 새 POST /route/design-terrain(설계 지형만 바꿈 · 노선 저장 체인 다시 · 노선 · 초기값 · 추천 저장본 그대로 · 잠금 · 실패 되돌림) - 걷음 — 추천 모달(_Recommend · _Help · _Map · CSS) · 좌측 「노선 추천」 칸 · saveRecommendedRoute · UI_RouteReset(서버 as_initial 길 · 시험은 남김) - 부품 상자 — createPickMenu(아이콘 고르기 메뉴 · 판 = body fixed · ✓) - 낡은 시험 고침 · 지움 — 모달 · 좌측 칸 · [적용] 화면 배선을 보던 시험(283 · 346_3 · 349 · 364_4 · 383_1 · 390_5 · 418 · 421 · 421_2 · 476_2 · 509_2 · 509_5 · 551_2 · 600_3 · b05_routeedit_initial · design_view_parity · modal_top · 133_1 · 133_2) · test_508_2 · helper_283 지움(모달 전용) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
79 lines
3.3 KiB
Python
79 lines
3.3 KiB
Python
"""B05 설계 지형 바꿈(PLAN 626-1 · 요구 530 · 결정 A④ · D2) — 평면 도구줄 지형 칩.
|
|
|
|
`POST /api/projects/{id}/route/design-terrain` 본문 `{terrain: "las" | "sheet"}` →
|
|
설계 지형만 바꾸고(`switch_design_terrain`) 노선 저장 체인을 다시 탐
|
|
(종단 · 횡단 · 배수 · 관 · 구조물 따라감 ·
|
|
계획고 옮김 없음 = 옛 · 새 계획 폴리라인 같음). 노선 · 노드 · 곡선표 = 지금 저장본 그대로(안 씀).
|
|
초기값(`initial_snapshot/`) · 추천 저장본 · 예정노선 안 씀(옛 추천 [적용] 길 `as_initial` 대신).
|
|
[저장]과 같은 프로젝트 잠금 · 떠 두고 실패면 되돌림(`common_util_save_guard`) · 같은 지형 = 바꿀 것 없음.
|
|
"""
|
|
|
|
import asyncio
|
|
import logging
|
|
from typing import Literal
|
|
from uuid import UUID
|
|
|
|
from fastapi.responses import JSONResponse
|
|
from pydantic import BaseModel
|
|
|
|
from B05_Profile.B05_Profile_Router_Terrain import router
|
|
from common_util.common_util_surface_confirmation import (
|
|
design_terrain,
|
|
get_surface_confirmation_params,
|
|
)
|
|
from config.config_db import get_db_pool
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class DesignTerrainRequest(BaseModel):
|
|
terrain: Literal["las", "sheet"]
|
|
|
|
|
|
@router.post("/{project_id}/route/design-terrain", response_model=None)
|
|
async def switch_route_design_terrain(
|
|
project_id: UUID, body: DesignTerrainRequest
|
|
) -> dict | JSONResponse:
|
|
"""설계 지형을 바꾸고 뒤 단계를 모두 다시 셈 — 노선 값 · 초기값은 그대로."""
|
|
from B05_Profile.B05_Profile_Router_Replan import (
|
|
_PROJECT_PATH_MISSING,
|
|
_planned_line,
|
|
_project_paths,
|
|
_recompute,
|
|
)
|
|
from B06_Section.B06_Section_Router_DesignSave import _restore
|
|
from common_util import common_util_save_guard as guard
|
|
|
|
lock = guard.project_lock(str(project_id))
|
|
async with lock:
|
|
paths = await _project_paths(project_id)
|
|
if paths is None:
|
|
return JSONResponse(status_code=404, content=_PROJECT_PATH_MISSING)
|
|
project_root, stored_path = paths
|
|
pool = get_db_pool()
|
|
async with pool.acquire() as connection:
|
|
now = design_terrain(await get_surface_confirmation_params(connection, str(project_id)))
|
|
if now == body.terrain:
|
|
return {"status": "success", "design": now, "changed": False}
|
|
rows = await guard.snapshot_rows(connection, str(project_id), surface=True)
|
|
files = await asyncio.to_thread(
|
|
guard.snapshot_storage, project_root, guard.STORAGE_SCOPE + guard.PIPE_SCOPE
|
|
)
|
|
try:
|
|
line = await asyncio.to_thread(_planned_line, project_root)
|
|
result = await _recompute(
|
|
project_id, project_root, stored_path, None, body.terrain, (line, line), False
|
|
)
|
|
if "error" in result:
|
|
await _restore(project_id, rows, files)
|
|
return JSONResponse(
|
|
status_code=409, content={"status": "error", "message": result["error"]}
|
|
)
|
|
except Exception:
|
|
await _restore(project_id, rows, files)
|
|
raise
|
|
finally:
|
|
files.discard()
|
|
logger.info("설계 지형 바꿈: project_id=%s %s → %s", project_id, now, body.terrain)
|
|
return {"status": "success", "design": body.terrain, "changed": True, **result}
|