Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn
89 lines
3.9 KiB
Python
89 lines
3.9 KiB
Python
"""갈 곳(`destination`) 기본값 금지 — 명세 13장 「⛔ 기본값 금지(빠진 것이 조용해짐)」 (2026-09-14).
|
|
|
|
종전 `DESTINATION.get(name, "quantity")` 는 표에 없는 이름을 **아무 축에도 안 가는 칸**으로 떨어뜨려
|
|
L형수로 이형철근·면목 · 개거 유로폼·면목 · 떼흙막이 떼가 자재총괄에서 통째로 빠져 있었음.
|
|
|
|
지키는 것
|
|
① 표에 없는 이름은 성분이 안 서고 **사유가 뜸**(조용히 새지 않음)
|
|
② 정본 표(개거·떼흙막이·바닥막이)의 모든 줄 이름이 갈 곳 표에 있음 — 줄이 늘면 여기서 걸림
|
|
③ 드러난 넷이 제자리로 감(관측 원단위와 같은 갈 곳)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from B08_Quantity.B08_Quantity_Engine_UnitQuantity_Base import DESTINATION, routed # noqa: E402
|
|
from B08_Quantity.B08_Quantity_Engine_UnitQuantity_Revetment import ( # noqa: E402
|
|
BED_SILL_FORMS,
|
|
OPEN_DITCH_FORMS,
|
|
SOIL_GUARD_SOD,
|
|
open_ditch,
|
|
soil_guard,
|
|
)
|
|
|
|
|
|
def test_표에_없는_이름은_막히고_사유가_뜸() -> None:
|
|
notes: list[str] = []
|
|
assert routed("낯선성분", notes) is None
|
|
assert routed("낯선성분", notes) is None
|
|
assert len(notes) == 1 and "갈 곳이 표" in notes[0] and "기본값 금지" in notes[0]
|
|
assert routed("터파기", notes) == "earthwork" and len(notes) == 1
|
|
|
|
|
|
def test_정본_표의_줄_이름은_전부_갈_곳_표에_있음() -> None:
|
|
names = {row[0] for table in OPEN_DITCH_FORMS.values() for row in table["rows"]}
|
|
names |= {row[0] for row in SOIL_GUARD_SOD["rows"]}
|
|
names |= {table["stone_name"] for table in BED_SILL_FORMS.values()}
|
|
assert sorted(name for name in names if name not in DESTINATION) == []
|
|
|
|
|
|
def test_드러난_넷이_제자리로_감() -> None:
|
|
ditch, notes = open_ditch(10.0, {"ditch_spec": "L형수로 H=0.2"})
|
|
got = {component.name: component.destination for component in ditch}
|
|
assert got["이형철근"] == "material" and got["면목"] == "material"
|
|
assert next(c.spec for c in ditch if c.name == "이형철근") == "D13" # 이름·규격 따로
|
|
assert not [note for note in notes if "갈 곳이 표" in note]
|
|
plain, _ = open_ditch(10.0, {})
|
|
assert {c.name: c.destination for c in plain}["유로폼"] == "unit_price"
|
|
sod, sod_notes = soil_guard({"form": "떼"})
|
|
assert {c.name: c.destination for c in sod}["떼"] == "material"
|
|
assert not [note for note in sod_notes if "갈 곳이 표" in note]
|
|
|
|
|
|
def test_관측_원단위_줄도_갈_곳이_없으면_막히고_사유() -> None:
|
|
"""관측 원단위 로더의 `destination or "material"` 도 같은 병 — 줄이 늘 때 바로 드러나게."""
|
|
from B08_Quantity.B08_Quantity_Engine_ObservedUnit import ObservedUnitTable, expand_observed
|
|
|
|
table = ObservedUnitTable(
|
|
entries=[
|
|
{
|
|
"type_id": "시험구조물",
|
|
"unit": "개소",
|
|
"components": [
|
|
{"name": "콘크리트", "unit": "㎥", "amount": 1.0, "destination": "unit_price"},
|
|
{"name": "새자재", "unit": "㎥", "amount": 2.0},
|
|
],
|
|
}
|
|
]
|
|
)
|
|
components, notes = expand_observed("시험구조물", {}, {"options": {}}, table)
|
|
assert [c["name"] for c in components] == ["콘크리트"]
|
|
assert any("새자재" in note and "기본값 금지" in note for note in notes)
|
|
|
|
|
|
def test_관측_원단위_표의_전_줄에_갈_곳이_있음() -> None:
|
|
from B08_Quantity.B08_Quantity_Engine_ObservedUnit import load_observed_table
|
|
|
|
missing = [
|
|
(entry.get("type_id"), item.get("name"))
|
|
for entry in load_observed_table().entries
|
|
for item in entry.get("components") or []
|
|
if not item.get("destination")
|
|
]
|
|
assert missing == []
|