fix(일위대가실무): 339 덧고침 맞춤 셋 — 규격 다른 별칭 꼬리표만 · 같은 장비 여러 줄 품 비교 합침 · 근거 안 닿은 덧 로직 후보로
- 규격 다른 별칭(품명|단위 느슨 열쇠) = 꼬리표 「별칭 · 규격 다름」 · 짝은 후보 끝 덤 · 상태 · 옵션은 줄 숫자 맞춤 - 품 비교 같은 갈래 장비 여러 줄은 합쳐 견줌(서버 _qty · 화면 compareText) - 조합 덧 로직 = 단위 맞음 + 조항 · 직종 · 이름 하나 닿을 때만 · 아니면 덧 후보 · 섞인 줄 그대로 · 맞춤셈 판 2 - 골든 사람 126 1순위 118 · 다섯 안 122 · 맞음 57 틀림 0 · 조합 62/83 그대로 · 338 대상 시험 142 통과 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
This commit is contained in:
@@ -4,10 +4,12 @@
|
||||
|
||||
상태 차례 = ① % ② 호표 참조(만들 층에 확인된 사전조합이면 체크) ③ 노임(그릇 없음) ④ 장부 「우리에
|
||||
없음 ·
|
||||
안 씀」 → 뺌 ⑤ 장부 짝 → 별칭(규격 다름 · 근거 다름 · 숫자 판정 맞음이 다른 로직이면 체크 안 함) ⑥
|
||||
안 씀」 → 뺌 ⑤ 장부 짝 → 별칭(근거 다름 · 숫자 판정 맞음이 다른 로직이면 체크 안 함) ⑥
|
||||
맞춤셈
|
||||
판정(맞음 = 체크 · 다른 점 · 후보) ⑦ 셈 전 · 숫자 없음 → 이름 · 근거 후보(「셈 중」 · 「숫자 판정
|
||||
없음」).
|
||||
장부 짝이 규격 다름(품명|단위 느슨 열쇠)이면 ⑤ 아님 — 꼬리표 「별칭 · 규격 다름」 · 짝은 후보
|
||||
끝 덤만.
|
||||
자재 · 별도계상 = 이름 · 규격 같음 하나면 맞음(체크) · 그 밖 후보.
|
||||
입력값 출처(칸마다) = 별칭 > 블록(옵션 찾기 값이 규격 읽기와 다름) > 규격(`spec_inputs`) > 자동값.
|
||||
체크 = 처음 제안일 뿐 — 들어감은 [확인하고 사전조합 만들기](다 창)만. 저장 없음 · 셈은 서버 단독.
|
||||
@@ -92,18 +94,24 @@ def _pair(pair: dict, line: dict, ctx: Ctx) -> dict:
|
||||
|
||||
|
||||
def _qty(entry: dict, found: dict | None) -> dict:
|
||||
"""품 비교 — 엑셀 · 우리 · 같음(직종 · 장비 갈래마다 R 허용)."""
|
||||
"""품 비교 — 엑셀 · 우리 · 같음(직종 · 장비 갈래마다 R 허용) · 같은 갈래 여러 줄은 합쳐 견줌
|
||||
(화면 품 비교 열쇠 = 갈래 가나다 차례 + 로 묶음)."""
|
||||
ex = entry.get("품") or {"인력": {}, "장비": [], "자재": []}
|
||||
us = (found or {}).get("우리품") or option.ours_qty(None)
|
||||
same = {}
|
||||
for t, a in ex["인력"].items():
|
||||
b = us["인력"].get(t)
|
||||
same[t] = bool(b) and option.near(a, b, fit.TOL[0], option.ru(a))
|
||||
sums: dict[str, list[float]] = {} # 열쇠 → [엑셀 합, 반올림 폭 합, 우리 합]
|
||||
for m in ex["장비"]:
|
||||
mine = [x["시간"] for x in us["장비"] if set(x["갈래"]) & set(m["갈래"])]
|
||||
hit = any(option.near(m["시간"], q, fit.TOL[0], option.ru(m["시간"])) for q in mine)
|
||||
name = "+".join(m["갈래"]) # 화면 품 비교 열쇠와 같음(갈래 + 로 묶음)
|
||||
same[name] = hit or same.get(name, False)
|
||||
one = sums.setdefault("+".join(sorted(m["갈래"])), [0.0, 0.0, 0.0])
|
||||
one[0] += m["시간"]
|
||||
one[1] += option.ru(m["시간"])
|
||||
for x in us["장비"]:
|
||||
if (one := sums.get("+".join(sorted(x["갈래"])))) is not None:
|
||||
one[2] += x["시간"]
|
||||
for name, (a, r, b) in sums.items():
|
||||
same[name] = option.near(a, b, fit.TOL[0], r)
|
||||
return {"엑셀": ex, "우리": us, "같음": same}
|
||||
|
||||
|
||||
@@ -201,17 +209,39 @@ def match_line(line: dict[str, Any], ctx: Ctx, full: bool = True) -> dict[str, A
|
||||
if kind == "노임":
|
||||
return {**out, "상태": "노임", "글": "노임 · 그릇 없음"}
|
||||
alias = ledger.recall(line, ctx.to, ctx.books)
|
||||
loose, alias = (alias, None) if alias and alias.get("규격다름") else (None, alias)
|
||||
entry = ctx.cache.get(fit.unit_key(line)) if kind not in hm.MATERIAL_KINDS else None
|
||||
if alias and alias.get("갈래") in SKIP:
|
||||
return {**out, "상태": "뺌", "뺌": alias["갈래"], "별칭": _alias_info(alias, False)}
|
||||
if alias and alias.get("갈래") == "짝" and alias.get("짝"):
|
||||
return {**out, **_aliased(line, ctx, alias, entry)}
|
||||
if kind in hm.MATERIAL_KINDS:
|
||||
return {**out, **_material(line, ctx, full)}
|
||||
if entry and entry["판정"]["글"] not in (fit.NO_NUMBER, "우리 로직 준비 중"):
|
||||
return {**out, **(_numeric(line, ctx, entry) if full else _brief(entry))}
|
||||
why = "셈 중" if not ctx.calc["끝"] else fit.NO_NUMBER
|
||||
return {**out, **_names_only(line, ctx, why, full)}
|
||||
got = _material(line, ctx, full)
|
||||
elif entry and entry["판정"]["글"] not in (fit.NO_NUMBER, "우리 로직 준비 중"):
|
||||
got = _numeric(line, ctx, entry) if full else _brief(entry)
|
||||
else:
|
||||
why = "셈 중" if not ctx.calc["끝"] else fit.NO_NUMBER
|
||||
got = _names_only(line, ctx, why, full)
|
||||
return {**out, **(_loose(got, loose, line, ctx) if loose and full else got)}
|
||||
|
||||
|
||||
def _loose(got: dict, alias: dict, line: dict, ctx: Ctx) -> dict:
|
||||
"""규격 다른 별칭 — 꼬리표 「별칭 · 규격 다름」 + 짝 로직 · 자재가 후보에 없으면 끝에 덤(상태 ·
|
||||
대상 · 옵션은 이 줄 숫자 그대로)."""
|
||||
tags = [*(got.get("꼬리표") or []), "별칭 · 규격 다름"]
|
||||
have = {c.get("로직") or c.get("자재") for c in got.get("후보") or []}
|
||||
have |= {t.get("로직") or t.get("자재") for t in got.get("대상") or []}
|
||||
extra = []
|
||||
for p in alias.get("짝") or []:
|
||||
code = p.get("로직") or p.get("자재")
|
||||
if code and code not in have:
|
||||
one = {
|
||||
k: v
|
||||
for k, v in _pair(p, line, ctx).items()
|
||||
if k in ("로직", "자재", "이름", "단위")
|
||||
}
|
||||
extra.append({**one, "점수": None, "판정": "후보", "글": "별칭 · 규격 다름"})
|
||||
return {**got, "꼬리표": tags, "후보": [*(got.get("후보") or []), *extra]}
|
||||
|
||||
|
||||
def _brief(entry: dict) -> dict:
|
||||
@@ -225,7 +255,7 @@ def _alias_info(alias: dict, basis_off: bool) -> dict:
|
||||
|
||||
|
||||
def _aliased(line: dict, ctx: Ctx, alias: dict, entry: dict | None) -> dict:
|
||||
"""⑤ 장부 짝 — 체크 = 규격 같음 · 근거 같음 · 숫자 판정 맞음이 다른 로직 아님."""
|
||||
"""⑤ 장부 짝(정확 열쇠) — 체크 = 근거 같음 · 숫자 판정 맞음이 다른 로직 아님."""
|
||||
targets = [_pair(p, line, ctx) for p in alias["짝"]]
|
||||
codes = {t["로직"] for t in targets if t.get("로직")}
|
||||
theirs = ((line.get("근거") or {}).get("출처")) or []
|
||||
@@ -234,9 +264,9 @@ def _aliased(line: dict, ctx: Ctx, alias: dict, entry: dict | None) -> dict:
|
||||
hm.clause(theirs, table[c])[0] < 0.9 for c in codes if c in table
|
||||
)
|
||||
other = bool(entry and entry["판정"]["상태"] == "맞음" and entry["차례"][0] not in codes)
|
||||
check = not alias.get("규격다름") and not off and not other
|
||||
check = not off and not other
|
||||
tags = ["별칭 — " + " · ".join(str(x) for x in (alias.get("층"), alias.get("때")) if x)]
|
||||
tags += ["규격 다름"] * bool(alias.get("규격다름")) + ["근거 다름"] * off
|
||||
tags += ["근거 다름"] * off
|
||||
tags += [f"숫자 판정 맞음 = {entry['차례'][0]}"] if other else []
|
||||
out = {"상태": "별칭", "체크": check, "대상": targets, "글": "별칭 장부 짝", "꼬리표": tags}
|
||||
out["별칭"] = _alias_info(alias, off)
|
||||
@@ -249,7 +279,7 @@ def whole(hopyo: dict, ctx: Ctx) -> dict | None:
|
||||
"""직접 줄 호표 통째 제안 — 장부 짝(호표 열쇠) 먼저 · 맞춤셈 「호표:번」."""
|
||||
head = {k: hopyo.get(k) for k in ("이름", "규격", "단위")}
|
||||
alias = ledger.recall(head, ctx.to, ctx.books, whole=True)
|
||||
if alias and alias.get("갈래") == "짝" and alias.get("짝"):
|
||||
if alias and alias.get("갈래") == "짝" and alias.get("짝") and not alias.get("규격다름"):
|
||||
return {
|
||||
"대상": [_pair(p, head, ctx) for p in alias["짝"]],
|
||||
"글": "별칭 장부 짝",
|
||||
|
||||
Reference in New Issue
Block a user