feat(M02): 구조물 도면 = 좌측 셋째 컨테이너 · 열마다 미리 만듦
- 좌측 「구조물 도면」을 「표 양식」·「도면 양식」과 같은 층 컨테이너로 - 구조물집계표 열마다 빈 구조물 도면을 서버가 미리 만들어 둠(도번 자동 · 도각 없는 빈 CAD 문서 · 산출근거 빈 줄 셋) — 좌측 줄에 항상 도번이 붙음 - 새 열을 더해 집계표를 저장하면 그 열의 빈 구조물 도면도 서버가 같이 만듦 (`M02_MasterTemplete_Store.write` → `backfill_missing_structures`) - 좌측 구조물 도면 줄을 누르면 그 CAD 화면이 곧장 열림(열 머리글 · 도번을 제목에) - 지금 있는 49개 열의 구조물 도면을 미리 만들어 커밋(`resources/master_template/structure/`) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K7JS47SacjPxZ718QsZKyr
This commit is contained in:
@@ -19,9 +19,8 @@ from M02_MasterTemplete import M02_Template_Layers as layers
|
||||
|
||||
FOLDER: Path = Path(__file__).resolve().parent.parent / "resources" / "master_template"
|
||||
KINDS = layers.KINDS # 시험은 FOLDER 를 사본으로 바꿈
|
||||
# 구조물 도면 = 구조물집계표 열 id 마다 하나(파일 이름 = 열 id) · 새로 만들 때 A1 도각을 깖
|
||||
# 구조물 도면 = 구조물집계표 열 id 마다 하나(파일 이름 = 열 id) · 도각 없는 전용 화면(그린 만큼이 설계 영역)
|
||||
STRUCTURE_TABLE = "구조물집계표"
|
||||
STRUCTURE_FRAME = "00_template_A1"
|
||||
_BASIS_HEAD = (("work", "공종"), ("spec", "규격"), ("detail", "산출 내역"), ("unit", "단위"))
|
||||
_NUMBER = re.compile(r"^구-(\d+)$")
|
||||
_BAD_NAME = re.compile(r'[\\/:*?"<>|\x00-\x1f]|\.\.')
|
||||
@@ -80,7 +79,9 @@ def _check_skeleton(kind: str, doc: Any) -> None:
|
||||
|
||||
|
||||
def write(kind: str, name: str, version: str, doc: Any) -> dict[str, Any]:
|
||||
"""`version` 이 빈 글이면 새로 만듦(이미 있으면 409) · 아니면 그 판일 때만 덮어씀."""
|
||||
"""`version` 이 빈 글이면 새로 만듦(이미 있으면 409) · 아니면 그 판일 때만 덮어씀.
|
||||
구조물집계표를 저장하면 — 새 열의 빈 구조물 도면도 같이 만듦(잠금 밖에서 · `create_structure`
|
||||
가 다시 잠금을 잡으므로 안에서 부르면 죽음)."""
|
||||
path = _path(kind, name)
|
||||
_check_skeleton(kind, doc)
|
||||
with _LOCK:
|
||||
@@ -88,7 +89,10 @@ def write(kind: str, name: str, version: str, doc: Any) -> dict[str, Any]:
|
||||
if have != (version or ""):
|
||||
raise StoreError(409, {"stale": [name], "판": have})
|
||||
atomic_write_json(path, doc)
|
||||
return _info(kind, path)
|
||||
info = _info(kind, path)
|
||||
if kind == "table" and name == STRUCTURE_TABLE:
|
||||
backfill_missing_structures()
|
||||
return info
|
||||
|
||||
|
||||
def delete(kind: str, name: str, version: str | None = None) -> None:
|
||||
@@ -127,9 +131,10 @@ def create_structure(column: str) -> dict[str, Any]:
|
||||
table = read("table", STRUCTURE_TABLE)["문서"]
|
||||
if column not in {col.get("id") for col in table.get("열", []) if isinstance(col, dict)}:
|
||||
raise StoreError(404, f"{STRUCTURE_TABLE}에 없는 열 「{column}」")
|
||||
frame = read("drawing", STRUCTURE_FRAME)["문서"]
|
||||
basis = [{"id": key, "머리": [label], "단위": None, "꼴": "글"} for key, label in _BASIS_HEAD]
|
||||
basis.append({"id": "qty", "머리": ["수량(m당)"], "단위": None, "꼴": "수"})
|
||||
# 빈 줄 몇 개를 미리 둠 — 「줄 더하기」 안 눌러도 바로 입력하게
|
||||
basis_rows = [{"id": str(i), "값": {}} for i in range(1, 4)]
|
||||
with _LOCK:
|
||||
if path.is_file():
|
||||
raise StoreError(409, f"이미 있는 구조물 도면 「{column}」")
|
||||
@@ -140,8 +145,26 @@ def create_structure(column: str) -> dict[str, Any]:
|
||||
"판": 1,
|
||||
"열": column,
|
||||
"도번": f"구-{number:02d}",
|
||||
"도면": frame,
|
||||
"산출근거": {"양식": "산출근거", "종류": "표", "판": 1, "열": basis, "줄": []},
|
||||
"도면": {"format": 6, "entities": []},
|
||||
"산출근거": {"양식": "산출근거", "종류": "표", "판": 1, "열": basis, "줄": basis_rows},
|
||||
}
|
||||
atomic_write_json(path, doc)
|
||||
return read("structure", column)
|
||||
|
||||
|
||||
def backfill_missing_structures() -> list[str]:
|
||||
"""구조물집계표 열마다 빈 구조물 도면이 있게 — 없는 열만 열 차례로 새로 만듦(도번 이어서).
|
||||
그 사이 남이 만들었거나(409) 열 규칙에 안 맞으면(404) 그 열만 건너뜀."""
|
||||
table = read("table", STRUCTURE_TABLE)["문서"]
|
||||
have = {name for name, _ in _structures()}
|
||||
made: list[str] = []
|
||||
for col in table.get("열", []):
|
||||
cid = col.get("id") if isinstance(col, dict) else None
|
||||
if not cid or cid in have:
|
||||
continue
|
||||
try:
|
||||
create_structure(cid)
|
||||
made.append(cid)
|
||||
except StoreError:
|
||||
pass
|
||||
return made
|
||||
|
||||
Reference in New Issue
Block a user