fix(812-2): 연결 찾기 로직 대조 다듬음 — 원파일 기계경비 묶음 ↔ 우리 기계 = 이름 종류 짝 · 율 대상 = (자원 갈래, 비목) · 번지 합 · 비목 이름 몫

- 기계경비 숫자 묶음(코드 없음) ↔ 우리 기계 = 이름 머리로 같은 기계(로울러 = 롤러 · 물탱크 = 살수차 등) · 시간당 단가 · 구성 = 참고
- 로직 같은 짝을 먼저 지음(같은 수량 줄 엇갈림 막음) · 한쪽 단가 없음(0) 비목 = 값
- 율 = 번지 합이면 핵심 줄 전부 · 「노무비 × n %」 = 그 비목 몫(기계 운전 노무비 포함) · 대상 = (갈래, 비목) 묶음
- test_812_2 — 기계 이름 짝 · 율 대상 범위 시험 더함

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-09 09:38:19 +09:00
co-authored by Claude Opus 5.5
parent 1e4ce036c6
commit f1abfc2fb1
3 changed files with 124 additions and 28 deletions
+59 -3
View File
@@ -1,6 +1,7 @@
"""812-2 지킴 — 연결 찾기 확정 = 로직(요구 712) · 값 차이 = 참고(`M02_Doc_Match_Note`).
(a) 단가만 다름 = 확정 + 참고 「단가 차이」 · 끝수만 다름 = 확정 + 참고 「끝수」
(a) 단가만 다름 = 확정 + 참고 「단가 차이」(원파일 기계경비 묶음 ↔ 우리 기계 = 이름 종류 같을 때) ·
끝수만 다름 = 확정 + 참고 「끝수」
(b) 로직 차이 = 다른 항 — 율 비율 다름(「율 값」) · 기계 규격 · 노임 종류(「자원」) · 산출 단가 · 비목
(c) 율 = 비율 — 거창 합판거푸집(블록 41): 가져온 「주자재소계 × 9 %」 = M01 소모자재 9 % 짝 · 율_2 1 % 재료비 ↔
공구손료 1 % 경비 = 「비목」 · 대전 합판 단가 = 참고
@@ -37,7 +38,7 @@ def _line(name, kind, qty, price, cost="노무비", code=""):
"단가": dm._key(p), "비목": {cost: dm._key(q * p)}, "금액": dm._key(q * p), "합밖": False} # fmt: skip
def _rate(name, rate, target=("노무비",), cost="경비"):
def _rate(name, rate, target=(("노임", "노무비"),), cost="경비"):
return {"번": 0, "이름": name, "갈래": "율", "코드": "", "수량": None, "단가": None,
"비목": {cost: D(1)}, "금액": D(1), "합밖": False, "율": D(rate), "대상": frozenset(target)} # fmt: skip
@@ -54,6 +55,24 @@ def test_price_only_is_sure_with_note() -> None:
mach = [_line("굴삭기", "기계", "0.1", "500", "경비", "0201-0070")]
other = [_line("굴삭기", "기계", "0.1", "530", "경비", "0201-0070")]
assert dm.verdict(mach, other, TOT, TOT)["판정"] == dm.SURE # 기계 시간당 단가 = 참고
file = [
_line("머캐덤로울러(자주식)", "산출", "0.1", "530", "경비")
] # 원파일 기계경비 묶음(코드 없음)
ours = [_line("탠덤롤러", "기계", "0.1", "500", "경비", "1206-0008")]
ours.append(_line("머캐덤롤러 10∼12ton", "기계", "0.1", "500", "경비", "1106-0012"))
res = dm.verdict(file, ours, TOT, TOT) # 이름 종류 같은 기계와 짝 · 단가 = 참고
assert (
not [d for d in res["다른"] if d["항"] != "줄 없음"] and res["참고"][0]["항"] == "단가 차이"
)
run = [{**_line("드릴", "산출", "0.1", "530", "경비"), "비목": {"노무비": D(1), "경비": D(2)}}]
res = dm.verdict(run, [_line("드릴", "기계", "0.1", "500", "경비", "0901-0010")], TOT, TOT)
assert res["판정"] == dm.SURE # 기계경비 구성(운전 노무비 포함) 차이 = 시간당 단가 = 참고
none = [{**_line("모래", "재료", "1", "0", "재료비"), "비목": {}}]
assert (
dm.verdict([_line("모래", "재료", "1", "9", "재료비")], none, TOT, TOT)["판정"] == dm.SURE
)
res = dm.verdict(file, ours[:1], TOT, TOT)
assert [d["항"] for d in res["다른"]] == ["기계 규격"]
def test_rounding_only_is_sure_with_note() -> None:
@@ -67,7 +86,9 @@ def test_rate_ratio_differs_blocks() -> None:
assert [d["항"] for d in res["다른"]] == ["율 값"] and res["판정"] == dm.NEAR
same = dm.verdict([*A, _rate("율", "0.02")], [*A, _rate("공구손료", "0.02")], TOT, TOT)
assert same["판정"] == dm.SURE # 율 · 대상 · 비목 같음 = 이름 달라도 같은 율 줄
tgt = dm.verdict([*A, _rate("율", "0.02", ("재료비",))], [*A, _rate("율", "0.02")], TOT, TOT)
tgt = dm.verdict(
[*A, _rate("율", "0.02", (("재료", "재료비"),))], [*A, _rate("율", "0.02")], TOT, TOT
)
assert [d["항"] for d in tgt["다른"]] == ["율 대상"]
cost = dm.verdict([*A, _rate("율", "0.02", cost="재료비")], [*A, _rate("율", "0.02")], TOT, TOT)
assert [d["항"] for d in cost["다른"]] == ["비목"]
@@ -120,3 +141,38 @@ def test_every_block_logic() -> None:
assert got["블록"] == 2220 and got["오류"] == 0 and got["확정다시셈다름"] == 0
assert not {"단가 차이", "끝수"} & set(got["근접항"])
assert got["확정참고블록"] >= 1 and got["판정"][dm.SURE] >= 98
def test_rate_target_scope() -> None:
"""율 대상 — 줄 기호 = 그 줄 · 비목 이름 = 그 비목 몫(기계 운전 노무비 포함) · 번지 합 = 핵심 줄 전부."""
from M02_MasterTemplete import M02_Doc_Match_Note as note
def run(rate_text: str) -> dict:
money = [
{"이름": "인부", "수량": "1", "단가": "100", "기호": "C_인부"},
{"이름": "굴삭기", "수량": "1", "단가": "300"},
{"이름": "율", "단가": rate_text},
]
rows = [
{"수량": D(1), "단가": D(100), "금액": D(100)},
{"수량": D(1), "단가": D(300), "금액": D(300)},
{"수량": D(1), "단가": D(0), "금액": D(0)},
]
facts = [
{"번": 0, "갈래": "노임", "비목": {"노무비": D(100)}, "합밖": False},
{"번": 1, "갈래": "산출", "비목": {"노무비": D(100), "경비": D(200)}, "합밖": False},
{"번": 2, "갈래": "율", "비목": {"경비": D(4)}, "합밖": False},
]
doc = {"변수": [], "식": [], "금액": money}
rows[2]["단가"] = {"C_인부 × 4%": D(4), "노무비 × 2%": D(4), "번지.A01.계 × 1%": D(4)}[
rate_text
]
note.rates(doc, {"줄": rows}, facts)
return facts[2]
one = run("C_인부 × 4%")
assert one["율"] == D("0.04") and one["대상"] == {("노임", "노무비")}
labor = run("노무비 × 2%") # 노무비 200(인부 100 + 굴삭기 운전 100)
assert labor["율"] == D("0.02") and labor["대상"] == {("노임", "노무비"), ("기계", "노무비")}
whole = run("번지.A01.계 × 1%") # 400 × 1 %
assert whole["율"] == D("0.01") and ("기계", "경비") in whole["대상"]