feat(811-1): 같은 층 SK 사본 안 만듦 · 조합 다이어그램 참조 카드 · 옮기기 목록

- Labor_SkPick — 주인 null(자기 층) = 로그인 사용자 층 주인으로 견줌 · 같은 층 SK 고름 = 그대로 참조(화면 확인 중 사본 생기던 흠)
- Labor_Combo — 다이어그램에 SK 참조 줄 카드(이름 · 값 · 누름 = 그 줄 모달) · 옮긴 뒤 다이어그램이 비지 않게
- 옮기기 보기 목록 _목록_811-1_일위대가참조.xlsx — 층 문서 26 · 로직 줄 172 · 같음 172 · 새 SK 130 · 다름 0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-08 21:09:26 +09:00
co-authored by Claude Opus 5.5
parent 4673fd89ab
commit 75bbeee0a6
4 changed files with 47 additions and 10 deletions
@@ -29,7 +29,10 @@ import {
buildLaborDiagram,
diagramTitle,
renderComboDiagram,
type DiagramLogic,
type DiagramOut,
} from "./M02_MasterTemplete_Labor_Diagram";
import { lineId } from "./M02_MasterTemplete_Labor_Calc";
import { openQtyModal } from "./M02_MasterTemplete_Labor_QtyModal";
import { qtyShort } from "./M02_MasterTemplete_Labor_Rows";
import { tc } from "./M02_MasterTemplete_Labor_Text";
@@ -155,6 +158,26 @@ export function createCombo(opt: ComboOptions): Combo {
};
}
/** 참조 줄 카드(811-1 · 단가산출 = SK 참조 한 행) — 이름 · 값 = 셈 답 · 넣을 값 없음 · 누름 = 그 줄 모달 */
function refCards(doc: LaborDoc, calc: LaborCalc | null): DiagramLogic[] {
return doc.담은로직.flatMap((r) => {
if (!r.참조) return [];
const line = calc?.줄.find((l) => lineId(l) === lineId(r));
const money = line?.반영 ?? line?.기준;
const out: DiagramOut = line?.까닭 ? { 멈춤: line.까닭 } : money ? { ...money } : null;
return [
{
key: r.참조.키, // 같은 참조 두 번 금지 = 줄 하나
name: r.별칭 || line?.이름 || r.참조.키,
unit: line?.분모 ?? "",
inputs: [],
out,
...(money ? { basis: line?.반영 ? "반영" : "기준" } : {}),
},
];
});
}
/** 다이어그램 상자(열 상세) — `draw` 를 표가 다시 그릴 때마다 부름 */
export function diagramBox(): {
root: HTMLElement;
@@ -179,18 +202,22 @@ export function diagramBox(): {
again = () => {
if (!root.open) return;
const data = buildLaborDiagram({
rows: doc.담은로직.filter((r) => !r.참조), // ponytail: 참조 줄은 다이어그램에 안 그림 — 그릴 때 카드 꼴 더함
rows: doc.담은로직.filter((r) => !r.참조),
logics: [...logics.values()],
calc,
mats: doc.자재.length,
});
const at = data.logics.findIndex((l) => l.material);
data.logics.splice(at < 0 ? data.logics.length : at, 0, ...refCards(doc, calc));
renderComboDiagram(host, data, {
focusInput: (key) => {
const i = doc.담은로직.findIndex((r) => r.로직 === key);
if (i >= 0) focus(i);
},
// 로직 카드 → 단가산출 로직 화면(떠날 때 물음은 UI_Main 의 leave guard)
// 로직 카드 → 단가산출 로직 화면(떠날 때 물음은 UI_Main 의 leave guard) · 참조 카드(811-1) = 그 줄 모달
openLogic: (key) => {
const ref = doc.담은로직.findIndex((r) => r.참조?.키 === key);
if (ref >= 0) return focus(ref);
setPendingLogicKey(key);
navigateTo(ROUTES.M01_MASTER_DATA);
},
@@ -6,6 +6,7 @@
* · 답 = 넣을 참조 {층, 주인, 키} · 취소 = null(일위대가 문서는 화면 [저장] 때 바뀜)
* ========================================================================== */
import { fetchSessionUser } from "../A06_Login/A06_Login_Api_Fetch";
import { call, newLibrary, type Layer } from "./M02_MasterTemplete_Api_Fetch";
import type { LaborRef } from "./M02_MasterTemplete_Labor_Calc";
import { withSameAsk } from "./M02_MasterTemplete_Library_SameAsk";
@@ -29,15 +30,19 @@ export const skFromLogic = async (s: SkPickScope, code: string): Promise<LaborRe
)
)?.참조 ?? null;
/** 이 층 주인 — 주인 null = 로그인 사용자 자기 층(회사 「C」 · 개인 「C/U」 · 서버 참조 꼴) */
async function ownerOf(s: SkPickScope): Promise<string | null> {
if (s.layer === "system" || s.owner) return s.layer === "system" ? null : s.owner;
const me = await fetchSessionUser();
if (!me) throw new Error("로그인이 끊김");
return s.layer === "company" ? String(me.company_id) : `${me.company_id}/${me.id}`;
}
/** 고른 SK — 이 층 것이면 그대로 · 다른 층이면 이 층 사본 */
export async function ownSk(s: SkPickScope, ref: LaborRef): Promise<LaborRef> {
const owner = s.layer === "system" ? null : s.owner;
const owner = await ownerOf(s);
if (ref.층 === s.layer && (ref.주인 ?? null) === owner) return ref;
const got = await newLibrary(
s.layer,
"sangeun",
{ 본뜬: { ...ref, 층: ref.층 as Layer } },
owner,
);
const 본뜬 = { ...ref, 층: ref.층 as Layer };
const got = await newLibrary(s.layer, "sangeun", { 본뜬 }, s.owner);
return { 층: s.layer, 주인: owner, 키: got.이름 };
}
+6 -1
View File
@@ -190,7 +190,12 @@ def test_화면_줄_넣기_SK_사본_참조_부품():
assert "return void skFromLogic(own, x.키).then(" in table # M01 기초 = SK 사본
assert "own && isSkRef(ref)" in table and "void ownSk(own, ref)" in table # 다른 층 = 사본
assert "if (isSkRef(row.참조) && !opt.calc)" in table # 줄 누름 = SK 수식 모달
assert "/sangeun/from-logic" in pick and "본뜬:" in pick and "withSameAsk(" in pick
assert "/sangeun/from-logic" in pick and "{ 본뜬 }" in pick and "withSameAsk(" in pick
assert (
"fetchSessionUser()" in pick
) # 주인 null = 자기 층 → 서버 참조 꼴(같은 층 SK 를 사본으로 안 만듦)
combo = _src("M02_MasterTemplete_Labor_Combo.ts")
assert "...refCards(doc, calc)" in combo and "key: r.참조.키," in combo # 다이어그램 참조 카드
for text in (table, pick):
assert len(text.splitlines()) <= 700
assert not re.search(r"""\bel\(\s*["'](button|input|select)["']""", text)