Files
Aislo/resources/tester/test_m02_df_values_old.py
T
eomsangdonandClaude Opus 5.5 3f71305ddb fix(M02): 흐름 셈 = 옛 셈 — 표 「·범위규칙」 줄 경계 말 · 검색어 조건 찾기 · 재료가 로직 입력 읽음 · 빈 단가 알림 · 고르기 글 값 그대로(PLAN 36-2 대조 49 → 8)
- main(sub7 a774b4e97 Model 덧) 받아 합침 · Compute 재료 조건 찾기는 sub7 의 틀 채우기 + 빈 단가 알림
- 남은 8: 표에 여럿 맞음 5(옛 find 의 값 칸 있는 줄만 거름 — lookup) · 빈 값이 든 식 3(옛 = 그 줄 비움 · 흐름 = 빈 칸 0)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KmELpdXFDRZHhfbGuRhSmL
2026-10-02 01:04:03 +09:00

106 lines
4.8 KiB
Python

# ruff: noqa: E501
"""흐름 셈 값 찾기 = 옛 셈과 같은 뜻(PLAN 36-2 변환 대조 · sub4) — 마스터 읽기만.
못박는 것
- 표 블록 끝 칸 「·범위규칙」 = 줄마다 경계 말(범위규칙 첫 낱말 · 「이하 포함」 이면 맨 윗줄 이상·이하)
- 재료 값이 로직 입력(자재지역 · 계약종별)을 읽음 · 빈 단가 = 알림(blank) — 셈은 계속
- 재료 조건 찾기 field 검색어 = 옛 검색어 찾기(틀의 {자리} 를 채운 글)
- 고르기 글 값(「080」)은 글 그대로 — 수로 바꾸면 고르기 밖
"""
from __future__ import annotations
import json
from decimal import Decimal
from M01_MasterData import M01_MasterData_Store as store
from M01_MasterData import M01_MasterData_Store_Flow as sflow
from M02_MasterTemplete.DataFlow import M02_DF_Compute as dc
from M02_MasterTemplete.DataFlow import M02_DF_Values as dv
def _old(key: str) -> dict:
row = store.logic(key)["logic"]
given = {k: str(v) for k, v in store.cm.시험입력(row).items()}
return {"given": given, "got": store.calc(key, given), "row": row}
def test_표_범위규칙_칸() -> None:
tables = [
t
for d in store.loaded()[0].values()
if d.get("그룹") in store.cm.mf.TABLE_GROUPS
for t in d.get("표") or []
]
ranged = [t for t in tables if "범위" in (t.get("조건") or {}).values()]
for t in ranged[:40]:
got = dv._table(str(t["키"]))
head, rows = got["rows"][0], got["rows"][1:]
assert head[-1] == dv.RANGE_RULE
first = str(t.get("범위규칙") or "초과·이하").split(" · ")[0].split(" (")[0]
assert {r[-1] for r in rows} <= {first, "이상·이하"}, t["키"]
closed = [
t
for t in ranged
if str(t.get("범위규칙") or "").startswith("이상·미만")
and "이하 포함" in str(t.get("범위규칙"))
]
for t in closed[:5]: # 맨 윗줄(위 끝이 가장 큰 줄)만 이상·이하
words = [r[-1] for r in dv._table(str(t["키"]))["rows"][1:]]
assert "이상·이하" in words and "이상·미만" in words, t["키"]
plain = next(t for t in tables if "범위" not in (t.get("조건") or {}).values())
assert dv.RANGE_RULE not in dv._table(str(plain["키"]))["rows"][0]
def test_재료는_로직_입력을_읽고_빈_단가는_알림() -> None:
old = _old("GC000685") # 모래 — 「지역: 입력」 · 입력 자재지역
line = next(x for x in old["got"]["lines"] if x["이름"] == "모래")
cond = next(x["요소"] for x in old["row"]["호표"] if x["이름"] == "모래")
assert dv._material(cond, "㎥", old["given"])["value"] == line["단가"]
alone = dv._material(cond, "㎥")
assert alone["ok"] is False and alone["blank"] is True # 입력이 없으면 그 값만 비움
el = {
"ref": "MT030715",
"name": "바퀴숫돌",
"spec": "",
"unit": "개",
"mode": "fixed",
} # 값 빈 품목
flow = {
"boxes": [
{
"id": "m",
"kind": "input",
"name": "재료",
"input": {"mode": "group", "group": "재료", "elements": [el], "variables": []},
}
],
"links": [],
}
if dv._price("재료", "MT030715").get("blank"):
got = dc.run(flow, {}, lambda k: {}, [], ["t"])
assert got["errors"] == [] and any("바퀴숫돌" in n for n in got["notes"])
def test_검색어_조건_찾기는_옛_검색어_찾기() -> None:
old = _old("GF000185") # 레미콘 {굵은골재최대치수}-{강도}-{슬럼프}
item = next(
x
for x in old["row"]["호표"]
if isinstance(x["요소"], dict) and "{" in str(x["요소"].get("검색어"))
)
want = next(x for x in old["got"]["lines"] if x["이름"] == item["이름"])["단가"]
text = store.cm.mf.fill(item["요소"]["검색어"], old["given"])
slot = {"mode": "rule", "field": "검색어", "op": "같음", "unit": item["단위"],
"scope": {k: item["요소"][k] for k in ("구분", "상세구분") if item["요소"].get(k)},
"ref": json.dumps(store._dec(item["요소"]), ensure_ascii=False, default=str), "inputs": old["given"]} # fmt: skip
assert dv.slot_price(slot, text)["value"] == want
assert dv.slot_price({**slot, "ref": None}, text)["value"] == want # 묶음 없이 범위 + 검색어
assert dv._filled("레미콘 {a}-{b}-{c}", "레미콘 25-18-080") == "레미콘 25-18-080"
assert dv._filled("싱글코아바렐 {규격}", "BX") == "싱글코아바렐 BX"
def test_고르기_글_값은_글_그대로() -> None:
assert sflow._value("080", {"080"}) == "080" and sflow._value("080") == Decimal(80)
assert sflow._value("3") == Decimal(3) and sflow._value("토사") == "토사"