feat(M01): 원 단위 입력 자동값 null · 그 입력 쓰는 줄만 비움
- master_auto: 단위에 원이 든 수 입력은 0 대신 null - master_formula: 비어 있는 입력을 쓰는 호표·덧줄 줄만 단가·금액 null + 까닭(입력 비어 있음) · 로직 계속 - 시험 test_m01_auto.py 둘 더함 · GF000056 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JgUhN55Z3BCYhUJTjwTNfj
This commit is contained in:
@@ -89,5 +89,8 @@ def values(master: mf.Master, row: dict) -> dict:
|
||||
out[name] = spec["범위"][0]
|
||||
else:
|
||||
got = _lowest(master, finds.get(name, []))
|
||||
out[name] = got if got is not None else Decimal(1 if name in divs else 0)
|
||||
if got is None and "원" in str(spec.get("단위") or ""):
|
||||
out[name] = None # 가격 입력 — 0 원처럼 보이지 않게 비워 둠
|
||||
else:
|
||||
out[name] = got if got is not None else Decimal(1 if name in divs else 0)
|
||||
return out
|
||||
|
||||
@@ -32,6 +32,10 @@ class FormulaError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
class EmptyInput(FormulaError):
|
||||
"""값을 안 넣은(null) 입력을 씀 — 그 줄만 비우고 로직은 계속(`run`)."""
|
||||
|
||||
|
||||
# ── 읽기 ──────────────────────────────────────────────────────────────
|
||||
class _Parser:
|
||||
def __init__(self, text: str):
|
||||
@@ -360,6 +364,8 @@ def evaluate(node, env: dict, master: Master, depth: int = 0):
|
||||
if kind == "name":
|
||||
if node[1] not in env:
|
||||
raise FormulaError(f"모르는 이름 「{node[1]}」")
|
||||
if env[node[1]] is None:
|
||||
raise EmptyInput(f"입력 「{node[1]}」 비어 있음")
|
||||
return env[node[1]]
|
||||
if kind == "ref":
|
||||
value = element(master, fill(node[1], env), env)[0]
|
||||
@@ -464,7 +470,7 @@ def _inputs(row: dict, given: dict) -> dict:
|
||||
raise FormulaError(f"입력 「{name}」={value} 고르기 밖")
|
||||
if "범위" in spec:
|
||||
low, high = spec["범위"]
|
||||
if not low <= value <= high:
|
||||
if value is not None and not low <= value <= high:
|
||||
raise FormulaError(f"입력 「{name}」={value} 범위 [{low}, {high}] 밖")
|
||||
env[name] = value
|
||||
unknown = set(given) - set(env)
|
||||
@@ -485,8 +491,23 @@ def run(master: Master, ref: str, given: dict, depth: int = 0) -> dict:
|
||||
sums = dict.fromkeys(COST_ITEMS, Decimal(0))
|
||||
lines = []
|
||||
for item in row.get("호표", []):
|
||||
qty = evaluate(parse(item["수량"]), env, master, depth)
|
||||
source = why = None
|
||||
try:
|
||||
qty = evaluate(parse(item["수량"]), env, master, depth)
|
||||
except EmptyInput as e: # 비어 있는 입력을 쓰는 줄만 비움
|
||||
qty, price, why = None, None, str(e)
|
||||
lines.append(
|
||||
{
|
||||
"이름": item.get("이름", ""),
|
||||
"단위": item.get("단위", ""),
|
||||
"수량": None,
|
||||
"단가": None,
|
||||
"금액": None,
|
||||
"비목": {item["비목"]: None} if "비목" in item else {},
|
||||
"까닭": why,
|
||||
}
|
||||
)
|
||||
continue
|
||||
if item["종류"] == "로직":
|
||||
bundle = evaluate(parse(item["요소"]), env, master, depth)
|
||||
price = bundle["계"]
|
||||
|
||||
Reference in New Issue
Block a user