feat(M01): 흐름 로직 줄 = 옛 식 칸(입력 · 중간 · 호표 · 결과 · 덧줄) 지움 · 읽는 곳은 흐름의 설계 때 정할 것 · 출력에서(사용자 결정)
- 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
This commit is contained in:
@@ -7,9 +7,12 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import itertools
|
||||
import re
|
||||
import sys
|
||||
from decimal import ROUND_DOWN, ROUND_HALF_UP, ROUND_UP, Decimal
|
||||
from pathlib import Path
|
||||
|
||||
import master_keys as mk
|
||||
|
||||
@@ -31,6 +34,26 @@ _ARITH = re.compile(r"[\d.\s+\-*/()]*\d[\d.\s+\-*/()]*") # 분수·식 값 칸(
|
||||
# 흐름도 로직(줄에 「흐름」) 셈 — 서버(`M01_MasterData_Store_Flow`)가 꽂음 · 없으면 옛 셈만
|
||||
# 꼴 = (master, 키, 줄, 입력) → `run` 과 같은 꼴(돈 = 줄 · 비목 합 · 계 / 돈 아님 = 결과)
|
||||
FLOW_RUN = None
|
||||
# 흐름 로직 입력 = 「설계 때 정할 것」 → 입력 꼴(이름 · 단위 · 고르기 · 범위 · 예시) — 서버가 꽂음
|
||||
FLOW_INPUTS = None
|
||||
OLD_FIELDS = ("입력", "중간", "호표", "결과", "덧줄") # 흐름 로직 줄에는 없음(흐름 하나가 정본)
|
||||
|
||||
|
||||
def _flow_hooks() -> None:
|
||||
"""흐름 셈 · 입력 갈래를 깖 — 서버가 안 깔았으면(스크립트 · 시험) 여기서 서버 모듈을 불러 깖."""
|
||||
if FLOW_RUN is None or FLOW_INPUTS is None:
|
||||
root = str(Path(__file__).resolve().parents[3])
|
||||
if root not in sys.path:
|
||||
sys.path.insert(0, root)
|
||||
importlib.import_module("M01_MasterData.M01_MasterData_Store_Flow")
|
||||
|
||||
|
||||
def inputs_of(row: dict) -> list[dict]:
|
||||
"""로직 입력 — 흐름 로직이면 흐름의 「설계 때 정할 것」 · 아니면 줄의 「입력」."""
|
||||
if isinstance(row.get("흐름"), dict):
|
||||
_flow_hooks()
|
||||
return FLOW_INPUTS(row)
|
||||
return row.get("입력", [])
|
||||
|
||||
|
||||
class FormulaError(ValueError):
|
||||
@@ -485,7 +508,7 @@ def fill_empty(row: dict, given: dict) -> dict:
|
||||
"""화면이 안 보낸 가격 입력(단위에 「원」)은 null 로 채움 — 빈 입력과 같이 그 줄만 비움."""
|
||||
gap = {
|
||||
s["이름"]: None
|
||||
for s in row.get("입력", [])
|
||||
for s in inputs_of(row)
|
||||
if s["이름"] not in given and "원" in str(s.get("단위") or "")
|
||||
}
|
||||
return {**given, **gap}
|
||||
@@ -543,7 +566,8 @@ def _blank_line(item: dict, why: str) -> dict:
|
||||
def run(master: Master, ref: str, given: dict, depth: int = 0) -> dict:
|
||||
"""로직 한 줄 계산 — 돈 로직은 호표 줄 · 비목 합 · 계, 돈 아닌 로직은 결과 수 하나."""
|
||||
row = master.logic(ref)
|
||||
if FLOW_RUN is not None and isinstance(row.get("흐름"), dict):
|
||||
if isinstance(row.get("흐름"), dict): # 흐름 로직 — 깔림에 기대지 않고 스스로 깖
|
||||
_flow_hooks()
|
||||
return FLOW_RUN(master, ref, row, given)
|
||||
env = _inputs(row, given)
|
||||
for step in row.get("중간", []):
|
||||
@@ -641,7 +665,7 @@ def run(master: Master, ref: str, given: dict, depth: int = 0) -> dict:
|
||||
# ── 검사 ──────────────────────────────────────────────────────────────
|
||||
def _choices(row: dict, name: str, master: Master):
|
||||
"""이름이 가질 수 있는 값 — 고르기 입력, 또는 고르기 입력만 끼운 요소 칸인 중간. 모르면 None."""
|
||||
for spec in row.get("입력", []):
|
||||
for spec in inputs_of(row):
|
||||
if spec["이름"] == name:
|
||||
return spec.get("고르기")
|
||||
for step in row.get("중간", []):
|
||||
@@ -729,7 +753,7 @@ def _check_node(row, node, known: set, master: Master, where: str, out: list, ca
|
||||
except FormulaError as e:
|
||||
out.append(f"{where} · {e}")
|
||||
continue
|
||||
names = {s["이름"] for s in target.get("입력", [])}
|
||||
names = {s["이름"] for s in inputs_of(target)}
|
||||
given = {k for k, _ in part[2]}
|
||||
for extra in sorted(given - names):
|
||||
out.append(f"{where} · 「{master.label(part[1])}」 에 입력 「{extra}」 없음")
|
||||
|
||||
Reference in New Issue
Block a user