Files
Aislo/resources/tester/test_m02_hopyo_grid.py
eomsangdonandClaude Opus 5.5 c5067aa2b6 feat(809-1a): 일위대가 불러오기 = 경쟁사 로직 인정 · 요소만 연결 · [수정] 모달 = 일위대가 컨테이너 부품 · 기초 판정 걷음
- [수정] 모달 = Labor_Table(읽기 · 덧칸 표지 · 엑셀 금액) · 줄 = 로직(단가산출 · 일위대가) / 요소(연결됨 · 후보 · 못 이음) · 단가산출 줄 = 가져온 식 SK 수식 탭 모달(Labor_SkEdit) · 서버 hopyo-view(M02_Hopyo_View)
- 엑셀 보기 목록 · 칠 = 줄 표지(View.listing) · 단가산출 탭 = 블록 목록 + [가져온 식으로 열기] · [내 단가산출로]
- 걷음(요구 703): 판정 체계 785(Judge · Solve · Bind · San_Basis 다섯 · Make.Move · Row 1차 판정 · 화면 Check · CheckRows · Rows · Block · JudgeApi · Picks · Judge.css) · [우리 기초로 바꾸기](to-base) · 근거 기초 제안 · Clause 기초 판정
- 시험 지움: 642_2(Bind · Solve) · 642_3(Row 1차 판정) · 642_5(옮기기 Move) · 642_6(판정 화면) · 786_2(옛 [수정] 모달) · 793_3a(근거 → 기초 제안) — 모두 걷은 기초 판정 길 몫
- 시험 고침: 642_1 · 794_2a2 · 794_2b(근거 제안 부분만 뺌) · 793_2 · 793_3b(기초 바꾸기 기대 → 없음) · 627 · 779_2 · 785_4 · 807_1 · m02_hopyo_excel · grid · stmate(judge 길 → view 길)
- 새 시험 test_809_1_import_labor(기초 길 0 · 표지 1,350 줄 · 가져온 식 SK · 모달 = Labor_Table · 금액 = 엑셀)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 19:17:58 +09:00

160 lines
6.9 KiB
Python

"""일위대가 실무자료 엑셀꼴 격자(PLAN 329-1 · `M02_Hopyo_Grid` · `GET hopyo-grid/{키}`).
북부청 임도 xls — 병합 11 · 15열 · B20 「제3호표」 · `#,##0` · 호표 68 행 범위 안 겹침 ·
제3호표 [20, 24] · 올리면 격자도 · 200 / 옛 파일 404 · 지우면 격자도 · 역할 · xlsx 값만 ·
STmate 격자(일위대가표 · 단가산출근거 · 숨은 칸 글 뺌 · 338) ·
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 client.delete(URL.format("personal") + "/HP-000001").status_code == 200
assert _post(client).status_code == 200 # 718-1 — 같은 엑셀은 지운 뒤 새 번
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
gone = client.get(URL.format("personal") + "-view/HP-000001/3") # 718-1 지운 뒤 = 없음
assert gone.status_code == 404 and "없는 실무자료" in gone.json()["detail"]
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(URL.format(layer)).json()[
"줄"
] # 위 층 목록(옛 「실무 호표」 고르기 줄 갈음 · 785-7)
res = client.get(GRID.format(layer, rows[0]["키"]))
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["단산"] == []
def test_STmate_격자():
from resources.tester.test_m02_hopyo_stmate import _path
path = _path("영월")
data = path.read_bytes()
parsed = hx.read_book(path.name, data)
grid = hg.read(path.name, data, parsed)
assert [s["이름"] for s in grid["책"]["시트"]] == [
"일위대가표",
"단가산출근거목록표",
"단가산출근거",
]
cells = _sheet(grid, "일위대가표")["칸"]
one = grid["호표"][0]
assert one == {"번": 1, "이름": "녹생토(종자배합)", "행": [5, 10]}
assert cells[f"A{one['행'][0]}"]["값"].strip().startswith("제")
assert cells["A10"]["값"] == "보통인부"
calc = _sheet(grid, "단가산출근거")["칸"]
block = next(b for b in grid["단산"] if b["번"] == 2)
assert calc[f"B{block['행'][0] + 1}"]["값"].startswith("구조물터파기(인력)")
assert not any(str(c.get("값")).startswith("_x000") for c in {**cells, **calc}.values())