- 흠: run_line 켜쌓기율 = 줄 0.1 원 버림 뒤 × 율 · 다시 버림 → 문서 셈 · B09(raw) 와 1 ~ 2 원 어긋남(GC000261 율 90 노무비 48,364 대 48,365 · 840-5 앞에도 율 400 갈래 중 GC000260 59 · GC000261 109 갈래 다름) · 고친 뒤 0 - 율 100 · 없음 · B09 raw 길 안 바뀜 · 빌더 1,520 --check 같음 · 840-5 직후 대 지금 표본 20,393 다름 0 낡은 시험 고침: - 728_2 사석 수상고르기 44,791.1 → 48,851.7 · 725_1 GF000099 서울 5,295 → 5,660 — 840-5 조종원 1/8 × 16/12 × 25/20(굴착기 시간당 노무비 35,412 → 59,020)만 - 715 사전조합 SK 넣기 — 811-1 뒤 SK 줄 = 참조 한 행 · 쓰는 SK 지우기 막음 - 717_3 화면_이음 지움 — 소스 글자만 보는 시험 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
127 lines
5.4 KiB
Python
127 lines
5.4 KiB
Python
"""728-2 지킴 — SK 단위 환산: 바탕 기준단위 → SK 단위 배 · 화면 줄 · 계 = SK 1 단위 몫 ·
|
||
계수 없으면 셈 막음 · 「식」 = 옛 셈 · 둘째 기초 수량 처음값 · 돈 아닌 기초 고르기 창에서 뺌 ·
|
||
고침 꼴 화면배 되돌림."""
|
||
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
import subprocess
|
||
import sys
|
||
from decimal import Decimal
|
||
from pathlib import Path
|
||
|
||
import pytest
|
||
|
||
ROOT = Path(__file__).resolve().parents[2]
|
||
HERE = Path(__file__).resolve().parent
|
||
sys.path.insert(0, str(ROOT))
|
||
sys.path.insert(0, str(ROOT / "resources/master_data/scripts"))
|
||
|
||
import master_unit as mu # noqa: E402
|
||
|
||
from M01_MasterData import M01_MasterData_Store as m01 # noqa: E402
|
||
from M02_MasterTemplete import M02_Sangeun_Calc as sc # noqa: E402
|
||
from M02_MasterTemplete import M02_Sangeun_Doc as sd # noqa: E402
|
||
|
||
|
||
@pytest.fixture(scope="module")
|
||
def whole():
|
||
return m01.loaded()[1]
|
||
|
||
|
||
def _doc(base, unit, **more):
|
||
return {"키": "SK-999999", "이름": "sub3임시", "단위": unit, "바탕": {"로직": base}, **more}
|
||
|
||
|
||
def _shown(whole, doc):
|
||
clean = sd.clean(doc, None, whole)
|
||
return sc.per_unit(sc.run(clean, whole), clean)
|
||
|
||
|
||
def test_단목베기_100본_제안_본으로_바꾸면_1본_계(whole):
|
||
full = _shown(whole, _doc("GF000287", "100본"))
|
||
assert full["배"] == 1 and full["기준"]["계"] == Decimal("153889") # 751-3 1 원 버림
|
||
assert sc.head_of({"단위": "100본"}) == "100본 당"
|
||
one = _shown(whole, _doc("GF000287", "본"))
|
||
assert one["배"] == 100 and round(one["기준"]["계"], 2) == Decimal("1538.89")
|
||
assert sc.head_of({"단위": "본"}) == "1 본 당"
|
||
pairs = [(x["수량"], y["수량"]) for x, y in zip(full["줄"], one["줄"], strict=True)]
|
||
assert all(b == a / 100 for a, b in pairs) and one["화면배"] == 100 # 세부 품 ÷100
|
||
|
||
|
||
def test_사석_수상고르기_10제곱미터_에서_1제곱미터(whole):
|
||
one = _shown(whole, _doc("GC000421", "㎡"))
|
||
# 10㎡ 488,517(1 원 버림) ÷10 — 굴착기 조종원 시간당 283,296 × 5/24 = 59,020(840-5) × 1.72
|
||
assert one["기준"]["계"] == Decimal("48851.7")
|
||
|
||
|
||
def test_성격_다르면_계수_칸_없으면_셈_막음(whole):
|
||
with pytest.raises(sd.DocError, match="환산 계수"):
|
||
_shown(whole, _doc("GF000099", "m"))
|
||
base = _shown(whole, _doc("GF000099", "㎥"))["기준"]["계"]
|
||
two = _shown(whole, _doc("GF000099", "m", 환산={"계수": 2}))
|
||
assert two["배"] == 2 and two["기준"]["계"] == base / 2
|
||
with pytest.raises(sd.DocError, match="단위중량"):
|
||
_shown(whole, _doc("GF000099", "톤"))
|
||
rock = _shown(
|
||
whole, _doc("GF000099", "톤", 환산={"단위중량": {"종별": "암석", "형상": "화강암"}})
|
||
)
|
||
assert rock["배"] == Decimal("2.7") # 1 ㎥ = 2.7 톤(2,700 ㎏/㎥)
|
||
with pytest.raises(sd.DocError, match="0 보다"):
|
||
sd.clean(_doc("GF000099", "m", 환산={"계수": 0}), None, whole)
|
||
|
||
|
||
def test_식_빈_단위는_옛_셈(whole):
|
||
old = _shown(whole, _doc("GF000287", "식"))
|
||
assert old["배"] == 100 and round(old["1단위"]["계"], 2) == Decimal("1538.89")
|
||
assert "화면배" not in old and old["기준"]["계"] == Decimal("153889") # 화면 = 바탕 몫 그대로
|
||
|
||
|
||
def test_둘째_기초_수량_처음값_배(whole):
|
||
"""바탕 10㎡(GC000421) + 둘째 기초 100㎡(GF000041) — 처음값 0.1 = 바탕 기준단위 몫."""
|
||
qty = mu.swap("10㎡", "100㎡")["배"]
|
||
assert qty == Decimal("0.1")
|
||
alone = sc.run(sd.clean(_doc("GF000041", "100㎡"), None, whole), whole)["1단위"]["계"]
|
||
one = {"종류": "로직", "로직": "GF000041", "입력값": {}, "수량": float(qty)}
|
||
got = sc.run(sd.clean(_doc("GC000421", "㎡", 더한줄=[one]), None, whole), whole)
|
||
bare = sc.run(sd.clean(_doc("GC000421", "㎡"), None, whole), whole)
|
||
added = got["1단위"]["계"] - bare["1단위"]["계"]
|
||
# ㎡ 몫 = 100㎡ 값 ÷100 · 비목 합 1 원 버림(751-3)이라 바탕 몫 ÷10 = 0.1 원 안
|
||
assert abs(added - alone * qty / 10) <= Decimal("0.1")
|
||
src = (ROOT / "M02_MasterTemplete/M02_MasterTemplete_Sangeun_Detail.ts").read_text(
|
||
encoding="utf-8"
|
||
)
|
||
assert "addBase(" not in src and "baseUnitOf(" in src # 840-1 [항목 추가] 걷음
|
||
|
||
|
||
def test_돈_아닌_기초_고르기_창에서_뺌(whole):
|
||
money = [
|
||
r
|
||
for tid, d in whole.index.items()
|
||
if tid in ("GC", "GF", "QC", "QF")
|
||
for r in d.values()
|
||
if isinstance(r, dict)
|
||
and "결과단위" in r
|
||
and not str(r["결과단위"]).strip().startswith("원")
|
||
]
|
||
assert len(money) == 65 # 지금 M01(785-7 · 옛 21 = M01 기초 늘기 전)
|
||
src = (ROOT / "M02_MasterTemplete/M02_MasterTemplete_Find_Pick.ts").read_text(encoding="utf-8")
|
||
assert '!logic.결과단위.trim().startsWith("원")' in src
|
||
|
||
|
||
def test_고침_꼴_화면배_되돌림():
|
||
proc = subprocess.run( # noqa: S603 — 고정 실행 파일
|
||
["node", str(HERE / "helper_728_2_cover_unit.cjs")],
|
||
capture_output=True,
|
||
text=True,
|
||
encoding="utf-8",
|
||
timeout=60,
|
||
)
|
||
assert proc.returncode == 0, proc.stderr
|
||
out = json.loads(proc.stdout)
|
||
assert out["was"]["qty"] == pytest.approx(0.2) # 바탕 값 = 문서 몫(100본)
|
||
assert out["cover"]["labor:LB000101#0"]["qty"] == pytest.approx(0.3)
|
||
assert out["added"] == pytest.approx(60)
|
||
assert out["shown"]["0"]["qty"] == pytest.approx(0.003) # 다시 그리면 화면 몫
|
||
assert out["shown"]["1"]["qty"] == pytest.approx(0.6)
|