"""714-1 지킴 — 계산서 줄 덧칸(쓰는 입력 · 묶음 · 기준단위 · 환산 근거) · M01 `/text` 와 M02 `/logic-lib/sheet` 가 같은 줄 꼴(`master_sheet_line`).""" from __future__ import annotations import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT)) from M01_MasterData import M01_MasterData_Store as store # noqa: E402 from M01_MasterData import M01_MasterData_Store_Sheet as sheet # noqa: E402 from M02_MasterTemplete import M02_Logic_Standard as standard # noqa: E402 msl = sheet.msl num = standard.labor_inputs._num # Decimal → JSON 수(두 길 같은 규칙) def _text(key: str) -> dict: auto = {k: v for k, v in store.auto(key)["값"].items() if v is not None} return sheet.text(key, auto) def _lines(got: dict, groups: str = "groups") -> list[dict]: return [line for g in got[groups] for line in g["줄"]] def test_line_keys_and_bundle(): got = _text("GF000103") # 구조물터파기 — 인력 + 굴착기 기계경비 줄 assert got["ok"] and got["기준단위"] == "㎥" lines = _lines(got) assert all({"쓰는입력", "묶음", "기준단위", "환산근거"} <= set(line) for line in lines) machine = [line for line in lines if line.get("장비")] assert machine and all(line["묶음"] == "경비" for line in machine) assert {"지역", "보정작업"} <= set(machine[0]["쓰는입력"]) assert any(line["묶음"] == "인력" for line in lines) def test_machine_spread(): """714-1b — 장비 줄 「펼침」 = 부른 기계경비 로직 계산서(조종원 · 연료 · 손료) · 시간당 계.""" lines = _lines(_text("GF000103")) spread = next(line for line in lines if line.get("장비"))["펼침"] assert spread["키"].startswith("GC0002") and spread["단위"] == "시간" names = " ".join(one["이름"] for one in spread["줄"]) assert "조종원" in names and "손료" in names sums = [v for v in spread["소계"].values() if v is not None] assert spread["계"] == sum(sums) and spread["계"] > 0 assert not any(line.get("펼침") for line in lines if not line.get("장비")) def test_uses_follow_middle_values(): """중간값을 거슬러 입력까지 — 돌쌓기 석공 품은 높이 · 쌓기 · 돌 입력을 씀.""" lines = _lines(_text("GF000219")) assert {"높이", "쌓기", "돌"} <= set(lines[0]["쓰는입력"]) def test_basis_note_tenfold(): """표 10㎡당 → 결과 원/㎡ 「÷10」 · 결과도 원/10㎡ 면 근거 없음.""" one = _lines(_text("GC000037")) assert one[0]["기준단위"] == "10㎡" and one[0]["환산근거"] == "10㎡당 → 1㎡당 ÷10" ten = _text("GF000124") assert ten["기준단위"] == "10㎡" and all(not x["환산근거"] for x in _lines(ten)) def test_two_routes_same_shape(): """M01 `/text` 와 M02 계산서 — 줄 차례 · 덧칸 값이 같음(금액 끝수만 다를 수 있음).""" for key in ("GF000169", "GF000103", "GF000219"): m01 = _lines(_text(key)) m02 = _lines(standard.sheet(key, {}), "묶음") assert len(m01) == len(m02) for a, b in zip(m01, m02): assert set(b) == {"이름", "글", "금액", *msl.KEYS} assert a["이름"] == b["이름"] assert num([a.get(k) for k in msl.KEYS]) == [b.get(k) for k in msl.KEYS]