- 끝수 한 곳 `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>
102 lines
4.7 KiB
Python
102 lines
4.7 KiB
Python
# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀
|
|
"""M02 단가산출(SK) 엔진 입력 덧칸(PLAN 715-1b · `master_pick`) — 고친 줄 값 = 손셈.
|
|
|
|
줄 단가 덮개 = 손 단가 · 로직 줄 노 · 재 · 경 덮개 = 값묶음(일부면 엔진 값 위) ·
|
|
덧줄 % 가 덮인 값에서 다시 셈 · 더한줄 참조(SK · SC) · 고정 = 1 단위 묶음 · 덧칸 없는 줄 = 엔진 값.
|
|
"""
|
|
|
|
from decimal import Decimal
|
|
|
|
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_Labor_Ref as refs
|
|
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
|
from M02_MasterTemplete import M02_Sangeun_Calc as calc
|
|
from resources.tester.test_m02_labor_ref import MINE, world # noqa: F401 — 같은 임시 층
|
|
|
|
PCT = "GC001109" # 원/㎡ · 인력 둘 + 「노무비 * 3 / 100」
|
|
SUB = "GC000999" # 원/주 · 인력 둘 + 로직 줄(GC000275)
|
|
|
|
|
|
def _whole():
|
|
return m01.loaded()[1]
|
|
|
|
|
|
def _run(**doc):
|
|
from M02_MasterTemplete import M02_Sangeun_Doc as sd
|
|
|
|
whole = _whole()
|
|
clean = sd.clean({"키": "SK-000001", "이름": "시험", "단위": "㎡", **doc}, None, whole)
|
|
return labor._json(calc.run(clean, whole))
|
|
|
|
|
|
def test_price_cover_is_hand_price_and_pct_follows():
|
|
bare = labor.run_line(_whole(), PCT, {})
|
|
first, second = bare["줄"][0], bare["줄"][1]
|
|
got = _run(바탕={"로직": PCT}, 덮개={"labor:LB000036#0": {"labor": 200000}})
|
|
line = got["줄"][0]
|
|
assert line["단가"] == 200000 and line["출처"] == "손 단가"
|
|
cut = labor.mcut.down # 751-3 — 줄 0.1 원 · 비목 합 1 원 버림
|
|
want = cut(Decimal(str(first["수량"])) * 200000, 1) + Decimal(str(second["금액"]))
|
|
assert got["기준"]["노무비"] == pytest.approx(float(cut(want, 0)))
|
|
assert got["기준"]["경비"] == pytest.approx(float(want * 3 / 100), abs=1)
|
|
|
|
|
|
def test_bundle_cover_on_logic_line_partial():
|
|
bare = labor.run_line(_whole(), SUB, {})
|
|
sub = bare["줄"][2]
|
|
got = _run(바탕={"로직": SUB}, 단위="주", 덮개={"logic:GC000275#0": {"expense": 1000}})
|
|
line = got["줄"][2]
|
|
qty = Decimal(str(sub["수량"]))
|
|
assert line["비목"]["경비"] == pytest.approx(float(qty * 1000))
|
|
assert line["비목"]["노무비"] == pytest.approx(
|
|
float(sub["비목"]["노무비"])
|
|
) # 안 덮은 칸 = 엔진 값
|
|
|
|
|
|
def test_untouched_lines_same_as_engine():
|
|
bare = labor.run_line(_whole(), SUB, {})
|
|
got = _run(바탕={"로직": SUB}, 단위="주") # 바탕 단위(728-2 — 성격 다르면 계수 칸)
|
|
assert got["기준"]["계"] == pytest.approx(float(bare["기준"]["계"]))
|
|
|
|
|
|
def test_added_ref_and_fixed_lines(world):
|
|
"""더한줄 = SK 참조 2 · 고정 줄 1 — 값 = 2 × 그 SK 1 단위 + 고정 단가."""
|
|
with store.at(world["personal"]):
|
|
sk = refs.create(
|
|
"sangeun", {"이름": "밑", "단위": "㎡", "바탕": {"로직": PCT}, "더한줄": []}
|
|
)["이름"]
|
|
unit = calc.calc_doc(store.read("sangeun", sk)["문서"])["1단위"]["계"]
|
|
top = refs.create(
|
|
"sangeun",
|
|
{
|
|
"이름": "위",
|
|
"단위": "식",
|
|
"바탕": None,
|
|
"더한줄": [
|
|
{"참조": {**MINE, "키": sk}, "수량": 2},
|
|
{"고정": {"이름": "운반", "단위": "식", "단가": {"경비": 5000}}, "수량": 1},
|
|
],
|
|
},
|
|
)["이름"]
|
|
got = calc.calc_doc(store.read("sangeun", top)["문서"])
|
|
assert got["기준"]["계"] == pytest.approx(unit * 2 + 5000, abs=1)
|
|
expense = labor.run_line(_whole(), PCT, {})["기준"]["경비"]
|
|
assert got["기준"]["경비"] == pytest.approx(5000 + 2 * float(expense), abs=1)
|
|
|
|
|
|
def test_added_material_counts_unless_apart():
|
|
"""사용자가 더한 재료 줄 = 기본 계 안(재료비 · 계에 더함) · 줄 「별도계상」 칸만 계 밖(재료 목록만)."""
|
|
one = {"종류": "재료", "요소": "MT000010", "수량": 3, "단가": 1200}
|
|
bare = _run(바탕={"로직": PCT})
|
|
inside = _run(바탕={"로직": PCT}, 더한줄=[one])
|
|
assert inside["기준"]["재료비"] == pytest.approx(bare["기준"]["재료비"] + 3600)
|
|
assert inside["기준"]["계"] == pytest.approx(bare["기준"]["계"] + 3600, abs=1)
|
|
assert any(x["cid"] == "add:#0" for x in inside["줄"])
|
|
apart = _run(바탕={"로직": PCT}, 더한줄=[{**one, "별도계상": True}])
|
|
assert apart["기준"]["계"] == pytest.approx(bare["기준"]["계"])
|
|
assert not any(x["cid"] == "add:#0" for x in apart["줄"])
|
|
assert any(m["금액"] == pytest.approx(3600) for m in apart["재료"])
|