feat(B09 설계내역서): 이 짝 잊기 = 잊음 표시를 기억에 남김 — 느슨한 기억(품명 · 단위 같음)으로도 다시 제안 안 됨 · 다시 이으면 풀림 (PLAN 707-4 덧)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,7 @@ from M02_MasterTemplete.M02_Hopyo_Match import line_key
|
|||||||
|
|
||||||
MEMORY = "내역맞춤"
|
MEMORY = "내역맞춤"
|
||||||
TABLE, RECALL = "짝 표", "지난번 이음"
|
TABLE, RECALL = "짝 표", "지난번 이음"
|
||||||
|
FORGOT = "잊음" # 기억 칸 {잊음: True} = 이 짝 잊기 표시 — 느슨한 기억에서도 안 불러옴 · 다시 이으면 덮임
|
||||||
HEADS = ("earth", "st", "haul")
|
HEADS = ("earth", "st", "haul")
|
||||||
_TAIL = re.compile(r"^(.+?)\((.*)\)$")
|
_TAIL = re.compile(r"^(.+?)\((.*)\)$")
|
||||||
ROCK = ("절토(연암)", "암발파")
|
ROCK = ("절토(연암)", "암발파")
|
||||||
@@ -97,11 +98,15 @@ def _loose(key: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def recall(memory: dict[str, dict[str, Any]], row: dict[str, Any]) -> dict[str, Any] | None:
|
def recall(memory: dict[str, dict[str, Any]], row: dict[str, Any]) -> dict[str, Any] | None:
|
||||||
"""기억 한 칸 — 같은 열쇠 · 없으면 품명 · 단위 같고 짝이 하나인 것."""
|
"""기억 한 칸 — 같은 열쇠 · 없으면 품명 · 단위 같고 짝이 하나인 것(잊은 칸 = 없음)."""
|
||||||
key = key_of(row)
|
key = key_of(row)
|
||||||
if isinstance(memory.get(key), dict):
|
if isinstance(memory.get(key), dict):
|
||||||
return memory[key]
|
return None if memory[key].get(FORGOT) else memory[key]
|
||||||
loose = [v for k, v in memory.items() if isinstance(v, dict) and _loose(k) == _loose(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
|
return loose[0] if len({v.get("확정") for v in loose}) == 1 else None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
이은 짝 = 맞춤 기억에 씀(회사 층 = 회사 관리자 · 아니면 개인 층)
|
이은 짝 = 맞춤 기억에 씀(회사 층 = 회사 관리자 · 아니면 개인 층)
|
||||||
POST …/link/undo {target, user?} → {user, 알림, payload} — 잇기 풀기(맞춤 기억 그대로)
|
POST …/link/undo {target, user?} → {user, 알림, payload} — 잇기 풀기(맞춤 기억 그대로)
|
||||||
POST …/link/forget {key, user?} → {잊음, 기억층, 남음} — 이 짝 잊기(불러온 줄 · 이은 줄 키 →
|
POST …/link/forget {key, user?} → {잊음, 기억층, 남음} — 이 짝 잊기(불러온 줄 · 이은 줄 키 →
|
||||||
맞춤 열쇠 · 쓸 수 있는 층에서 지움 · 남음 = 못 지운 위 층 기억)
|
맞춤 열쇠 · 쓸 수 있는 층에 잊음 표시 `{잊음: True}` — 느슨한 기억도 안 불러옴 ·
|
||||||
|
개인 층 표시가 회사 기억을 덮음 · 남음 = 그래도 살아 있는 기억)
|
||||||
맞춤 기억 = 층 `실무자료/내역맞춤.json`(실무자료 맞춤 꼴) · 읽기 = 회사 + 개인(개인이 이김).
|
맞춤 기억 = 층 `실무자료/내역맞춤.json`(실무자료 맞춤 꼴) · 읽기 = 회사 + 개인(개인이 이김).
|
||||||
끼워 넣기 = `B09_Estimation_Router`(같은 머리 · 같은 권한) · 화면 = `B09_Estimation_UI_Link`.
|
끼워 넣기 = `B09_Estimation_Router`(같은 머리 · 같은 권한) · 화면 = `B09_Estimation_UI_Link`.
|
||||||
"""
|
"""
|
||||||
@@ -175,6 +176,6 @@ async def forget(
|
|||||||
memo = memo or next((r["memo"] for r in board["이은"] if r["key"] == body.key), None)
|
memo = memo or next((r["memo"] for r in board["이은"] if r["key"] == body.key), None)
|
||||||
if not memo:
|
if not memo:
|
||||||
raise HTTPException(status_code=400, detail="불러온 줄 · 이은 줄이 아님")
|
raise HTTPException(status_code=400, detail="불러온 줄 · 이은 줄이 아님")
|
||||||
layer = await asyncio.to_thread(keep, session, {memo: None})
|
layer = await asyncio.to_thread(keep, session, {memo: {linker.FORGOT: True}})
|
||||||
left = memo in await asyncio.to_thread(recalled, session)
|
left = bool((await asyncio.to_thread(recalled, session)).get(memo, {}).get("확정"))
|
||||||
return {"잊음": memo, "기억층": layer, "남음": left}
|
return {"잊음": memo, "기억층": layer, "남음": left}
|
||||||
|
|||||||
@@ -274,9 +274,28 @@ def test_줄마다_갈래_판(geo):
|
|||||||
def test_이_짝_잊기(tmp_path, monkeypatch):
|
def test_이_짝_잊기(tmp_path, monkeypatch):
|
||||||
monkeypatch.setattr(route.access, "folder", lambda got, create=False: tmp_path / got.layer)
|
monkeypatch.setattr(route.access, "folder", lambda got, create=False: tmp_path / got.layer)
|
||||||
user = {"company_id": 7, "user_id": 3, "role": "USER"}
|
user = {"company_id": 7, "user_id": 3, "role": "USER"}
|
||||||
|
gone = {lk.FORGOT: True}
|
||||||
route.keep(user, {"a||": {"확정": "earth:4"}, "b||": {"확정": "earth:5"}})
|
route.keep(user, {"a||": {"확정": "earth:4"}, "b||": {"확정": "earth:5"}})
|
||||||
hopyo_store.remember(tmp_path / "company", {"c||": {"확정": "x"}}, lk.MEMORY)
|
hopyo_store.remember(tmp_path / "company", {"c||": {"확정": "x"}}, lk.MEMORY)
|
||||||
assert route.keep(user, {"a||": None}) == "personal"
|
assert route.keep(user, {"a||": gone}) == "personal"
|
||||||
assert set(route.recalled(user)) == {"b||", "c||"}
|
assert route.recalled(user)["a||"] == gone and route.recalled(user)["b||"]["확정"] == "earth:5"
|
||||||
route.keep(user, {"c||": None})
|
route.keep(user, {"c||": gone}) # 일반 = 회사 기억을 개인 층 표시로 덮음
|
||||||
assert "c||" in route.recalled(user) # 일반 = 회사 기억 못 지움(남음)
|
assert route.recalled(user)["c||"] == gone
|
||||||
|
|
||||||
|
|
||||||
|
def test_잊은_짝_느슨한_기억에도_안_나옴(tmp_path, monkeypatch):
|
||||||
|
monkeypatch.setattr(route.access, "folder", lambda got, create=False: tmp_path / got.layer)
|
||||||
|
user = {"company_id": 7, "user_id": 3, "role": "USER"}
|
||||||
|
row = {"name": "토사절취", "spec": "A", "unit": "m3"}
|
||||||
|
other = {"name": "토사절취", "spec": "B", "unit": "m3"}
|
||||||
|
live = {"확정": "earth:4", "이름": "절토(토사)"}
|
||||||
|
route.keep(user, {lk.key_of(other): live})
|
||||||
|
assert (
|
||||||
|
lk.recall(route.recalled(user), row) == live
|
||||||
|
) # 규격 달라도 품명 · 단위 같음 = 느슨한 기억
|
||||||
|
route.keep(user, {lk.key_of(row): {lk.FORGOT: True}})
|
||||||
|
memory = route.recalled(user)
|
||||||
|
assert lk.recall(memory, row) is None # 잊음 = 느슨한 기억도 끊김
|
||||||
|
assert lk.recall(memory, other) == live # 다른 줄은 그대로
|
||||||
|
route.keep(user, {lk.key_of(row): live}) # 다시 이음 = 풀림
|
||||||
|
assert lk.recall(route.recalled(user), row) == live
|
||||||
|
|||||||
Reference in New Issue
Block a user