Files
Aislo/tools/stmate-test/api_ui_contract.py
T

81 lines
3.4 KiB
Python

# -*- 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)}