Files
Aislo/resources/tester/test_717_1_logic_lib.py
T
eomsangdonandClaude Opus 5.5 f4be6782a5 feat(751-3): M01 · M02 셈 끝수 = 품셈 1-2-2 버림 — 줄 0.1 원 · 비목 소계 1 원 · 계 = 셋 합 · B09 와 같은 값
- 끝수 한 곳 `master_cut.py`(B09 `rounddown` 재사용) — 엔진 답에 입힘: 줄 비목마다 0.1 원 버림 · 하위 로직 줄 = 하위 끝수 계 × 수량 · 덧줄 = 버린 줄 합으로 다시 셈 · 비목 합 1 원 버림 · 중간 칸도 버린 값
- 쓰는 곳: M01 시험 계산(`check_master.calc`) · 읽는 식(`master_text.lines`) · 옛 조합 미리보기(`master_combo`) · M02 `run_line`(단가산출 · 일위대가 · 펼침) · 별도계상 뺀 기준 · 켜쌓기율 곱 뒤 · 일위대가 반영 · 반영합 · 비율 줄 · 사전조합 안 줄
- 일위대가 반영 TS 짝(`Labor_Calc.ts`) 같은 끝수 · 거울 헬퍼가 상대 경로 .ts 가져옴
- B09 = `run_line(raw=True)` 엔진 날 값(제 단가로 다시 버림 · % 덧줄 율 비 그대로) — 검증_sub3 B09 247 칸 전후 같음
- `master_text` 꼴 셋 = `common_util_money` 로 갈음(줄 금액 `fmt_line_money` · 식 안 금액 = 버린 0.1 원)
- 화면: 상세 줄 금액 · 시험 계산 줄 · 중간 돈 = `formatLineMoney` · 일위대가 반영 칸 0.1 원 · 상세 바닥 · 박스 · 인력재료경비 비목 소계 = 줄 합 1 원 버림
- 테스트1 네 보기 · 서고 목록 = 124,419(옛 124,420 / 124,419.85) · 재료 줄 11,694.6 + 23,425.6 + 1,404.8 = 소계 36,525
- 새 지킴 시험 test_751_3_money_cut
- 옛 날 금액(끝수 없음)을 대조하던 시험 24 파일 고침 — 까닭 = 금액 규칙이 줄 0.1 원 · 소계 1 원 버림으로 바뀜(고정 값 → 새 값 · 줄 합 = 계 → 줄 합 아래 비목마다 1 원 안 · 곱 비 = 끝수 폭 안) · 실무 xlsx 영월 엑셀 같음 22 → 23 · 이어 붙이는 TS 시험(704_3 · 717_2b)에 `rounddown` 같은 식

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 06:16:01 +09:00

95 lines
4.5 KiB
Python

