fix(m02-df): 흐름 셈 = 옛 셈 — 빈 단가 줄을 부르는 덧줄은 빈 값 · 전수 1,472 모두 맞음
- 빈 단가(blank) 요소 값 = 「#N/A」(서버 Compute · 화면 값 받기 Entry_Detail · Api CfAnswer.blank) → 그 값을 쓰는 식은 빈 값 · 결과가 오류일 때만 끊긴 곳 「단가 없는 품목을 씀」(Eval NoPrice · Compute 같음) - 변환: 비목 합 · 덧줄의 비목 이름 = 빈 줄 0(SUM(IFERROR…)) · 호표 줄 = IF(수량=0,0,수량×단가) · 줄.이름은 빈 줄이면 빈 값(옛 env 줄) - 오류 값 칸은 NA() 로(Compute _is_err · Eval isErrorValue) - Compute 700줄 넘어 표 찾기 · 값 같음을 M02_DF_Lookup.py 로 나눔(Compute 가 다시 내보냄) - 전수 대조 시험입력 · 기본 입력 1,472/1,472 · 시험 test_m02_df_model 37 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VBToTCGk5dqDKeXCEP3vhk
This commit is contained in:
@@ -968,3 +968,69 @@ def test_표_찾기_글은_대소문자까지_같아야() -> None:
|
||||
)
|
||||
assert got == [[3, None], [1, None], [0.45, None], [0.96, None], [None, "표에 없는 조건"]]
|
||||
assert [list(cp._lookup(rule, block, {"g": g})) for g in gs] == got
|
||||
|
||||
|
||||
def _fn(i: str, ins: list[str], formula: str) -> dict:
|
||||
cells = {f"B{k + 2}": {"값": 0} for k in range(len(ins))}
|
||||
out = f"B{len(ins) + 2}"
|
||||
cells[out] = {"식": formula}
|
||||
func = {"sheet": {"id": f"s{i}", "이름": i, "칸": cells}, "variables": []}
|
||||
func["inputs"] = [{"port": p, "cell": f"B{k + 2}"} for k, p in enumerate(ins)]
|
||||
func["output"] = {"cell": out, "name": i, "unit": "-"}
|
||||
return {
|
||||
"id": i,
|
||||
"kind": "function",
|
||||
"name": i,
|
||||
"color": "#000",
|
||||
"unit": "-",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"func": func,
|
||||
}
|
||||
|
||||
|
||||
def test_빈_단가_쓰는_식은_빈_값_비목_합은_0_끊긴_곳(monkeypatch) -> None:
|
||||
g = {"mode": "group", "group": "재료", "variables": [], "elements": [
|
||||
{"ref": "MT1", "name": "p1", "spec": "", "unit": "-"}, {"ref": "MT2", "name": "p2", "spec": "", "unit": "-"}]} # fmt: skip
|
||||
boxes = [
|
||||
{"id": "g", "kind": "input", "name": "재료", "color": "#000", "unit": "-", "x": 0, "y": 0, "input": g},
|
||||
_fn("a", ["p1"], "IF(2=0,0,2*B2)"),
|
||||
_fn("b", ["p2"], "IF(1=0,0,1*B2)"),
|
||||
_fn("z", ["a", "b"], "(B2+B3)*2/100"), # 줄 이름을 부르는 덧줄 — 빈 줄이 끼면 빈 값
|
||||
_fn("s", ["a", "b", "z"], "SUM(IFERROR(B2,0),IFERROR(B3,0),IFERROR(B4,0))"),
|
||||
{"id": "o", "kind": "output", "name": "재료비", "color": "#000", "unit": "원", "x": 0, "y": 0,
|
||||
"output": {"cost": "재료비", "unit": "원"}},
|
||||
] # fmt: skip
|
||||
pairs = [
|
||||
("g", "p1", "a", "p1"),
|
||||
("g", "p2", "b", "p2"),
|
||||
("a", "a", "z", "a"),
|
||||
("b", "b", "z", "b"),
|
||||
]
|
||||
pairs += [
|
||||
("a", "a", "s", "a"),
|
||||
("b", "b", "s", "b"),
|
||||
("z", "z", "s", "z"),
|
||||
("s", "s", "o", "값"),
|
||||
]
|
||||
links = [{"id": f"l{k}", "from": {"box": a, "name": ap}, "to": {"box": b, "name": bp}}
|
||||
for k, (a, ap, b, bp) in enumerate(pairs)] # fmt: skip
|
||||
lg = {
|
||||
"key": None,
|
||||
"name": "t",
|
||||
"resultUnit": "",
|
||||
"boxes": boxes,
|
||||
"links": links,
|
||||
"userElements": [],
|
||||
}
|
||||
values = {"g": {"p1": "#N/A", "p2": 100}}
|
||||
got = _run(
|
||||
f"const ev = E.evalLogic({json.dumps(lg, ensure_ascii=False)}, {json.dumps(values)});\n"
|
||||
"out([ev.cost.재료비, ev.ports.z.z, ev.breaks.map(b => [b.kind, b.box])]);"
|
||||
)
|
||||
assert got == [100, "#N/A", [["단가 없는 품목", "a"]]]
|
||||
from M02_MasterTemplete.DataFlow import M02_DF_Compute as cp
|
||||
|
||||
srv = cp.run(lg, values, lambda key: {}, [])
|
||||
assert float(srv["cost"]["재료비"]) == 100 and srv["ports"]["z"]["z"] == "#N/A"
|
||||
assert [[b["kind"], b["box"]] for b in srv["breaks"]] == got[2]
|
||||
|
||||
Reference in New Issue
Block a user