Files
Aislo/resources/tester/test_structure_group_items.py
T
eomsangdonandClaude Opus 5.5 15e08b28cb feat(B05·B06·M02): 46-3·46-4 옵션 그룹 보조 컨테이너 — 구조물 하나 · 조합 여럿
- 구조물 기록 · 관 지점 기록에 group_items {그룹 id: summary_item} 칸(검사 parse_group_items)
- 폼: 종류의 그룹마다 상자(제목 = 그룹 이름) · 그 그룹 옵션 칸을 옮겨 담음 · 「집계 항목」 [고르기][해제] · 빈 그룹도 상자
- 정의가 사라진 그룹 연결 = 값 보존 · 경고 한 줄
- 복사본 = 그룹 연결마다 {구조물 id}__{그룹 id} 폴더(관 pipe@측점__그룹)
- 집계표 채움 = 정의된 그룹마다 한 건 더(그 그룹이 고른 열) · 미지정 그룹은 「미지정」 알림에 셈
- B06 관 초안 · B05 시설 보관소 · 병합도 그룹 칸을 이음
- 시험 test_structure_group_items.py · 코드 글자를 보던 시험 셋은 바뀐 자리로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MPcuokNm1ZR2kqgGGDfaJA
2026-10-05 13:39:12 +09:00

98 lines
4.6 KiB
Python

"""옵션 그룹별 집계 항목 `group_items` (PLAN 46-3 · 46-4).
못박는 것
- 칸 모양: `{그룹 id: summary_item}` · null 항목 뺌 · 빈 묶음 = None · 그룹 id · 항목이 틀리면 거절.
- 구조물 기록 · 관 지점 기록 둘 다 칸을 읽고 씀(옛 파일 = 칸 없음).
- [저장] 뒤 복사본: 그룹 연결마다 `{구조물 id}__{그룹 id}` 폴더(본체와 따로).
- 집계표 채움: 정의된 그룹마다 한 건 더(그 그룹이 고른 열) · 미지정 그룹은 「미지정」 알림에 셈 ·
정의가 사라진 그룹 연결은 표에 안 들어감(기록 · 복사본은 남음).
"""
from __future__ import annotations
import json
from pathlib import Path
import pytest
from B05_Profile.B05_Profile_Structures_Schema import StructureInstance
from common_util.common_util_drainage_pipes import parse_pipe_points
from common_util.common_util_summary_item import parse_group_items
from M02_MasterTemplete import M02_Item_Snapshot as snap
from M02_MasterTemplete import M02_MasterTemplete_Store as store
from M02_MasterTemplete import M02_Table_Fill as fill
from M02_MasterTemplete.StructOptions import M02_SO_Groups as groups
from resources.tester.test_structures_summary_snapshot import ( # noqa: F401 — world 고정물
MS,
PIPE,
RV,
_dry,
_items,
_pipe,
_save,
world,
)
def _define(system: Path, monkeypatch, doc: dict) -> None:
monkeypatch.setattr(store, "FOLDER", system)
(system / groups.FILE).write_text(json.dumps(doc, ensure_ascii=False), encoding="utf-8")
def test_칸_모양():
assert parse_group_items(None) is None
assert parse_group_items({}) is None
assert parse_group_items({"g1": None}) is None
assert parse_group_items({"g1": MS, "g2": None}) == {"g1": MS}
for bad in ({"G1": MS}, {"g1": {"layer": "x"}}, ["g1"], {"g_1": MS}):
with pytest.raises(ValueError):
parse_group_items(bad)
def test_구조물_관_기록이_칸을_읽고_씀():
item = StructureInstance(
type_id="x", placement="point", chainage_m=1, group_items={"g1": MS, "g2": None}
)
assert item.group_items == {"g1": MS}
assert StructureInstance(type_id="x", placement="point", chainage_m=1).group_items is None
point = parse_pipe_points([{"chainage_m": 10.0, "source": "user", "group_items": {"g9": RV}}])
assert point[0].group_items == {"g9": RV}
assert point[0].as_dict()["group_items"] == {"g9": RV}
plain = parse_pipe_points([{"chainage_m": 10.0, "source": "user"}])[0]
assert "group_items" not in plain.as_dict()
def test_그룹_연결마다_복사본_폴더가_따로(world):
root = world["root"]
wall = {**_dry(MS), "group_items": {"g1": RV}}
pipe = {**_pipe(PIPE), "group_items": {"gin": MS}}
result = _save(root, [wall], [pipe])
assert result["만듦"] == ["pipe@40.0", "pipe@40.0__gin", "st0", "st0__g1"]
assert snap.FOLDER_PATTERN.match("pipe@40.0__gin")
manifest = json.loads((_items(root) / "st0__g1/manifest.json").read_text("utf-8"))
assert manifest["원본"]["key"] == RV["key"] and manifest["구조물"] == ["st0__g1"]
# 그룹 연결을 풀면 그 복사본만 지움
again = _save(root, [_dry(MS)], [pipe])
assert again["지움"] == ["st0__g1"] and again["만듦"] == []
def test_채움은_정의된_그룹마다_한_건_더(world, monkeypatch):
"""메쌓기 벽 = 본체(돌쌓기 ms) + 그룹 「기슭막이」(rv) — 한 구조물이 두 열에 · 길이 10."""
root, system = world["root"], world["system"]
_define(system, monkeypatch, {"masonry_dry": [{"id": "g1", "이름": "기슭막이", "옵션": []}]})
linked = {**_dry(MS), "group_items": {"g1": RV, "gold": PIPE}} # gold = 정의 없음
bare = {**_dry(None), "chainage_m": 125, "start_m": 120, "end_m": 130}
_save(root, [linked, bare], [])
table = json.loads((system / "table/구조물집계표.json").read_text("utf-8"))
doc = fill.fill_table(root, table)
values = {row["id"]: row["값"] for row in doc["줄"] if not row.get("고정")}
row = {key.split("|")[0]: value for key, value in values["s80.00~90.00"].items()}
assert row["ms"] == 10 # 본체 = 돌쌓기
assert row["rv"] == 10 # 그룹 = 기슭막이(같은 벽 길이)
assert set(values) == {"s80.00~90.00"} # 미지정 벽은 줄도 없음
# 둘째 벽: 본체 미지정 + 그룹 미지정 = 2건 · 정의 없는 gold 는 셈 밖
assert "집계 항목 미지정 2건 — 표에 안 들어감" in doc["알림"]
items = fill.collect_items(root)
assert [i["복사본"] for i in items] == ["st0", "st0__g1", "st1", "st1__g1"]
assert items[1]["그룹"] == "기슭막이" and items[1]["summary_item"] == RV