fix(m01): 자동값 빈 줄에서 텍스트 수식이 멈추지 않음 — 빈 줄은 빈 글
- 빈 줄(후보 0 · 값 빈 품목 · 빈 덧줄)은 글 빈 값 · 금액 null 그대로 · 덧줄 식을 다시 셈하지 않음 - 덧줄 합 · 이름 값에 빈 줄을 넣지 않음 - 자동값으로 1,354 전부 텍스트 멈춤 62 → 0 검증: test_m01_text 23개 통과 · 자동값 1,354 멈춤 0 · GC000027 계 = 계산 계. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ACe3CR4gBWhWUN5p44fLe4
This commit is contained in:
@@ -353,7 +353,9 @@ def _shares(line: dict) -> list[tuple[str, Decimal]]:
|
||||
|
||||
|
||||
def _line_text(item: dict, line: dict, env: dict, master, part: str | None) -> str:
|
||||
"""「단가 * 수량식 = 금액」 — 비목이 나뉜 로직 줄은 그 비목 몫만."""
|
||||
"""「단가 * 수량식 = 금액」 — 비목이 나뉜 로직 줄은 그 비목 몫만 · 빈 줄(금액 null)은 빈 글."""
|
||||
if line["금액"] is None:
|
||||
return ""
|
||||
qty = render(mf.parse(item["수량"]), env, master)
|
||||
money = line["비목"][part] if part else line["금액"]
|
||||
price = line["단가"] if part is None or line["수량"] == 0 else money / line["수량"]
|
||||
@@ -370,6 +372,8 @@ def _line_names(item: dict, line: dict, env: dict, master, part: str | None, nam
|
||||
|
||||
|
||||
def _extra_text(extra: dict, line: dict, env: dict, master) -> str:
|
||||
if line["금액"] is None: # 빈 덧줄 — 식을 다시 셈하지 않음
|
||||
return ""
|
||||
return f"{render(mf.parse(extra['식']), env, master)} = {fmt_money(line['금액'])}"
|
||||
|
||||
|
||||
@@ -520,7 +524,9 @@ def _extras(
|
||||
row: dict, shown: list, made: dict, env: dict, master, name_of: dict, alias_by_name: dict
|
||||
) -> None:
|
||||
"""덧줄 — 앞선 줄까지의 비목 합을 넣고 한 줄씩(식 안의 비목 이름은 그 수로 바뀜)."""
|
||||
sums = {name: sum((one["금액"] for one in made[name]), Decimal(0)) for name in mf.COST_ITEMS}
|
||||
sums = {
|
||||
name: sum((one["금액"] or 0 for one in made[name]), Decimal(0)) for name in mf.COST_ITEMS
|
||||
}
|
||||
for extra, line in zip(row.get("덧줄") or [], shown):
|
||||
env.update(sums)
|
||||
one = {
|
||||
@@ -531,8 +537,9 @@ def _extras(
|
||||
"조각": _formula_pieces(extra["식"], env, master, name_of, alias_by_name),
|
||||
}
|
||||
made[extra["비목"]].append(one)
|
||||
sums[extra["비목"]] += line["금액"]
|
||||
env[extra["이름"]] = line["금액"]
|
||||
if line["금액"] is not None: # 빈 덧줄은 합·이름 값에 안 넣음
|
||||
sums[extra["비목"]] += line["금액"]
|
||||
env[extra["이름"]] = line["금액"]
|
||||
|
||||
|
||||
def _cut_note(row: dict, on: str = "계") -> str:
|
||||
|
||||
@@ -303,3 +303,31 @@ def test_글_안의_돈은_정수_계산_값은_소수_그대로(client: TestCli
|
||||
first = _all_lines(got)[0]
|
||||
assert first["글"] == "275,790 * 0.22 * 1.31 = 79,483" # 수량·비율은 소수 그대로
|
||||
assert Decimal(str(first["금액"])) == Decimal("79482.678") # 값은 그대로
|
||||
|
||||
|
||||
def test_자동값으로_모든_로직을_돌려도_멈추지_않는다() -> None:
|
||||
"""빈 줄(후보 0 · 값 빈 품목) — 그 줄만 빈 글 · 로직은 계속(PLAN 3-2)."""
|
||||
files = store.cm.load(folder=REAL)
|
||||
master = store.cm.master(REAL)
|
||||
stops = []
|
||||
for rows in master.index.values():
|
||||
for key in rows:
|
||||
if mt.mf.mk.GROUP_OF.get(key[:2]) != "로직":
|
||||
continue
|
||||
given = {n: store._dec(v) for n, v in store.auto(key)["값"].items()}
|
||||
try:
|
||||
mt.lines(files, key, given)
|
||||
except mt._CALC_ERRORS as e:
|
||||
stops.append((key, str(e)))
|
||||
assert not stops, stops[:3]
|
||||
|
||||
|
||||
def test_빈_줄은_빈_글이고_소계는_빈_줄_빼고_더한다(client: TestClient) -> None:
|
||||
key = "GC000027"
|
||||
given = {n: str(v) for n, v in store.auto(key)["값"].items()}
|
||||
got = client.post("/api/m01/text", json={"key": key, "inputs": given}).json()
|
||||
calc = client.post("/api/m01/calc", json={"key": key, "inputs": given}).json()
|
||||
assert got["ok"] is True
|
||||
blank = [one for one in _all_lines(got) if one["금액"] is None]
|
||||
assert blank and all(one["글"] == "" and one["까닭"] for one in blank)
|
||||
assert Decimal(str(got["계"])) == Decimal(str(calc["sums"]["계"]))
|
||||
|
||||
Reference in New Issue
Block a user