Files
Aislo/resources/tester/test_816_3_chainsaw.py
T
eomsangdonandClaude Opus 5.5 d9337a0714 feat(816-3): 체인톱 시간당 기계경비 GF000337 · 체인톱에 이어진 기계 줄 시간당 = 1 일 1 대당 ÷ 8
- 새 로직 파일 산림품셈 02장(차례 0) GF000337 — GF000076 체인톱 줄(2-1-1 휘발유 · 체인오일 · 잡품 · 2-2-1 손료) × 시간환산 · 수식 문서 빌더 변환(옛 엔진 = 새 계산기)
- M02_Machine_Hourly 기계 줄만의 식 고름 = 기계 줄 값(가격 · 손료계수)을 읽는 기계경비식
- 별칭 값은 사용자 몫(마스터에 안 넣음) · 인치 따옴표 통째 별칭은 master_alias 그대로 깨지지 않음(시험 = 임시 별칭)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 19:46:23 +09:00

72 lines
3.5 KiB
Python

"""816-3 지킴 — 가져온 「엔진톱」 = 우리 체인톱 EQ000620(요구 771 · 방향 장부 N2).
(a) 별칭 길 — 사용자가 EQ000620 「별칭」 칸에 「엔진톱 18", 엔진톱」 을 넣으면(시험 = 임시 별칭 · 마스터엔
안 넣음) 인치 따옴표가 깨지지 않고 「엔진톱 18"」 · 「엔진톱」(규격 빔) → EQ000620 · 다른 톱 · 다른 규격은 안 이음
(b) 시간당 = GF000337 「체인톱 시간당 기계경비」 = 산림품셈 1 일 1 대당(2-1-1 휘발유 · 체인오일 · 잡품 ·
2-2-1 손료) ÷ 8 — GF000076 체인톱 줄(1 일 1 대당) 단가 그대로 · 수량 × 시간환산
(c) 이음 한 길 — `M02_Machine_Hourly.hourly` · `M02_Doc_Import.hourly_link` = GF000337(기계 입력 없음)
"""
from __future__ import annotations
import importlib
import sys
from decimal import Decimal
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
for p in (ROOT, ROOT / "resources/master_data/scripts"):
if str(p) not in sys.path:
sys.path.insert(0, str(p))
from M01_MasterData import M01_MasterData_Store as m01 # noqa: E402
from M02_MasterTemplete import M02_Doc_Import as di # noqa: E402
from M02_MasterTemplete import M02_Machine_Find as mf # noqa: E402
from M02_MasterTemplete import M02_Machine_Hourly as mh # noqa: E402
from test_815_1_import_link import aliases # noqa: E402 — M01 별칭 칸 임시
ml = importlib.import_module("master_doc_link")
mc = importlib.import_module("master_doc_calc")
SAW = "EQ000620"
def _calc(key: str) -> dict:
docs = ml.load_all()
return mc.calc(docs[key], ml.Links(m01.loaded()[1], docs))
def test_alias() -> None:
am = importlib.import_module("master_alias")
assert not m01.loaded()[1].get(SAW).get("별칭") # 별칭 값 = 사용자 몫
assert mf.find("엔진톱", '18"')["키"] is None
for text in ('엔진톱 18", 엔진톱', '"엔진톱 18"", 엔진톱'):
assert am.names(text) == ['엔진톱 18"', "엔진톱"], text
with aliases("EQ", {SAW: '엔진톱 18", 엔진톱'}):
for name, spec in (("엔진톱", '18"'), ("엔진톱", ""), ("엔진톱", '18 "')):
got = mf.find(name, spec)
assert (got["판정"], got["키"]) == (mf.ALIAS, SAW), (name, spec)
for name, spec in (("엔진톱", '24"'), ("체인톱", '18"')):
assert mf.find(name, spec)["키"] is None, (name, spec)
def test_hourly_is_day_over_8() -> None:
hour = _calc("GF000337")
day = {x["이름"]: x for x in _calc("GF000076")["줄"]} # 같은 체인톱 줄(1 일 1 대당 × 벌목부수)
lines = {x["이름"]: x for x in hour["줄"]}
assert set(lines) == {"휘발유(체인톱)", "체인오일", "체인톱 손료", "잡품"}
for name in ("휘발유(체인톱)", "체인오일", "체인톱 손료"):
assert lines[name]["단가"] == day[name]["단가"], name
assert lines["휘발유(체인톱)"]["수량"] == Decimal("5.6") / 8
assert lines["체인톱 손료"]["수량"] == Decimal("0.0084") / 8
assert hour["셈됨"] and hour["노무비"] == 0 and hour["계"] > 0
def test_one_way() -> None:
got = mh.hourly(SAW)
doc = _calc("GF000337")
assert got["ok"] and got["로직"] == "GF000337"
assert [got[k] for k in ("재료비", "경비", "계")] == [float(doc[k]) for k in ("재료비", "경비", "계")] # fmt: skip
link = di.hourly_link(SAW, "재료비")
assert link["키"] == "GF000337" and "기계" not in link["입력"]
assert mh.hourly("EQ000621")["ok"] is False # 예취기 = 시간당 식 없음 그대로