fix(M02 실무자료): 361-1 지역만 다른 자재 = 전국 — 줄 글 지역 · (전국) 품목 · 없으면 키 없는 전국 자리표 · 고르기 창 지역 변형 접음 · 전국 되돌림 · 만들기 본뜬.전국자재

- 맞춤: 줄 글 지역 = 그 지역 변형(꼬리표 「지역 — 줄 글」) · 지역 없는 변형((전국) 품목 먼저) · 없으면(레미콘) 「전국」 자리표(바탕 이름(전국)-관급/사급 · 규격 · 단위 · 키 · 단가 없음 · 꼬리표 「전국 — 지역은 프로젝트에서」) · 옛 「못 가림 — N개 중 첫째」 없앰
- 후보 = 그 품목 변형 모두(`변형`) · 고르기 창 1위 / 전국 / 지역 변형(접힘) · 대상 꼴 `{전국: true}`
- 미리 셈 · 만들기: 전국 대상은 서버가 줄에서 다시 셈 · 일위대가 자재 칸이 M01 키만 받아 사전조합 `본뜬.전국자재` 에 적고 빠진 줄 까닭 · 장부엔 안 남김 · 만들기 몸 꼴에 `전국` 칸
- 시험: 전국 · 줄 글 지역 · (전국) 품목 · 고르기 지역 → 전국 되돌림 · 만들기 결과 · 화면 도우미

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWh5wNNycMkbwMpACz1rte
This commit is contained in:
2026-10-16 23:03:56 +09:00
co-authored by Claude Opus 5.5
parent 8799cf0c97
commit a2c2ad92de
14 changed files with 266 additions and 32 deletions
+17 -6
View File
@@ -198,7 +198,8 @@ def _names_only(line: dict, ctx: Ctx, why: str, full: bool) -> dict:
def _material(line: dict, ctx: Ctx, full: bool) -> dict:
"""자재 · 별도계상 줄(358-2 · `M02_Hopyo_Material`) — 「별도계상」 글 = 꼬리표 · 맞음 =
이름 · 규격 같음 하나 · 또는 바탕 이름 · 규격 수 같은 한 품목(변형 = 첫째 + 꼬리표)."""
이름 · 규격 같음 하나 · 또는 바탕 이름 · 규격 수 같은 한 품목(줄 글 지역 · 지역 없는 것 ·
「전국」 자리표 · 361-1) · 후보 = 그 품목 변형 모두(`변형` · 고르기 창이 접음)."""
me, apart = hmat.clean(line)
tags = [hmat.APART] if apart else []
found = hm._exact(me, "자재", ctx.got)
@@ -207,14 +208,14 @@ def _material(line: dict, ctx: Ctx, full: bool) -> dict:
sure, more = hmat.sure(me)
found, text, tags = [r["one"] for r in sure], "바탕 이름 · 규격 같음", tags + more
if found:
one = found[0]
conv = hm.factor(line.get("단위"), one["단위"], line.get("규격"))
target = {**hm._public(one), "입력값": {}, "못읽음": [], "출처": {}, "환산": conv}
target.update(몫=None, 배=conv["배"])
target = _mat_target(found[0], line)
conv = target["환산"]
ok = conv["배"] is not None and conv["갈래"] != "추정"
many = len(found) > 1
cands = [
{**hm._public(x), "점수": None, "판정": "맞음" if not at else "후보", "글": text}
for at, x in enumerate(found[:6])
| ({"변형": True} if many and "자재" in x else {})
for at, x in enumerate(found)
]
out = {"상태": "맞음", "체크": ok, "대상": [target], "후보": cands if full else []}
return {**out, "글": text, "꼬리표": tags}
@@ -223,6 +224,14 @@ def _material(line: dict, ctx: Ctx, full: bool) -> dict:
return {"상태": state, "체크": False, "대상": [], "후보": cands, "꼬리표": tags}
def _mat_target(one: dict, line: dict, times: Any = None) -> dict:
"""자재 · 「전국」 자리표 → 대상(배 = 환산 · `times` 주면 그것)."""
conv = hm.factor(line.get("단위"), one["단위"], line.get("규격"))
target = {**hm._public(one), "입력값": {}, "못읽음": [], "출처": {}, "환산": conv}
ok = isinstance(times, (int, float)) and not isinstance(times, bool) and times > 0
return {**target, "몫": None, "배": times if ok else conv["배"]}
def match_line(line: dict[str, Any], ctx: Ctx, full: bool = True) -> dict[str, Any]:
"""줄 → 맞춤(설계 3-3) — `full` 아니면 상태 · 체크만(호표 목록 수)."""
out: dict[str, Any] = {"열쇠": hm.line_key(line), "체크": False, "대상": [], "후보": []}
@@ -421,6 +430,8 @@ def guess(
targets.append(one)
elif t.get("자재") in ctx.mats:
targets.append(_pair({"자재": t["자재"], "배": t.get("배")}, line, ctx))
elif t.get("전국") and (one := hmat.national(line)):
targets.append(_mat_target(one, line, t.get("배")))
else:
raise store.StoreError(400, "돈 로직 · 우리 자재가 아님")
qty = _qty(entry, {"우리품": option.ours_qty(total)})