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
This commit is contained in:
2026-10-02 01:04:03 +09:00
co-authored by Claude Opus 5.5
16 changed files with 345 additions and 42 deletions
+11 -3
View File
@@ -155,8 +155,10 @@ def old_designs(key: str) -> list[dict]:
return out
def _value(v: Any) -> Any:
"""화면이 보낸 값 — 수 글은 수로(「3」 → 3) · 그 밖은 그대로."""
def _value(v: Any, words: set | frozenset = frozenset()) -> Any:
"""화면이 보낸 값 — 수 글은 수로(「3」 → 3) · 고르기 글 값(「080」 · 「1048」)은 글 그대로."""
if isinstance(v, str) and v in words:
return v
if isinstance(v, str) and v.strip():
try:
return Decimal(v.strip())
@@ -172,7 +174,13 @@ def run(flow: dict, key: str, inputs: dict) -> dict:
raise store.cm.mf.FormulaError(f"로직이 서로를 부름 — {' → '.join([*active, key])}")
token = _ACTIVE.set((*active, key))
try:
given = {k: _value(v) for k, v in (inputs or {}).items()}
words = { # 고르기에 글로 든 값 — 옛 셈처럼 글 그대로(수로 바꾸면 고르기 밖)
c
for d in dc.design_inputs(flow)
for c in (d.get("variable") or {}).get("choices") or []
if isinstance(c, str)
}
given = {k: _value(v, words) for k, v in (inputs or {}).items()}
flow = {**flow, "key": key}
values = dc._design_values(flow, given)
return dc.run(flow, values, load, flow.get("userElements") or [], [key])
@@ -21,7 +21,12 @@ import {
type FormulaLine,
} from "../M02_MasterTemplete/DataFlow/M02_DF_FormulaView";
import type { CfLogic } from "../M02_MasterTemplete/DataFlow/M02_DF_Model";
import { itemRoundNow, totalRoundNow } from "../M02_MasterTemplete/DataFlow/M02_DF_Round";
import {
itemRoundNow,
roundText,
totalRoundNow,
totalRoundOf,
} from "../M02_MasterTemplete/DataFlow/M02_DF_Round";
import {
flowRows,
type FlowFunc,
@@ -42,7 +47,7 @@ const TEXT = {
HValue: ["값", "Value"],
Sub: ["소계", "Subtotal"],
Total: ["계", "Total"],
TotalNote: ["합계 끝수 기본 = 1원 미만 버림", "Total rounding default: floor to 1 won"],
TotalNote: ["합계 끝수", "Total rounding"],
None: ["출력 상자가 없음", "No output box"],
NoFunc: ["함수 상자가 없음", "No function box"],
} as const;
@@ -158,7 +163,8 @@ export function buildFlowView(
);
return;
}
const rows = flowRows(lg, ev, { item: itemRoundNow(), total: totalRoundNow() });
const totalRound = totalRoundOf(lg, totalRoundNow());
const rows = flowRows(lg, ev, { item: itemRoundNow(), total: totalRound });
const detail = section(tf("Detail"), [
...(rows.groups.length
? rows.groups.map(groupTable)
@@ -168,7 +174,10 @@ export function buildFlowView(
attrs: { "data-sum": String(rows.total) },
text: `${tf("Total")} ${rows.totalText}`,
}),
el("p", { className: "m01-logic__muted", text: tf("TotalNote") }),
el("p", {
className: "m01-logic__muted",
text: `${tf("TotalNote")}: ${roundText(totalRound)}`,
}),
...rows.errors.slice(0, 3).map((t) => el("p", { className: "m01flow__warn", text: t })),
]);
/** 함수 상자마다 식 두 줄(sub2 식 보기 · 받는 알약 값을 칸에 넣고 셈) — 못 그리면 이름 = 값만 */