From b1cba8ed142658a57e0ff68499d97a571721e762 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Mon, 2 Nov 2026 00:00:45 +0900 Subject: [PATCH] =?UTF-8?q?fix(725-3=C2=B7725-4):=20=EB=B0=94=ED=83=95=20?= =?UTF-8?q?=EC=97=86=EB=8A=94=20SK=20=EA=B1=B0=EC=A7=93=20M01=20=EA=B0=9C?= =?UTF-8?q?=EC=A0=95=20=EB=A7=89=EC=9D=8C=20=C2=B7=20=EB=8B=A8=EA=B0=80?= =?UTF-8?q?=EC=82=B0=EC=B6=9C=EB=A1=9C=EB=8F=84=20=EC=A0=80=EC=9E=A5=20?= =?UTF-8?q?=EB=92=A4=20=EB=82=98=EB=AC=B4=20=EB=8B=A4=EC=8B=9C=20=EC=9D=BD?= =?UTF-8?q?=EC=9D=8C=20=C2=B7=20=EB=8D=94=ED=95=9C=20=EC=A4=84=20=EB=8B=A8?= =?UTF-8?q?=EA=B0=80=20=EC=B0=BE=EC=95=84=20=EC=98=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 725-3 Sangeun_Detail — 개정 판정(배지 · 띠)은 바탕이 있을 때만(바탕 없는 SK 지문은 이름 · 단위 따라 바뀜) - 725-4 Labor_RowModal — 단가산출로도 저장 성공 뒤 서고 목록 알림(HOPYO_BUILT) · 단가산출 나무 바로 갱신 - 725-4 LogicLab_Modal — prices 에 없는 요소(M02 더한 석공 · 합판)도 키로 찾아 단가 보임(lookup 하나로 합침) - 시험 test_717_2b 에 725 단언 하나 더함 Co-Authored-By: Claude Sonnet 5.5 --- .../M01_MasterData_UI_LogicLab_Modal.ts | 36 +++++++++---------- .../M02_MasterTemplete_Labor_RowModal.ts | 2 ++ .../M02_MasterTemplete_Sangeun_Detail.ts | 7 ++-- .../tester/test_717_2b_sangeun_detail.py | 12 +++++++ 4 files changed, 37 insertions(+), 20 deletions(-) diff --git a/M01_MasterData/M01_MasterData_UI_LogicLab_Modal.ts b/M01_MasterData/M01_MasterData_UI_LogicLab_Modal.ts index 619b2a157..d6e8dede0 100644 --- a/M01_MasterData/M01_MasterData_UI_LogicLab_Modal.ts +++ b/M01_MasterData/M01_MasterData_UI_LogicLab_Modal.ts @@ -454,6 +454,22 @@ export function openMaterialModal(target: ModalTarget): void { }; setSum(known); const rate = el("div", { className: "m01lab__modal-body" }); + /** `prices` 에 있으면 그대로 · 없으면 키로 찾아 옴 — 못 찾으면 「관리자 값 미확정」 */ + const lookup = (ref: string, label: string): void => { + const show = (brief: ElementBrief | null): void => { + rate.replaceChildren( + brief ? priceView(ref, brief) : muted(`${label} — ${tl("Pill_NoValue")}`), + ); + setSum(brief); + }; + rate.append(muted("…")); + const cached = target.prices[ref]; + if (cached) show(cached); + else + void searchElements(groupOf(ref), ref) + .then((got) => show(got.items.find((it) => it.ref === ref) ?? null)) + .catch(() => show(null)); + }; if (known && priceRef) { rate.append(priceView(priceRef, known, target.usedSlot)); } else if (logicKey) { @@ -484,25 +500,9 @@ export function openMaterialModal(target: ModalTarget): void { if (!ref) { const names = [...element.matchAll(/\{([^}]+)\}/g)].map((m) => m[1]).join(" · "); rate.append(muted(`${target.unitText || names} — ${tl("Pill_Unresolved")}`)); - } else { - const show = (brief: ElementBrief | null): void => { - rate.replaceChildren( - brief - ? priceView(ref, brief) - : muted(`${target.unitText ?? ref} — ${tl("Pill_NoValue")}`), - ); - setSum(brief); - }; - rate.append(muted("…")); - const cached = target.prices[ref]; - if (cached) show(cached); - else - void searchElements(groupOf(ref), ref) - .then((got) => show(got.items.find((it) => it.ref === ref) ?? null)) - .catch(() => show(null)); - } + } else lookup(ref, target.unitText ?? ref); } else if (element) { - rate.append(muted(`${element} — ${tl("Pill_NoValue")}`)); + lookup(element, element); // 더한 줄(M02) 등 `prices` 에 없는 요소 — 키로 찾아 옴(725-4) } body.replaceChildren( ...(target.edit ? [target.edit(close)] : []), diff --git a/M02_MasterTemplete/M02_MasterTemplete_Labor_RowModal.ts b/M02_MasterTemplete/M02_MasterTemplete_Labor_RowModal.ts index 395279114..2696ff5d8 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Labor_RowModal.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Labor_RowModal.ts @@ -14,6 +14,7 @@ import { createButton, el, showToast } from "@ui/ui_template_elements"; import { askConfirm, openModal } from "@ui/ui_template_modal"; import { createText } from "@ui/ui_template_text"; import type { ItemLogic } from "./M02_MasterTemplete_Api_Fetch"; +import { HOPYO_BUILT } from "./M02_MasterTemplete_Hopyo_Check"; import type { LaborCalc, LaborMat, LaborRow, MatMarkKey } from "./M02_MasterTemplete_Labor_Api"; import { openLaborInput } from "./M02_MasterTemplete_Labor_Input"; import { logicMatRows } from "./M02_MasterTemplete_Labor_LogicMats"; @@ -175,6 +176,7 @@ export function openRowModal(o: RowModalOptions): void { try { const name = await saveAsSk(row, got?.patch ?? row.패치 ?? null, o.title, o.unit); showToast(t("Saved").replace("{k}", name), "success"); + document.dispatchEvent(new Event(HOPYO_BUILT)); // 좌측 단가산출 나무 다시 읽음(725-4) } catch (error) { return showToast(error instanceof Error ? error.message : String(error), "error"); } diff --git a/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Detail.ts b/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Detail.ts index a7f97bb36..7ad6f00ee 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Detail.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Detail.ts @@ -139,6 +139,9 @@ export function mountSangeunDetail( ); const opened = (): boolean => (doc.열린입력 ?? []).length > 0; + // 바탕 없는 SK 의 지문 = 이름 · 단위 따라 바뀜 — 바탕이 있을 때만 M01 개정으로 봄(725-3) + const revisedBase = (): boolean => + !!(doc.바탕 && doc.바탕판 && ans?.바탕판 && doc.바탕판 !== ans.바탕판); const baseKey = (): string | null => doc.바탕?.로직 ?? null; /** 바탕 없는 · 참조 바탕 SK 의 기본정보 자리 줄 */ @@ -191,7 +194,7 @@ export function mountSangeunDetail( }; const baseName = base ? `${base.logic.키} ${base.logic.이름}` : null; const baseText = baseName ?? doc.바탕?.참조?.키 ?? L("M02_SangeunNoBase"); - const revised = !!(doc.바탕판 && ans?.바탕판 && doc.바탕판 !== ans.바탕판); + const revised = revisedBase(); pick.hidden = !edit || !!doc.바탕 || !!doc.뺀줄?.length || !!Object.keys(doc.덮개 ?? {}).length; head.replaceChildren( field(L("M02_Name"), "이름"), @@ -211,7 +214,7 @@ export function mountSangeunDetail( function drawNotes(): void { const lost = ans?.짝잃음 ?? []; - const revised = !!(doc.바탕판 && ans?.바탕판 && doc.바탕판 !== ans.바탕판); + const revised = revisedBase(); notes.replaceChildren( ...(fail || ans?.까닭 ? [createBanner({ tone: "danger", text: fail || String(ans?.까닭) })] diff --git a/resources/tester/test_717_2b_sangeun_detail.py b/resources/tester/test_717_2b_sangeun_detail.py index d22602679..cacc11c8f 100644 --- a/resources/tester/test_717_2b_sangeun_detail.py +++ b/resources/tester/test_717_2b_sangeun_detail.py @@ -233,3 +233,15 @@ def test_화면_문서_꼴_서버_저장_셈(world): # noqa: F811 — 가져온 assert added["수량"] == pytest.approx(0.01) assert added["단가"] == pytest.approx(lines["labor:LB000002#0"]["단가"]) assert got["기준"]["계"] == pytest.approx(sum(x["금액"] for x in got["줄"])) + + +def test_725_바탕_없으면_개정_안_뜸_새_SK_나무_다시_읽음_더한줄_단가_찾음(): + """725-3 바탕 없는 SK 는 이름 · 단위 따라 지문이 바뀌어도 M01 개정 아님 · 725-4 새 SK 뒤 나무 알림 · + `prices` 에 없는 요소 = 키로 찾아 옴.""" + detail = _text(M02 / "M02_MasterTemplete_Sangeun_Detail.ts") + assert "!!(doc.바탕 && doc.바탕판 && ans?.바탕판 && doc.바탕판 !== ans.바탕판)" in detail + assert detail.count("const revised = revisedBase();") == 2 + modal = _text(M02 / "M02_MasterTemplete_Labor_RowModal.ts") + assert modal.index("saveAsSk(row") < modal.index("dispatchEvent(new Event(HOPYO_BUILT))") + lab = _text(ROOT / "M01_MasterData" / "M01_MasterData_UI_LogicLab_Modal.ts") + assert "lookup(element, element)" in lab and "Pill_NoValue" in lab