Files
Aislo/resources/tester/test_778_5_hopyo_units.py
T
eomsangdonandClaude Opus 5.5 1f9f8a1467 fix(827-6): 호표 자재 이음 되살림(어닐링철선 결속선) · 가져온 식 검산 묶은 줄 합 맞댐 · 계약 블록
- M02_Hopyo_Material.spec_fit: 827-2 「자재 수 한 번씩」 을 좁힘 — 줄 수와 그대로 같은 자재 수만 그 줄 수 몫 · 배율로만 맞는 수는 같이 씀(글 붙은 「#200.9mm200.4m/kg」 = #20 0.9mm 200.4m/kg → MT000209 되살림 · 블레이드 d=320~400 t=3.2 → 4"×3.2 는 그대로 풀림 · 21-17-17 의 17 둘 각각)
- 호표 길 전수(실무 엑셀 8 · 일위대가 줄 1564): 827-2 앞 대비 바뀜 = 블레이드 1 줄(틀린 이음 풀림)뿐 · 어닐링철선 5 줄 되살림 · 단산 길 전수 827-2 전후표 수치 그대로(새 이음 · 풀림 · 키 바뀜 0)
- M02_Sangeun_Imported 검산: 첫 자리가 같은 글줄 여럿(814-1 기계 노 · 재 · 경 · 노 줄만 딸린 기계까지) = 값 합으로도 맞댐(check · 화면 more 둘 다) · 계약(낙찰률) 블록 = 비목 × 낙찰률 원 버림과도 맞댐(머리 금액만 있는 STmate)
- 세 원천 3241 블록 검산 다름 287 → 4(EST main 1308 · 북부청임도 2 · 4 · 48 = 엑셀 글 소계가 줄 합과 다름 — 진짜 다름 · 금액은 같음)
- 시험: 827-5 xfail 셋 뗌(test_778_5 자재 표 · test_793_2 동부청영월 · 울진소광) · 지킴 둘 더함(글 붙은 규격 수 · 묶은 줄 합 · 계약 셈)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 15:48:04 +09:00

147 lines
7.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""778-5 줄 잇기 한 벌 · 블록 = 줄 판정 모음 · 단위 SK(D-2 · D-3 · 요구 622 · 623 · 624).
- 줄 잇기(`M02_Hopyo_Units`) — 작업반장 = 건설업 · 숫자 규격 치수 차례 · 구분자 무관 · 글자 규격 = 고를 것 ·
손료율 = 자재 줄 방법 · 우리에 없는 율 항목(설치비 · 제경비) = 율 줄 · 여덟 파일 묶음별 수 굳힘
- 단위 SK(`M02_Hopyo_SkUnit` · `M02_Hopyo_Sangeun`) — 확인 안 한 블록 안 만듦 · 확인 블록 = 바탕 없는 SK +
근거 꼬리표 · 고를 줄 남으면 못만듦 · 고르면 만듦 · 다시 올려도 같은 SK 재사용 · 일위대가 = 확인 전 못 이음
층 = 임시 폴더 · M01 · 마스터 읽기만.
"""
from __future__ import annotations
import json
import pytest
from M02_MasterTemplete import M02_Hopyo_Material as hmat
from M02_MasterTemplete import M02_Hopyo_Sangeun as sangeun
from M02_MasterTemplete import M02_Hopyo_SkUnit as skunit
from M02_MasterTemplete import M02_Hopyo_Units as units
from M02_MasterTemplete import M02_Labor_Doc as labor
from M02_MasterTemplete import M02_Sangeun_Calc as calc
from M02_MasterTemplete import M02_Sangeun_Doc as sd
from resources.tester import helper_m02_hopyo_golden as golden
from resources.tester.test_m02_hopyo_excel import URL, _post, client, master_hash # noqa: F401
# 여덟 파일 불리는 블록 줄 연결 표(778-5 D-2 · 바닥값 — 이어짐은 이 수 이상 · 고를 것 · 못 이음은 이 수 이하 ·
# 마스터 · 기계 자료가 좋아지면 바닥이 오름 · 줄 수는 엑셀 몫이라 그대로)
TABLE = {
"L": {"이어짐": 366, "고를 것": 0, "못 이음": 0},
"X": {"이어짐": 187, "고를 것": 1, "못 이음": 2}, # 812-9 찾기 · 못 이음 = 조합 · 괄호 깨짐
"M": {"이어짐": 71, "고를 것": 55, "못 이음": 4},
"R": {"이어짐": 150, "고를 것": 2, "못 이음": 0},
"S": {"이어짐": 3, "고를 것": 0, "못 이음": 0},
"E": {"이어짐": 1, "고를 것": 0, "못 이음": 0},
}
ALL_LINKED = 161 # 815-3 호표 기계 글 쌍점 · 율 꼬리 뗌 — 줄이 다 이어진 블록 수 바닥
BLOCKS = 206
@pytest.fixture(scope="module")
def us():
return units.Units()
def test_작업반장_건설업_기본(us):
got = us.line({"묶음": "L", "이름": "작업반장", "직종": "작업반장", "품": 0.1})
assert got["상태"] == units.LINKED and got["단위"] == {"노임": "LB000001"} # 건설업
assert got["꼬리표"] == ["기본 — 건설업 작업반장"] and got["후보"][0]["키"] == "LB000261"
one = us.line({"묶음": "L", "이름": "보통인부", "직종": "보통인부", "품": 0.5})
assert one["단위"] == {"노임": "LB000002"} and not one["꼬리표"]
def test_숫자_규격_차례_구분자_무관_글자_규격_후보(us):
assert hmat.dims("600×1200") == hmat.dims("1200x600 mm") == hmat.dims("1200*600㎜")
assert hmat.dims("1종2류(철재)") is None and hmat.lettered("1종2류(철재)")
assert not hmat.lettered("600*1200mm") and not hmat.lettered("#20, 0.9mm")
for spec in ("600×1200", "1200x600", "1200 X 600mm"):
got = us.line({"묶음": "M", "이름": "유로폼패널", "규격": spec, "단위": "매", "품": 1})
assert got["상태"] == units.LINKED and got["단위"] == {"자재": "MT000467"}, spec
named = us.line({"묶음": "M", "이름": "유로폼(패널)(600×1200)", "단위": None, "품": 1})
assert named["단위"] == {"자재": "MT000467"} # 「유로폼(패널)」 = 유로폼패널 · 단위 없는 EST 줄
paint = {"묶음": "M", "이름": "광명단조합페인트", "규격": "1종2류(철재)", "단위": "L", "품": 1}
got = us.line(paint)
assert got["상태"] == units.PICK and got["글"] == units.LETTERS and got["후보"]
def test_손료율_자재_줄_율_항목_율_줄(us):
wear = us.line({"묶음": "M", "이름": "유로폼패널", "규격": "600×1200", "품": 0.267,
"손료율": 0.267}) # fmt: skip
assert wear["방법"] == units.WEAR and wear["상태"] == units.LINKED
setup = {"묶음": "R", "이름": "설치비(재료비의 5%)", "품": 0.05, "기준꼴": "자재"}
assert us.line(setup)["단위"] == {"기준": "재료", "비목": "재료비"} # 우리에 없는 율 항목
rest = {"묶음": "R", "이름": "제경비(노무비의 60%)", "품": 0.6, "기준꼴": "노무비"}
assert us.line(rest)["단위"] == {"기준": "노무비", "비목": "경비"}
lost = us.line({"묶음": "R", "이름": "기구손료(노무비의 9%)", "기준": "노무비", "품": 0.09})
assert lost["상태"] == units.PICK and lost["후보"] == [{"기준": "노무비", "비목": "경비"}]
# 단위 SK 셈 — 설치비 = 재료 줄 × 5 % · 제경비 = 노무비 × 60 %
block = {"항목": [
{"묶음": "L", "이름": "보통인부", "직종": "보통인부", "품": 0.5, "행": 1},
{"묶음": "M", "이름": "유로폼패널", "규격": "600×1200", "단위": "매", "품": 2, "행": 2},
{**setup, "행": 3}, {**rest, "행": 4},
]} # fmt: skip
got = skunit.judge(block, us, lambda sub: None, None, "㎡")
assert got["판정"] == skunit.GOOD and [r["상태"] for r in got["줄"]] == [units.LINKED] * 4
labor_, mat = (got["줄"][0]["우리금액"], got["줄"][1]["우리금액"])
assert got["줄"][2]["우리금액"] == pytest.approx(mat * 0.05, abs=0.1)
assert got["줄"][3]["우리금액"] == pytest.approx(labor_ * 0.6, abs=0.1)
doc = {"키": "SK-000001", "이름": "t", "단위": "㎡", "바탕": None, "더한줄": got["더한줄"]}
whole = us.whole
ran = labor._json(calc.run(sd.clean(doc, None, whole), whole))
assert ran["1단위"]["계"] == pytest.approx(got["우리금액"])
def test_글_붙은_규격_수_배율_같이_씀_같은_수는_한_번(us):
"""827-6 — 「#200.9mm200.4m/kg」(#20 0.9mm 200.4m/kg 글 붙음) = 어닐링철선 이음 · 같은 수 두 번
맞춤(블레이드 320 · 3.2 → 4"×3.2) · 이름 다른 드릴롯드 = 이음 안 함 · 21-17-17 의 17 둘."""
def got(name, spec=""):
return us.line({"묶음": "M", "이름": name, "규격": spec, "품": 1})
wire = got("어닐링철선(결속선)(#200.9mm200.4m/kg)")
assert wire["상태"] == units.LINKED and wire["단위"] == {"자재": "MT000209"}
assert got("블레이드", "d=320~400mm t=3.2")["상태"] != units.LINKED
assert got("유압식드릴롯드", "T38×R32x3660mm")["상태"] != units.LINKED
assert got("복합비료(21-17-1720kg/포)")["단위"] == {"자재": "MT006490"}
@pytest.fixture(scope="module")
def table(us):
rows, full, blocks = [], 0, 0
for tag in golden.FILES:
hp = golden.read(tag)
_, first = sangeun.calls(hp)
for b in hp["단산"]:
if int(b["번"]) not in first:
continue
got = [(o["묶음"], us.line(o)["상태"]) for o in b.get("항목") or [] if not o.get("밖")]
rows += got
blocks += 1
full += all(s == units.LINKED for _, s in got)
return units.summary(rows), full, blocks
def _floor(got: dict, kind: str) -> None:
want = TABLE[kind]
assert sum(got[kind].values()) == sum(want.values()), kind # 줄 수 = 엑셀 몫
assert got[kind][units.LINKED] >= want[units.LINKED], kind
assert got[kind][units.PICK] <= want[units.PICK], kind
assert got[kind][units.NONE] <= want[units.NONE], kind
def test_여덟_파일_줄_연결_표(table):
got, _, blocks = table
assert set(got) == set(TABLE) and blocks == BLOCKS
for kind in "LXRSE":
_floor(got, kind)
def test_여덟_파일_자재_줄_연결_표(table):
got, full, _ = table
_floor(got, "M")
assert full >= ALL_LINKED
def _sks(folder) -> dict[str, dict]:
return {p.stem: json.loads(p.read_bytes()) for p in (folder / "sangeun").glob("SK-*.json")}