fix(466 덧 · 470 N1 N2): [확정] 성공 뒤 상세 비움 · B06 폼 관 옮김 + 옵션 = 옮긴 관에 붙음

- [확정] 성공 길도 [저장]처럼 invalidateSectionDetail — 다음 페이지(B07)가 정본을 받음
- B06 폼 onPipeUpdate — 옮긴 뒤 옵션 · 캐시 얹기 · 집계 항목을 옮긴 자리(맞춘 정수 m)로 찾음(옛: 옛 자리로 찾아 옵션 잃음 · 비운 옛 자리 그림에 얹음)
- 시험 test_466_pipe_move_options · test_272_detail_memory 확정 항목

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-19 07:41:22 +09:00
co-authored by Claude Opus 5.5
parent bc481453d7
commit 58be37b0d5
5 changed files with 324 additions and 11 deletions
@@ -298,12 +298,13 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
// 값 수정·기준점 이동 모두 B06 에서 받는다 — 이동은 종단 끌기와 **같은 함수**를 탄다
// (2026-09-12 일원화). 세부유역은 관 초안을 쓰면 배수유역도가 뒤에서 다시 나눈다(298-1).
onPipeUpdate: (fromChainageM, toChainageM, attributes) => {
// 값만 고치면 폼이 옛 측점을 그대로 돌려줌(안 고친 칸) — 0.005m 넘으면 옮긴 것(80.17 → 80 도 · 234-1)
if (Math.abs(fromChainageM - toChainageM) > 0.005) movePipeTo(fromChainageM, toChainageM);
// 값만 고치면 폼이 옛 측점을 그대로 돌려줌(안 고친 칸) — 0.005m 넘으면 옮긴 것(80.17 → 80 도 · 234-1) ·
// 옮긴 뒤 옵션 · 캐시 얹기는 옮긴 자리(맞춘 정수 m)로 찾음(옛 자리 = 비운 그림 · 470 N2)
const moved = Math.abs(fromChainageM - toChainageM) > 0.005;
const at = (moved ? movePipeTo(fromChainageM, toChainageM) : null) ?? fromChainageM;
if (attributes.summary_item !== undefined || attributes.group_items !== undefined) {
// 옮긴 뒤 자리(toChainageM)에서 찾는다 — 안 옮겼으면 from 과 0.51m 안이라 같은 관이다.
const mine = pipeFacilities.find(
(entry) => Math.abs(entry.chainage_m - toChainageM) < PIPE_MATCH_M,
(entry) => Math.abs(entry.chainage_m - at) < PIPE_MATCH_M,
);
const before = mine ? JSON.stringify(linkFields(mine)) : "";
if (mine && attributes.summary_item !== undefined)
@@ -322,14 +323,12 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
return;
}
// 값은 관 목록 초안(가게 pipes) 하나로 나간다 — 조정 예약(culvertopt)에 따로 담으면 비운 칸이
// [저장] 때 옛 값으로 되살아난다. 옮기기 전 자리로 찾는다(저장 시점 목록 기준).
const hit = pipeFacilities.find(
(entry) => Math.abs(entry.chainage_m - fromChainageM) < PIPE_MATCH_M,
);
// [저장] 때 옛 값으로 되살아난다.
const hit = pipeFacilities.find((entry) => Math.abs(entry.chainage_m - at) < PIPE_MATCH_M);
const was = hit?.facility ?? "pipe";
const facility = attributes.facility ?? was;
// 종류를 바꿈(54-4) — 옛 종류 그림 캐시에 새 종류 칸을 얹지 않음 · 옛 칸은 안 이음
if (facility === was) deps.applyPipeOptions?.(fromChainageM, patch);
if (facility === was) deps.applyPipeOptions?.(at, patch);
if (hit) {
hit.options =
mergeFacilityOptions(
@@ -533,10 +532,11 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
}
/** 관 옮기기 — 폼의 측점 칸과 종단 끌기가 같은 길을 탄다. 재분할은 [저장]·[확정] 뒤. */
function movePipeTo(fromChainageM: number, toChainageM: number): void {
/** 관을 옮김 — 옮긴 자리(정수 m) · 그 자리 관이 없으면 null. */
function movePipeTo(fromChainageM: number, toChainageM: number): number | null {
if (!deps.projectId) {
showToast(PIPE_MOVE_GUIDE, "error");
return;
return null;
}
const to = snapStructureStation(toChainageM); // 정수 m · 일반 측점 붙기(234-1)
const hit = pipeFacilities.find(
@@ -555,6 +555,7 @@ export function createB06StructuresPanel(deps: B06StructuresPanelDeps): B06Struc
section.setPipeFacilities(pipeFacilities);
pushMarks();
showToast(PIPE_MOVE_NOTICE, "success");
return hit ? to : null;
}
/** 관 빼기 — 목록·폼·종단 우클릭이 같은 길을 탄다. 정본은 [저장]·[확정]에서 나간다. */