feat(472-6 6-B 노선 바뀐 [저장] 한 본문): 노선 저장 · 관 · 구조물 다시 얹기 · 횡단 고침 넘김을 서버 한 창구로 — 전부 아니면 없음

- POST /design/save 에 route(노선 초안) · carry(옛 노선 세션 칸) 칸 · 서버 = 노선 저장 → Node facility.rebase(rebasePipeDraft · rebaseStructureDraft) → 6-A 차례(새 노선) → Node stations.carry(routeCarryPatches) → 횡단 저장
- 되돌림 범위 = 노선 행 · 자식 표 · 단계 · 배수 폴더 · 노선 파일 · 지표면 확정(설계 지형 바꿈)
- 손 상단측은 안 넘김(요구 274) · 노선 바뀐 [확정] = [저장](새 노선 본 뒤 다시)
- 브라우저 = 노선 초안 + 사용자 칸만 한 본문 · 옛 차례 길(saveRouteDraft 뒤 flush · carryAfterRouteSave · keepDraftsOnNewRoute) · 부름 0 된 flush 창구 여섯 · saveCachedCrossPatches 걷음
- 등록부 R9 stations.carry · F10 facility.rebase · 옛 차례 단언 시험 한 본문 꼴로 · test_472_6_route_save(옛 길 = 새 길 · 실패 되돌림)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-19 12:07:12 +09:00
co-authored by Claude Opus 5.5
parent de0141b8fc
commit 4b6800e387
48 changed files with 1340 additions and 731 deletions
@@ -16,10 +16,10 @@ source: ["docs/raw/조사/2026-10-19_470_B05B06_데이터흐름.md", "docs/raw/
| 조작 | 처음 놓이는 곳 | 브라우저 즉시 셈(모듈) | 서버 뒤 셈(API) | [저장]·[확정] 때 | 사본 | 위치(파일:줄) |
|---|---|---|---|---|---|---|
| 교점 끌기 | 편집기 메모리(planned · curveRadius · curveArc) → 놓을 때 세션 `route-draft` · 첫 초안이면 초안 전 상세를 hold | 묶음 전 단계(노선 초안 차례 · 새 표본) | 지반 대체 `/route/elevations` · 배수 `/drainage/live` · 유토 배분 `/haul-plan` | `/route/replan` — 노선 · 측점 · 표본 · 횡단 서버가 처음부터 · 뒤 차례 = 새 노선 | 11 | `B05_Profile_UI_RouteEdit.ts:126-145` · `B05_Profile_UI_RouteEdit_Pointer.ts:387-430` · `design_pipeline_page.ts:636-659` · `B05_Profile_UI_RouteEdit_Apply.ts:98-135` → `B05_Profile_Router_Replan.py:552-605` → `B05_Profile_Route_Save.py:337-510` |
| 교점 끌기 | 편집기 메모리(planned · curveRadius · curveArc) → 놓을 때 세션 `route-draft` · 첫 초안이면 초안 전 상세를 hold | 묶음 전 단계(노선 초안 차례 · 새 표본) | 지반 대체 `/route/elevations` · 배수 `/drainage/live` · 유토 배분 `/haul-plan` | `/design/save` `route` 칸 — 서버가 노선 · 측점 · 표본 · 횡단 처음부터 · 관 · 구조물 다시 얹기 · 세션 횡단 고침 넘김(Node) · 뒤 차례 = 새 노선 · 전부 아니면 없음 | 11 | `B05_Profile_UI_RouteEdit.ts:126-145` · `B05_Profile_UI_RouteEdit_Pointer.ts:387-430` · `design_pipeline_page.ts:636-659` · `B05_Profile_UI_RouteEdit_Apply.ts:94-135` → `B06_Section_Router_DesignSave.py:128-145` → `B05_Profile_Router_Replan.py:552-605` → `B05_Profile_Route_Save.py:337-510` |
| 방향키(0.1 m · Shift 1 m) | 교점 끌기와 같음 | 같음 | 같음 | 같음 | 11 | `B05_Profile_UI_RouteEdit_Keys.ts:61-64 · 118-159` |
| 교점 추가 · 삭제 | 편집기 메모리 → `route-draft` | 묶음 전 단계 · 측점 수 바뀜 → 갈아끼움 | 같음 | 같음 | 11 | `B05_Profile_UI_RouteEdit_Input.ts:149-158` · `logic/B05_Profile_UI_RouteEdit_Edits.ts:410-426` |
| 곡선 R · L | 편집기 `curveRadius` · `curveArc` → `route-draft` | 묶음 전 단계 · 확폭 · MC 이동 → 곡선 열쇠 옮김(`curveMoves`) | 같음 | `/route/replan` — 넣은 R · L 로 서버가 같은 규칙 | 11 | `B05_Profile_UI_RouteEdit_CurveBar.ts:76-162` · `logic/B05_Profile_Sections_Stations.ts:332-337` · `B05_Profile_Router_Replan.py:582 · 599-600` |
| 곡선 R · L | 편집기 `curveRadius` · `curveArc` → `route-draft` | 묶음 전 단계 · 확폭 · MC 이동 → 곡선 열쇠 옮김(`curveMoves`) | 같음 | `/design/save` `route` 칸 — 넣은 R · L 로 서버가 같은 규칙 | 11 | `B05_Profile_UI_RouteEdit_CurveBar.ts:76-162` · `logic/B05_Profile_Sections_Stations.ts:332-337` · `B05_Profile_Router_Replan.py:582 · 599-600` |
| 스냅 켬 · 간격 | 간격 = pref `routeedit-snap-step` · 켬 = `route-draft.stationSnap` | 켬 = 곡선 IP 를 옮김(한 걸음) → 묶음 전 단계 | — | 곡선표 파일 · 서버는 측점만 맞춤(IP 맞춤은 브라우저만) | 3 | `B05_Profile_UI_RouteEdit_SnapStep.ts:74-78` · `logic/design_pipeline_stations.ts:52-59` · `B05_Profile_Engine_Sections_Core.py:457-464` |
| 추천 노선 [적용] | result `routeedit-initial` → `route-draft` | 묶음 한 바퀴 | 미리 셈 `/route/initial` → `route_recommend/*` | **저장 밖** — 바로 `/route/replan`(as_initial) · 초기값 다시 뜸 · 초안 전부 지움 · 페이지 다시 세움 | 11 | `B05_Profile_UI_RouteEdit_Initial.ts:139 · 161-181` · `B05_Profile_UI_RouteEdit_Apply.ts:211 · 220-245` · `B05_Profile_Router_Replan.py:659-662` |
@@ -31,6 +31,6 @@ source: ["docs/raw/조사/2026-10-19_470_B05B06_데이터흐름.md", "docs/raw/
|---|---|---|---|---|---|---|
| B06 폼 관 측점 · 옵션 고침 | `pipeFacilities` → 세션 `pipes` · 옮긴 자리(정수 m)로 옵션 · 캐시 얹기 · 집계 찾음 | B05 관 옮김과 같음 | 배수유역 다시 나눔 | 관 차례 `PUT /drainage/pipe-points` | 14 | `B06_Section_UI_Page_Structures_Panel.ts:300-345 · 536-560` |
| B06 구조물 패널 | 보기 `structures` → 시설 줄 `set` → 세션 `structures` | B05 구조물과 같음 | — | `PUT /route/structures` | 11 | `B06_Section_UI_Page_Structures_Panel.ts:211-227 · 582-598` |
| B06 평면 패널 끌기 | B05 교점 끌기와 같음(같은 편집기를 옮겨 붙임) | 같음 · B06 쪽 갈아끼움이 먼저 | 같음 | `/route/replan` | 11 | `design_plan_peek.ts:61-77` · `B05_Profile_UI_RouteEdit.ts:290-293 · 599-601` · `B06_Section_UI_Page_Station_Swap.ts:35` |
| B06 평면 패널 끌기 | B05 교점 끌기와 같음(같은 편집기를 옮겨 붙임) | 같음 · B06 쪽 갈아끼움이 먼저 | 같음 | `/design/save` `route` 칸 | 11 | `design_plan_peek.ts:61-77` · `B05_Profile_UI_RouteEdit.ts:290-293 · 599-601` · `B06_Section_UI_Page_Station_Swap.ts:35` |
| 넓힘(표본 폭 넘음) | 없음 — 확인창 뒤 바로 서버 | 응답 뒤 상세 강제 다시 받음 | `/sections/{노선}/regenerate` | **저장 밖** — DB 바로 씀(이미 정본) | 3 | `B06_Section_UI_Page_Common.ts:32-63` · `B06_Section_Router.py:378-388` · `B06_Section_Router_Widen.py:80` |
| [측점 만들기] | 없음 — 바로 서버 | 응답 뒤 상세 비움 · 강제 다시 받음 · 알림 | `/section/missing-stations` | **저장 밖** — 종단 · 횡단 파일 바로 씀 | 3 | `B06_Section_UI_Missing_Stations.ts:86-138` · `B06_Section_Router_Stations.py:236-296 · 365-407` |
@@ -19,26 +19,25 @@ source: ["docs/raw/조사/2026-10-19_470_B05B06_데이터흐름.md", "docs/raw/
| 새로고침 | 세션 남음 · 메모리 전부 잃음 | 세션 상세로 먼저 섬 → 서버 정본과 비교(`checkSessionCanon`) → 다르면 갈아씀 · 노선 초안 있으면 hold · 관 · 구조물 · 추가 측점 초안 있으면 측점 냄 · 없으면 조용히 열고 가게 측점 = 상세 측점 | 상세 GET(정본 확인) | — | — | `B06_Section_Section_Store.ts:117-135` · `design_pipeline_page.ts:528-545` · `design_pipeline_page_publish.ts` opened · shown |
| 떠남 [취소] | 없음 — 페이지 그대로 | — | — | — | — | `design_leave.ts:95-123` |
| 떠남 [폐기] | 세션 고침 칸 지움(모든 노선 · `NOT_EDITS` · B08 · B09 칸 뺌) → 떠남 = dispose | dispose = 묶음 · 시설 줄 · 페이지 자료(`forgetPageData`) · 상세 메모리(`forgetSectionMemory`) 버림 · 다시 열면 새로고침 길 | — | — | — | `design_leave.ts:27-42 · 85-87` · `design_page.ts:286-295` · `B06_Section_Section_Store.ts:424-428` |
| [저장] | — | 앞 단계 `prepare` = 전 측점 강제 다시 셈(서버가 면적 버림) · 화면 잠금 | 노선 안 바뀜 = 조각 한 본문 `POST /design/save`(서버가 아래 차례 · 전부 아니면 없음) · 노선 바뀜 = 아래 차례 표(옛 길) · 서버 정본 다시 셈 | 끝 = `invalidateSectionDetail` · 두 보기가 새 상세 한 객체 받음 · 노선 바뀜 = 페이지 다시 세움 | — | `design_shared.ts:395-448` · `design_save.ts:237-324` |
| [확정] | — | [저장]과 같음 | [저장] + 빈 측점 기본 설계 · 단계 완료 · 측구 쪽을 B05 종단 파일로 되씀 | 끝 = `invalidateSectionDetail` → B07 로 넘어감 · 노선이 바뀐 [확정] = 노선만 저장 · 다시 [확정] 알림 | — | `design_shared.ts:426-432` · `design_save.ts:303-310` · `B06_Section_Router_Confirm.py:368-496` |
| [저장] | — | 앞 단계 `prepare` = 전 측점 강제 다시 셈(서버가 면적 버림) · 화면 잠금 | 조각 한 본문 `POST /design/save`(서버가 아래 차례 · 전부 아니면 없음 · 노선 바뀜도) · 서버 정본 다시 셈 | 끝 = `invalidateSectionDetail` · 두 보기가 새 상세 한 객체 받음 · 노선 바뀜 = 페이지 다시 세움 | — | `design_shared.ts:395-448` · `design_save.ts:183-237` |
| [확정] | — | [저장]과 같음 | [저장] + 빈 측점 기본 설계 · 단계 완료 · 측구 쪽을 B05 종단 파일로 되씀 | 끝 = `invalidateSectionDetail` → B07 로 넘어감 · 노선이 바뀐 [확정] = [저장]으로 · 다시 [확정] 알림 | — | `design_shared.ts:426-432` · `design_save.ts:224-228` · `B06_Section_Router_Confirm.py:368-496` |
| [초기화] | — | 상세 비움 · 새로고침(메모리 전부 버림) | `/route/reset` | DB 노선 행 지우고 초기값으로 · 파일 트리 복원 · 세션 초안 전부 지움(B08 · B09 뺌) | — | `design_reset.ts:30-62` · `B05_Profile_Router_Lifecycle.py:234-390` · `common_util_initial_snapshot.py:38-54 · 266-327` |
## [저장] 차례(`DESIGN_SAVE_ORDER` `design_save.ts:58-68`)
## [저장] 차례(서버 `B06_Section_Router_DesignSave.py:99-195` · 칸 = `design_save_api.ts` SAVE_PART_KEYS)
- 노선 안 바뀐 [저장] · [확정](472-6 6-A) — 브라우저가 차례마다 조각(본문 · 저장 뒤 정리)을 모아 한 요청 (`design_save.ts` saveOneBody · `design_save_api.ts`) · 서버 `B06_Section_Router_DesignSave.py` 가 같은 차례로 아래 창구 함수를 부름 · 하나라도 실패 = DB 행 · storage 되돌림(`common_util_save_guard.py`) · 차례 이름째 알림 · 같은 프로젝트 저장 겹침 = 뒤 요청 기다림.
- 노선 바뀐 [저장] = 아래 표 차례마다 요청(6-B 전).
- [저장] · [확정] = 한 본문 한 요청(472-6) — 브라우저가 차례마다 조각(본문 · 저장 뒤 정리)을 모아 `POST /design/save`(`design_save.ts:183-237`) · 서버가 아래 차례로 안쪽 창구 함수를 부름 · 하나라도 실패 = DB 행 · storage 되돌림(`common_util_save_guard.py`) · 차례 이름째 알림 · 다 저장한 뒤에만 조각 정리 · 같은 프로젝트 저장 겹침 = 뒤 요청 기다림.
- 노선 바뀐 [저장](6-B) = 같은 본문에 `route`(노선 초안) · `carry`(옛 노선 세션 횡단 고침 원본 `routeCarryInputs` `B06_Section_Station_Keys.ts:314`) · 기본 조각만(화면 몫 건너뜀) · 늘 [저장](노선이 바뀐 [확정] = 노선만 저장 · 다시 [확정] 알림) · 되돌림 범위 + 배수 폴더 · 지표면 확정.
| 차례 | 기본 창구 | 서버 | 노선 바뀐 [저장] | 위치(파일:줄) |
| 차례 | 브라우저 조각 | 서버 | 노선 바뀐 [저장] | 위치(파일:줄) |
|---|---|---|---|---|
| route | `pendingRouteSave` → `saveRouteDraft` | `/route/replan` · 관 · 구조물 따라감 · 노선 밖 알림 | 새 노선 id · 관 · 구조물 초안 다시 얹음 | `design_save.ts:255-274` |
| settings | `flushPageSettings` | `PUT /route/page-settings` | 그대로 | `design_save.ts:177-178` |
| pipes | `flushPendingPipes` + 화면 몫(배수판 다시 받음 · PUT 없음) | `PUT /drainage/pipe-points` | 기본 창구만 | `design_save.ts:179-180 · 289-294` |
| structures | `flushPendingStructures` | `PUT /route/structures` | 기본 창구만 | `design_save.ts:181-182` |
| plusStations | `flushPlusStations` | `PUT /section/plus-stations` | 기본 창구만 | `design_save.ts:183-184` |
| alignment | `flushAlignmentDraft` | `PUT /route/profile-alignment` | 초안 노선 0 편집을 새 노선에 | `design_save.ts:185-186` |
| culvertOptions | `flushCulvertOptions`(`culvertopt` · 옛 노선 열쇠) | `pipe_points.json` 한 번 더 PUT | 옛 노선 열쇠로 읽음 | `design_save.ts:187-188` · `B06_Section_Api_Culvert_Options.ts:67-95` |
| uphill | `flushRouteParts` | 상단측 | 건너뜀 — 횡단 차례가 옮긴 뒤 보냄 | `design_save.ts:189-190 · 285` · `B05_Profile_Api_Fetch.ts:321-342` |
| cross | `ctx.cross(confirm)` = 횡단 패치 한 요청 | `/sections/{노선}/save` · `confirm` · 재계산 맨 앞 종단 경고 다시 씀(`B06_Section_Server_Calc_Prebuild.py` refresh_alignment) | `carryAfterRouteSave`(새 측점으로 옮김) | `design_save.ts:275-283` |
| route | `pendingRouteSave` → 본문 `route` | `replan_route`(`/route/replan` 체인 · 관 · 구조물 · 추가 측점 좌표 따라감 · 종횡단 · 계획고 이월) | 맨 앞 · 새 노선 id · 관 · 구조물 초안 다시 얹기 = Node `facility.rebase`(`rebasePipeDraft` · `rebaseStructureDraft`) · 구조물 판번호 = 저장 뒤 판 | `B06_Section_Router_DesignSave.py:128-145` · `B06_Section_Router_DesignSave_Route.py` |
| settings | `pageSettingsPart` | `save_page_settings` | 그대로 | `design_save.ts:137` |
| pipes | `pipesPart` + 화면 몫(배수판 다시 받음 · PUT 없음) | `put_pipe_points`(`confirm` = 배수유역 다시 셈) | 기본 조각만 · 다시 얹은 목록 | `design_save.ts:139` |
| structures | `structuresPart` | `write_structures` | 기본 조각만 · 다시 얹은 목록 | `design_save.ts:141` |
| plusStations | `plusStationsPart` | `put_plus_stations` | 기본 조각만 | `design_save.ts:143` |
| alignment | `alignmentPart` | `save_profile_alignment` | 노선 초안 칸(0) ?? 옛 노선 칸 → 서버가 새 노선 번호로 · 저장 뒤 두 칸 비움 | `design_save.ts:115-126` |
| culvertOptions | `culvertOptionsPart`(`culvertopt` · 노선 열쇠) | 저장 관 위에 얹어 `pipe_points.json` 다시 씀 | 옛 노선 열쇠(누가거리)로 읽음 | `B06_Section_Api_Culvert_Options.ts:102-106` |
| uphill | `routePartsBody` | `confirm_latest_route`(상단측 · 비정규 측점 횡단) | 안 보냄 · 서버도 안 받음 · 저장 뒤 세션 비우고 수 알림(요구 274) | `design_save.ts:149-155` |
| cross | `ctx.crossPart(confirm)` = 횡단 patch | `save_sections` · `confirm_sections` · 재계산 맨 앞 종단 경고 다시 씀 | 옛 노선 세션 칸 → 새 측점 patch = Node `stations.carry`(`routeCarryPatches` `B06_Section_Route_Carry_Patch.ts:368` · 넘김 규칙 `logic/B06_Section_Route_Carry.ts`) · 고침이 없어도 한 번 · 표준 횡단면 · 풍선 = `routeCarryPart` | `B06_Section_Router_DesignSave.py:172-195` · `B05_Profile_UI_RouteEdit_Apply.ts:157` |
- 차례마다 따로 커밋 — 실패 = 그 차례에서 멈춤 · 이름째 알림 · 앞 차례는 저장된 채(`design_save.ts:297-299`).
- 저장 중 = `saving` 표시 · 묶음 맞춤은 저장 뒤로 미룸(`design_pipeline_page.ts:520`).
+1 -2
View File
@@ -49,9 +49,8 @@ source: ["CLAUDE.md §5", "docs/raw/조사/2026-10-19_465_요구272_값안변함
| 내용 | 자리(파일:줄) | 상태 |
|---|---|---|
| 저장 밖 정본 쓰기 셋 — 넓힘 `/regenerate` · [측점 만들기] · 추천 [적용] | `B06_Section_Router.py:378-388` · `B06_Section_Router_Stations.py:236-296` · `B05_Profile_UI_RouteEdit_Apply.ts:220-245` | 사용자 확정 · 확인창 · 472-6 협의 |
| 노선 바뀐 [저장]만 9 차례 · 차례마다 따로 커밋 — 실패 = 앞 차례만 저장(노선 안 바뀐 저장 = 한 본문 · 전부 아니면 없음) | `design_save.ts:253-299` · `B06_Section_Router_DesignSave.py` | 472-6 6-B |
| `pipe_points.json` 한 [저장]에 두 번 PUT(관 · 관 옵션) | `B06_Section_Api_Culvert_Options.ts:67-95` | 코드 확인 |
| 노선 바뀐 [저장]의 관 옵션 차례 = 옛 노선 열쇠 | `design_save.ts:187-188` | 추정 |
| 노선 바뀐 [저장]의 관 옵션 차례 = 옛 노선 열쇠(누가거리 · 관이 따라 옮긴 새 자리와 안 맞으면 안 얹힘) | `design_save.ts:145` · `B06_Section_Router_DesignSave.py` `_patched_points` | 추정 · 옛 길과 같음 |
| ↶ ↷ 가 세션을 직접 되씀 — 관 · 구조물 · 추가 측점은 되쓴 뒤 가게 듣는 쪽을 부름(`announceDesignStore` · 472-5) · B06 조정 메모리 맵 · B05 상단측 맵은 아직 옛 값일 수 있음 | `B05_Profile_UI_Profile_History.ts` apply · `design_store.ts` announceDesignStore | 관 · 구조물 = `test_472_5_shop_owner` · 나머지 추정 |
| 스냅 켬 · 간격 = 되돌리기 밖 | `B05_Profile_UI_RouteEdit_SnapStep.ts:74-78` | 추정 |
| `flushDesignStore` 부름 없음 — 멈춘 뒤 1 s 안 새로고침 = 가게 세션 사본 잃음(다시 셈) | `design_store.ts:179` | 코드 확인 |