- 끝수 한 곳 `master_cut.py`(B09 `rounddown` 재사용) — 엔진 답에 입힘: 줄 비목마다 0.1 원 버림 · 하위 로직 줄 = 하위 끝수 계 × 수량 · 덧줄 = 버린 줄 합으로 다시 셈 · 비목 합 1 원 버림 · 중간 칸도 버린 값 - 쓰는 곳: M01 시험 계산(`check_master.calc`) · 읽는 식(`master_text.lines`) · 옛 조합 미리보기(`master_combo`) · M02 `run_line`(단가산출 · 일위대가 · 펼침) · 별도계상 뺀 기준 · 켜쌓기율 곱 뒤 · 일위대가 반영 · 반영합 · 비율 줄 · 사전조합 안 줄 - 일위대가 반영 TS 짝(`Labor_Calc.ts`) 같은 끝수 · 거울 헬퍼가 상대 경로 .ts 가져옴 - B09 = `run_line(raw=True)` 엔진 날 값(제 단가로 다시 버림 · % 덧줄 율 비 그대로) — 검증_sub3 B09 247 칸 전후 같음 - `master_text` 꼴 셋 = `common_util_money` 로 갈음(줄 금액 `fmt_line_money` · 식 안 금액 = 버린 0.1 원) - 화면: 상세 줄 금액 · 시험 계산 줄 · 중간 돈 = `formatLineMoney` · 일위대가 반영 칸 0.1 원 · 상세 바닥 · 박스 · 인력재료경비 비목 소계 = 줄 합 1 원 버림 - 테스트1 네 보기 · 서고 목록 = 124,419(옛 124,420 / 124,419.85) · 재료 줄 11,694.6 + 23,425.6 + 1,404.8 = 소계 36,525 - 새 지킴 시험 test_751_3_money_cut - 옛 날 금액(끝수 없음)을 대조하던 시험 24 파일 고침 — 까닭 = 금액 규칙이 줄 0.1 원 · 소계 1 원 버림으로 바뀜(고정 값 → 새 값 · 줄 합 = 계 → 줄 합 아래 비목마다 1 원 안 · 곱 비 = 끝수 폭 안) · 실무 xlsx 영월 엑셀 같음 22 → 23 · 이어 붙이는 TS 시험(704_3 · 717_2b)에 `rounddown` 같은 식 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
97 lines
4.4 KiB
Python
97 lines
4.4 KiB
Python
"""SK 보기 넷 = 셈 답 하나(PLAN 750-1 · 요구 588-1) — 화면 셈 답 `글`(텍스트 수식) ·
|
|
시험 계산(`줄` · `기준` · `중간`) = SK 줄 · 계 · 변형 일곱(기본 · 줄 빼기 · 더하기 · 덧줄 ·
|
|
별도계상 · 단위 환산 · 재료 고름) + 참조 바탕 · 일위대가 줄 모달(`줄모드`) = 일위대가 그 줄 셈 ·
|
|
`보기` false = 덧칸 없음 · M01 엔진 · storage 안 씀."""
|
|
|
|
import pytest
|
|
|
|
from M01_MasterData import M01_MasterData_Store as m01
|
|
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 M02_MasterTemplete import M02_Sangeun_Views as views
|
|
|
|
FORM = "GC000211" # 6-3-1 합판거푸집 — 재료 일곱 · 소모자재 = 재료비 % 덧줄
|
|
PLY = "material:합판(내수 12㎜)#0"
|
|
DOC = {"키": "SK-000002", "이름": "테스트1", "단위": "㎡", "바탕": {"로직": FORM}}
|
|
ADD = {"종류": "인력", "요소": "LB000002", "이름": "보통인부(더함)", "단위": "인", "수량": 0.05}
|
|
CASES = {
|
|
"기본": {},
|
|
"줄 빼기": {"뺀줄": ["material:각재#0"]},
|
|
"더하기": {"더한줄": [ADD]},
|
|
"덧줄": {"덮개": {"pct:소모자재#0": {"qty": 5}}},
|
|
"별도계상": {"자재표시": {PLY: {"별도계상": "별도계상"}}},
|
|
"단위 환산": {"단위": "10㎡"},
|
|
"재료 고름": {"고름": {PLY: "MT000020"}},
|
|
}
|
|
|
|
|
|
def _whole():
|
|
return m01.loaded()[1]
|
|
|
|
|
|
def _answer(doc: dict, read=None, line: bool = False) -> dict:
|
|
"""`calc_doc` 와 같은 길(층 검사만 뺌)."""
|
|
whole = _whole()
|
|
clean = sd.clean(doc, None, whole)
|
|
got = calc.run(clean, whole, None, read or calc.refs.read_ref, detail=True, line=line)
|
|
return labor._json(views.finish(calc.per_unit(got, clean)))
|
|
|
|
|
|
def _same(a: dict) -> None:
|
|
text, base = a["글"], a["기준"]
|
|
assert text["ok"] is True
|
|
money: dict[str, float] = {}
|
|
for g in text["groups"]:
|
|
assert g["소계"] == pytest.approx(base[g["비목"]])
|
|
for one in g["줄"]:
|
|
money[one["cid"]] = money.get(one["cid"], 0) + (one["금액"] or 0)
|
|
assert set(money) == {x["cid"] for x in a["줄"]} # 글 줄 = SK 줄(cid)
|
|
for x in a["줄"]:
|
|
assert money[x["cid"]] == pytest.approx(x["금액"] or 0)
|
|
assert text["계"] == pytest.approx(base["계"])
|
|
# 시험 계산 표 합 — 줄 0.1 원 · 비목 합 1 원 버림(751-3) = 줄 합 아래 비목마다 1 원(× 화면 배) 안
|
|
gap = sum(x["금액"] or 0 for x in a["줄"]) - base["계"]
|
|
assert -1e-6 <= gap < 3 / (a.get("화면배") or 1)
|
|
assert a["중간"] and all(not isinstance(v, (dict, list)) for v in a["중간"].values())
|
|
|
|
|
|
@pytest.mark.parametrize("name", list(CASES))
|
|
def test_four_views_one_answer(name):
|
|
a = _answer({**DOC, **CASES[name]})
|
|
_same(a)
|
|
if name == "별도계상":
|
|
assert all(one.get("cid") != PLY for g in a["글"]["groups"] for one in g["줄"])
|
|
if name == "단위 환산":
|
|
assert a["글"]["나눔"] == pytest.approx(0.1)
|
|
plain = _answer(DOC)
|
|
assert a["기준"]["계"] == pytest.approx(plain["기준"]["계"] * 10)
|
|
if name == "재료 고름":
|
|
assert a["기준"]["재료비"] != pytest.approx(_answer(DOC)["기준"]["재료비"])
|
|
|
|
|
|
def test_ref_base_same():
|
|
"""참조 바탕(SK 위 SK) — 글도 바탕 SK 고친 줄 위에서."""
|
|
parent = {**DOC, **CASES["덧줄"], "뺀줄": ["material:각재#0"]}
|
|
ref = {"층": "personal", "주인": None, "키": "SK-000002"}
|
|
_same(_answer({**DOC, "키": "SK-000003", "바탕": {"참조": ref}}, read=lambda r: parent))
|
|
|
|
|
|
def test_row_modal_is_hopyo_line():
|
|
"""일위대가 줄 모달(`줄모드`) = 일위대가 그 줄 셈(별도계상 기본 · 747 한쪽 흠)."""
|
|
whole = _whole()
|
|
line = labor._json(labor.drop_apart(labor.run_line(whole, FORM, None), {}))
|
|
got = _answer({**DOC, "단위": "식", "줄모드": True}, line=True)
|
|
assert got["기준"]["계"] == pytest.approx(line["기준"]["계"])
|
|
assert [x["이름"] for x in got["줄"]] == [x["이름"] for x in line["줄"]]
|
|
_same(got)
|
|
|
|
|
|
def test_no_views_flag():
|
|
"""`보기` false(바탕 원값 셈) = 금액만 · 덧칸 없음 · 금액 같음."""
|
|
whole = _whole()
|
|
clean = sd.clean(DOC, None, whole)
|
|
got = labor._json(calc.run(clean, whole, None, detail=True, seen=False))
|
|
assert "글" not in got and "중간" not in got
|
|
assert got["기준"]["계"] == pytest.approx(_answer(DOC)["기준"]["계"])
|