- 까닭: 747-1 뒤 SK 셈은 바탕 재료 빈 칸 = 직접계산 · 일위대가 줄(덮개 줄 line=True)은 별도계상 기본 → 펼친 줄이 재료비를 잃음(합판거푸집 GC000211 SK 를 일위대가에 넣으면 금액 줄어듦)
- Library_Flat.sk_line: 바탕 재료 줄마다 자재표시 {별도계상: 직접계산} + 고른 두 칸 그대로
- 지킴 시험: 740-1 에 747 겹침(덮개 있음 · 없음 두 갈래 전후 금액 같음 · 고치기 전 실패 확인)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
394 lines
19 KiB
Python
394 lines
19 KiB
Python
# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀
|
||
"""740-1 단가산출(SK) · 일위대가(SC) 서로 독립 · 연결 = M01 키 · 초기화(임시 storage · M01 읽기만).
|
||
|
||
- 넣기 = 펼침(SK 에 SK = 몸 통째 한 줄 · SC 에 SK = 로직 줄 + 패치 · SK 에 SC = 줄마다
|
||
더한줄 · SC 에 SC = 넣기 길만 안 줄 펴 넣음 · 저장 · 읽기는 하위 호표 참조 그대로) · 줄 `본뜬` ·
|
||
펼치기 전후 금액 같음 · 원본 고쳐도 · 지워도 그대로
|
||
- 분석 579-2 실측 E1(129,073 → 481,406) = 이제 안 일어남
|
||
- 바탕 SK 참조 · 패치 SK 참조 = 덮개 겹침 · 못 펼침(겹침 · 바탕 없음 · 환산) = 넣기 400 ·
|
||
저장은 옛 참조
|
||
- 초기화 = 덮개 · 뺀줄 · 더한줄 단가 걷음 → M01 값 · 옵션 · 항목 · 수량 남음 · 길(미리 보기 · 씀)
|
||
- 옮기기 함수 = 옛 참조 문서 펼쳐 씀(전후 같음 · 겹침 남김 · 두 번째 = 할 것 없음) · 733 지문 같음
|
||
- B09 = SC 덮개 줄 굳힘 → 대가 블록 금액 = M02(옛 산근 길은 덮개를 안 읽었음)
|
||
"""
|
||
|
||
import json
|
||
|
||
import pytest
|
||
from fastapi import FastAPI
|
||
from fastapi.testclient import TestClient
|
||
|
||
from common_util.common_util_auth import verify_session
|
||
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_Library_Flat as flat
|
||
from M02_MasterTemplete import M02_Library_Same as same
|
||
from M02_MasterTemplete import M02_Library_Same_Router as same_router
|
||
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
||
from M02_MasterTemplete import M02_Sangeun_Calc as calc
|
||
from M02_MasterTemplete import M02_Sangeun_Doc as sd
|
||
from resources.tester.test_m02_labor_ref import MINE, world # noqa: F401
|
||
|
||
GF = "GF000099" # 측구터파기 토사 · 원/㎥
|
||
PCT = "GC001109" # 원/㎡ · 지붕잇기공 · 보통인부 · 「노무비 * 3 / 100」
|
||
ADD = {
|
||
"종류": "인력",
|
||
"요소": "LB000002",
|
||
"비목": "노무비",
|
||
"이름": "보통인부",
|
||
"단위": "인",
|
||
"수량": 0.5,
|
||
}
|
||
USER = {"user_id": 42, "company_id": 7, "role": "USER", "is_master": False, "name": "갑"}
|
||
|
||
|
||
def _whole():
|
||
return m01.loaded()[1]
|
||
|
||
|
||
def _raw(folder, kind, **doc):
|
||
"""옛 꼴 문서(참조 줄 그대로) — 저장 길을 거치지 않고 파일로."""
|
||
(folder / kind).mkdir(parents=True, exist_ok=True)
|
||
key = f"{refs.PREFIX[kind]}-{len(list((folder / kind).glob('*.json'))) + 1:06d}"
|
||
head = {"종류": refs.TITLE[kind], "키": key, "단위": "㎡"}
|
||
body = {"입력값": {}, "덮개": {}, "뺀줄": [], "고름": {}, "자재표시": {}, "더한줄": []}
|
||
full = {**head, **(body if kind == "sangeun" else {"자재": []}), **doc}
|
||
(folder / kind / f"{key}.json").write_text(json.dumps(full, ensure_ascii=False), "utf-8")
|
||
return key
|
||
|
||
|
||
def _make(folder, kind, **doc):
|
||
with store.at(folder):
|
||
extra = {"더한줄": []} if kind == "sangeun" else {}
|
||
return refs.create(kind, {"단위": "㎡", **extra, **doc})["이름"]
|
||
|
||
|
||
def _read(folder, kind, key):
|
||
with store.at(folder):
|
||
return store.read(kind, key)["문서"]
|
||
|
||
|
||
def _sk_total(folder, doc):
|
||
with store.at(folder):
|
||
return float(calc.run(sd.clean(doc, None, _whole()), _whole())["1단위"]["계"])
|
||
|
||
|
||
def _sc_value(folder, key, read=None):
|
||
with store.at(folder):
|
||
got = flat._value({**MINE, "키": key}, read or refs.read_ref, _whole())
|
||
assert got is not None
|
||
return got["계"]
|
||
|
||
|
||
def _y(folder):
|
||
"""원본 SK — 바탕 PCT(% 덧줄) · 품 덮개 · 인력 더한줄(덧줄 밑에 듦)."""
|
||
return _make(
|
||
folder,
|
||
"sangeun",
|
||
이름="원본",
|
||
바탕={"로직": PCT},
|
||
덮개={"labor:LB000036#0": {"qty": 0.036}},
|
||
더한줄=[ADD],
|
||
)
|
||
|
||
|
||
def test_SK_에_SK_몸_통째_금액_같음_원본_고쳐도_지워도_그대로(world):
|
||
me = world["personal"]
|
||
y = _y(me)
|
||
legacy = {
|
||
"이름": "밖",
|
||
"단위": "㎥",
|
||
"바탕": {"로직": GF},
|
||
"더한줄": [{"참조": {**MINE, "키": y}, "수량": 2}],
|
||
}
|
||
before = _sk_total(me, {"키": "SK-000099", **legacy})
|
||
x = _make(me, "sangeun", **legacy)
|
||
doc = _read(me, "sangeun", x)
|
||
entry = doc["더한줄"][0]
|
||
assert not refs.refs_in(doc)
|
||
assert entry["로직"] == PCT and entry["덮개"] and entry["더한줄"][0]["요소"] == "LB000002"
|
||
assert entry["본뜬"]["키"] == y and entry["본뜬"]["이름"] == "원본" and entry["본뜬"]["때"]
|
||
assert _sk_total(me, doc) == pytest.approx(before, rel=1e-9)
|
||
with store.at(me): # 원본 고침 · 지움 → 넣은 쪽 그대로
|
||
now = store.read("sangeun", y)
|
||
store.write(
|
||
"sangeun", y, now["판"], {**now["문서"], "덮개": {"labor:LB000002#0": {"qty": 2}}}
|
||
)
|
||
assert refs.users({**MINE, "키": y}) == []
|
||
store.delete("sangeun", y)
|
||
assert _sk_total(me, _read(me, "sangeun", x)) == pytest.approx(before, rel=1e-9)
|
||
with store.at(me): # 화면 셈 길 = 넣은 줄 세부 펼침(안 더한줄 = add:#0/add:#0)
|
||
got = calc.calc_doc(_read(me, "sangeun", x))
|
||
sub = next(r for r in got["줄"] if r["cid"] == "add:#0")["펼침"]
|
||
assert "add:#0/add:#0" in [r["cid"] for r in sub]
|
||
|
||
|
||
def test_SC_에_SK_패치_겹침_E1_원본_고쳐도_그대로(world):
|
||
"""분석 579-2 E1 — 밖 SC(SK 참조 + 줄 패치 · 안 SC) 의 원본 SK 다른 줄을 고쳐도 밖 금액
|
||
그대로."""
|
||
me = world["personal"]
|
||
sk = _make(me, "sangeun", 이름="밑", 바탕={"로직": PCT}, 더한줄=[])
|
||
inner = _make(me, "precombo", 이름="안", 담은로직=[{"로직": "GC001111"}])
|
||
lines = [
|
||
{"참조": {**MINE, "키": sk}, "패치": {"덮개": {"labor:LB000036#0": {"qty": 0.5}}}},
|
||
{"참조": {**MINE, "키": inner}},
|
||
]
|
||
old = _raw(me, "precombo", 이름="옛 밖", 담은로직=lines)
|
||
before = _sc_value(me, old)
|
||
host = _make(me, "precombo", 이름="밖", 담은로직=lines)
|
||
doc = _read(me, "precombo", host)
|
||
assert doc["담은로직"][0]["로직"] == PCT and doc["담은로직"][0]["본뜬"]["키"] == sk
|
||
assert doc["담은로직"][0]["패치"]["덮개"] == {"labor:LB000036#0": {"qty": 0.5}}
|
||
assert doc["담은로직"][1]["참조"]["층"] == "사본" # 하위 호표(SC 안 SC) = 사본 블록
|
||
assert doc["담은로직"][1]["본뜬"]["키"] == inner
|
||
assert _sc_value(me, host) == pytest.approx(before, rel=1e-9)
|
||
with store.at(me): # E1 — 원본 SK 의 덮지 않은 줄 품 2
|
||
now = store.read("sangeun", sk)
|
||
store.write(
|
||
"sangeun", sk, now["판"], {**now["문서"], "덮개": {"labor:LB000002#0": {"qty": 2}}}
|
||
)
|
||
assert _sc_value(me, old) > before * 3 # 옛 참조 = 따라감(129,073 → 481,406 꼴)
|
||
assert _sc_value(me, host) == pytest.approx(before, rel=1e-9) # 펼친 것 = 그대로
|
||
|
||
|
||
def test_SC_에_SC_사본_블록_실무수량_겹침_원본_지워도(world):
|
||
"""하위 호표(SC 안 SC) = 사본 블록 — 원본 연결 없음 · 금액 같음 · 같은 기초 겹침도 블록 안."""
|
||
me = world["personal"]
|
||
hands = {"층": "실무자료", "실무수량": {"줄": {"0": 3}, "자재": {}}}
|
||
inner = _make(me, "precombo", 이름="안", 담은로직=[{"로직": PCT}], 본뜬=hands)
|
||
lines = [{"로직": PCT}, {"참조": {**MINE, "키": inner}, "별칭": "안쪽"}] # 같은 기초 겹침
|
||
old = _raw(me, "precombo", 이름="옛", 담은로직=lines)
|
||
before = _sc_value(me, old)
|
||
host = _make(me, "precombo", 이름="밖", 담은로직=lines)
|
||
line = _read(me, "precombo", host)["담은로직"][1]
|
||
block = line["참조"]
|
||
assert block["층"] == "사본" and block["키"] == inner and line["본뜬"]["키"] == inner
|
||
assert block["몸"]["담은로직"][0]["로직"] == PCT and line["별칭"] == "안쪽"
|
||
assert block["몸"]["본뜬"]["실무수량"]["줄"] == {"0": 3} # 엑셀 대조 · 하위 호표 끝수
|
||
assert _sc_value(me, host) == pytest.approx(before, rel=1e-9)
|
||
with store.at(me):
|
||
got = flat.flat_lines("precombo", {**MINE, "키": old}, None, {"담은로직": [{"로직": GF}]})
|
||
(me / "precombo" / f"{old}.json").unlink() # 옛 꼴 문서(참조) 치움
|
||
assert refs.users({**MINE, "키": inner}) == []
|
||
store.delete("precombo", inner)
|
||
assert _sc_value(me, host) == pytest.approx(before, rel=1e-9) # 원본 지워도 그대로
|
||
assert got["담은로직"][0]["참조"]["층"] == "사본" # 넣기 길도 블록(겹침 없음)
|
||
|
||
|
||
def test_SK_에_SC_줄마다_더한줄(world):
|
||
me = world["personal"]
|
||
sc = _make(me, "precombo", 이름="조합", 담은로직=[{"로직": GF}])
|
||
with store.at(me):
|
||
got = flat.flat_lines("sangeun", {**MINE, "키": sc}, 2)["더한줄"]
|
||
assert len(got) == 1 and got[0]["로직"] == GF and got[0]["수량"] == 2 # 실무수량 없음 = 1 × 2
|
||
assert got[0]["본뜬"]["키"] == sc
|
||
# 742-1 저장 수량(수량.손)이 있으면 그 수 · 안 SC 펴기 = 바깥 × 안
|
||
from decimal import Decimal
|
||
|
||
hand = flat.sc_adds({"담은로직": [{"로직": GF, "수량": {"손": 3}}]}, Decimal(2), _whole(), {})
|
||
assert hand[0]["수량"] == 6
|
||
block = {"참조": refs.copy_ref({"담은로직": [{"로직": GF, "수량": {"손": 3}}]}, "SC-000001")}
|
||
deep = flat.sc_adds({"담은로직": [{**block, "수량": {"손": 2}}]}, Decimal(1), _whole(), {})
|
||
assert deep[0]["로직"] == GF and deep[0]["수량"] == 6 # 사본 블록 = 바깥 × 안
|
||
doc = {"키": "SK-000099", "이름": "x", "단위": "㎥", "바탕": None, "더한줄": got}
|
||
one = float(labor.run_line(_whole(), GF, {})["기준"]["계"])
|
||
assert _sk_total(me, doc) == pytest.approx(2 * one, rel=1e-9)
|
||
|
||
|
||
def test_바탕_SK_겹침_못_펼침_까닭(world):
|
||
me = world["personal"]
|
||
under = _make(
|
||
me, "sangeun", 이름="밑", 바탕={"로직": PCT}, 덮개={"labor:LB000036#0": {"qty": 0.1}}
|
||
)
|
||
over = {"이름": "위", "단위": "㎡", "바탕": {"참조": {**MINE, "키": under}}, "더한줄": [ADD]}
|
||
over |= {"덮개": {"labor:LB000036#0": {"배율": 2}}, "뺀줄": ["labor:LB000002#0"]}
|
||
before = _sk_total(me, {"키": "SK-000099", **over})
|
||
got = flat.flat_doc("sangeun", {"키": "SK-000099", **over})
|
||
assert got["바탕"] == {"로직": PCT} and got["덮개"]["labor:LB000036#0"]["qty"] == 0.2
|
||
assert got["뺀줄"] == ["labor:LB000002#0"]
|
||
assert _sk_total(me, got) == pytest.approx(before, rel=1e-9)
|
||
# SC 에 바탕 없는 SK · 단위 환산 SK = 못 넣음
|
||
bare = _make(me, "sangeun", 이름="바탕 없음", 바탕=None, 더한줄=[ADD])
|
||
with store.at(me):
|
||
for key, why in ((bare, "바탕 기초 없는"),):
|
||
with pytest.raises(store.StoreError) as e:
|
||
flat.flat_lines("precombo", {**MINE, "키": key})
|
||
assert e.value.status == 400 and why in str(e.value.detail)
|
||
|
||
|
||
def test_초기화_SK_SC_M01_값_옵션_남음(world):
|
||
me = world["personal"]
|
||
rock = {"보정작업": "암석작업(연암・보통암・경암)"}
|
||
entry = {
|
||
"종류": "로직",
|
||
"로직": PCT,
|
||
"입력값": {},
|
||
"수량": 1,
|
||
"덮개": {"labor:LB000036#0": {"qty": 1}},
|
||
}
|
||
priced = {**ADD, "단가": 1}
|
||
x = _make(
|
||
me,
|
||
"sangeun",
|
||
이름="고친 것",
|
||
단위="㎥",
|
||
바탕={"로직": GF},
|
||
입력값=rock,
|
||
덮개={"labor:LB000002#0": {"qty": 1}},
|
||
뺀줄=["logic:GC000267#0"],
|
||
더한줄=[entry, priced],
|
||
)
|
||
with store.at(me):
|
||
look = flat.reset_doc("sangeun", x, None, True, None)
|
||
assert look["걷힘"] == 4 and _read(me, "sangeun", x)["덮개"] # 미리 보기 = 안 씀
|
||
done = flat.reset_doc("sangeun", x, None, False, None)
|
||
doc = _read(me, "sangeun", x)
|
||
assert doc["덮개"] == {} and doc["뺀줄"] == [] and doc["입력값"] == rock
|
||
assert [x.get("요소") or x.get("로직") for x in doc["더한줄"]] == [PCT, "LB000002"]
|
||
assert "덮개" not in doc["더한줄"][0] and "단가" not in doc["더한줄"][1]
|
||
assert done["걷힘"] == 4
|
||
plain = {"키": "SK-000099", "이름": "x", "단위": "㎥", "바탕": {"로직": GF}, "입력값": rock}
|
||
plain["더한줄"] = [{**entry, "덮개": {}}, ADD]
|
||
assert _sk_total(me, doc) == pytest.approx(_sk_total(me, plain), rel=1e-9)
|
||
sc = _make(
|
||
me,
|
||
"precombo",
|
||
이름="줄 덮개",
|
||
담은로직=[
|
||
{"로직": PCT, "패치": {"덮개": {"labor:LB000036#0": {"qty": 1}}, "더한줄": [priced]}}
|
||
],
|
||
)
|
||
with store.at(me):
|
||
got = flat.reset_doc("precombo", sc, None, False, None)
|
||
line = _read(me, "precombo", sc)["담은로직"][0]
|
||
assert got["걷힘"] == 2 and line["패치"] == {"더한줄": [{**ADD, "수량": 0.5, "처음수량": 0.5}]}
|
||
# 이음 기계 고정 줄(736-3) = M01 기계 한 시간 값 다시 받음
|
||
from M02_MasterTemplete import M02_Machine_Hourly as machine
|
||
|
||
hour = machine.hourly("EQ000019")
|
||
fx = {"이름": "굴착기", "단위": "시간", "단가": {"노무비": 1, "재료비": 1, "경비": 1}}
|
||
fx["이음"] = {"기계": "EQ000019"}
|
||
mc = _make(me, "precombo", 이름="기계", 담은로직=[{"고정": fx}])
|
||
with store.at(me):
|
||
assert flat.reset_doc("precombo", mc, None, False, None)["걷힘"] == 1
|
||
price = _read(me, "precombo", mc)["담은로직"][0]["고정"]["단가"]
|
||
assert price["노무비"] == pytest.approx(hour["노무비"]) and price["경비"] == pytest.approx(
|
||
hour["경비"]
|
||
)
|
||
|
||
|
||
def test_길_넣기_초기화_권한(world):
|
||
app = FastAPI()
|
||
app.include_router(same_router.router)
|
||
app.dependency_overrides[verify_session] = lambda: USER
|
||
client = TestClient(app)
|
||
me = world["personal"]
|
||
y = _y(me)
|
||
url = "/api/m02/layers/personal/{}-{}"
|
||
res = client.post(url.format("sangeun", "flat"), json={"참조": {**MINE, "키": y}, "수량": 1})
|
||
assert res.status_code == 200, res.text
|
||
assert res.json()["더한줄"][0]["본뜬"]["키"] == y
|
||
bad = client.post(url.format("precombo", "flat"), json={"참조": {**MINE, "키": "SK-000777"}})
|
||
assert bad.status_code == 400
|
||
look = client.post(url.format("sangeun", "reset"), json={"키": y})
|
||
assert look.status_code == 200 and look.json()["걷힘"] == 1
|
||
firm = client.post("/api/m02/layers/company/sangeun-reset", json={"키": y, "미리보기": False})
|
||
assert firm.status_code == 403 # 일반 사용자 회사 층 쓰기 막힘
|
||
|
||
|
||
def test_옮기기_함수_전후_같음_사본_블록(world):
|
||
me = world["personal"]
|
||
y = _y(me)
|
||
inner = _make(me, "precombo", 이름="안", 담은로직=[{"로직": GF}])
|
||
sk = _raw(
|
||
me,
|
||
"sangeun",
|
||
이름="옛 SK",
|
||
단위="㎥",
|
||
바탕={"로직": GF},
|
||
더한줄=[{"참조": {**MINE, "키": y}, "수량": 1}],
|
||
)
|
||
sc = _raw(
|
||
me,
|
||
"precombo",
|
||
이름="옛 SC",
|
||
담은로직=[{"참조": {**MINE, "키": y}}, {"참조": {**MINE, "키": inner}}],
|
||
)
|
||
dup = _raw(
|
||
me, "precombo", 이름="겹침", 담은로직=[{"로직": GF}, {"참조": {**MINE, "키": inner}}]
|
||
)
|
||
before = {k: _sc_value(me, k) for k in (sc, dup)} | {
|
||
sk: _sk_total(me, _read(me, "sangeun", sk))
|
||
}
|
||
look = {r["키"]: r for r in flat.migrate(False)}
|
||
assert all(look[k]["같음"] and look[k]["펼침"] and not look[k]["씀"] for k in (sk, sc, dup))
|
||
rows = {r["키"]: r for r in flat.migrate(True)}
|
||
assert all(rows[k]["씀"] for k in (sk, sc, dup))
|
||
assert not refs.refs_in(json.loads((me / "sangeun" / f"{sk}.json").read_bytes()))
|
||
for key in (sc, dup): # 하위 호표 = 사본 블록만 남음(원본 연결 없음)
|
||
left = refs.refs_in(json.loads((me / "precombo" / f"{key}.json").read_bytes()))
|
||
assert [(r["층"], r["키"]) for r in left] == [("사본", inner)]
|
||
assert _sk_total(me, _read(me, "sangeun", sk)) == pytest.approx(before[sk], rel=1e-9)
|
||
assert _sc_value(me, sc) == pytest.approx(before[sc], rel=1e-9)
|
||
assert _sc_value(me, dup) == pytest.approx(before[dup], rel=1e-9)
|
||
again = flat.migrate(True) # 두 번째 = 바꿀 것 없음
|
||
assert all(r["펼침"] and not r["씀"] for r in again)
|
||
|
||
|
||
def test_733_지문_옛_참조_펼친_것_같음(world):
|
||
me = world["personal"]
|
||
y = _y(me)
|
||
old = _raw(me, "precombo", 이름="옛", 담은로직=[{"참조": {**MINE, "키": y}}, {"로직": GF}])
|
||
new = _make(me, "precombo", 이름="새", 담은로직=[{"참조": {**MINE, "키": y}}, {"로직": GF}])
|
||
assert not refs.refs_in(_read(me, "precombo", new))
|
||
fingers = {k: same.finger("precombo", _read(me, "precombo", k)) for k in (old, new)}
|
||
assert fingers[old] == fingers[new]
|
||
|
||
|
||
def test_B09_SC_덮개_줄_대가_금액_M02_같음(world, tmp_path):
|
||
"""SC 덮개 줄(SK 넣기 꼴) — 옛 B09 = 산근(덮개 안 읽음) · 이제 굳힌 줄 대가 = M02 값."""
|
||
from B09_Estimation import B09_Estimation_Bill_Library as library
|
||
from resources.tester.test_719_2_sk_project import _b09, _project
|
||
|
||
me = world["personal"]
|
||
cover = {"labor:LB000036#0": {"qty": 0.5}}
|
||
sc = _make(
|
||
me,
|
||
"precombo",
|
||
이름="덮은 줄",
|
||
담은로직=[{"로직": PCT, "패치": {"덮개": cover, "더한줄": [ADD]}}],
|
||
)
|
||
m02 = _sc_value(me, sc)
|
||
bare = float(labor.run_line(_whole(), PCT, {})["기준"]["계"])
|
||
assert m02 > bare * 2 # 덮개 · 더한줄이 값에 듦(옛 B09 산근 = bare)
|
||
root = _project(tmp_path / "proj", [])
|
||
made = library.import_copy(root, "precombo", "personal", "7/42", sc)
|
||
daega, done, _ = _b09(root)
|
||
block = done[daega["libs"][made["폴더"]]]
|
||
line = block["lines"][0]
|
||
assert line["kind"] == "daega" and block["blank"] == 1 # 안 줄 수량 = 이 공사에서 입력(723-4)
|
||
cover_qty = {block["cover"]: {line["cid"]: {"qty": 1}}}
|
||
block = _b09(root, cover_qty)[1][daega["libs"][made["폴더"]]]
|
||
assert block["blank"] == 0
|
||
assert block["sum"] == pytest.approx(m02, abs=5) # 끝수(내림)만 다름
|
||
|
||
|
||
def test_747_SK_재료_직접계산_일위대가에_넣어도_같은_금액(world):
|
||
"""747-1 SK 바탕 재료 = 직접계산 · 일위대가 줄 기본 = 별도계상 → 펼친 줄에 적어 둠."""
|
||
me = world["personal"]
|
||
form = "GC000211" # 합판거푸집 — 재료 줄 있음
|
||
plain = _make(me, "sangeun", 이름="거푸집", 바탕={"로직": form})
|
||
cover = {"material:합판(내수 12㎜)#0": {"qty": 2}}
|
||
covered = _make(me, "sangeun", 이름="거푸집 고침", 바탕={"로직": form}, 덮개=cover)
|
||
for sk in (plain, covered):
|
||
lines = [{"참조": {**MINE, "키": sk}}]
|
||
old = _raw(me, "precombo", 이름="옛", 담은로직=lines)
|
||
before = _sc_value(me, old)
|
||
host = _make(me, "precombo", 이름="새", 담은로직=lines)
|
||
line = _read(me, "precombo", host)["담은로직"][0]
|
||
assert line["자재표시"] and all(
|
||
v["별도계상"] == "직접계산" for v in line["자재표시"].values()
|
||
)
|
||
assert _sc_value(me, host) == pytest.approx(before, rel=1e-9)
|