fix(823-1): 불러온 단가산출 기계 바꿔 끼움 = 그 줄만 우리 값 즉시 · 바꿈 표시 · 되돌리기

- 원인: 다시 고르기(repick)가 엑셀 값 기억을 일부러 남김(812-9) → 엑셀 단가 기준 보기가 바꾼 기계 줄도 옛 엑셀 값으로 셈 · 이름만 바뀜
- 이은 가져온 줄을 다른 것으로 = 엑셀 값 뗌 · 연결 `바꿈` = 원래 연결 · 이름 · 규격 · 원래 것 다시 고름 = 되돌림 · 못 이은 줄 고름(812-9)은 그대로
- 줄에 「바꿈」 배지 + [되돌리기] · 머리 「바꾼 줄 n — 원본과 다름」 · 인력 · 재료 바꿈도 같은 길
- 서버: 바꾼 줄 있으면 셈 색인 = 로직 사본 위 · 저장 때 셈이 읽은 줄(내 기계 등)을 로직 사본에 박음(822-1 사본 규칙)
- 옛 칸 지문: 파일 24554.0 = 화면 왕복 24554 — 가져온 식 수식 저장 뒤 페이지 [저장] 409(「그 사이 양식이 바뀜」) 막음
- 시험 test_823_1_imported_swap 5(+ 헬퍼 helper_823_1_swap.cjs)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-12 18:54:16 +09:00
co-authored by Claude Opus 5.5
parent 4cfa405a5b
commit 8bb22b39b1
11 changed files with 351 additions and 14 deletions
+54 -6
View File
@@ -129,20 +129,68 @@ export function addPicked(doc: FormulaDoc, item: StackItem, kind: MoneyKind, p:
return id;
}
/** 있는 줄 바꿔 고름 — 그 줄 단가 기호 연결 · 줄 이름 · 규격(단위 · 수량은 그대로 · 같은 로직이면 넘길 입력 그대로) */
/** 가져온 줄 바꿔 끼움 표지(823-1) — 원래 연결(엑셀 값 기억째) · 줄 이름 · 규격 · 되돌리기용 */
export interface Swap {
연결: Link;
이름?: string;
규격?: string;
/** 단가 기호 이름 */
기호이름?: string;
}
type Kept = Link & { 엑셀?: unknown; 바꿈?: Swap };
const sameRes = (a: Link, b: Link): boolean => {
const args = (l: Link): string =>
JSON.stringify(Object.entries(l.입력 ?? {}).sort(([x], [y]) => (x < y ? -1 : 1)));
return a.갈래 === b.갈래 && a.키 === b.키 && args(a) === args(b);
};
/** 바꾼 가져온 줄 수(823-1 · 「바꾼 줄 n — 원본과 다름」) */
export const swappedCount = (doc: FormulaDoc): number =>
(doc.변수 ?? []).filter((v) => (v.연결 as Kept | undefined)?.바꿈).length;
/** 바꾼 가져온 줄 되돌리기(823-1) — 원래 연결(엑셀 값) · 이름 · 규격 */
export function unswap(doc: FormulaDoc, i: number, id: string): void {
const v = (doc.변수 ?? []).find((x) => varId(x) === id);
const line = (doc.금액 ?? [])[i] as { 이름?: string; 규격?: string } | undefined;
const sw = (v?.연결 as Kept | undefined)?.바꿈;
if (!v || !line || !sw) return;
v.연결 = sw.연결;
if (sw.기호이름 !== undefined) v.이름 = sw.기호이름;
else delete v.이름;
if (sw.이름 !== undefined) line.이름 = sw.이름;
else delete line.이름;
if (sw.규격) line.규격 = sw.규격;
else delete line.규격;
}
/** 있는 줄 바꿔 고름 — 그 줄 단가 기호 연결 · 줄 이름 · 규격(단위 · 수량은 그대로 · 같은 로직이면 넘길 입력 그대로) ·
* 가져온 이은 줄(엑셀 값 기억)을 다른 것으로 = 그 줄만 우리 값(엑셀 값 뗌 · `바꿈` = 원래 · 823-1) · 원래 것 다시 고름 = 되돌림 */
export function repick(doc: FormulaDoc, i: number, id: string, kind: MoneyKind, p: Picked): void {
const v = (doc.변수 ?? []).find((x) => varId(x) === id);
const line = (doc.금액 ?? [])[i] as { 이름?: string; 규격?: string } | undefined;
if (!v || !line) return;
const was = v.연결 ?? {};
const now = linkOf(kind, p);
const was = (v.연결 ?? {}) as Kept;
const now = linkOf(kind, p) as Kept;
if (now.갈래 === "요소" && was.지역) now.지역 = was.지역; // 지역 옵션 이음 그대로
if (now.갈래 === "단가산출" && was.키 === now.키) now.입력 = { ...was.입력, ...now.입력 }; // 같은 로직 = 다른 넘길 입력 그대로
// 가져온 기계 줄(812-9) — 엑셀 값 기억 그대로(엑셀 단가 기준 금액 안 바뀜 · 못 이은 기계 = 숫자 값 · 묶음)
const kept = (was as { 엑셀?: unknown }).엑셀 ?? (was.갈래 === "숫자" ? was.값 : undefined);
if (kind === "기계" && kept !== undefined) (now as { 엑셀?: unknown }).엑셀 = kept;
const orig = (was.바꿈?.연결 ?? was) as Kept;
if (was.바꿈 && sameRes(orig, now)) return unswap(doc, i, id); // 원래 것 다시 고름
const cost = (line as { 비목?: string }).비목 ?? "";
if (kind === "기계" && ["노무비", "재료비", "경비"].includes(cost)) now.칸 = cost; // 비목 한 칸 줄 = 그 칸
if ("엑셀" in orig && orig.갈래 !== "숫자") {
if (sameRes(orig, now)) return; // 같은 것 = 그대로
now.바꿈 = was.바꿈 ?? {
연결: was,
...(line.이름 !== undefined ? { 이름: line.이름 } : {}),
...(line.규격 ? { 규격: line.규격 } : {}),
...(v.이름 !== undefined ? { 기호이름: v.이름 } : {}),
};
} else {
// 못 이은 가져온 기계 줄(812-9) 고름 = 이음 — 엑셀 값 기억(엑셀 단가 기준 금액 안 바뀜 · 숫자 값 · 묶음)
const kept = was.엑셀 ?? (was.갈래 === "숫자" ? was.값 : undefined);
if (kind === "기계" && kept !== undefined) now.엑셀 = kept;
}
v.연결 = now;
v.이름 = p.이름;
line.이름 = p.이름;