Files
Aislo/resources/tester/test_796_2c_m02_equation_full.py
T
eomsangdonandClaude Opus 5.5 58a3e039b3 feat(813-2): 보조 문서 부품 표지 73 · 작업량당 기계경비 6 지움 · 단가산출 목록에서 뺌 · 기계 → 부품 길
- 표지 = 수식 문서 머리 · 옛 로직 줄 칸 「부품」 — 기계경비식 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>
2026-11-09 20:49:52 +09:00

207 lines
8.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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