feat(520-4): B05 · B06 페이지 넘김 공용 moveStage — B06 [>] 잠금판 「설계 확정」 서버 저장 차례 n/N 이름 · 배수유역 다시 셈 한 번
- B06 [>] · 단계 판 B07~B09 = moveStage 한 단계(설계 확정) · progress = GET /design/save/progress 1 s 물음 · B03 · B04 로 = moveStage 잠금 길(떠남 확인은 잠금 풀린 뒤) - 낡음 확인 창 · 화면 side.update() 걷음 — 배수유역은 서버 [확정] 관 차례가 한 번만 셈 · 진행 이름 「배수유역 다시 셈」(basins) - 서버 _run_steps step() 진행을 메모리(B06_Section_Router_DesignSave_Progress) · 차례 목록 = N · 끝에 비움 - 노선 바뀐 채 [>] = 물음(잠금판 위 · z 1050 > 900) → 다시 세운 페이지 둘째 확정을 저장 줄 밖에서 기다림 → 잠금판이 다시 마운트를 넘어 이어져 이동 · 120 s 넘으면 머묾 - saveSharedDesign 이 참 · 거짓을 돌려줌 · 확정 이동은 부른 쪽(moveStage) - 낡은 시험 고침 — 512_2(확인 창 → 잠금판 한 단계 · 서버 basins) · 298_3 · 272 · b06_save_channels · b06_save_recompute(글 약속 새 길) - helper_ts_stub_loader .css = 빈 모듈 — 520-3 ui_template_progress.css import 로 451 · 384_4 · 416 등 helper 시험이 깨짐(브레인 승인) - 새 시험 test_520_4_save_progress(n/N · 배수유역 자리) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,7 @@ from B05_Profile.B05_Profile_Schema import (
|
||||
RouteConfirmRequest,
|
||||
)
|
||||
from B05_Profile.B05_Profile_Structures_Schema import StructureSaveRequest
|
||||
from B06_Section import B06_Section_Router_DesignSave_Progress as progress
|
||||
from B06_Section.B06_Section_Router_DesignSave_Route import RouteCarryRequest, StepFailed
|
||||
from B06_Section.B06_Section_Router_Stations import PlusStationsRequest
|
||||
from B06_Section.B06_Section_Schema import SectionConfirmRequest
|
||||
@@ -83,6 +84,15 @@ def _body(response: Any) -> dict[str, Any]:
|
||||
return dict(response or {})
|
||||
|
||||
|
||||
async def _stale_or_false(stale: Any, project_id: UUID) -> bool:
|
||||
"""진행 이름 고르기만 — 판정 실패는 저장을 막지 않음(관 차례가 다시 판정)."""
|
||||
try:
|
||||
return bool(await stale(project_id))
|
||||
except Exception:
|
||||
logger.exception("한 본문 저장 배수유역 낡음 판정 실패: project_id=%s", project_id)
|
||||
return False
|
||||
|
||||
|
||||
def _patched_points(stored: dict[str, Any], patches: dict[str, dict[str, Any]]) -> list | None:
|
||||
"""저장된 관 목록에 관 옵션 조각 — 고친 것이 없으면 None(브라우저 `flushCulvertOptions` 짝)."""
|
||||
points, touched = [], False
|
||||
@@ -100,7 +110,11 @@ async def _run_steps(
|
||||
project_id: UUID, request: DesignSaveRequest, session: dict[str, Any] | None
|
||||
) -> dict[str, Any]:
|
||||
"""차례대로 안쪽 창구 · 차례 이름째 실패를 던짐 → 차례별 응답(알림 · 화면 맞춤용)."""
|
||||
from B04_PreProcess.B04_PreProcess_Router_Basins import get_pipe_points, put_pipe_points
|
||||
from B04_PreProcess.B04_PreProcess_Router_Basins import (
|
||||
_analysis_stale,
|
||||
get_pipe_points,
|
||||
put_pipe_points,
|
||||
)
|
||||
from B05_Profile.B05_Profile_Router import save_profile_alignment
|
||||
from B05_Profile.B05_Profile_Router_Lifecycle import confirm_latest_route, save_page_settings
|
||||
from B05_Profile.B05_Profile_Structures_Router import write_structures
|
||||
@@ -111,8 +125,26 @@ async def _run_steps(
|
||||
route_id = request.route_id
|
||||
moved = request.route is not None
|
||||
before: dict[str, Any] = {}
|
||||
# 잠금판 진행(520-4) — 이 본문이 거칠 차례 목록 = N
|
||||
planned = [
|
||||
name
|
||||
for name, on in (
|
||||
("route", moved),
|
||||
("settings", request.settings is not None),
|
||||
("pipes", request.pipes is not None or request.confirm),
|
||||
("structures", request.structures is not None),
|
||||
("plusStations", request.plus_stations is not None),
|
||||
("alignment", request.alignment is not None),
|
||||
("culvertOptions", bool(request.culvert_options)),
|
||||
("uphill", request.uphill is not None and not moved),
|
||||
("cross", moved or request.cross is not None),
|
||||
)
|
||||
if on
|
||||
]
|
||||
progress.begin(project_id, planned)
|
||||
|
||||
async def step(name: str, call: Any) -> dict[str, Any]:
|
||||
async def step(name: str, call: Any, label: str | None = None) -> dict[str, Any]:
|
||||
progress.mark(project_id, label or name)
|
||||
try:
|
||||
out[name] = _body(await call)
|
||||
except StepFailed as failed:
|
||||
@@ -146,8 +178,12 @@ async def _run_steps(
|
||||
if request.settings is not None:
|
||||
await step("settings", save_page_settings(project_id, request.settings))
|
||||
if request.pipes is not None or request.confirm:
|
||||
# [확정] + 낡은 분석 = 관 차례가 배수유역부터 다시 셈(한 번 · 화면 [업데이트] 없음 · 520-4)
|
||||
basins = request.confirm and await _stale_or_false(_analysis_stale, project_id)
|
||||
pipes = await step(
|
||||
"pipes", put_pipe_points(project_id, request.pipes or {}, session, request.confirm)
|
||||
"pipes",
|
||||
put_pipe_points(project_id, request.pipes or {}, session, request.confirm),
|
||||
"basins" if basins else None,
|
||||
)
|
||||
if pipes.get("stations_failed"):
|
||||
raise StepFailed("pipes", "관 자리 측점을 못 맞췄습니다")
|
||||
@@ -170,6 +206,7 @@ async def _run_steps(
|
||||
raise StepFailed("uphill", " · ".join(parts["failed_parts"]) + " 실패")
|
||||
# 노선 바뀜 = 옛 노선 세션 칸 → 새 측점 patch(Node) · 고침이 없어도 한 번(429 ④)
|
||||
if moved:
|
||||
progress.mark(project_id, "cross")
|
||||
try:
|
||||
carried = await moving.carry_cross(project_id, route_id, request.carry, before)
|
||||
except StepFailed:
|
||||
@@ -251,9 +288,16 @@ async def save_design(
|
||||
)
|
||||
finally:
|
||||
files.discard()
|
||||
progress.end(project_id)
|
||||
return JSONResponse(content={"status": "success", "waited": waited, "steps": steps})
|
||||
|
||||
|
||||
@router.get("/{project_id}/design/save/progress")
|
||||
async def get_design_save_progress(project_id: UUID) -> dict[str, Any]:
|
||||
"""잠금판 진행 묻기(520-4) — 차례 이름 · n/N · 지난 초 · 안 돌면 active 거짓."""
|
||||
return progress.snapshot(project_id)
|
||||
|
||||
|
||||
async def _restore(project_id: UUID, rows: dict[str, list], files: guard.StorageSnapshot) -> bool:
|
||||
"""떠 둔 대로 — 성공 = 참 · 하나라도 못 되돌리면 로그 남기고 거짓(조용히 넘기지 않음)."""
|
||||
ok = True
|
||||
|
||||
Reference in New Issue
Block a user