Files
Aislo/resources/tester/test_m02_hopyo_grid.py
T
eomsangdonandClaude Opus 5.5 510b36eea2 fix(일위대가실무): 330 덧고침 — 후보 다섯에 이름 1순위 자리 · 낱말 안 겹치는 근거 후보 뒤로 · 위 층 격자 읽기 시험
- Basis.merge 같은 점수는 이름 겹침 큰 쪽 · 이름 · 낱말(괄호 글 포함 · 인력 · 기계 · 장비 뺌) 안 겹치는 근거 후보는 근거 맞음(조항 · 직종 · 단위)이 아니면 겹치는 근거 후보 뒤로
- Basis.pick 다섯 안에 이름 1순위 하나 늘 남김 · Match match_line 이 씀
- 시험 basis(제3호표 구조물터파기 다섯 = 굴착(인력/토사) 1위 · 육상토사 안 · 터널굴착 밖 · pick) · match(이름 1순위 자리) · grid(고르기 줄 층 · 주인 그대로 회사 · 시스템 격자 읽기)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
2026-10-15 12:50:31 +09:00

134 lines
5.7 KiB
Python

"""일위대가 실무자료 엑셀꼴 격자(PLAN 329-1 · `M02_Hopyo_Grid` · `GET hopyo-grid/{키}`).
북부청 임도 xls — 병합 11 · 15열 · B20 「제3호표」 · `#,##0` · 호표 68 행 범위 안 겹침 ·
제3호표 [20, 24] · 올리면 격자도 · 200 / 옛 파일 404 · 지우면 격자도 · 역할 · xlsx 값만 ·
master_data 그대로.
"""
import pytest
from M02_MasterTemplete import M02_Hopyo_Excel as hx
from M02_MasterTemplete import M02_Hopyo_Grid as hg
from M02_MasterTemplete import M02_Hopyo_Store as hs
from M02_MasterTemplete import M02_Template_Layers as layers
from resources.tester import test_m02_hopyo_excel as base
from resources.tester.test_m02_hopyo_excel import (
NORTH,
URL,
_post,
_xlsx,
master_hash,
)
client = base.client # 공용 고정물(임시 층)
GRID = "/api/m02/layers/{}/hopyo-grid/{}"
@pytest.fixture(scope="module")
def north() -> dict:
data = NORTH.read_bytes()
return hg.read(NORTH.name, data, hx.read_book(NORTH.name, data))
def _sheet(grid: dict, name: str) -> dict:
return next(s for s in grid["책"]["시트"] if s["이름"] == name)
def test_격자_모양(north):
book = north["책"]
assert (book["종류"], book["판"], book["활성"]) == ("통합문서", 1, "s1")
assert [s["이름"] for s in book["시트"]] == ["일위대가", "단가산출"]
sheet = _sheet(north, "일위대가")
assert len(sheet["병합"]) == 11 and "B1:O2" in sheet["병합"]
assert len(sheet["열"]) == 15 and sheet["열"]["C"]["폭"] == round(7208 / 256, 2)
assert sheet["틀고정"] == {"행": 4}
assert sheet["칸"]["B20"]["값"] == "제3호표"
assert sheet["칸"]["H5"]["값"] == 1040052
styles = book["서식"]
assert styles[0] == {} and any(s.get("형식") == "#,##0" for s in styles)
assert any(s.get("테두리") for s in styles)
assert _sheet(north, "단가산출")["칸"]["B4"]["값"] == "1.유용토운반(무대)[㎥]"
def test_호표_단산_행_범위(north):
rows = [h["행"] for h in north["호표"]]
assert len(rows) == 68
assert all(a[1] < b[0] for a, b in zip(sorted(rows), sorted(rows)[1:], strict=False))
assert next(h for h in north["호표"] if h["번"] == 3) == {
"번": 3,
"이름": "임도표지석",
"행": [20, 24],
}
assert len(north["단산"]) == 95
assert next(b for b in north["단산"] if b["번"] == 93)["행"] == [4229, 4244]
def test_줄_행(north):
book = hx.read_book(NORTH.name, NORTH.read_bytes())
three = next(h for h in book["호표"] if h["번"] == 3)
assert three["행"] == [20, 24] and [x["행"] for x in three["줄"]] == [21, 22, 23, 24]
def test_올리기_격자_200_404_지우기(client):
before = master_hash()
assert _post(client).status_code == 200
res = client.get(GRID.format("personal", "HP-000001"))
assert res.status_code == 200, res.text
got = res.json()
assert got["책"]["열"] == "HP-000001" and len(got["호표"]) == 68
folder = layers.personal_dir(7, 42)
path = folder / hs.DIRNAME / hs.GRID / "HP-000001.json"
assert path.is_file()
assert [r["키"] for r in client.get(URL.format("personal")).json()["줄"]] == ["HP-000001"]
path.unlink() # 옛 파일(324) = 격자 없음
old = client.get(GRID.format("personal", "HP-000001"))
assert old.status_code == 404 and old.json()["detail"] == "격자 없음 — 다시 올리면 보임"
assert _post(client).status_code == 200
assert client.get(GRID.format("personal", "HP-000002")).status_code == 200
assert client.delete(URL.format("personal") + "/HP-000002").status_code == 200
assert not (folder / hs.DIRNAME / hs.GRID / "HP-000002.json").exists()
assert client.get(GRID.format("personal", "HP-000002")).status_code == 404
assert client.get(GRID.format("personal", "../x")).status_code == 404
assert client.get(URL.format("personal") + "/HP-000001/3").status_code == 200 # 길 안 부딪힘
assert master_hash() == before
@pytest.mark.parametrize(
("role", "layer", "owner", "want"),
[
({"role": "USER"}, "personal", None, 200),
({"role": "USER"}, "personal", "7/43", 403),
({"role": "USER"}, "company", None, 200),
({"role": "USER"}, "system", None, 200),
],
)
def test_역할_읽기(client, role, layer, owner, want):
client.who.update({"role": "SYSTEM_ADMIN"})
assert _post(client, layer if want == 200 else "personal").status_code == 200
client.who.update(role)
params = {"owner": owner} if owner else {}
assert client.get(GRID.format(layer, "HP-000001"), params=params).status_code == want
@pytest.mark.parametrize("layer", ["company", "system"])
def test_위_층_격자_읽기(client, layer):
"""아래 층 사용자가 고르기 줄(층 · 주인) 그대로 위 층 파일 격자를 읽음."""
client.who.update({"role": "SYSTEM_ADMIN"})
assert _post(client, layer).status_code == 200
client.who.update({"role": "USER"})
rows = client.get("/api/m02/layers/personal/hopyo-picks").json()["줄"]
row = next(r for r in rows if r["층"] == layer)
params = {"owner": row["주인"]} if row["주인"] else {}
res = client.get(GRID.format(row["층"], row["키"]), params=params)
assert res.status_code == 200 and len(res.json()["호표"]) == 68
def test_xlsx_값만():
data = _xlsx()
grid = hg.read("a.xlsx", data, hx.read_book("a.xlsx", data))
sheet = grid["책"]["시트"][0]
assert sheet["이름"] == "일위대가" and sheet["틀고정"] == {"행": 4}
assert sheet["칸"]["B5"] == {"값": "제 1 호표"} and sheet["칸"]["E6"] == {"값": 0.5}
assert "K6" not in sheet["칸"] # 머리 글(앞 4 줄) 마지막 열 J 까지
assert grid["호표"] == [{"번": 1, "이름": "표지석", "행": [5, 6]}] and grid["단산"] == []