- 표지 = 수식 문서 머리 · 옛 로직 줄 칸 「부품」 — 기계경비식 9 · 작업량 틀 60(기종 = 기계표 상세구분 · 규격 열쇠) · 계수식 4 · 변환기가 옮김 · 틀 문서 9 장 - 지움 = 작업량당 기계경비 6(GC001145 · 1148 · 1151 · 1156 · 1159 · 1166 · 부르는 곳 0 · 요구 734-4 · 735-4) — 수식 문서 · 옛 로직 · 키대장 폐기 칸 · 빌더 · 변수표 - 이름 꼬리 4 = 원문 제목(지게운반 · 인력운반(기계설비) · 벽돌운반 · 수중펌프 설치 및 해체) · 키 폐기 0 - 서버 = `M01_MasterData_Parts` — M01 `/logics` · M02 `/logic-lib/logics` 목록에서 부품 뺌(1,440) · 키로 열기 · 부르기 그대로 · `/m01/parts`(기종 계산식 · 틀 · 계수식) · `/m02/logic-lib/machine-parts` · 연결 찾기 과녁에서 부품 뺌(1,444 → 1,435 · 판정 코드 그대로) - 금액 전후 = 문서 1,513 · 셈 9,626(기본 + 옵션 표본) 모두 같음 · 791_1 지문 남은 1,513 같음 → 지문 다시 뜸 · 802_2 변환 대조 1,513 · 목록 xlsx 다시 씀(요약 수) - 낡은 시험 = 1,519 · 1,518 기대 → 1,513 · GC001148 견본 → 같은 꼴 GF000089 토사깍기(기계)(블록 Q 39.293 · 합계 2,190) · 지운 6 을 셈하던 줄 걷음 · 목록 수 1,440 · 묶음 328 · 부르는 수 507 - 새 지킴 시험 test_813_2_parts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
118 lines
4.9 KiB
Python
118 lines
4.9 KiB
Python
"""801-3 수식 탭 소계 묶음(요구 662-3) 지킴 — 금액 셈은 그대로 · 묶음만 다시.
|
|
|
|
① 묶음 = 부른 단가산출(갈래 블록) 하나씩 + 직접 줄 한 묶음(갈래 직접) · 돈 없는 줄 = 묶음 아님 · 안쪽 말 0
|
|
② M01 전수 — 묶음 합 + 끝수 = 합계(엔진 비목 합 그대로) · 직접 묶음 하나뿐
|
|
③ 부품 — 묶음 하나 = 머리 없음 · 계 / 둘 이상 = 머리 · 소계 / 단가산출 둘 이상 = 합계 · 안쪽 말 글 0
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib
|
|
from decimal import Decimal as D
|
|
from pathlib import Path
|
|
|
|
from M01_MasterData import M01_MasterData_Store as store
|
|
|
|
mf = importlib.import_module("master_formula")
|
|
meq = importlib.import_module("master_equation")
|
|
grp = importlib.import_module("master_equation_group")
|
|
|
|
COSTS = ("노무비", "재료비", "경비", "계")
|
|
BAD = ("자기", "자원", "덧줄", "블록") # 코드 안쪽 말 — 화면 글에 0
|
|
|
|
|
|
def _w():
|
|
return store.loaded()[1]
|
|
|
|
|
|
def _export(key: str) -> dict:
|
|
w = _w()
|
|
return meq.export(w, key, meq.given_of(w, w.logic(key), None))
|
|
|
|
|
|
def _row(kind, name, cost=(0, 0, 0), **more):
|
|
got = dict(zip(COSTS[:3], (D(x) for x in cost), strict=True))
|
|
return {"갈래": kind, "이름": name, **got, "계": sum(got.values(), D(0))} | more
|
|
|
|
|
|
def test_묶음_함수_하나뿐_직접_한_묶음():
|
|
got = grp.bundles(
|
|
[
|
|
_row("블록", "굴착기", (1, 2, 3)),
|
|
_row("블록", "쉬는 단가산출"), # 돈 0 = 묶음 아님
|
|
_row("자원", "보통인부", (5, 0, 0), 종류="인력"),
|
|
_row("자원", "시멘트", (0, 7, 0), 종류="재료"),
|
|
_row("덧줄", "공구손료", (0, 0, 1)),
|
|
]
|
|
)
|
|
assert [r["갈래"] for r in got["줄"]] == ["블록", "직접"]
|
|
assert got["줄"][0]["이름"] == "굴착기" and got["줄"][1]["이름"] == "인력 · 재료"
|
|
assert (got["줄"][1]["노무비"], got["줄"][1]["재료비"], got["줄"][1]["경비"]) == (5, 7, 1)
|
|
only = grp.bundles([_row("덧줄", "공구손료", (0, 0, 1))])["줄"]
|
|
assert [r["이름"] for r in only] == ["경비"] and not grp.bundles([_row("블록", "빈")])["줄"]
|
|
|
|
|
|
def test_M02_상태_줄():
|
|
got = grp.bundles(
|
|
[
|
|
_row("자원", "보통인부", (5, 0, 0), 상태="더함", 종류="인력"),
|
|
_row("자원", "형틀목공", (4, 0, 0), 상태="덮음", 원래=D(9), 종류="인력"),
|
|
_row("자원", "지운 줄", 상태="뺌", 종류="인력"),
|
|
_row("자원", "밖 줄", 합밖=True, 밖금액=D(8)),
|
|
]
|
|
)
|
|
assert [x["이름"] for x in got["줄"][0]["낱줄"]] == ["보통인부", "형틀목공"]
|
|
assert got["밖"] == [{"이름": "밖 줄", "밖금액": D(8)}] and got["줄"][0]["계"] == 9
|
|
|
|
|
|
def test_거푸집_한_묶음_굴착기_한_묶음():
|
|
eq = _export("GC000211")
|
|
assert [r["갈래"] for r in eq["소계"]["줄"]] == ["직접"]
|
|
assert eq["소계"]["줄"][0]["이름"] == "인력 · 재료"
|
|
eq = _export("GF000089")
|
|
rows = eq["소계"]["줄"]
|
|
assert [(r["갈래"], r["이름"]) for r in rows] == [("블록", "굴착기(무한궤도) 0.7㎥")]
|
|
assert eq["합계"]["계"] == D("2190.0") and eq["소계"]["끝수"]["계"] == D("-1.0")
|
|
|
|
|
|
def test_M01_전수_묶음_합_끝수_합계_안쪽_말_0():
|
|
w = _w()
|
|
many = seen = 0
|
|
for tid, rows in sorted(w.index.items()):
|
|
if mf.mk.GROUP_OF.get(tid) != "로직":
|
|
continue
|
|
for logic in rows.values():
|
|
if not logic.get("호표"):
|
|
continue
|
|
try:
|
|
eq = _export(logic["키"])
|
|
except mf.FormulaError:
|
|
continue
|
|
sub = eq.get("소계")
|
|
if not sub:
|
|
continue
|
|
seen += 1
|
|
lines = sub["줄"]
|
|
assert sum(r["갈래"] == "직접" for r in lines) <= 1, logic["키"]
|
|
assert all(r["계"] != 0 for r in lines), logic["키"]
|
|
for r in lines:
|
|
assert not any(b in r["이름"] for b in BAD), (logic["키"], r["이름"])
|
|
for k in COSTS:
|
|
got = sum((r[k] for r in lines), D(0)) + sub["끝수"][k]
|
|
assert got == eq["합계"][k], (logic["키"], k)
|
|
many += sum(r["갈래"] == "블록" for r in lines) >= 2
|
|
assert seen > 400 and many >= 10, (seen, many)
|
|
|
|
|
|
def test_부품_머리_소계_합계_규칙_안쪽_말_0():
|
|
ts = Path("ui_template/ui_template_equation_sum.ts").read_text(encoding="utf-8")
|
|
assert "sub.줄.length >= 2" in ts # 묶음 하나 = 머리 · 소계 없음
|
|
assert '"합계" : "계"' in ts and '=== "블록").length >= 2' in ts # 합계 = 단가산출 둘 이상
|
|
ui = "".join(
|
|
line
|
|
for line in ts.splitlines(keepends=True)
|
|
if not line.lstrip().startswith(("*", "/*", "//", "/**"))
|
|
)
|
|
for word in ("자기 자원", "덧줄", "KIND"):
|
|
assert word not in ui, word
|