Merge remote-tracking branches 'origin/sub_laptop_2' and 'origin/sub_laptop_4' into sub_laptop_1

This commit is contained in:
2026-09-25 10:19:34 +09:00
4 changed files with 142 additions and 4 deletions
@@ -252,13 +252,17 @@ async def save_layer_template(
session: dict[str, Any] = Depends(verify_session),
) -> dict[str, Any]:
folder = await _layer_dir(session, layer, project_id=project_id, write=True)
document = body.문서
if kind == "table" and fill.is_fillable(document):
# 채운 표가 와도 설계값은 안 받아 적음 — 양식 + 손 값만(5장 · 브라우저 값을 믿지 않음)
document = fill.strip_design(document)
try:
version = await asyncio.to_thread(
layers.write_template,
folder,
kind,
name,
body.문서,
document,
version=body.판,
check_version=True,
)
+72 -3
View File
@@ -36,6 +36,9 @@ FACILITY_TYPES = {
"revetment": "revetment",
}
EMPTY_LABEL = "-"
ORPHAN_NOTE = "설계에서 측점 없어짐"
#: 채운 표에 실어 보내는 펼침 전 열 — 저장 때 빠진 규칙 열을 되살리는 데만 씀.
RULE_COLUMNS_KEY = "양식열"
_REF = re.compile(r"\[([^\]$@][^\]@]*)\]")
@@ -354,7 +357,8 @@ def fill_document(
doc = copy.deepcopy(document)
variables = dict(doc.get("변수") or {})
interval = _number(variables.get("측점간격_m")) or 20.0
columns, made = _expand_columns(doc.get("열") or [], items, variables, _choices(types))
rule_columns = _unexpand(doc.get("열") or [])
columns, made = _expand_columns(rule_columns, items, variables, _choices(types))
notes: list[str] = []
# 줄 자리 — 관은 한 줄에 하나(둘째 관부터 줄을 나눔)
@@ -411,7 +415,7 @@ def fill_document(
notes.append(f"가드레일·경계석·위험표지 종류 미정 {loose}건 — 표에 안 셈")
# 손 값 지키기 — 같은 줄 id 의 손 열 · 전구간 줄 · 사용자가 더한 줄
hand = {column["id"] for column in columns if column.get("손")}
hand = _hand_ids(columns)
old_rows = {row.get("id"): row for row in doc.get("줄") or []}
fixed = [row for row in doc.get("줄") or [] if row.get("고정")]
added = [row for row in doc.get("줄") or [] if row.get("손") and not row.get("고정")]
@@ -438,13 +442,78 @@ def fill_document(
}
if values:
sta = (row.get("값") or {}).get("sta")
added.append({"id": row["id"], "값": {"sta": sta, **values}, "손": True})
memo = " · ".join(filter(None, [str(values.get("memo") or ""), ORPHAN_NOTE]))
added.append({"id": row["id"], "값": {"sta": sta, **values, "memo": memo}, "손": True})
doc["열"] = columns
doc["줄"] = [*fixed, *design_rows, *added]
doc["알림"] = notes
doc[RULE_COLUMNS_KEY] = copy.deepcopy(rule_columns) # 저장 때 설계에 안 쓰인 펼침 열도 되살림
return doc
def _hand_ids(columns: list[dict[str, Any]]) -> set[str]:
"""사람이 적는 열 — 바인딩 없는 열(손 열 · 비고 · 사용자가 더한 열) · 차례 · 측점 빼고."""
return {
column["id"]
for column in columns
if not column.get("바인딩") and column["id"] not in ("no", "sta")
}
def _restore_rules(
columns: list[dict[str, Any]], rules: list[dict[str, Any]]
) -> list[dict[str, Any]]:
"""채울 때 설계 값이 없어 빠졌던 펼침 열을 원래 자리(앞 열 뒤)에 되살림."""
out = list(columns)
for index, rule in enumerate(rules):
if not rule.get("펼침") or any(c["id"] == rule["id"] for c in out):
continue
before = [r["id"] for r in rules[:index]]
at = max((i + 1 for i, c in enumerate(out) if c["id"] in before), default=0)
out.insert(at, copy.deepcopy(rule))
return out
def strip_design(document: dict[str, Any]) -> dict[str, Any]:
"""작업본에 둘 것만 — 양식(열 · 식 · 변수 · 머리) + 손 값 + 전구간 줄 · 사용자 줄.
채운 표가 [저장]으로 와도 설계값 · 펼친 열은 버림(펼침 규칙 열 하나로 되돌림) ·
측점 줄은 손 값이 있을 때만 `{id(측점 키), sta, 손 값}` 으로 남김 —
다시 채우면 같은 측점에 붙음.
"""
doc = copy.deepcopy(document)
for key in ("알림", "결과"):
doc.pop(key, None)
columns = _restore_rules(_unexpand(doc.get("열") or []), doc.pop(RULE_COLUMNS_KEY, None) or [])
hand = _hand_ids(columns)
rows = []
for row in doc.get("줄") or []:
if row.get("고정"):
rows.append(row)
continue
values = row.get("값") or {}
kept = {k: v for k, v in values.items() if k in hand and v not in (None, "")}
if row.get("손"):
formulas = {k: v for k, v in (row.get("식") or {}).items() if k in hand}
new = {**row, "값": {"sta": values.get("sta"), **kept}}
new.pop("식", None)
if formulas:
new["식"] = formulas
rows.append(new)
elif kept:
rows.append({"id": row["id"], "값": {"sta": values.get("sta"), **kept}})
doc["열"] = columns
doc["줄"] = rows
return doc
def is_fillable(document: Any) -> bool:
"""설계값을 받는 표인가 — 바인딩 열이 하나라도 있으면."""
return isinstance(document, dict) and any(
isinstance(column, dict) and column.get("바인딩") for column in document.get("열") or []
)
def fill_table(
project_root: str | Path,
document: dict[str, Any],