# -*- coding: utf-8 -*- """설계 → 계약자료 변환등록(wM_Conv_Mode · wM_Mk_Cont) 끼워 넣기 API. 근거: 27_계약_실행_기성_단계.md §2(계약 변환 옵션 · 적용제외) · 26 §4(NAGCD 낙찰율 열 · 계약단가) · 16 §4.5(통합형 BOQ11 설계 + BOQ12 계약) · ui_form_catalog wM_Conv_Mode(당초/변경 수량·단가 · 레벨) 실증(울진 2025): 소광 원설계 STC → 계약 STC = PRJLST 새 행(PCODE 다음 번호 · CCODE = 설계 PCODE · PCLASS 4) + BOQ1m = 설계 내역 복사 위 계약 공종(새 코드 · 비목 단가 버림) + COSTN 새 코드 행(산근 글·구성표 그대로) 흐름: 화면(contract_calc.registerRows)이 계약 행을 만들고 서버는 stc_project.copy_register(그대로 복사) → stc_save.apply_save(새 표 행 · 새 COSTN · 산근 · 구성표 · PRJLST) 만 함. """ from __future__ import annotations import pathlib from bdqty import decode_bdqty from fastapi import APIRouter, HTTPException from pydantic import BaseModel from stc_project import copy_register, write_output from stc_read import Source from stc_save import apply_save router = APIRouter() CONTRACT_PCLASS = 4 # 계약 공사(울진 2025 계약 행 · REA K_ORD 표 PCLASS 4) def _root() -> pathlib.Path: import server # 실행 중 바뀔 수 있는 작업 폴더(시험은 임시 폴더로 바꿈) return server.WORK_DBF_ROOT class ContractRegReq(BaseModel): source_path: str src_pcode: str = "11" pname: str = "" pnum: str = "" boq_rows: list[dict] = [] # 계약 공종 행 — {_recno, BDCODE1, 단가·금액 칸} costn_rows: list[dict] = [] # 새 코드 COSTN 행 costn_memos: dict[str, str] = {} # 새 산근 코드 → 산출근거 글 bdqty_rows: list[dict] = [] # 새 대가 코드 구성행(decode_bdqty 꼴) costw1: float | None = None # 계약 총공사비(화면 계약 원가계산서) target_folder_name: str = "" def contract_register(files: dict, req: ContractRegReq) -> tuple[dict, str, list]: """(새 files, 새 PCODE, 바뀐 칸 목록) — 쓰기 없음(시험용).""" out, pcode, log0 = copy_register(files, req.src_pcode, "copy", req.pname) prj_upd = {"CCODE": req.src_pcode, "PCLASS": CONTRACT_PCLASS} if req.pnum: prj_upd["PNUM"] = req.pnum if req.costw1 is not None: prj_upd["COSTW1"] = req.costw1 save = { "boq_table": f"BOQ{pcode}.DBF", "boq_updates": [dict(r) for r in req.boq_rows], "costn_updates": [dict(r) for r in req.costn_rows], "costn_memo_updates": dict(req.costn_memos), "prjlst_updates": prj_upd, } if req.bdqty_rows and "BDQTY.DBF" in out: save["bdqty_rows"] = decode_bdqty(out["BDQTY.DBF"]) + [dict(r) for r in req.bdqty_rows] out2, log = apply_save(out, save) return out2, pcode, log0 + log @router.post("/api/ui/contract-register") def api_contract_register(req: ContractRegReq): try: s = Source(req.source_path) except (FileNotFoundError, ValueError) as e: raise HTTPException(400, str(e)) try: files, pcode, changes = contract_register(s.files, req) except (ValueError, KeyError) as e: raise HTTPException(400, str(e)) target = req.target_folder_name or f"{s.path.stem}_계약{pcode}" names = dict(s.names, **{f"BOQ{pcode}.DBF": f"BOQ{pcode}.DBF"}) res = write_output(_root(), target, files, names, s.entries) return {**res, "new_pcode": pcode, "change_count": len(changes)}