Files
Aislo/resources/tester/test_stmate_file_payload.py
T
eomsangdonandClaude Opus 5.5 e987602f24 feat(stmate-test): 무손실 저장 — 손대지 않은 저장 = 원본 STC 바이트 동일 · 고친 칸만 다시 씀
- DBF 고친 칸만 다시 씀(한글 깨짐 · 2칸을 1칸으로 · 3칸 87.745% 덮어쓰기 없앰) · 단가 → 내역 행 → 소계 → 직공비 다시 셈 · 행 끼우기·지우기
- SIxMemo(COSTN.SMT · PRJLST.SMT) 블록 구조 유지 · 넘치면 뒤에 붙이고 가리키는 값 갱신
- STC 다시 묶기(같은 파일은 원본 바이트) · 검사 · 자동 백업·복원 · 새 공사 · 복사등록(차수 인계) · 해당분 압축
- BDQTY 역변환(쓰기 준비) · 모듈 dbf_rw · dbf_memo · dbf_crypt · stc_archive · stc_save · stc_read · stc_project · api_file · scr_file
- 지킴 시험 test_stmate_file_roundtrip · file_project · file_payload — 실무 STC 7건 왕복

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 18:42:04 +09:00

60 lines
2.4 KiB
Python

"""STMATE 재현 앱 화면 저장 요청(view_prj_boq.js buildSavePayload) — 고치지 않으면 저장해도 한 칸도 안 바뀜.
옛 요청은 2차 칸을 1차로, 3차(계약) 칸을 고정 낙찰율로 덮었음 — 이제 바뀐 칸만 나감을 실무 STC 7건으로 확인.
"""
import json
import subprocess
import sys
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "tools/stmate-test"))
import server # noqa: E402
from stc_save import _leaf, apply_save # noqa: E402
HELPER = Path(__file__).with_name("helper_stmate_file_payload.cjs")
STCS = sorted((ROOT / "resources/knowledge/original/실무문서").rglob("*.STC"))
IDS = [p.stem[:16] for p in STCS]
def _payload(load, edit=None):
raw = json.dumps({"load": load, "edit": edit}, default=str).encode()
return json.loads(subprocess.check_output(["node", str(HELPER)], input=raw))
@pytest.mark.parametrize("stc", STCS, ids=IDS)
def test_screen_payload_without_edits_changes_nothing(stc):
load = server.api_load(server.LoadReq(source_path=str(stc)))
p = _payload(load)
by = {r["_recno"]: r for r in load["boq_rows"]}
for u in p["boq_updates"]: # 2·3차 단가는 불러온 값 그대로(1차 복사·고정 낙찰율 아님)
for k in ("MAMT2", "LAMT2", "MAMT3", "LAMT3", "SAMT3"):
if k in u and u.get("_recno") in by:
assert float(u[k] or 0) == float(by[u["_recno"]][k] or 0)
files = server.read_project_files(str(stc))
out, log = apply_save(files, p)
assert log == [] and all(out[k] is files[k] for k in files)
@pytest.mark.parametrize("stc", STCS, ids=IDS)
def test_screen_qty_edit_touches_slot1_only(stc):
load = server.api_load(server.LoadReq(source_path=str(stc)))
leaf = next(
r
for r in load["boq_rows"]
if _leaf(r["BDCODE1"].strip())
and float(r["TAMT1"] or 0) > 0
and not r["UNIT1"].strip().endswith("%")
)
q = float(leaf["QTY1"]) + 3
p = _payload(load, {"recno": leaf["_recno"], "qty": q})
files = server.read_project_files(str(stc))
_out, log = apply_save(files, p)
fields = {(x["table"], x["field"]) for x in log}
assert ("BOQ11.DBF", "QTY1") in fields
assert all(f[1][-1] == "1" or f[1].startswith("COSTW") for f in fields), fields
assert {x["recno"] for x in log if x["field"] == "QTY1"} == {leaf["_recno"]}