fix(534-3): E05 길 저장 · 갱신 · 초기화가 옛 모듈을 부름 · 시트 서명 수 꼴 맞춤 · 화면 높이

- 길: asyncio.to_thread(build.save · refresh · reset) → store(나눈 storage 모듈) — PUT 500 고침
- 시트 서명: 수를 float 로 맞춤 — 화면(JS)을 거친 10.0 → 10 을 사용자 고침으로 잘못 알리던 덮임 알림 고침
- 화면: 본문 칸이 min-height 뿐이라 내장 엑셀 격자 높이 0 — 본문 높이 calc(100dvh - 머리)
- 그림: 우기 · 지진 임계면 점선(건기와 겹쳐도 보임) · 해석 방법 글 짧게(Bishop)
- 시험: 길(TestClient — 판 409 · 저장 · 갱신 · 그림 · xlsx · 초기화) · 서명 화면 왕복 같음 — 7 통과

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 20:58:02 +09:00
co-authored by Claude Opus 5.5
parent e7afaa6664
commit 340e90d6cc
5 changed files with 74 additions and 11 deletions
+52 -3
View File
@@ -1,7 +1,8 @@
"""534-3(빌더 · storage) — E05 안정성평가 보고서 `E05_StabReport_Build` · `_Store`.
"""534-3(빌더 · storage · 길) — E05 안정성평가 보고서 `E05_StabReport_Build` · `_Store` · `_Router`.
가짜 E 프로젝트(2D 요약 · 측점별 저장본 · 대표 단면 · 지반 조건 · 3D 저장본 하나 · 복사본 읽기는 바꿔 끼움)로
측점 수 = 줄 수 · N.G 수 · 그림 파일 수 · 갱신 뒤 사용자 몫 불변 · 덮임 목록 · 초기화 · xlsx 되읽기 · PDF 쪽 수.
가짜 E 프로젝트(2D 요약 · 측점별 저장본 · 대표 단면 · 지반 조건 · 3D 저장본 하나 ·
복사본 읽기는 바꿔 끼움)로 측점 수 = 줄 수 · N.G 수 · 그림 파일 수 · 갱신 뒤 사용자 몫 불변 ·
덮임 목록 · 초기화 · 판 409 · xlsx 되읽기 · PDF 쪽 수.
"""
import io
@@ -294,3 +295,51 @@ def test_단면_그림_SVG():
)
assert svg.startswith("<svg") and "건기 임계면 Fs 1.30" in svg and "노폭 4.00 m" in svg
assert "H 4.00 m" in svg and svg.count("<polyline") >= 4
def test_길_저장_409_갱신_초기화_내보내기(project, monkeypatch):
from fastapi import FastAPI
from fastapi.testclient import TestClient
from common_util.common_util_auth import verify_session
from E05_StabReport import E05_StabReport_Router as router_mod
async def fake_project(_pid):
return project, 3
monkeypatch.setattr(router_mod, "_project", fake_project)
app = FastAPI()
app.include_router(router_mod.router)
app.dependency_overrides[verify_session] = lambda: {"role": "USER", "company_id": 3}
client = TestClient(app)
url = "/api/projects/3d3776a1-2973-4385-8dcc-fdc6e49a900e/stab/report"
try:
got = client.get(url).json()
except PrintError as error:
pytest.skip(f"브라우저 없음 — {error}")
assert got["editable"] and got["stale"] is False and len(got["book"]["시트"]) == 6
book = got["book"]
_sheets(book)["표지"]["칸"]["C10"] = {"값": "산림청", "서식": 5}
assert client.put(url, json={"rev": "옛판", "book": book}).status_code == 409
saved = client.put(url, json={"rev": got["rev"], "book": book}).json()
assert saved["rev"] != got["rev"]
assert client.post(f"{url}/refresh", json={"rev": got["rev"]}).status_code == 409
out = client.post(f"{url}/refresh", json={"rev": saved["rev"]}).json()
assert out["overwritten"] == [] and _sheets(out["book"])["표지"]["칸"]["C10"]["값"] == "산림청"
fig = client.get(f"{url}/fig", params={"key": build.fig_key("grid:3")})
assert fig.status_code == 200 and fig.content[:4] == b"\x89PNG"
assert client.get(f"{url}/fig", params={"key": "../x"}).status_code == 400
x = client.post(f"{url}/xlsx", json={"book": out["book"]})
assert x.status_code == 200 and load_workbook(io.BytesIO(x.content)).sheetnames[0] == "표지"
back = client.post(f"{url}/reset").json()
assert "값" not in _sheets(back["book"])["표지"]["칸"].get("C10", {})
def test_서명_화면_왕복_같음(project):
"""JS 를 거친 책(10.0 → 10)도 같은 서명 — 안 고친 시트를 덮임으로 알리지 않음."""
book = build.form()
build.build_program(book, build.gather(project))
s3 = _sheets(book)["입력조건"]
assert s3["칸"]["B22"]["값"] == 10.0
trip = json.loads(json.dumps(s3).replace("10.0", "10"))
assert trip["칸"]["B22"]["값"] == 10 and build.sheet_sign(trip) == build.sheet_sign(s3)