- 산출근거: 일당 「시간당 작업량 = 시공량 560 ㎥/일 ÷ (1 대 × 8 시간) = 70 ㎥/시간」 · 시간당 식 = q · K · f · E · cm 값 줄 + 한 층 분수 Q 식 · 비목 줄 「59,020 원/시간 ÷ 70 ㎥/시간 = 843.1 원」(금액 그대로) - 제어 구역: 「시간당 작업량」 묶음 맨 위 — 방식 고르기(식 없는 기계 = 잠김 + 까닭) · 시간당 = 작업량 틀 변수 칸(고침 · 원래 값) · 덮음 = 기계덮음.<기계>.작업량 - 기계 보기: 왼쪽 작업량 카드(기계 정본 변수) · 오른쪽 풀이 · 서버가 작업량 틀 연결을 실음(M02_MyMachine_Sheet._work) - 시험: test_846_2_work_view 새로 · test_845_2 GC000088 비목 줄 기대값을 새 꼴로 고침(846-2 표시 변경) · 헬퍼 가짜 DOM 이 진짜 DOM 처럼 요소를 옮김(같은 요소 두 줄 재사용 흠을 잡게) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
155 lines
6.7 KiB
Python
155 lines
6.7 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""PLAN 845-2(요구 879 · 880) — 단가산출 기초 단위 표시 규칙 한 벌 · 기계 산출근거 겹분수 행 나눔(그림만).
|
||
|
||
① 전수 1,520 — 산출근거(펼침 모두)를 진짜 코드로 차린 줄 글:
|
||
금액 · 소계 · 합계 = 「원」 · 수량이 식이면 괄호로 식 전체에 단위(「÷ 560 시간」 꼴 없음) ·
|
||
메타 단위(「… 따름」 · 「수(…)」) 글 0 · 기계경비식(맨 위 · 펼침) 분수 한 층 · 문서 자료 안 바뀜
|
||
② GC000088 — 사용자 그림 자리: 「59,020 원/시간 ÷ 70 ㎥/시간 = 843.1 원」(846-2) · 펼친 굴착기 = 상여 · 휴지 · 손료계수 중간 줄
|
||
③ 왼쪽 — 기계 제어 구역 값 칸 단위 = 오른쪽 펼침과 같은 글(천원 · 10⁻⁷/시간 · ℓ/hr) · 단위는 칸 밖 바로 뒤
|
||
④ 단위 규칙 낱개 — 메타 · 설명 괄호 · 10⁻⁷ · 기계 칸 연결 · 금액 줄 자리
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import importlib
|
||
import json
|
||
import os
|
||
import subprocess
|
||
|
||
import pytest
|
||
|
||
from M01_MasterData import M01_MasterData_Store as m01 # noqa: F401 (scripts 길)
|
||
from M02_MasterTemplete import M02_Doc_Copy as dc
|
||
|
||
mr = importlib.import_module("master_doc_record")
|
||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||
MACHINE = "기계경비식"
|
||
|
||
|
||
def _js(payload: dict):
|
||
proc = subprocess.run(
|
||
["node", os.path.join(HERE, "helper_845_2_unit_show.cjs")],
|
||
input=json.dumps(dc.ml._norm(payload), ensure_ascii=False),
|
||
capture_output=True,
|
||
text=True,
|
||
encoding="utf-8",
|
||
)
|
||
assert proc.returncode == 0, proc.stderr[-3000:]
|
||
return json.loads(proc.stdout)
|
||
|
||
|
||
@pytest.fixture(scope="module")
|
||
def world():
|
||
docs = dc.folder()
|
||
links = dc.ml.Links(dc.skc.whole_(), docs)
|
||
cases = []
|
||
for key, doc in sorted(docs.items()):
|
||
rec = mr.Rec(links)
|
||
rec.prefetch(doc)
|
||
dc.mc.calc(doc, rec)
|
||
cases.append(
|
||
{
|
||
"키": key,
|
||
"문서": doc,
|
||
"연결": rec.out(),
|
||
"기계": (doc.get("부품") or {}).get("갈래") == MACHINE,
|
||
}
|
||
)
|
||
names = [c["문서"].get("이름") for c in cases if c["기계"]]
|
||
got = _js(
|
||
{"할일": "전수", "문서들": cases, "보기": ["GC000088", "GC000006"], "기계이름": names}
|
||
)
|
||
return {g["키"]: g for g in got}
|
||
|
||
|
||
def test_전수_규칙_어긋남_0(world):
|
||
assert len(world) >= 1513
|
||
bad = {k: g["bad"][:2] for k, g in world.items() if g["bad"]}
|
||
assert bad == {}
|
||
assert all(g["같음"] for g in world.values()) # 그리기만 — 문서 자료 안 바뀜
|
||
|
||
|
||
def test_GC000088_비목_줄_단위_자리(world):
|
||
rows = [r["t"] for r in world["GC000088"]["오른쪽"]]
|
||
# 846-2 기계 줄 = 「÷ 시간당 작업량」(시간 수량 식 「× (1 × 8 ÷ 560) 시간」 대신)
|
||
labor = next(t for t in rows if t.startswith("노무비 : 59,020"))
|
||
assert labor == "노무비 : 59,020 원/시간 ⟦{}\\div 70\\ \\text{㎥/시간}⟧ = 843.1 원"
|
||
assert any(t.startswith("소 계 : ") and t.endswith(" 원") for t in rows)
|
||
assert any(t.startswith("계 : ") and t.endswith(" 원") for t in rows)
|
||
# 펼친 굴착기 시간당 경비 — 겹분수 대신 중간 줄
|
||
sub = "\n".join(rows)
|
||
assert (
|
||
"⟦\\text{상여}⟧ = ⟦\\dfrac{\\text{상여분자}}{\\text{상여분모}}⟧ = ⟦\\dfrac{16}{12}⟧" in sub
|
||
)
|
||
assert (
|
||
"⟦\\text{휴지}⟧ = ⟦\\dfrac{\\text{휴지분자}}{\\text{휴지분모}}⟧ = ⟦\\dfrac{25}{20}⟧" in sub
|
||
)
|
||
assert "\\dfrac{1}{8} \\times 1.333333 \\times 1.25⟧ = ⟦0.208333" in sub
|
||
assert "⟦\\text{손료계수}⟧ = " in sub and "= ⟦2{,}085\\ \\text{10⁻⁷/시간}⟧" in sub
|
||
assert "\\dfrac{142{,}069 \\times 1{,}000 \\times 2{,}085}{10{,}000{,}000}⟧ = ⟦29{,}621" in sub
|
||
assert "⟦\\text{가격}⟧ = 142,069 천원" in sub
|
||
assert "⟦\\text{직종}⟧ = 1048" in sub # 코드 값 = 쉼표 없음
|
||
assert (
|
||
"조종원 : ⟦283{,}297⟧ 원/인 × ⟦\\left(1 \\times 0.208333\\right)⟧ 인 = 59,020.2 원" in sub
|
||
)
|
||
assert "⟦\\text{가산}⟧ = ⟦0\\ \\text{\\%}⟧" in sub # % = TeX 글(주석으로 안 먹힘)
|
||
|
||
|
||
def test_줄_따름_고른_표_줄_단위(world):
|
||
rows = "\n".join(r["t"] for r in world["GC000006"]["오른쪽"])
|
||
assert "⟦Q_{\\text{비계공2}}⟧ = 3 인" in rows # 변수 단위 「줄 따름」 = 고른 줄(비계공) 단위 칸
|
||
assert "비계공 : ⟦281{,}939⟧ 원/인 × ⟦0.03⟧ 인 = 8,458.1 원" in rows # 노임 원/일 = 인 하루 값
|
||
|
||
|
||
def test_왼쪽_제어_구역_단위_오른쪽과_같은_글(world):
|
||
rows = {r["sym"]: r["t"] for r in world["GC000088"]["왼쪽"]}
|
||
assert rows["가격"] == "가격=[142069]천원"
|
||
assert rows["상각비계수"] == "상각=[900]10⁻⁷/시간"
|
||
assert rows["주연료"] == "주연료=[19.5]ℓ/hr"
|
||
assert rows["Q_시공^표"].startswith("Q_시공2=[560]㎥")
|
||
|
||
|
||
def test_단위_규칙_낱개():
|
||
got = _js(
|
||
{
|
||
"할일": "단위",
|
||
"글": [
|
||
"구분 따름",
|
||
"줄 따름",
|
||
"수(단위는 줄의 단위 칸 따름)",
|
||
"수",
|
||
"원문 단위 없음",
|
||
"%(주연료비의)",
|
||
"10^-7/시간",
|
||
"㎥/hr",
|
||
"인",
|
||
"",
|
||
], # fmt: skip
|
||
"변수": [
|
||
{"단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "가격"}},
|
||
{"단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "잡재료율"}},
|
||
{"단위": "%", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "가격"}},
|
||
{"단위": "", "연결": {"갈래": "요소", "키": "LB:{S_직종}"}},
|
||
{"단위": "kWh/hr"},
|
||
],
|
||
"금액": [
|
||
[
|
||
{"단위": "시간", "수량": "Q × 8 ÷ Q2"},
|
||
["var", "P"],
|
||
["bin", "/", ["var", "a"], ["var", "b"]],
|
||
{"단위": ""},
|
||
{"결과단위": "원/시간"},
|
||
], # fmt: skip
|
||
[{"단위": "인", "수량": "Q"}, ["var", "w"], ["var", "Q"], {"단위": "원/일"}, None],
|
||
[{"단위": "식"}, ["bin", "*", ["var", "a"], ["var", "b"]], None, None, None],
|
||
],
|
||
}
|
||
)
|
||
assert got["글"] == ["", "", "", "", "", "%", "10⁻⁷/시간", "㎥/hr", "인", ""]
|
||
assert got["변수"] == ["천원", "%", "%", "", "㎾h/hr"]
|
||
assert got["금액"] == [
|
||
{"price": "원/시간", "qty": "시간", "wrap": True},
|
||
{"price": "원/인", "qty": "인", "wrap": False},
|
||
{"price": "", "qty": "", "wrap": False},
|
||
]
|