- 공용 표 level 옵션: 레벨 칸 class is-lv1~5 · 묶음 줄 is-node(group 지정 · 안 주면 바로 아래 줄이 더 깊은 줄) - 크기 Lv1 16 · Lv2 15 · Lv3 14 · Lv4 13 · Lv5 12(토큰) · 굵게 = 묶음 · 항목 줄은 14 이하 - 들여쓰기 한 단 = 표 기본 1em 토큰(레벨 글자 크기와 무관 · 끌기 한 단과 같음) - 설계내역서 group = 항목 아닌 줄(빈 공종도 묶음) · 들여 · 내어쓰기는 셈 다시 → 레벨 · 글꼴 바로 - 새 시험 test_228_1 · test_200_2 · 201_1 · 185_1 기대값 고침 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SE9MxeXTu2uaDZ55BJowAY
77 lines
3.3 KiB
Python
77 lines
3.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""185-1 B09 총괄설계내역서 · 공사원가계산서 줄 레벨 — 줄 `level` · 1단 굵게 · 공용 표 level 옵션(201-1).
|
|
|
|
레벨 = 화면이 정함(줄 짜임이 `B09_Estimation_UI_Tabs_Total.ts` 에 있음 · 셈 짝은 값만 냄 → 거울 없음).
|
|
총괄 = 가.~바. 소계 1(굵게) · 그 밖 2 · 원가계산서 = 구분만 1 · 비목 소계 2 · 세목 3.
|
|
들여쓰기 = 공용 표 level { key: 명칭 칸 · of = 줄 level }(201-1 · 옛 is-lvN · is-indent · is-flat 갈음).
|
|
"""
|
|
|
|
import json
|
|
import re
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
B09 = ROOT / "B09_Estimation"
|
|
IMPORTS = re.compile(r"^import[^;]*;\n", re.MULTILINE)
|
|
|
|
SUMS = {"material": 194234417, "labor": 346800554, "expense": 169324165, "supply_net": 69474220}
|
|
|
|
BODY = f"""
|
|
const user = {{ estimate: {{}} }};
|
|
const ctx = {{ sheets: {{ total: computeTotal({json.dumps(SUMS)}, user.estimate) }}, payload: {{}}, user, setUser: () => {{}} }};
|
|
const pack = (t) => t.rows.map((r, i) => [r.key, r.level, t.rowClass(i), t.level.key, t.level.of(i), t.cellClass ?? null]);
|
|
console.log(JSON.stringify({{ total: pack(buildTotal(ctx)), cost: pack(buildCost(ctx)) }}));
|
|
"""
|
|
|
|
|
|
def _run() -> dict:
|
|
names = ("Calc_Base", "Calc_Total", "UI_Tabs", "UI_Tabs_Total")
|
|
script = "".join(
|
|
IMPORTS.sub("", (B09 / f"B09_Estimation_{n}.ts").read_text(encoding="utf-8")) for n in names
|
|
)
|
|
result = subprocess.run(
|
|
["node", "--experimental-strip-types", "--no-warnings",
|
|
"--input-type=module-typescript"],
|
|
input=script + BODY, capture_output=True, text=True, encoding="utf-8", timeout=60,
|
|
) # fmt: skip
|
|
assert result.returncode == 0, result.stderr
|
|
return json.loads(result.stdout)
|
|
|
|
|
|
def test_총괄_레벨():
|
|
rows = {k: (lv, cls) for k, lv, cls, *_ in _run()["total"]}
|
|
top = ["direct", "net_cost", "da", "supply_price", "contract", "grand"]
|
|
assert all(rows[k] == (1, "is-title") for k in top)
|
|
for k in ["in_price", "in_env", "indirect_labor", "machine", "retirement", "overhead", "vat",
|
|
"supply"]: # fmt: skip
|
|
assert rows[k] == (2, None), k
|
|
assert {lv for lv, _ in rows.values()} == {1, 2}
|
|
|
|
|
|
def test_원가계산서_레벨():
|
|
rows = {k: (lv, cls) for k, lv, cls, *_ in _run()["cost"]}
|
|
for k in ["overhead", "profit", "supply_price", "vat", "contract", "supply", "grand"]:
|
|
assert rows[k] == (1, "is-title"), k
|
|
for k in ["material", "labor", "expense_sum"]:
|
|
assert rows[k] == (2, None), k
|
|
for k in ["direct_material", "scrap", "direct_labor", "indirect_labor", "expense", "safety"]:
|
|
assert rows[k] == (3, None), k
|
|
|
|
|
|
def test_명칭_칸만_들여씀_공용_level():
|
|
out = _run()
|
|
for tab in ("total", "cost"):
|
|
for _k, lv, _cls, key, of, cell in out[tab]:
|
|
assert (key, of, cell) == ("name", lv, None) # 칸 class(is-indent · is-flat) 없음
|
|
|
|
|
|
def test_CSS_옛_레벨_규칙_없음_공용_표로():
|
|
css = (B09 / "B09_Estimation_UI_Page.css").read_text(encoding="utf-8")
|
|
assert "is-indent" not in css and "is-flat" not in css and "is-lv" not in css
|
|
common = (ROOT / "ui_template" / "ui_template_data_table.css").read_text(encoding="utf-8")
|
|
assert re.search(
|
|
r"td\.ui-data-table__lv \{\s*padding-left: calc\(var\(--spacing-8\) \+ var\(--dt-lv, 0\) \* var\(--dt-indent\)\);",
|
|
common,
|
|
)
|