feat(799-1): 수식 탭 단가산출 소계 · 끝수 · 합계 — 블록마다 노 · 재 · 경 소계 보이기만(금액 그대로)
- 서버 master_equation.subtotals — 호표 줄(하위 로직 블록 한 줄씩 · 자원 · 덧줄)의 버린 줄 비목 + 끝수(합계 − 줄 합) - 부품 ui_template_equation_sum — 줄 이음 아래 소계 표(M01 · M02 수식 탭 같이) - 시험 test_799_1_subtotals — 줄 합 + 끝수 = 합계 · 합계 = 엔진 끝수 입힌 비목 합(전후 같음) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -389,6 +389,39 @@ def _line(ctx: _Ctx, kind: str, key: str, text: str, value, **more) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def subtotals(logic: dict, cut: dict, total: dict) -> dict:
|
||||
"""호표 줄 → 소계(799-1 · 보이기만) — 하위 로직 줄 = 블록마다 · 그 밖 자원 · 덧줄은 한 줄씩 + 끝수.
|
||||
|
||||
값 = `master_cut.engine` 이 버린 줄 비목(0.1 원) 그대로 · 합계 = 엔진 비목 합(1 원 버림) ·
|
||||
끝수 = 합계 − 줄 합(금액 셈은 안 바꿈 · 사용자 확정 뒤에 정함).
|
||||
"""
|
||||
items, adds = logic.get("호표") or [], logic.get("덧줄") or []
|
||||
skip = mcut.ms.skipped(logic) if mcut.ms.uses(logic) else set()
|
||||
rows: list[dict] = []
|
||||
pool: dict[str, dict] = {}
|
||||
for n, line in enumerate(cut.get("줄") or []):
|
||||
if n in skip:
|
||||
continue
|
||||
split = {k: line.get("비목", {}).get(k) or Decimal(0) for k in mf.COST_ITEMS}
|
||||
if n < len(items) and items[n].get("종류") == "로직":
|
||||
rows.append({"갈래": "블록", "이름": str(items[n].get("이름") or ""), **split})
|
||||
continue
|
||||
kind = "덧줄" if n >= len(items) else "자원"
|
||||
one = pool.setdefault(
|
||||
kind, {"갈래": kind, "이름": kind, **dict.fromkeys(mf.COST_ITEMS, Decimal(0))}
|
||||
)
|
||||
for k in mf.COST_ITEMS:
|
||||
one[k] += split[k]
|
||||
rows += [pool[k] for k in ("자원", "덧줄") if k in pool]
|
||||
for one in rows:
|
||||
one["계"] = sum((one[k] for k in mf.COST_ITEMS), Decimal(0))
|
||||
rest = {
|
||||
k: (total.get(k) or Decimal(0)) - sum((one[k] for one in rows), Decimal(0))
|
||||
for k in mf.BUNDLE
|
||||
}
|
||||
return {"줄": rows, "끝수": rest}
|
||||
|
||||
|
||||
def export(master, key: str, given: dict | None = None, depth: int = 0) -> dict:
|
||||
"""로직 키 → 수식 {열쇠, 이름, 결과단위, 줄, 풀이, 변수표, 합계 | 결과} — 셈은 엔진 한 벌."""
|
||||
row = master.logic(key)
|
||||
@@ -402,6 +435,7 @@ def export(master, key: str, given: dict | None = None, depth: int = 0) -> dict:
|
||||
more = {"표시": step["표시"]} if step.get("표시") is not None else {}
|
||||
out_lines.append(_line(ctx, "중간", name, step["식"], env.get(name), **more))
|
||||
total: dict = {}
|
||||
sub: dict = {}
|
||||
if "결과" in row:
|
||||
out_lines.append(_line(ctx, "결과", "결과", row["결과"]["식"], raw["결과"]))
|
||||
total = {"결과": raw["결과"]}
|
||||
@@ -415,6 +449,8 @@ def export(master, key: str, given: dict | None = None, depth: int = 0) -> dict:
|
||||
one = _line(ctx, "덧줄", extra["이름"], extra["식"], got, 차례=at)
|
||||
out_lines.append(one | {"비목": extra.get("비목")})
|
||||
total = {k: cut.get(k) for k in mf.BUNDLE}
|
||||
if depth == 0:
|
||||
sub = {"소계": subtotals(row, cut, total)}
|
||||
return _clean(
|
||||
{
|
||||
"열쇠": row.get("키"),
|
||||
@@ -424,6 +460,7 @@ def export(master, key: str, given: dict | None = None, depth: int = 0) -> dict:
|
||||
"풀이": list(ctx.used.values()),
|
||||
"변수표": table(row, master),
|
||||
"합계": total,
|
||||
**sub,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user