- 표지 = 수식 문서 머리 · 옛 로직 줄 칸 「부품」 — 기계경비식 9 · 작업량 틀 60(기종 = 기계표 상세구분 · 규격 열쇠) · 계수식 4 · 변환기가 옮김 · 틀 문서 9 장 - 지움 = 작업량당 기계경비 6(GC001145 · 1148 · 1151 · 1156 · 1159 · 1166 · 부르는 곳 0 · 요구 734-4 · 735-4) — 수식 문서 · 옛 로직 · 키대장 폐기 칸 · 빌더 · 변수표 - 이름 꼬리 4 = 원문 제목(지게운반 · 인력운반(기계설비) · 벽돌운반 · 수중펌프 설치 및 해체) · 키 폐기 0 - 서버 = `M01_MasterData_Parts` — M01 `/logics` · M02 `/logic-lib/logics` 목록에서 부품 뺌(1,440) · 키로 열기 · 부르기 그대로 · `/m01/parts`(기종 계산식 · 틀 · 계수식) · `/m02/logic-lib/machine-parts` · 연결 찾기 과녁에서 부품 뺌(1,444 → 1,435 · 판정 코드 그대로) - 금액 전후 = 문서 1,513 · 셈 9,626(기본 + 옵션 표본) 모두 같음 · 791_1 지문 남은 1,513 같음 → 지문 다시 뜸 · 802_2 변환 대조 1,513 · 목록 xlsx 다시 씀(요약 수) - 낡은 시험 = 1,519 · 1,518 기대 → 1,513 · GC001148 견본 → 같은 꼴 GF000089 토사깍기(기계)(블록 Q 39.293 · 합계 2,190) · 지운 6 을 셈하던 줄 걷음 · 목록 수 1,440 · 묶음 328 · 부르는 수 507 - 새 지킴 시험 test_813_2_parts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
207 lines
8.6 KiB
Python
207 lines
8.6 KiB
Python
# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀
|
||
"""796-2c M02 수식 탭이 SK 셈 답 전체를 그림 — 더한 기초 · 뺀줄 · 덮개 · 율 줄 · 참조 · 가져온 식.
|
||
|
||
견본 셋(임시 storage · M01 그대로):
|
||
A 거푸집 + 더한 기초(굴착기) + 더한 인력 + 뺀줄 + 품 덮개 + 식 덮개
|
||
B 포장 + 단가 덮개 + 율 줄 + 참조 SK
|
||
C 가져온 식 + 더한 인력 + 품 덮개
|
||
지킴: 수식 탭 합계 = SK 셈 답 `기준`(원 단위까지) · 행 합 + 끝수 = 합계(비목마다) ·
|
||
상태(덮음 · 더함 · 뺌) · 고친 칸 표지(원래 · 지금) · 더한 기초 수식 나무 ·
|
||
미리 셈 전/후 = SK 금액 · SK 금액 전후 같음.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from decimal import Decimal as D
|
||
|
||
import pytest
|
||
|
||
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
||
from M02_MasterTemplete import M02_Sangeun_Equation as eqm
|
||
from M02_MasterTemplete import M02_Sangeun_Imported as imp
|
||
from resources.tester.test_795_1_sk_copy import _calc, _doc, _imported_row, _save, _sk
|
||
from resources.tester.test_m02_labor_ref import world # noqa: F401 — 같은 임시 층
|
||
|
||
SUMS = ("노무비", "재료비", "경비", "계")
|
||
BASIC = {
|
||
"종류": "로직",
|
||
"로직": "GF000089",
|
||
"수량": 2,
|
||
"입력값": {},
|
||
} # 토사깍기(기계) — 굴착기 0.7㎥ 시간당 × 1 / 작업량(813-2 GC001148 지움 뒤)
|
||
MAN = {"종류": "인력", "요소": "LB000002", "이름": "sub2임시 인부", "단위": "인", "수량": 1}
|
||
FORM = "GC000211" # 합판거푸집 — 형틀목공 · 보통인부 · 중간 시공량
|
||
MINE = {"층": "personal", "주인": "7/42"}
|
||
|
||
|
||
def _d(v) -> D:
|
||
return D(str(v))
|
||
|
||
|
||
def _read(folder, doc, inputs=None):
|
||
with store.at(folder):
|
||
got = eqm.read(doc, inputs)
|
||
assert got["ok"], got
|
||
return got["수식"]
|
||
|
||
|
||
def _rows(eq) -> dict:
|
||
"""묶음(801-3) — 더한 · 부른 단가산출 = cid 로 · 직접 줄 묶음 속 더함 · 덮음 줄 = 이름으로."""
|
||
got = {r["cid"]: r for r in eq["소계"]["줄"] if "cid" in r}
|
||
for r in eq["소계"]["줄"]:
|
||
got |= {x["이름"]: x for x in r.get("낱줄", [])}
|
||
return got
|
||
|
||
|
||
def _closes(eq, ans) -> None:
|
||
"""합계 = SK 셈 답 원 단위까지 · 행 합 + 끝수 = 합계 · 끝수 작음."""
|
||
sub = eq["소계"]
|
||
for k in SUMS:
|
||
assert eq["합계"][k] == _d(ans["기준"][k]), k
|
||
assert sum((r[k] for r in sub["줄"]), D(0)) + sub["끝수"][k] == eq["합계"][k], k
|
||
assert abs(sub["끝수"]["계"]) < 2, sub["끝수"]
|
||
|
||
|
||
def _line(eq, kind, key):
|
||
return next(x for x in eq["줄"] if x["갈래"] == kind and x["열쇠"] == key)
|
||
|
||
|
||
@pytest.fixture
|
||
def made(world):
|
||
me = world["personal"]
|
||
plain = _sk(me, 바탕={"로직": FORM}) # 고침 없는 같은 바탕 — 원래 값 대조용
|
||
key = _sk(
|
||
me,
|
||
바탕={"로직": FORM},
|
||
더한줄=[dict(BASIC), dict(MAN)],
|
||
뺀줄=["labor:LB000002#0"],
|
||
덮개={"labor:LB000007#0": {"qty": 0.5}},
|
||
식덮개={"mid:시공량": "50"},
|
||
)
|
||
return me, key, plain
|
||
|
||
|
||
def test_A_added_removed_covered_total_equals_sk(made):
|
||
me, key, plain = made
|
||
doc, bare = _doc(me, key), _calc(me, _doc(me, plain))
|
||
ans = _calc(me, doc)
|
||
eq = _read(me, doc)
|
||
_closes(eq, ans)
|
||
rows = _rows(eq)
|
||
# 덮음 — 형틀목공 품 덮개 · 원래 = 고침 없는 SK 의 같은 줄 금액
|
||
cover = rows["형틀목공"] # 직접 묶음 속 덮은 줄(이름)
|
||
was = next(x for x in bare["줄"] if x["cid"] == "labor:LB000007#0")["금액"]
|
||
assert cover["상태"] == "덮음"
|
||
assert _d(cover["원래"]) == _d(was)
|
||
assert cover["계"] == D("137895") # 품 0.5 × 단가 275,790
|
||
# 뺌 — 지운 줄 = 묶음 아님(식 줄 표지로만 · 아래 `out["뺌"]`)
|
||
assert "labor:LB000002#0" not in rows and "보통인부" not in rows
|
||
# 더함 — 기초(토사깍기 2,190 × 2) = 묶음 · 인력 = 직접 묶음 속 더한 줄 · 기초는 수식 나무
|
||
basic = rows["add:#0"]
|
||
man = next(x for r in eq["소계"]["줄"] for x in r.get("낱줄", []) if x["상태"] == "더함")
|
||
assert basic["상태"] == man["상태"] == "더함" and basic["갈래"] == "블록"
|
||
assert [r["갈래"] for r in eq["소계"]["줄"]] == ["블록", "직접"]
|
||
assert basic["계"] > 0 and man["계"] > 0
|
||
assert basic["나무"]["열쇠"] == "GF000089" and basic["나무"]["줄"]
|
||
# 나무 합계 × 수량 = 행(같은 입력)
|
||
assert abs(basic["나무"]["합계"]["계"] * 2 - basic["계"]) <= 2
|
||
# 고친 칸 표지 — 수식 탭 줄(식 덮개 · 품 · 뺌)
|
||
mid = _line(eq, "중간", "시공량")
|
||
assert mid["표지"] == ["식"] and mid.get("원래") is not None and "50" in mid["식"]
|
||
assert _line(eq, "호표", "형틀목공")["표지"] == ["품"]
|
||
out = _line(eq, "호표", "보통인부")
|
||
assert out["뺌"] is True and out["표지"] == []
|
||
# 고침 없는 SK(plain)는 표지도 더함도 없음 — 합계 = 같은 바탕 금액
|
||
flat = _read(me, _doc(me, plain))
|
||
assert {r.get("상태", "바탕") for r in flat["소계"]["줄"]} == {"바탕"}
|
||
assert [r["갈래"] for r in flat["소계"]["줄"]] == ["직접"] # 801-3 한 묶음 · 낱줄 없음
|
||
assert flat["합계"]["계"] == _d(bare["기준"]["계"])
|
||
assert not any("표지" in x for x in flat["줄"])
|
||
|
||
|
||
def test_A_preview_before_after_and_save_same(made):
|
||
"""고침 미리 셈 전/후 = SK 금액 · 저장 뒤 셈 = 미리 셈 · 더한 것도 합계에 듦."""
|
||
me, key, _ = made
|
||
doc = _doc(me, key)
|
||
was = _calc(me, doc)["기준"]["계"]
|
||
edit = [{"할일": "식", "자리": "호표:3", "식": "0.038 × 2", "까닭": "sub2임시 2c"}]
|
||
with store.at(me):
|
||
got = eqm.preview(doc, edit)
|
||
assert got["되나"], got["까닭"]
|
||
assert got["전"]["계"] == _d(was) and got["후"]["계"] != got["전"]["계"]
|
||
_save(me, key, {**doc, eqm.KEY: edit})
|
||
now = _calc(me, _doc(me, key))
|
||
assert _d(now["기준"]["계"]) == got["후"]["계"]
|
||
eq = _read(me, _doc(me, key))
|
||
_closes(eq, now)
|
||
|
||
|
||
def test_B_unit_cover_rate_and_reference(world):
|
||
"""B 단가 덮개 · 율 줄 · 참조 SK 가 소계에 들고 합계 = SK 금액."""
|
||
me = world["personal"]
|
||
ref = _sk(me, 바탕={"로직": FORM})
|
||
rate = {
|
||
"고정": {
|
||
"이름": "sub2임시 율",
|
||
"단가": {},
|
||
"이음": {},
|
||
"비율": {"기준": "인력", "비목": "경비"},
|
||
}
|
||
}
|
||
adds = [{**rate, "수량": 3}, {"참조": {**MINE, "키": ref}, "수량": 1}]
|
||
key = _sk(
|
||
me,
|
||
바탕={"로직": "GC001109"},
|
||
더한줄=adds,
|
||
덮개={"labor:LB000002#0": {"labor": 200000}},
|
||
)
|
||
doc, ans = _doc(me, key), _calc(me, _doc(me, key))
|
||
eq = _read(me, doc)
|
||
_closes(eq, ans)
|
||
rows = _rows(eq)
|
||
pool = next(r for r in eq["소계"]["줄"] if r["갈래"] == "직접")
|
||
price = next(x for x in pool["낱줄"] if x["상태"] == "덮음")
|
||
assert price["원래"] is not None and "sub2임시 율" in pool["이름"] and pool["경비"] > 0
|
||
assert rows["add:#1"]["갈래"] == "블록" and rows["add:#1"]["상태"] == "더함"
|
||
assert _line(eq, "호표", price["이름"])["표지"] == ["단가"]
|
||
|
||
|
||
def test_C_imported_sk_same_rule(world):
|
||
"""C 가져온 식 SK — 더한 인력 · 품 덮개 · 합계 = SK 금액."""
|
||
me = world["personal"]
|
||
with store.at(me):
|
||
key = imp.create(_imported_row(), None, "sub2임시 가져온")["이름"]
|
||
doc = _doc(me, key)
|
||
cid = next(x["cid"] for x in _calc(me, doc)["줄"] if x["cid"].startswith("labor:"))
|
||
_save(me, key, {**doc, "더한줄": [dict(MAN)], "덮개": {cid: {"qty": 1}}})
|
||
doc = _doc(me, key)
|
||
ans = _calc(me, doc)
|
||
eq = _read(me, doc)
|
||
_closes(eq, ans)
|
||
rows = _rows(eq)
|
||
assert [x["상태"] for x in eq["소계"]["줄"][-1]["낱줄"]] == ["덮음", "더함"], rows
|
||
|
||
|
||
def test_plain_sk_has_answer_table(world):
|
||
"""고침 없는 SK = 답까닭 없음 · 소계 표 있음."""
|
||
me = world["personal"]
|
||
key = _sk(me, 바탕={"로직": FORM})
|
||
eq = _read(me, _doc(me, key))
|
||
assert "답까닭" not in eq and eq["소계"]["줄"]
|
||
|
||
|
||
def test_D_imported_outside_total_line_not_in_sum(world):
|
||
"""D 가져온 식 `합밖` 줄 = 합계에 안 듦 → 묶음 아님 · `밖` 글 · 끝수에 안 섞임."""
|
||
me = world["personal"]
|
||
row = _imported_row()
|
||
row["호표"][1] = {**row["호표"][1], "합밖": True}
|
||
with store.at(me):
|
||
key = imp.create(row, None, "sub2임시 합밖")["이름"]
|
||
doc = _doc(me, key)
|
||
ans = _calc(me, doc)
|
||
eq = _read(me, doc)
|
||
_closes(eq, ans)
|
||
out = eq["소계"]["밖"]
|
||
assert len(out) == 1 and out[0]["밖금액"] > 0
|
||
assert abs(eq["소계"]["끝수"]["계"]) < 1
|