Merge remote-tracking branch 'origin/dev' into main_desktop_1
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,93 @@
|
||||
"""M02 구조물 도면(structure) — 새로 · 도번 자동 · 409 · 저장 · 지운 뒤 번호 · 프로젝트 복사."""
|
||||
|
||||
import shutil
|
||||
|
||||
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
|
||||
|
||||
REAL = store.FOLDER
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def client(tmp_path, monkeypatch):
|
||||
for kind in store.KINDS:
|
||||
(tmp_path / kind).mkdir()
|
||||
shutil.copy(REAL / "table/구조물집계표.json", tmp_path / "table")
|
||||
shutil.copy(REAL / "drawing/00_template_A1.json", tmp_path / "drawing")
|
||||
monkeypatch.setattr(store, "FOLDER", tmp_path)
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
return TestClient(app)
|
||||
|
||||
|
||||
def test_새로_도번_자동_409_없는_열(client):
|
||||
made = client.post("/api/m02/structures/pp_len")
|
||||
assert made.status_code == 200
|
||||
doc = made.json()["문서"]
|
||||
assert (doc["양식"], doc["종류"], doc["열"], doc["도번"]) == (
|
||||
"구조물도면",
|
||||
"structure",
|
||||
"pp_len",
|
||||
"구-01",
|
||||
)
|
||||
assert (
|
||||
doc["도면"]["entities"] and doc["도면"] == store.read("drawing", "00_template_A1")["문서"]
|
||||
)
|
||||
basis = doc["산출근거"]
|
||||
assert [c["머리"][0] for c in basis["열"]] == ["공종", "규격", "산출 내역", "단위", "수량(m당)"]
|
||||
assert basis["줄"] == [] and basis["종류"] == "표"
|
||||
|
||||
assert client.post("/api/m02/structures/rv").json()["문서"]["도번"] == "구-02"
|
||||
assert client.post("/api/m02/structures/pp_len").status_code == 409
|
||||
assert client.post("/api/m02/structures/없는열").status_code == 404
|
||||
assert client.get("/api/m02/structures/numbers").json() == {"pp_len": "구-01", "rv": "구-02"}
|
||||
rows = client.get("/api/m02/templates").json()
|
||||
assert {(r["종류"], r["이름"]) for r in rows if r["종류"] == "structure"} == {
|
||||
("structure", "pp_len"),
|
||||
("structure", "rv"),
|
||||
}
|
||||
|
||||
|
||||
def test_저장_뼈대_거름(client):
|
||||
got = client.post("/api/m02/structures/pp_len").json()
|
||||
doc = got["문서"]
|
||||
doc["산출근거"]["줄"] = [{"id": "r1", "값": {"work": "관 부설"}}]
|
||||
saved = client.put("/api/m02/templates/structure/pp_len", json={"판": got["판"], "문서": doc})
|
||||
assert saved.status_code == 200 and saved.json()["판"] != got["판"]
|
||||
for bad in ({}, {**doc, "도면": {}}, {**doc, "산출근거": {"열": "x"}}, {**doc, "도면": []}):
|
||||
r = client.put(
|
||||
"/api/m02/templates/structure/pp_len", json={"판": saved.json()["판"], "문서": bad}
|
||||
)
|
||||
assert r.status_code == 400
|
||||
assert client.get("/api/m02/templates/structure/pp_len").json()["문서"] == doc
|
||||
|
||||
|
||||
def test_지워도_번호를_당기지_않음(client):
|
||||
for column in ("pp_len", "rv", "ms"):
|
||||
client.post(f"/api/m02/structures/{column}")
|
||||
assert client.delete("/api/m02/templates/structure/pp_len").status_code == 200
|
||||
assert client.get("/api/m02/structures/numbers").json() == {"rv": "구-02", "ms": "구-03"}
|
||||
assert client.post("/api/m02/structures/fb").json()["문서"]["도번"] == "구-04"
|
||||
# 가장 큰 번호를 지우면 그 번호부터 다시(있는 것 중 가장 큰 번호 + 1)
|
||||
client.delete("/api/m02/templates/structure/fb")
|
||||
assert client.post("/api/m02/structures/ec").json()["문서"]["도번"] == "구-04"
|
||||
|
||||
|
||||
def test_프로젝트_복사와_층_저장에_실림(client, tmp_path, monkeypatch):
|
||||
doc = client.post("/api/m02/structures/pp_len").json()["문서"]
|
||||
monkeypatch.setattr(layers, "SYSTEM_ROOT", tmp_path)
|
||||
project = tmp_path / "project"
|
||||
copied = layers.seed_project(project)
|
||||
assert "structure/pp_len" in copied["작업본"] and "structure/pp_len" in copied["초기"]
|
||||
work = layers.project_dir(project)
|
||||
assert layers.read_template(work, "structure", "pp_len")["문서"] == doc
|
||||
assert layers.read_template(layers.initial_dir(project), "structure", "pp_len")["문서"] == doc
|
||||
assert ("structure", "pp_len") in {(r["종류"], r["이름"]) for r in layers.list_templates(work)}
|
||||
layers.check_skeleton("structure", doc)
|
||||
with pytest.raises(ValueError):
|
||||
layers.check_skeleton("structure", {**doc, "산출근거": None})
|
||||
@@ -0,0 +1,64 @@
|
||||
"""표 도면 줄 · 칸 고르기 신호 — `ui_template_sheet_ops.ts` 를 Node 로 바로 돌려 봄.
|
||||
|
||||
도면 줄 `s:drawing` = master 만 · 일위대가 줄 바로 아래(키보드 차례) · project 에는 없음.
|
||||
`selectionOf` = 격자가 `onSelect` 로 넘기는 모양({row, col, colId} · 모르는 열은 col -1 · colId null).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
OPS = ROOT / "ui_template" / "sheet" / "ui_template_sheet_ops.ts"
|
||||
|
||||
pytestmark = pytest.mark.skipif(shutil.which("node") is None, reason="node 가 없음")
|
||||
|
||||
SCRIPT = """
|
||||
const { navRows, selectionOf } = await import(process.argv[1]);
|
||||
const doc = JSON.parse(process.argv[2]);
|
||||
console.log(JSON.stringify({
|
||||
master: navRows(doc, "master"),
|
||||
project: navRows(doc, "project"),
|
||||
pick: [selectionOf(doc, "s:drawing", "c2"), selectionOf(doc, "d:r1", "c1"), selectionOf(doc, "s:unit", "zz")],
|
||||
}));
|
||||
"""
|
||||
|
||||
DOC = {
|
||||
"양식": "시험",
|
||||
"종류": "표",
|
||||
"판": 1,
|
||||
"열": [{"id": "c1", "머리": ["가"]}, {"id": "c2", "머리": ["나"]}],
|
||||
"줄": [{"id": "r1", "값": {}}],
|
||||
"합계줄": [{"id": "t1", "이름": "계", "식": "SUM"}],
|
||||
}
|
||||
|
||||
|
||||
def _run() -> dict:
|
||||
result = subprocess.run(
|
||||
["node", "--experimental-strip-types", "--no-warnings", "--input-type=module", "-e",
|
||||
SCRIPT, OPS.as_uri(), json.dumps(DOC, ensure_ascii=False)],
|
||||
capture_output=True, text=True, encoding="utf-8", timeout=60,
|
||||
) # fmt: skip
|
||||
assert result.returncode == 0, result.stderr
|
||||
return json.loads(result.stdout)
|
||||
|
||||
|
||||
def test_drawing_row_under_price_master_only():
|
||||
got = _run()
|
||||
assert got["master"] == [
|
||||
"s:unit", "s:formula", "s:desc", "s:price", "s:drawing", "d:r1", "t:t1",
|
||||
] # fmt: skip
|
||||
assert got["project"] == ["s:unit", "d:r1", "t:t1"]
|
||||
|
||||
|
||||
def test_selection_shape():
|
||||
assert _run()["pick"] == [
|
||||
{"row": "s:drawing", "col": 1, "colId": "c2"},
|
||||
{"row": "d:r1", "col": 0, "colId": "c1"},
|
||||
{"row": "s:unit", "col": -1, "colId": None},
|
||||
]
|
||||
Reference in New Issue
Block a user