- master_formula.inputs_of · FLOW_INPUTS · OLD_FIELDS · mf.run 이 흐름 줄이면 스스로 서버 갈래를 깖(스크립트 · 시험도) - check_master 틀 검사 · 시험입력 · 로직(…) 입력 검사 · master_auto 자동값 · 프로젝트 빈 입력 · 연결 · 다시 적용 값이 흐름 입력으로 - 프로젝트 단가 묶음(collect)이 흐름의 요소 · 표 · 다른 로직 · 기계 시간당 경비 로직을 모음 - 옛 엔진 갈래 결과 = 옛 꼴(돈 출력 줄 · 값들 · 알림) · 조합 · 프로젝트에서 안 준 입력은 빈 입력 알림(예시값 아님) - /text 흐름 로직 = 출력 상자 줄 · GET /logic 은 보기용으로 설계 때 정할 것을 입력 꼴로 얹음(파일은 그대로) - 찾을 값이 빈 조건 찾기는 그 값만 비움(옛 셈처럼) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmELpdXFDRZHhfbGuRhSmL
66 lines
2.9 KiB
Python
66 lines
2.9 KiB
Python
# ruff: noqa: E501
|
|
"""흐름 로직(옛 식 칸 지운 줄)이 조합 · 프로젝트 길에서도 옛 셈과 같음(PLAN 36 · 사용자 결정 · 사본 폴더).
|
|
|
|
못박는 것 — 옛 로직 하나를 변환해 흐름으로 저장(옛 칸 지움)한 뒤
|
|
- 옛 엔진 `mf.run`(조합 · 프로젝트 길) 합계 = 바꾸기 전 옛 셈 합계
|
|
- 프로젝트 단가 묶음(`M02_Item_Prices.collect`)만으로 셈 = 같은 합계(흐름이 쓰는 요소 · 표 · 다른 로직이 담김)
|
|
- 입력 목록(`mf.inputs_of`) = 옛 입력 이름 · 안 준 입력은 「빈 입력」 알림(예시값으로 안 넘어감)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import shutil
|
|
from decimal import Decimal
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from M01_MasterData import M01_MasterData_Store as store
|
|
from M01_MasterData import M01_MasterData_Store_Flow as sflow
|
|
from M02_MasterTemplete import M02_Item_Prices as prices
|
|
from M02_MasterTemplete.DataFlow import M02_DF_Convert as cv
|
|
|
|
REAL = store.FOLDER
|
|
KEYS = ("GF000185", "GF000219") # 레미콘 검색어 · 펌프차 기계 · 인력 / 표 찾기 · 인력
|
|
|
|
|
|
@pytest.fixture
|
|
def folder(tmp_path: Path, monkeypatch) -> Path:
|
|
for path in REAL.glob("*.json"):
|
|
shutil.copy(path, tmp_path / path.name)
|
|
monkeypatch.setattr(store, "FOLDER", tmp_path)
|
|
return tmp_path
|
|
|
|
|
|
def _sums(got: dict) -> dict:
|
|
return {k: round(Decimal(str(got[k])), 6) for k in ("노무비", "재료비", "경비", "계")}
|
|
|
|
|
|
@pytest.mark.parametrize("key", KEYS)
|
|
def test_흐름으로_바꾼_로직_조합_프로젝트_길도_옛_셈과_같음(folder: Path, key: str) -> None:
|
|
mf = store.cm.mf
|
|
got = store.logic(key)
|
|
old_row = got["logic"]
|
|
names = [s["이름"] for s in old_row.get("입력") or []]
|
|
given = {k: v for k, v in store.cm.시험입력(old_row).items()}
|
|
before = _sums(mf.run(mf.Master(store.cm.load(folder=folder)), key, dict(given)))
|
|
flow = cv.convert(old_row, {"key": key, "master": store.loaded()[1]})["flow"]
|
|
flow.pop("key", None)
|
|
part = {
|
|
"file": got["file"],
|
|
"version": got["version"],
|
|
"changes": [{"op": "edit", "key": key, "row": {**old_row, "흐름": flow}}],
|
|
}
|
|
sflow.save([store._dec(part)])
|
|
row = store.logic(key)["logic"]
|
|
assert not set(row) & set(mf.OLD_FIELDS)
|
|
assert [s["이름"] for s in mf.inputs_of(row)] == names
|
|
assert _sums(mf.run(mf.Master(store.cm.load(folder=folder)), key, dict(given))) == before
|
|
bundle = prices.collect([key])
|
|
assert "_빠진" not in bundle, bundle.get("_빠진")
|
|
snapshot = prices.load_prices(prices.to_json(bundle))
|
|
assert _sums(mf.run(snapshot, key, dict(given))) == before # 단가 묶음만으로 같은 합계
|
|
if key == "GF000185": # 빈 입력 — 재료 찾기 자리(표 찾기 빈 조건은 sub7 lookup 몫)
|
|
blank = mf.run(snapshot, key, {k: v for k, v in given.items() if k != names[0]})
|
|
assert any(f"「{names[0]}」 빈 입력" in n for n in blank.get("알림") or [])
|