- M02_MasterTemplete_Router_Drawing.py — B07 Engine_Frame_Import · title_block_fields 다시 씀 - 자리표 키 목록 18 개(프로젝트 14 · 도면 4) · project_id 를 주면 표제란 값 함께 - main.py include 는 sub1 몫 - 시험 test_m02_router_drawing.py Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PxvYb5ufV1kWdBvZbpDfu6
96 lines
4.1 KiB
Python
96 lines
4.1 KiB
Python
"""M02 도면 양식 서버 길 — 외부 도각 파일 불러오기 · 자리표 키 목록 (PLAN 10-3).
|
|
|
|
양식을 읽고 쓰는 길은 `M02_MasterTemplete_Router.py`(시스템 층)·`_Router_Layers.py`(층)가 맡는다.
|
|
여기는 도면 양식 편집 화면만 쓰는 두 길 — B07 의 불러오기 엔진 · 표제란 값을 그대로 다시 쓴다.
|
|
"""
|
|
|
|
import asyncio
|
|
import logging
|
|
from uuid import UUID
|
|
|
|
from fastapi import APIRouter, File, UploadFile
|
|
from fastapi.responses import JSONResponse
|
|
|
|
from B07_DesignDetail.B07_DesignDetail_Engine_Frame_Import import import_frame_file
|
|
from B07_DesignDetail.B07_DesignDetail_Engine_Template import (
|
|
frame_document,
|
|
validate_template_entities,
|
|
)
|
|
from B07_DesignDetail.B07_DesignDetail_Router import title_block_fields
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter(prefix="/api/m02", tags=["M02 MasterTemplete"])
|
|
|
|
# 도각 파일 상한 — A1 도각 한 장은 보통 1MB 아래다. 큰 도면 전체를 올리는 실수를 막는다.
|
|
_IMPORT_MAX_BYTES = 20 * 1024 * 1024
|
|
|
|
# 자리표 `{{키}}` 로 쓸 수 있는 키 — 도면을 그릴 때 채워지는 것만 둔다.
|
|
# 프로젝트 값은 B07 `title_block_fields` 가 · 도면 값은 도면을 그리는 엔진이 채운다.
|
|
DRAWING_FIELDS: tuple[tuple[str, str, str], ...] = (
|
|
("공사명", "프로젝트", "프로젝트 이름"),
|
|
("위치", "프로젝트", "사업 위치"),
|
|
("시행청", "프로젝트", "발주 기관"),
|
|
("연도기번", "프로젝트", "프로젝트 번호"),
|
|
("사업량", "프로젝트", "사업량"),
|
|
("설계일자", "프로젝트", "설계 일자"),
|
|
("용역회사", "프로젝트", "회사 이름"),
|
|
("설계자", "프로젝트", "설계자 이름"),
|
|
("과업책임자", "프로젝트", "과업책임자 이름"),
|
|
("분야별책임자", "프로젝트", "분야별책임자 이름"),
|
|
("회사로고", "프로젝트", "회사 로고 그림"),
|
|
("설계자서명", "프로젝트", "설계자 서명 그림"),
|
|
("과업책임자서명", "프로젝트", "과업책임자 서명 그림"),
|
|
("분야별책임자서명", "프로젝트", "분야별책임자 서명 그림"),
|
|
("도면명", "도면", "도면 이름"),
|
|
("도면번호", "도면", "도면 목록 순번"),
|
|
("축척_A1", "도면", "A1 축척 분모"),
|
|
("축척_A3", "도면", "A3 축척 분모"),
|
|
)
|
|
|
|
|
|
@router.post("/drawing-import")
|
|
async def import_drawing_file(file: UploadFile = File(...)) -> JSONResponse:
|
|
"""외부 도각 파일(DXF·DWG)을 읽어 **편집 화면에 실을 도면**으로 돌려준다 — 저장하지 않는다."""
|
|
try:
|
|
data = await file.read()
|
|
if len(data) > _IMPORT_MAX_BYTES:
|
|
raise ValueError("도각 파일이 너무 큽니다(20MB 넘음).")
|
|
entities = await asyncio.to_thread(import_frame_file, file.filename or "", data)
|
|
validate_template_entities(entities)
|
|
return JSONResponse(
|
|
{
|
|
"status": "success",
|
|
"drawing": frame_document(entities),
|
|
"entity_count": len(entities),
|
|
}
|
|
)
|
|
except ValueError as exc:
|
|
return JSONResponse(status_code=400, content={"status": "error", "message": str(exc)})
|
|
except Exception:
|
|
logger.exception("M02 도각 불러오기 실패: %s", file.filename)
|
|
return JSONResponse(
|
|
status_code=500,
|
|
content={"status": "error", "message": "도각 파일을 읽지 못했습니다."},
|
|
)
|
|
|
|
|
|
@router.get("/drawing-fields")
|
|
async def get_drawing_fields(project_id: UUID | None = None) -> JSONResponse:
|
|
"""자리표 키 목록. project_id 를 주면 그 프로젝트의 표제란 값도 함께(미리보기용)."""
|
|
try:
|
|
values = await title_block_fields(project_id) if project_id else {}
|
|
except Exception:
|
|
logger.exception("M02 자리표 값 조회 실패: project_id=%s", project_id)
|
|
values = {}
|
|
return JSONResponse(
|
|
{
|
|
"status": "success",
|
|
"fields": [
|
|
{"key": key, "source": source, "label": label}
|
|
for key, source, label in DRAWING_FIELDS
|
|
],
|
|
"values": values,
|
|
}
|
|
)
|