Files
Aislo/M02_MasterTemplete/M02_Table_Fill_Spec.py
T
eomsangdonandClaude Opus 5.5 14965f811b fix(M02): 집계표 흙막이 줄은 선 다단 수까지만(54-11)
- 배관 흙막이 컨테이너 줄 = 서버가 [저장] 때 세운 유출 다단 수(design.extra_walls)까지 · 넘친 상자 값은 파일에 그대로 · 단 수를 늘리면 되살아남
- 집계 항목 미지정 알림도 같은 수로 셈(같은 뿌리)
- 다단 목록 없는 옛 측점 = 저장된 것 전부(옛 동작)
- 시험 test_52_1b_pipe_links 둘 더 · 화면 점검 ui_checks/54-11_흙막이_집계

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVPp2o6Mh2FZJr72yW3ofZ
2026-10-06 11:26:43 +09:00

91 lines
4.2 KiB
Python

"""집계표 채움 — 구조물 명세 선택 컨테이너마다 한 건 더(PLAN 52-1b).
선택 컨테이너 인스턴스(옵션 `{머리}_{n}_{항목}`)마다 같은 구조물 · 자리에 한 건 —
집계 항목 = 잇기 `group_items[{잇기}{n}]` · 복사본 `{구조물 id}__{잇기}{n}` · 옵션 = 그 컨테이너 값.
열 바인딩이 읽는 칸이 갈래마다 달라(독립 기슭막이 `form` · `length_m` … · 관 `{유입|유출}_revet_*`)
컨테이너 값을 그 칸들에 함께 얹음 — 어느 출처로 읽어도 그 컨테이너 값.
짝: `A00_Common/design/design_structure_pipe.ts` · `_road.ts` 선택 컨테이너(머리 · 잇기 · 제목) —
시험이 대조.
기타(52-14) = 사용자가 적은 상세 종류 이름이 집계 건 이름(`그룹`) · 비면 「기타」.
배관 흙막이 = 지형이 세운 유출 다단 수(`흙막이단`)까지만 — 넘친 컨테이너 값은 파일에만(54-11).
"""
from __future__ import annotations
import re
from typing import Any
from common_util.common_util_summary_item import GROUP_JOIN
#: 종류 → 선택 컨테이너 (머리, 잇기, 제목)
SPEC_CONTAINERS: dict[str, tuple[tuple[str, str, str], ...]] = {
"pipe": (
("soil_add", "gsoiladd", "흙막이"),
("chute_add", "gchuteadd", "도수로/돌붙임"),
),
"ford_pavement": (("ford_chute", "gfordpavechute", "도수로/돌붙임"),),
"etc": (("etc_detail", "getcdetail", "상세 내용"),),
}
_TEXT = ("structure", "form", "note")
def etc_label(type_id: str, options: dict[str, Any] | None) -> dict[str, str]:
"""기타 집계 건 이름 `{그룹: 상세 종류 이름}`(비면 「기타」) — 다른 종류는 빈 묶음."""
if type_id != "etc":
return {}
return {"그룹": str((options or {}).get("name") or "").strip() or "기타"}
def soil_tiers_from_designs(designs: Any) -> dict[float, int]:
"""B06 횡단 설계 → `{주인 측점: 선 유출 다단 수}` — 서버가 세운 `extra_walls` 목록이 있는 측점만
(B06 `pipeExtraCount` 와 같은 수 · 54-11)."""
found: dict[float, int] = {}
for row in designs or []:
walls = (row.get("design") or {}).get("extra_walls") if isinstance(row, dict) else None
if isinstance(walls, list):
outlet = [w for w in walls if isinstance(w, dict) and w.get("side") == "outlet"]
found[round(float(row.get("chainage_m") or 0.0), 3)] = len(outlet)
return found
def _as_options(values: dict[str, Any]) -> dict[str, Any]:
"""컨테이너 값 → 열이 읽는 칸 — 구조 = `structure` · `{쪽}_type` ·
나머지 = 맨 칸 + `{쪽}_revet_*`."""
out: dict[str, Any] = {}
for item, value in values.items():
if item == "structure":
out.update(structure=value, inlet_type=value, outlet_type=value)
continue
name = item if item in _TEXT else f"{item}_m"
out[name] = value
for side in ("inlet", "outlet"):
out[f"{side}_revet_{name}"] = value
return out
def container_rows(item: dict[str, Any], links: dict[str, Any]) -> list[dict[str, Any]]:
"""한 구조물의 선택 컨테이너 인스턴스마다 한 건(n 차례) — 컨테이너 없는 종류는 빈 목록."""
rows: list[dict[str, Any]] = []
tiers = item.get("흙막이단") # None = 모름(저장된 것 그대로)
for prefix, link, title in SPEC_CONTAINERS.get(item["type_id"], ()):
head = re.compile(rf"^{prefix}_(\d+)_(.+)$")
found: dict[int, dict[str, Any]] = {}
for key, value in item["options"].items():
hit = head.match(key)
if hit:
found.setdefault(int(hit.group(1)), {})[hit.group(2)] = value
for n in sorted(found):
if prefix == "soil_add" and tiers is not None and n > tiers:
continue
gid = f"{link}{n}"
rows.append(
{
**item,
"options": {**item["options"], **_as_options(found[n])},
"summary_item": links.get(gid),
"복사본": f"{item['복사본']}{GROUP_JOIN}{gid}",
"그룹": f"{item.get('그룹', title)} {n}",
}
)
return rows