"""166-6 일위대가목록표 블록 합 — 빈 줄 있는 블록 = 아는 줄 합 + 「빈 줄 n」 · 내역 단가엔 안 넘김. 견본 = 대가 A(노무 아는 줄 · 자재 단가 없음 줄) · 대가 B(A 를 부름 → 그 줄도 빈 줄) · 대가 C(빈 줄 없음). 파이썬 `B09_Estimation_Calc_Labor` ↔ TS 짝 거울 + 목록표 화면 「빈 줄 n」 · 풍선(Node 타입 지움). """ import json import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[2] if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) from B09_Estimation.B09_Estimation_Calc_Labor import compute_labor, daega_price # noqa: E402 from test_145_2_b09_labor_calc import _same, _ts # noqa: E402 from test_155_b09_tabs import _node # noqa: E402 SHEETS = { "labor": [{"key": "L1", "price": 165545}], "material": [{"key": "M1", "price": None}], "machine": [], "gaps": [], } def _b(bid, name, lines): return { "id": bid, "kind": "조합", "name": name, "spec": "", "unit": "m", "cite": "", "lines": lines, } DAEGA = { "blocks": [ _b("A", "기슭막이", [ {"kind": "labor", "key": "L1", "qty": 0.5, "name": "보통인부"}, {"kind": "material", "key": "M1", "qty": 2, "name": "토목용부직포"}, ]), _b("B", "겹 대가", [ {"kind": "labor", "key": "L1", "qty": 0.1, "name": "보통인부"}, {"kind": "daega", "key": "A", "qty": 1, "name": "기슭막이"}, ]), _b("C", "아는 줄만", [{"kind": "labor", "key": "L1", "qty": 1, "name": "보통인부"}]), ], "owners": {"pipe@100.0": "A", "pipe@200.0": "C"}, } # fmt: skip def test_아는_줄_합_빈_줄_n(): out = compute_labor(DAEGA, SHEETS) rows = {r["key"]: r for r in out["daega"]} # 165,545 × 0.5 = 82,772.5 → 블록 ROUNDDOWN 0 · 자재 줄은 빈 줄 assert (rows["A"]["sum"], rows["A"]["labor"], rows["A"]["material"]) == (82772, 82772, 0) assert (rows["A"]["blank"], rows["A"]["blank_names"]) == (1, ["토목용부직포"]) # 부른 대가에 빈 줄 → 그 줄도 빈 줄(아는 줄 합을 위로 안 넘김) assert (rows["B"]["sum"], rows["B"]["blank"], rows["B"]["blank_names"]) == ( 16554, 1, ["기슭막이"], ) assert (rows["C"]["sum"], rows["C"]["blank"]) == (165545, 0) # 목록표 = 블록 합계 그대로(같은 셈 한 벌) for b in out["daega_blocks"]: assert _same( {k: rows[b["key"]][k] for k in ("sum", "blank")}, {"sum": b["sum"], "blank": b["blank"]} ) # 내역 단가 = 빈 줄 블록은 빈칸 · 없는 블록은 그대로 assert daega_price(out, "pipe@100.0")["sum"] is None assert daega_price(out, "pipe@100.0")["labor"] is None assert daega_price(out, "pipe@200.0")["sum"] == 165545 def test_거울_파이썬_TS(): py = json.loads(json.dumps(compute_labor(DAEGA, SHEETS), ensure_ascii=False)) ts = _ts(DAEGA, SHEETS, {}) assert _same(py, ts["out"]) assert _same(daega_price(py, "pipe@100.0"), ts["price"]) def test_목록표_빈_줄_글_풍선(): sheets = json.dumps(compute_labor(DAEGA, SHEETS), ensure_ascii=False) out = _node( f"\nconst t = buildDaegaList({{ sheets: {sheets} }});" "\nconsole.log(JSON.stringify({ notes: t.rows.map((r) => r.blank_note)," " sums: t.rows.map((r) => r.sum), cols: t.columns.map((c) => c.key)," " tips: t.rows.map((_, i) => t.tip(i, 'blank_note') ?? null) }));" ) assert out["cols"][5:7] == ["sum", "blank_note"] # 합계 바로 옆 assert out["notes"] == ["빈 줄 1", "빈 줄 1", ""] assert out["sums"] == [82772, 16554, 165545] assert out["tips"] == ["빈 줄 — 토목용부직포", "빈 줄 — 기슭막이", None]