feat(733-2): 사람 길 만들 때 같은 내용 409 물음 · 복사 딸림 재사용
- 새 M02_Library_Ask — 같은 층 같은 내용(733-1 지문) = 409 {같은것: [{키, 이름, 층, 주인}], 까닭} · 몸 새로 = 그래도 새로 · 씀 = 그 키(새 문서 0 · 같은 내용 아닌 키 = 다시 409)
- 길 = 새로 만들기(빈 문서 · 같은 층 복사 = 안 물음) · [단가산출로 저장] from-line · B09 내 자료집(같은이름 409 와 한 몸 · 하위 호표 지문 = 굳힌 문서) · 공유 요청 승인(일위대가 · 씀 = 사본 키) · 실무 호표 [구조물 조합으로](구조물 조합 지문 = 줄 수량 넣음)
- 복사 딸림 carry — 받는 층에 같은 원본 + 같은 내용 사본이 있으면 그 키 재사용(refs.copied_from) · B09 하위 호표 재사용 목록 = 실무자료 한정 → 모든 사본 원본
- 낡은 시험 고침: test_703 자료집 같은 이름 물음 — 새 이름이라도 같은 내용이면 409(정함 3장 3) → new=True 로 새로 · 씀 확인 더함
- 새 시험 test_733_2_library_ask(새로 · from-line · 승인 · carry) · test_705_2 구조물 조합으로 409
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
"""사람 길 만들 때 물음(PLAN 733-2 · 요구서_572 3장 3) — 같은 층 같은 내용 문서가 있으면 409.
|
||||
|
||||
409 detail = `{같은것: [{키, 이름, 층, 주인}], 까닭}` → 다시 보냄 몸 `새로: true` = 그래도 새로 ·
|
||||
`씀: <키>` = 그것을 씀(새로 안 만듦 · 그 키를 돌려줌 · 같은 내용이 아니면 다시 409).
|
||||
지문 = `M02_Library_Same`(일위대가 SC · 단가산출 SK) · 구조물 조합(labor) = 같은 꼴 + 줄 수량 넣음.
|
||||
빈 문서(지문 없음) = 안 물음 · 같은 층 [복사] · 붙여넣기 = 안 물음(복사가 뜻).
|
||||
부르는 쪽 = 지금 층(`store.at` 안).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from common_util.common_util_derived_store import derived_key
|
||||
from M02_MasterTemplete import M02_Labor_Ref as refs
|
||||
from M02_MasterTemplete import M02_Library_Same as same
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Tree as tree
|
||||
|
||||
WHY = "같은 층에 같은 내용 문서가 있음 — 그것을 씀 · 그래도 새로"
|
||||
|
||||
|
||||
def _cleaned(kind: str, doc: dict[str, Any]) -> dict[str, Any]:
|
||||
"""저장될 꼴로 견줌(서버 정리) — 틀린 문서는 그대로(만들 때 까닭이 남)."""
|
||||
try:
|
||||
return refs.clean_doc(kind, {**doc, "키": refs.next_key(kind)})
|
||||
except store.StoreError:
|
||||
return doc
|
||||
|
||||
|
||||
def _refuse(rows: list[dict[str, Any]], why: str = WHY) -> store.StoreError:
|
||||
return store.StoreError(409, {"같은것": rows, "까닭": why})
|
||||
|
||||
|
||||
def _pick(found: list[str], rows: list[dict[str, Any]], new: bool, use: str | None) -> str | None:
|
||||
if use:
|
||||
if use in found:
|
||||
return use
|
||||
raise _refuse(rows, f"고른 「{use}」 가 같은 내용이 아님 — 다시 고름")
|
||||
if found and not new:
|
||||
raise _refuse(rows)
|
||||
return None
|
||||
|
||||
|
||||
def ask(
|
||||
kind: str,
|
||||
doc: dict[str, Any],
|
||||
new: bool = False,
|
||||
use: str | None = None,
|
||||
s: same.Same | None = None,
|
||||
) -> str | None:
|
||||
"""서고 문서(SC · SK) — 씀 키 | None(새로 만듦) · 같은 것 있고 물음 없으면 409 ·
|
||||
`s` = 미리 채운 지문 한 벌(층 밖 참조 지문 등)."""
|
||||
folder = store.root()
|
||||
found = (s or same.Same()).find_same(folder, kind, _cleaned(kind, doc))
|
||||
at = refs.where(folder)
|
||||
rows = [
|
||||
{
|
||||
"키": key,
|
||||
"이름": (refs.read_ref({"층": at[0], "주인": at[1], "키": key}) or {}).get("이름"),
|
||||
}
|
||||
for key in found
|
||||
]
|
||||
return _pick(found, [{**r, "층": at[0], "주인": at[1]} for r in rows], new, use)
|
||||
|
||||
|
||||
def labor_finger(doc: Any) -> str | None:
|
||||
"""구조물 조합 일위대가 지문 — 담은로직 · 자재 · 단위 · 규격(줄 수량 넣음 · 차례 무시)."""
|
||||
if not isinstance(doc, dict):
|
||||
return None
|
||||
s = same.Same()
|
||||
mats = [same.norm(m) for m in doc.get("자재") or []]
|
||||
body = {
|
||||
"단위": same.unit(doc.get("단위")),
|
||||
"담은로직": same._sorted([s._line(x, (), True) for x in doc.get("담은로직") or []]),
|
||||
"자재": same._sorted(mats),
|
||||
"규격": same.norm(doc.get("규격")),
|
||||
}
|
||||
body = {k: v for k, v in body.items() if v not in same.EMPTY}
|
||||
if not body.get("담은로직") and not body.get("자재"):
|
||||
return None
|
||||
return f"SU:{derived_key(body)}"
|
||||
|
||||
|
||||
def ask_item(
|
||||
folder: Path, doc: dict[str, Any], new: bool = False, use: str | None = None
|
||||
) -> dict[str, Any] | None:
|
||||
"""구조물 조합 항목(실무 호표 [구조물 조합으로]) — 씀 = `{key, 열, 이름}` | None(새로) · 409."""
|
||||
from M02_MasterTemplete import M02_Labor_Doc as labor
|
||||
|
||||
try:
|
||||
doc = {**labor.clean(doc), "규격": doc.get("규격")} # 저장될 꼴로 견줌
|
||||
except store.StoreError:
|
||||
pass
|
||||
want = labor_finger(doc)
|
||||
if not want:
|
||||
return None
|
||||
at = refs.where(folder)
|
||||
with store.at(folder):
|
||||
table = store.read("table", store.STRUCTURE_TABLE)["문서"]
|
||||
cols = {c["id"]: c for c in table.get("열") or [] if tree.is_item(c)}
|
||||
found, rows = [], []
|
||||
for key, col in cols.items():
|
||||
try:
|
||||
have = json.loads((Path(folder) / "labor" / f"{key}.json").read_bytes())
|
||||
except (OSError, ValueError):
|
||||
continue
|
||||
if labor_finger(have) == want:
|
||||
name = " / ".join(tree.path_of(col))
|
||||
found.append(key)
|
||||
rows.append({"키": key, "이름": name, "층": at[0], "주인": at[1]})
|
||||
got = _pick(found, rows, new, use)
|
||||
if got is None:
|
||||
return None
|
||||
return {"key": got, "열": got, "이름": rows[found.index(got)]["이름"], "씀": True}
|
||||
|
||||
|
||||
def create(kind: str, doc: dict[str, Any], new: bool = False, use: str | None = None) -> dict:
|
||||
"""[새로 만들기](733-2) — 같은 것 물음 뒤 `refs.create` · 씀 = `{이름: 그 키, 씀: true}`."""
|
||||
got = ask(kind, doc, new, use)
|
||||
return {"이름": got, "씀": True} if got else refs.create(kind, doc)
|
||||
Reference in New Issue
Block a user