From 74f3fb80092333aa3f8fc3709bccfbcfc64e60e3 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sat, 31 Oct 2026 17:46:00 +0900 Subject: [PATCH] =?UTF-8?q?feat(B09=20=EC=84=A4=EA=B3=84=EB=82=B4=EC=97=AD?= =?UTF-8?q?=EC=84=9C):=20=EB=B6=88=EB=9F=AC=EC=98=A4=EA=B8=B0=20=EB=81=9D?= =?UTF-8?q?=20=3D=20=EC=A7=80=EB=82=9C=EB=B2=88=20=EC=9D=B4=EC=9D=8C=20?= =?UTF-8?q?=EB=B0=94=EB=A1=9C=20=EC=9E=87=EA=B3=A0=20=EB=82=A8=EC=9D=80=20?= =?UTF-8?q?=EC=A0=9C=EC=95=88=EB=A7=8C=20=EC=B0=BD=EC=97=90(=EB=82=A8?= =?UTF-8?q?=EC=9D=80=200=20=3D=20=EC=B0=BD=20=EC=97=86=EC=9D=8C)=20=C2=B7?= =?UTF-8?q?=20=EC=9E=8A=EC=9D=80=20=EC=A7=9D=20=EA=B3=81=20=EB=8A=90?= =?UTF-8?q?=EC=8A=A8=ED=95=9C=20=EA=B8=B0=EC=96=B5=20=EC=95=88=20=EC=A2=81?= =?UTF-8?q?=ED=9E=98=20(PLAN=20707-4=20=EB=8D=A7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5.5 --- B09_Estimation/B09_Estimation_Bill_Link.py | 11 ++++----- B09_Estimation/B09_Estimation_UI_Import.ts | 2 +- B09_Estimation/B09_Estimation_UI_Link.ts | 27 ++++++++++++++++++++-- resources/tester/test_707_4_bill_link.py | 2 ++ 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/B09_Estimation/B09_Estimation_Bill_Link.py b/B09_Estimation/B09_Estimation_Bill_Link.py index 456cc062c..97920a1d7 100644 --- a/B09_Estimation/B09_Estimation_Bill_Link.py +++ b/B09_Estimation/B09_Estimation_Bill_Link.py @@ -98,16 +98,13 @@ def _loose(key: str) -> str: def recall(memory: dict[str, dict[str, Any]], row: dict[str, Any]) -> dict[str, Any] | None: - """기억 한 칸 — 같은 열쇠 · 없으면 품명 · 단위 같고 짝이 하나인 것(잊은 칸 = 없음).""" + """기억 한 칸 — 같은 열쇠 · 없으면 품명 · 단위 같고 짝이 하나인 것 · + 잊은 칸은 없음 취급 + 느슨한 기억에서는 다른 짝으로 셈(잊은 짝 곁에서 하나로 좁히지 않음).""" key = key_of(row) if isinstance(memory.get(key), dict): return None if memory[key].get(FORGOT) else memory[key] - loose = [ - v - for k, v in memory.items() - if isinstance(v, dict) and not v.get(FORGOT) and _loose(k) == _loose(key) - ] - return loose[0] if len({v.get("확정") for v in loose}) == 1 else None + loose = [v for k, v in memory.items() if isinstance(v, dict) and _loose(k) == _loose(key)] + return loose[0] if len({v.get("확정") for v in loose}) == 1 and loose[0].get("확정") else None def _targets(rows: list[dict[str, Any]]) -> dict[str, dict[str, Any]]: diff --git a/B09_Estimation/B09_Estimation_UI_Import.ts b/B09_Estimation/B09_Estimation_UI_Import.ts index 889de4691..9d88bcd11 100644 --- a/B09_Estimation/B09_Estimation_UI_Import.ts +++ b/B09_Estimation/B09_Estimation_UI_Import.ts @@ -161,7 +161,7 @@ export function createBillImport( // 창 닫고 다시 그림 — 표 높이(fillViewport)가 열린 창 가림막을 아래 자리로 셈 close(); done(got.payload, made); - void openBillLink(user(), done, mode.value); // 707-4 다음: 우리 공종으로 잇기 + void openBillLink(user(), done, mode.value, true); // 707-4 다음: 지난번 이음 바로 · 남은 것만 창 const n = got.알림 || {}; const head = `새 줄 ${n.실음} · 붙임 ${n.붙임} · 지움 ${n.지움} · 이음 ${n.이음}${tail} — [저장]해야 남음`; const off: Row[] = got.어긋남 || []; diff --git a/B09_Estimation/B09_Estimation_UI_Link.ts b/B09_Estimation/B09_Estimation_UI_Link.ts index bd87dca85..59e495b2c 100644 --- a/B09_Estimation/B09_Estimation_UI_Link.ts +++ b/B09_Estimation/B09_Estimation_UI_Link.ts @@ -110,16 +110,39 @@ function pickOurs(spots: Row[], line: Row, take: (key: string) => void): void { }); } -/** 잇기 창 — user = 지금 캐시 · mode = 불러올 때 고른 갈래(없으면 마지막) */ -export async function openBillLink(user: Row, done: LinkDone, mode?: string): Promise { +/** 잇기 창 — user = 지금 캐시 · mode = 불러올 때 고른 갈래(없으면 마지막) · + * fresh = 불러오기 끝에서 부름 — 지난번 이음은 먼저 바로 잇고 남은 것만 창에(남은 0 = 창 없음) */ +export async function openBillLink( + user: Row, + done: LinkDone, + mode?: string, + fresh = false, +): Promise { if (mode === "take" || mode === "price") lastMode = mode; let cur = user; let seen: Row; try { seen = await post("suggest", { user: cur }); + if (fresh && seen.저절로) { + const got = await post("apply", { + pairs: [], + auto: true, + mode: lastMode, + counts: {}, + user: cur, + }); + done(got.payload, got.user); + cur = got.user; + showToast( + `지난번 이음 ${got.알림.이음 + got.알림.묶음} 줄 바로 이음 — [저장]해야 남음`, + "success", + ); + seen = await post("suggest", { user: cur }); + } } catch (error) { return fail("제안을 못 받음")(error); } + if (fresh && !seen.남은.length) return; // 남은 줄 없음 — 창 안 뜸 if (!seen.남은.length && !seen.이은.length) return; // 불러온 줄 없음 let busy = false; const run = (job: () => Promise): void => { diff --git a/resources/tester/test_707_4_bill_link.py b/resources/tester/test_707_4_bill_link.py index 4be04925b..f6ce3ddf5 100644 --- a/resources/tester/test_707_4_bill_link.py +++ b/resources/tester/test_707_4_bill_link.py @@ -297,5 +297,7 @@ def test_잊은_짝_느슨한_기억에도_안_나옴(tmp_path, monkeypatch): memory = route.recalled(user) assert lk.recall(memory, row) is None # 잊음 = 느슨한 기억도 끊김 assert lk.recall(memory, other) == live # 다른 줄은 그대로 + third = {"name": "토사절취", "spec": "C", "unit": "m3"} + assert lk.recall(memory, third) is None # 잊은 짝 곁에서는 느슨하게 안 좁힘 route.keep(user, {lk.key_of(row): live}) # 다시 이음 = 풀림 assert lk.recall(route.recalled(user), row) == live