"""717-1 상세 부품 공용 — 길 주입(TS) · M02 `logic-lib` 읽기 · 셈 길(로그인 · 쓰기 없음).
TS = `helper_717_1_logic_api_paths.cjs`(가짜 fetch 주소) · 서버 = 정본 읽기만(파일 지문 같음).
"""
from __future__ import annotations
import hashlib
import json
import subprocess
from pathlib import Path
import pytest
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
from common_util.common_util_auth import verify_session
from M01_MasterData import M01_MasterData_Store as store
from M02_MasterTemplete import M02_Logic_Lib_Read as lib
ROOT = Path(__file__).resolve().parents[2]
HELPER = Path(__file__).parent / "helper_717_1_logic_api_paths.cjs"
KEY = "GF000001" # 경계표시 — 보통인부 한 줄
BASE = "/api/m02/logic-lib"
@pytest.mark.skipif(not (ROOT / "config" / "node_modules").is_dir(), reason="의존성 미설치")
def test_길_주입_없으면_m01_있으면_넘긴_길() -> None:
done = subprocess.run( # noqa: S603 — 고정 실행 파일
["node", str(HELPER)], cwd=str(ROOT), capture_output=True, text=True, encoding="utf-8"
)
assert done.returncode == 0, done.stderr
out = json.loads(done.stdout)
assert out["before"] == out["after"] # 안 넘기면 지금 그대로
assert all(u.startswith("/m01/") for u in out["before"])
shared, admin = out["injected"][:-2], out["injected"][-2:]
assert all(u.startswith(("/m02/logic-lib/", "/m02/calc-x/")) for u in shared)
assert [u for u in shared if u.startswith("/m02/calc-x/")] == [
"/m02/calc-x/calc",
"/m02/calc-x/text",
]
assert admin == ["/m01/groups", "/m01/save"] # 관리자 · 저장 길은 늘 M01
@pytest.fixture(scope="module")
def user() -> TestClient:
"""main.py 와 같은 등록(로그인만) · 일반 사용자."""
app = FastAPI()
app.include_router(lib.router, dependencies=[Depends(verify_session)])
app.dependency_overrides[verify_session] = lambda: {
"user_id": 42, "company_id": 7, "role": "USER", "is_master": False,
} # fmt: skip
return TestClient(app)
def _prints() -> dict[str, str]:
return {p.name: hashlib.sha256(p.read_bytes()).hexdigest() for p in store.FOLDER.glob("*.json")}
def test_일반_계정_읽기(user: TestClient) -> None:
assert user.get(f"{BASE}/logic/auto", params={"key": KEY}).status_code == 200
assert user.get(f"{BASE}/elements", params={"group": "인력", "q": "LB000002"}).json()["items"]
assert user.get(f"{BASE}/pick", params={"kind": "price", "q": "시멘트"}).status_code == 200
assert user.get(f"{BASE}/rows", params={"file": "기계.json", "size": 3}).json()["rows"]
assert user.get(f"{BASE}/materials", params={"sub": "시멘트"}).status_code == 200
flow = user.get(f"{BASE}/logic/flow", params={"key": KEY})
assert flow.status_code == 200 and "flow" in flow.json()
found = user.get(f"{BASE}/elements", params={"group": "소요량", "q": "QF000025"}).json()
file = next(i["file"] for i in found["items"] if i["ref"] == "QF000025")
assert user.get(f"{BASE}/table", params={"file": file, "key": "QF000025"}).json()["table"]
def test_요소_표_밖_파일은_막음(user: TestClient) -> None:
logic_file = store.logics("", "", "", None, "")[0]["file"]
assert user.get(f"{BASE}/rows", params={"file": logic_file}).status_code == 403
assert user.get(f"{BASE}/table", params={"file": "기계.json", "key": "x"}).status_code == 403
assert user.get(f"{BASE}/rows", params={"file": "재료_../x.json"}).status_code == 404
def test_저장_안_한_줄_셈_쓰기_없음(user: TestClient) -> None:
before = _prints()
saved = user.post(f"{BASE}/calc", json={"key": KEY, "inputs": {}}).json()
row = store.logic(KEY)["logic"]
same = user.post(f"{BASE}/calc", json={"key": KEY, "inputs": {}, "row": row}).json()
line = row["호표"][0]
row2 = {**row, "호표": [{**line, "수량": f"({line['수량']}) * 2"}, *row["호표"][1:]]}
double = user.post(f"{BASE}/calc", json={"key": KEY, "inputs": {}, "row": row2}).json()
text = user.post(f"{BASE}/text", json={"key": KEY, "inputs": {}, "row": row2}).json()
assert saved["ok"] and same["sums"] == saved["sums"]
# 751-3 — 줄 0.1 원 · 소계 1 원 버림이라 두 배는 1 원 안
assert double["sums"]["노무비"] == pytest.approx(saved["sums"]["노무비"] * 2, abs=2)
assert text["ok"] and text["계"] == pytest.approx(double["sums"]["계"], rel=1e-6)
assert store.logic(KEY)["logic"]["호표"][0]["수량"] == line["수량"] # 정본 그대로
assert _prints() == before