Merge remote-tracking branch 'origin/sub_laptop_6' into sub_laptop_5
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
"daega_cover": {블록 cover: {줄 cid: {qty?, labor?, material?, expense?}}}
|
||||
(702-2 일위대가 고친 칸 덮개 — 수만 · 셈 = `B09_Estimation_Calc_Labor`)
|
||||
+ 복사본 `K:…` 의 `@copy` {from · name · spec}(703-2 · 글만)
|
||||
+ 붙인 줄 `@add` [블록 줄 fixed · pct](705-2 · `clean_added`)
|
||||
|
||||
quotes/<자재 키>/ 견적서 파일(166-4 · 여러 개) — 폴더가 목록(키의 못 쓰는 글자는 %XX) ·
|
||||
읽을 때 materials[키].files = 이름들 · 사용자 값으로는 저장 안 함
|
||||
@@ -32,7 +33,7 @@ from urllib.parse import unquote
|
||||
|
||||
from B09_Estimation.B09_Estimation_Calc_Base import SOURCES, SUPPLY
|
||||
from B09_Estimation.B09_Estimation_Calc_Bill import SECTIONS
|
||||
from B09_Estimation.B09_Estimation_Calc_Labor import COVER_KEYS
|
||||
from B09_Estimation.B09_Estimation_Calc_Labor import ADD, COVER_KEYS, PARTS
|
||||
|
||||
try: # 252 공기 초안(draft 폴더 · 지우면 공기 값 없이)
|
||||
from B09_Estimation.draft.B09_Draft_Schedule_Source import clean_schedule
|
||||
@@ -253,6 +254,10 @@ def clean_cover(raw: Any) -> dict[str, Any]:
|
||||
kept = {}
|
||||
for cid, cell in (lines if isinstance(lines, dict) else {}).items():
|
||||
cell = cell if isinstance(cell, dict) else {}
|
||||
if cid == ADD:
|
||||
if got := clean_added(lines.get(ADD)):
|
||||
kept[cid] = got
|
||||
continue
|
||||
if cid == "@copy":
|
||||
if _text(cell.get("from")):
|
||||
kept[cid] = {k: _text(cell[k]) for k in ("from", "name", "spec") if k in cell}
|
||||
@@ -265,6 +270,33 @@ def clean_cover(raw: Any) -> dict[str, Any]:
|
||||
return out
|
||||
|
||||
|
||||
ADD_MAX = 500
|
||||
|
||||
|
||||
def clean_added(raw: Any) -> list[dict[str, Any]]:
|
||||
"""붙인 줄(705-2) — fixed = 이름 · 규격 · 단위 · 수량 · 붙인 단가(own) · 이음 키(link) · pct = 비목 · 밑 ·
|
||||
율 · cid `@add|…` 만 · 모르는 칸 버림 · 숫자 아닌 단가 = 0."""
|
||||
out: list[dict[str, Any]] = []
|
||||
for ln in raw[:ADD_MAX] if isinstance(raw, list) else []:
|
||||
if not isinstance(ln, dict) or not str(ln.get("cid") or "").startswith(f"{ADD}|"):
|
||||
continue
|
||||
head = {k: _text(ln.get(k))[:200] for k in ("cid", "name", "spec", "unit")}
|
||||
if ln.get("kind") == "pct" and ln.get("part") in PARTS:
|
||||
base = str(ln.get("base") or "")
|
||||
if base.removeprefix("part:") in PARTS:
|
||||
out.append({**head, "kind": "pct", "part": ln["part"], "base": base,
|
||||
"qty": _num(ln.get("qty"))}) # fmt: skip
|
||||
continue
|
||||
if ln.get("kind") != "fixed":
|
||||
continue
|
||||
own, link = ln.get("own") or {}, ln.get("link") or {}
|
||||
out.append({**head, "kind": "fixed", "qty": _num(ln.get("qty")),
|
||||
"own": {p: _num(own.get(p)) or 0 for p in PARTS if isinstance(own, dict)},
|
||||
"link": {k: _text(link.get(k))[:40] or None for k in ("labor", "material", "machine")
|
||||
if isinstance(link, dict)}}) # fmt: skip
|
||||
return out
|
||||
|
||||
|
||||
def clean_user(raw: Any) -> dict[str, Any]:
|
||||
"""사용자 값 다듬기 — 모르는 칸 버림 · 수 칸은 수 · null(빈칸)만."""
|
||||
raw = raw if isinstance(raw, dict) else {}
|
||||
|
||||
Reference in New Issue
Block a user