Files
Aislo/resources/tester/test_m02_structure_combo.py
T
eomsangdonandClaude Opus 5.5 6c0014a430 feat(M02): 구조물집계표조합 표 — 구조물 열마다 한 줄 · 키 SS · 집계표 [저장] 때 서버가 맞춤
- resources/master_template/구조물집계표조합.json (그룹 · 판 · 비고 · 다음 · 줄) · 지금 열 51개로 처음 만듦(SS000001~SS000051)
- 줄 칸: 키 · 열 · 종류 · 분류1~3 · 단위 · 일위대가 · 도번 · 면적번 · 재료번 · 바인딩 · 펼침 · 꼴=수 열만
- 새 열 = 새 SS 키 · 지운 열 = 줄 지움(키 다시 안 씀) · 고친 열 = 칸 갱신 · 새 프로젝트 복사에도 실림
- GET /api/m02/structure-combos · Api_Fetch fetchStructureCombos()
- 시험: 견본 표로 키 유지 · 새 열 · 지운 열 · 글 열 제외 · 키대장 머리글과 안 겹침 · 프로젝트 복사

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EUypcnp5d1gU2aeKh9F2H7
2026-09-28 16:12:12 +09:00

110 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""구조물집계표조합 — 서버가 집계표 [저장] 때 맞추는 장부(키 SS · 열마다 한 줄).
견본 표(`write_sample_table`)로만 봄 — 실제 마스터 양식은 안 읽음.
"""
import json
from pathlib import Path
import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from M02_MasterTemplete import M02_MasterTemplete_Store as store
from M02_MasterTemplete import M02_Template_Layers as layers
from M02_MasterTemplete.M02_MasterTemplete_Router import router
from resources.tester.test_m02_structure import write_sample_table
ROOT = Path(__file__).resolve().parents[2]
TABLE = "/api/m02/templates/table/구조물집계표"
@pytest.fixture()
def client(tmp_path, monkeypatch):
write_sample_table(tmp_path)
monkeypatch.setattr(store, "FOLDER", tmp_path)
app = FastAPI()
app.include_router(router)
return TestClient(app)
def _save_table(client, change) -> None:
got = client.get(TABLE).json()
change(got["문서"])
assert client.put(TABLE, json={"판": got["판"], "문서": got["문서"]}).status_code == 200
def _keys(client) -> dict[str, str]:
return {row["열"]: row["키"] for row in client.get("/api/m02/structure-combos").json()["줄"]}
def test_처음_한_번_만듦_글_열_빼고_칸은_집계표_그대로(client, tmp_path):
assert not (tmp_path / store.COMBO_FILE).exists()
doc = client.get("/api/m02/structure-combos").json()
assert (doc["그룹"], doc["다음"]) == ("구조물집계표조합", 14)
rows = doc["줄"]
assert [r["열"] for r in rows][:3] == ["rv", "c1", "pv_b"]
assert {"no", "sta", "memo"}.isdisjoint(r["열"] for r in rows) # 글 열 빼기
assert (rows[0]["키"], rows[-1]["키"]) == ("SS000001", "SS000013")
assert rows[-1]["열"] == "h_rip_m"
fb = next(r for r in rows if r["열"] == "fb")
assert (fb["종류"], fb["분류1"], fb["분류2"], fb["분류3"]) == (
"세월교",
"(관경 × 련수마다)",
None,
None,
)
assert (tmp_path / store.COMBO_FILE).is_file()
def test_집계표_저장_때_새_열_지운_열_고친_열을_맞춤_키_유지(client):
before = _keys(client)
def change(table):
cols = table["열"]
cols[:] = [c for c in cols if c["id"] != "h_rip_m"] # 맨 끝 키 SS000013 열 지움
rv = next(c for c in cols if c["id"] == "rv")
rv["머리"] = ["돌기슭막이", "메쌓기", "1.2m", "기초유"]
rv.update(단위="m", 일위대가="UA000004", 펼침=True, 바인딩={"종류": "revetment"})
cols.insert(3, {"id": "new1", "머리": ["옹벽", None, None, None], "단위": "m", "꼴": "수"})
_save_table(client, change)
doc = client.get("/api/m02/structure-combos").json()
rows = {r["열"]: r for r in doc["줄"]}
assert "h_rip_m" not in rows
assert rows["new1"]["키"] == "SS000014" # 지운 열의 SS000013 은 다시 안 씀
assert [r["열"] for r in doc["줄"]][:4] == ["rv", "new1", "c1", "pv_b"] # 집계표 차례
assert all(rows[c]["키"] == k for c, k in before.items() if c != "h_rip_m")
rv = rows["rv"]
assert (rv["분류1"], rv["분류3"], rv["단위"], rv["일위대가"]) == (
"메쌓기",
"기초유",
"m",
"UA000004",
)
assert (rv["바인딩"], rv["펼침"]) == ({"종류": "revetment"}, True)
# 번호는 세 파일과 같음 — 새 열도 [저장] 한 번에 SD · SA · SM 이 섬
numbers = client.get("/api/m02/structures/numbers").json()
assert {k: rows["new1"][k] for k in ("도번", "면적번", "재료번")} == numbers["new1"]
assert rows["new1"]["도번"].startswith("SD")
# 또 저장해도(바뀐 것 없음) 키 · 다음 그대로
_save_table(client, lambda table: None)
again = client.get("/api/m02/structure-combos").json()
assert (again["다음"], again["줄"]) == (15, doc["줄"])
def test_SS_머리글은_키대장과_안_겹침():
ledger = json.loads((ROOT / "resources/master_data/_키대장.json").read_text("utf-8"))
assert "SS" not in ledger["다음"]
assert store._COMBO_HEAD == "SS"
def test_새_프로젝트_복사에_실림(client, tmp_path, monkeypatch):
client.get("/api/m02/structure-combos")
monkeypatch.setattr(layers, "SYSTEM_ROOT", tmp_path)
copied = layers.seed_project(tmp_path / "project")
assert "구조물집계표조합" in copied["작업본"] and "구조물집계표조합" in copied["초기"]
target = layers.project_dir(tmp_path / "project") / store.COMBO_FILE
assert json.loads(target.read_bytes())["줄"][0]["키"] == "SS000001"