feat(b09): 설계내역서 자유 편집 셈 · 저장 — user.bill v2 덮개 · 차례 · 부모 · gone · 새 1단 공종 · 블록 키 · 옛 꼴 읽음(184-2)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JywHxQuWPk6UYXTebyrBoU
This commit is contained in:
2026-10-10 13:07:26 +09:00
co-authored by Claude Opus 5.5
parent 0970a2665c
commit d7df6dec14
9 changed files with 928 additions and 265 deletions
+42 -2
View File
@@ -110,10 +110,50 @@ def _clean_ref(ref: Any) -> dict[str, Any] | None:
return None
def _clean_v2(raw: dict[str, Any]) -> dict[str, Any]:
"""184 덮개 v2 — 표 차례(겹친 키 · `fee` 버림) · 새 줄(`hand:`) = 모든 칸 ·
자동 줄 = 고친 칸만(값 · null = 일부러 빈칸 · 못 쓰는 값 = 칸 버림) · `gone` = 자동 줄 키."""
rows, seen = [], set()
for row in raw.get("rows") if isinstance(raw.get("rows"), list) else []:
key = row.get("key") if isinstance(row, dict) else None
if not isinstance(key, str) or not key or key in seen or key == "fee":
continue
seen.add(key)
parent = row.get("parent")
out: dict[str, Any] = {"key": key}
if isinstance(parent, str) and parent:
out["parent"] = parent
if key.startswith("hand:"):
group = row.get("kind") == "group"
if group:
out["kind"] = "group"
if row.get("cost") == "direct":
out["cost"] = "direct"
out.update({k: _text(row.get(k)) for k in ("name", "spec", "unit")})
out["qty"] = None if group else _num(row.get("qty"))
out["ref"] = None if group else _clean_ref(row.get("ref"))
else:
for k in ("name", "spec", "unit"):
if k in row:
out[k] = None if row[k] is None else _text(row[k])
if "qty" in row and (row["qty"] is None or _num(row["qty"]) is not None):
out["qty"] = _num(row["qty"])
if "ref" in row and (row["ref"] is None or _clean_ref(row["ref"]) is not None):
out["ref"] = _clean_ref(row["ref"])
rows.append(out)
given = raw.get("gone") if isinstance(raw.get("gone"), list) else []
gone = list(
dict.fromkeys(k for k in given if isinstance(k, str) and k[:5] not in ("", "hand:"))
)
return {"v": 2, "rows": rows, "gone": gone} if rows or gone else {}
def clean_bill(raw: Any) -> dict[str, Any]:
"""설계내역서 손질(166-2) — 수량 덮어쓰기(수만) · 손 줄(`hand:` 키 · 아는 공종만) ·
182 레벨 = `kind`(group) · `parent`(`hand:` 키)."""
"""설계내역서 덮개 — 184 v2(`_clean_v2`) · 옛 꼴(166-2 수량 덮어쓰기(수만) · 손 줄(`hand:` 키 ·
아는 공종만) · 182 레벨 = `kind`(group) · `parent`(`hand:` 키))."""
raw = raw if isinstance(raw, dict) else {}
if raw.get("v") == 2:
return _clean_v2(raw)
qty = raw.get("qty") if isinstance(raw.get("qty"), dict) else {}
codes = {code for code, _name, _parent in SECTIONS}
rows = []