- 시험 615 통과 · 브라우저 화면 13개·메뉴 90개 오류 0 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
81 lines
3.4 KiB
Python
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)}
|