Files
Aislo/resources/tester/test_715_3_labor_patch.py
T

136 lines
6.2 KiB
Python

# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀
"""일위대가 · 사전조합 줄 덮개 · [단가산출로 저장] · 단위 빈칸 막기(PLAN 715-3) — 임시 storage.
줄 덮개 = 그 줄에만(단가산출 원본 그대로) · 값 = 같은 덮개 SK 값 = 손셈 ·
줄 고름(차례)이 뺀줄 뒤 제자리 ·
[단가산출로 저장] = 새 SK + 참조 줄 · 같은 값 · 단위 빈칸 400 · 덮개 없는 줄 = 옛 값.
"""
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" # 원/㎡ · 인력 둘(LB000036 · LB000002) + 「노무비 * 3 / 100」
TWO_MATS = "GC000565" # 원/m · 재료 줄 둘
COVER = {"덮개": {"labor:LB000036#0": {"qty": 0.5}}}
def _whole():
return m01.loaded()[1]
def _sc(folder, lines, unit="㎡"):
with store.at(folder):
return refs.create("precombo", {"이름": "조합", "단위": unit, "담은로직": lines})["이름"]
def _value(folder, key):
with store.at(folder):
return refs.Expand(_whole())({**MINE, "키": key})
def test_logic_line_cover_in_precombo(world):
"""사전조합 로직 줄 덮개 = 같은 덮개 SK 값 · 손셈(품 0.5 × 단가 + 둘째 줄 · 3 % 덧줄)."""
bare = labor.run_line(_whole(), PCT, {})
sc = _sc(world["personal"], [{"로직": PCT, "패치": COVER}])
with store.at(world["personal"]):
kept = store.read("precombo", sc)["문서"]["담은로직"][0]
assert kept["패치"] == COVER
got = _value(world["personal"], sc)["기준"]
labor_sum = Decimal("0.5") * Decimal(str(bare["줄"][0]["단가"])) + Decimal(
str(bare["줄"][1]["금액"])
)
assert got["노무비"] == pytest.approx(labor_sum)
assert got["경비"] == pytest.approx(labor_sum * 3 / 100, abs=1)
def test_line_pick_by_order_stays_after_drop(world):
"""줄 고름 = 바탕 호표 차례(2) · 패치 뺀줄로 첫 재료 줄을 빼도 그 자재가 그 줄에."""
import master_pick as mp
whole = _whole()
row = whole.logic(TWO_MATS)
item = row["호표"][2]
want = mp.search(whole, item["요소"], {}, item.get("단위"))[1]
one = {
"로직": TWO_MATS,
"고름": {"2": want},
"자재표시": {"2": {"별도계상": "직접계산"}},
"패치": {"뺀줄": ["material:" + row["호표"][1]["이름"] + "#0"]},
}
with store.at(world["personal"]):
doc = labor.clean({"담은로직": [one]})
got = labor.calc(doc, {})["줄"][0]
picked = [x for x in got["줄"] if x.get("품목")]
assert [x["품목"]["키"] for x in picked] == [want]
def test_ref_line_cover_only_that_line(world):
"""SK 참조 줄 덮개 = 그 줄만 · SK 원본 · 다른 줄 값 그대로."""
with store.at(world["personal"]):
sk = refs.create(
"sangeun", {"이름": "밑", "단위": "㎡", "바탕": {"로직": PCT}, "더한줄": []}
)["이름"]
before = store.read("sangeun", sk)["판"]
ref = {**MINE, "키": sk}
sc = _sc(
world["personal"],
[{"참조": ref, "수량": {"손": 1}, "패치": COVER}, {"로직": "GC001111", "수량": {"손": 1}}],
)
inner = _value(world["personal"], sc)["안"]
plain = _value(world["personal"], _sc(world["personal"], [{"참조": ref}]))["기준"]
covered = calc.calc_doc(
{"키": "SK-000999", "이름": "x", "단위": "㎡", "바탕": {"로직": PCT}, **COVER}
)
assert inner[0]["기준"]["계"] == pytest.approx(Decimal(str(covered["1단위"]["계"])))
assert inner[0]["기준"]["계"] != plain["계"]
with store.at(world["personal"]):
assert store.read("sangeun", sk)["판"] == before
def test_save_as_sangeun(world):
"""[단가산출로 저장] — 새 SK(바탕 · 입력값 · 고름 cid · 덮개) · 참조 줄 · 같은 1 단위 값."""
one = {"로직": PCT, "패치": COVER, "수량": {"손": 2}, "별칭": "내 줄"}
with store.at(world["personal"]):
line_value = labor.calc(labor.clean({"담은로직": [one]}), {})["줄"][0]["기준"]
got = calc.from_line(one, "줄로 만든", "㎡")
doc = store.read("sangeun", got["이름"])["문서"]
value = calc.calc_doc(doc)["기준"]
assert got["줄"] == {"참조": {**MINE, "키": got["이름"]}, "수량": {"손": 2}, "별칭": "내 줄"}
assert doc["바탕"] == {"로직": PCT} and doc["덮개"]["labor:LB000036#0"]["qty"] == 0.5
assert value["계"] == pytest.approx(line_value["계"])
def test_refusals(world):
with store.at(world["personal"]):
with pytest.raises(store.StoreError, match="단위가 빔"):
refs.create("precombo", {"이름": "x", "단위": " ", "담은로직": [{"로직": PCT}]})
assert refs.create("precombo", {"이름": "빈 새 문서", "단위": None, "담은로직": []})["이름"]
bad = {"로직": PCT, "패치": {"더한줄": [{"참조": {**MINE, "키": "SK-000001"}, "수량": 1}]}}
with pytest.raises(store.StoreError, match="참조 못 넣음"):
labor.clean({"담은로직": [bad]})
with pytest.raises(store.StoreError, match="수가 아님"):
labor.clean(
{"담은로직": [{"로직": PCT, "패치": {"덮개": {"labor:LB000036#0": {"qty": "식"}}}}]}
)
sc = _sc(world["personal"], [{"로직": PCT}])
with pytest.raises(store.StoreError, match="줄 덮개는"):
labor.clean({"담은로직": [{"참조": {**MINE, "키": sc}, "패치": COVER}]})
def test_no_patch_same_value(world):
"""덮개 없는 줄 = run_line 값 그대로(옛 셈 길)."""
sc = _sc(world["personal"], [{"로직": PCT, "패치": {}}])
with store.at(world["personal"]):
assert "패치" not in store.read("precombo", sc)["문서"]["담은로직"][0]
assert _value(world["personal"], sc)["기준"]["계"] == pytest.approx(
labor.run_line(_whole(), PCT, {})["기준"]["계"]
)