Files
Aislo/M02_MasterTemplete/M02_Sangeun_Views.py
T
eomsangdonandClaude Opus 5.5 9d2b8e4021 feat(750-1): SK 셈 답 하나에 보기 넷 — 텍스트 수식 글 · 시험 계산 중간 · 일위대가 줄 모달 줄모드
- 새 `M02_Sangeun_Views` — SK 고친 줄(`_Over`) · 같은 입력 · 같은 고름 위에서 `master_text.lines` + `annotate` = `글` · 줄마다 cid · 금액 · 소계 · 계 = SK 줄 · 기준(별도계상 뺌 · 단위 환산 ÷배 · 못 셈 까닭) · `중간` = 시험 계산 중간값
- `calc_doc` — 문서 `줄모드` true = 일위대가 그 줄 셈(`line` · 별도계상 기본) · 몸 `보기` false = 덧칸 안 지음(바탕 원값 셈)
- `master_text.lines` · `master_sheet_line.annotate` — `files` 자리에 Master 도 받음(파일 묶음 길 그대로 · M01 `/text` 답 같음)
- `lineDoc` — `줄모드: true`(일위대가 줄 모달 89,299.60 = 그 줄 금액)
- 시험 `test_717_3` — lineDoc = as_doc 대조에서 `줄모드` 칸 따로 확인(서버 as_doc 은 `line` 인자로 줄 셈 · 문서 칸 없음)
- 새 지킴 `test_750_1_sk_views` — 변형 일곱 · 참조 바탕 · 줄 모달 · 보기 false

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 22:32:23 +09:00

84 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""M02 단가산출(SK) 보기 넷 = 셈 답 하나(PLAN 750-1 · 요구 588-1) — 화면 셈 길 답 덧칸.
- `글` = 읽는 식(M01 `/text` 와 같은 꼴 · `master_text.lines` + `master_sheet_line.annotate`) ·
SK 고친 줄(`_Over`) · 같은 입력(자동값 + 입력값) · 같은 고름(`choosing`) 위에서 지음.
줄마다 `cid` = SK 줄 cid(`annotate` 와 같은 차례 — 호표 줄 × `_shares` 비목 · 뒤 덧줄).
금액 · 소계 · 계 = SK `줄` · `기준` 그대로(`finish` — 별도계상 뺌 · 켜쌓기율 · 단위 환산 ÷배 ·
못 셈 줄 까닭) · 식 글(`글` · `이름글`)은 바탕 단위 셈 그대로 + 머리 `나눔`(배 ≠ 1).
- `중간` = 시험 계산 중간값(수 · 글만) — 시험 계산 = {lines: `줄`, sums: `기준`, middle: `중간`}.
계산 자리 = 서버 단독(CLAUDE.md 5장 ③) · 화면은 그리기만.
"""
from __future__ import annotations
from decimal import Decimal
from typing import Any
from M02_MasterTemplete import M02_Labor_Doc as labor
mf = labor.m01.cm.mf
import master_sheet_line as msl # noqa: E402 — scripts 길은 `m01` 이 둠
import master_text as mtx # noqa: E402
_ERRORS = (mf.FormulaError, ArithmeticError, KeyError, TypeError, ValueError)
def text_of(over: Any, key: str, values: dict, picks: Any, ids: list, eng: list) -> dict:
"""`{글, 중간}` — `eng` = `run_line` 줄(별도계상 빼기 전 · 차례 맞춤용) · 못 지음 = 까닭."""
row = over.logic(key)
auto = {k: v for k, v in labor.m01.mau.values(over, row).items() if v is not None}
given = {**auto, **labor.m01._dec(values or {})}
try:
with mf.mp.choosing(picks or None):
text = msl.annotate(over, key, given, mtx.lines(over, key, given))
mid = mf.run(over, key, given).get("중간") or {}
except _ERRORS as e:
return {"글": {"ok": False, "reason": str(e) or type(e).__name__}, "중간": {}}
if text.get("ok") and "groups" in text and "결과" not in row:
_tag(row, ids, eng, text)
keep = (Decimal, int, float, str, bool)
return {"글": text, "중간": {k: v for k, v in mid.items() if isinstance(v, keep)}}
def _tag(row: dict, ids: list, eng: list, text: dict) -> None:
"""글 줄마다 `cid` — `annotate` 와 같은 차례(호표 줄 × 몫 비목 → 덧줄)."""
slots = {g["비목"]: iter(g["줄"]) for g in text["groups"]}
items, adds = row.get("호표") or [], row.get("덧줄") or []
for n, line in enumerate(eng):
if n < len(items):
parts = [p for p, _ in mtx._shares(line)] if line.get("비목") else []
else:
parts = [adds[n - len(items)]["비목"]] if n - len(items) < len(adds) else []
for part in parts:
one = next(slots.get(part, iter(())), None)
if one is not None and n < len(ids):
one["cid"] = ids[n]
def finish(ans: dict) -> dict:
"""화면 답(`per_unit` 뒤) — 글 금액 · 소계 · 계 = SK 줄 · 기준 · SK 에 없는 줄(별도계상) 뺌."""
text = ans.get("글") or {}
base = ans.get("기준")
if not text.get("ok") or "groups" not in text or not base:
return ans
sk = {x["cid"]: x for x in ans.get("줄") or [] if x.get("cid")}
groups = []
for g in text["groups"]:
kept = []
for one in g["줄"]:
line = sk.get(one.get("cid"))
if line is None and one.get("cid"):
continue # SK 에서 빠진 줄(별도계상)
if line is not None:
parts = line.get("비목") or {}
money = parts.get(g["비목"]) if len(parts) > 1 else line.get("금액")
one = {**one, "금액": money}
if line.get("까닭"):
one["까닭"] = line["까닭"]
kept.append(one)
if kept:
groups.append({**g, "줄": kept, "소계": base.get(g["비목"])})
times = ans.get("화면배")
head = {"나눔": times} if times not in (None, 1) else {}
return {**ans, "글": {**text, "groups": groups, "계": base.get("계"), **head}}