- PRJLST.SMT 는 PRJ_MEMO 가 가리키는 블록만 읽음 — 남은 옛 블록이 덮어써 울진 2025 가 틀리던 원인 - 총액 절사 = 총공사비(도급 + 관급) 기준 · 절사 없음이면 저장된 이윤 감액 적용 - 관급자재·조달수수료 = SMT 입력값 · 추가금액 저장 단계 1~4 반영 · 안전관리비 기초액 0 처리 - `Number(x) ?? 기본값` 버그 → num 기본값 - 새 공사 기본 상태에서 봉화 금액 걷음 · 제잡비 설정은 kanjub_cfg.py 로 나눔 - 지킴 시험 test_stmate_kanjub_stc.py — 봉화·울진 2025·영월·울진 대흥 18항목 1원 - PLAN.md = 원본 기능 245 개 장부(구현 29 · 부분 92 · 없음 124) · 「95% · 100% 일치」 기록 폐기 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
98 lines
3.0 KiB
Python
98 lines
3.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""PRJLST.SMT [1_KANJUB]·[KANJUB_ADD] 키 → 원가계산서(제잡비) 계산 설정 (kanjub_cfg.py).
|
|
|
|
근거: 지식DB STmate/old/20_분석 06(간접비·끝전) · 11 §9(추가금액 단계) · 25 §1(저장키).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
RATE_KEYS = {
|
|
"KANNO": "1_R_KANNO",
|
|
"SANBO": "1_R_SANBO",
|
|
"KOBO": "1_R_KOBO",
|
|
"KUNBO": "1_R_KUNBO",
|
|
"SLVBO": "1_R_SLVBO",
|
|
"YUNBO": "1_R_YUNBO",
|
|
"TBUGUM": "1_R_TBUGUM",
|
|
"ANJUN": "1_R_ANJUN",
|
|
"KITA": "1_R_T_KITA",
|
|
"HWAN": "1_R_HWAN",
|
|
"EQIP": "1_R_EQIPSU",
|
|
"ILBAN": "1_R_ILBAN",
|
|
"IYUN": "1_R_IYUN",
|
|
"S_SUDO": "1_R_S_SUDO",
|
|
"S_BOKRI": "1_R_S_BOKRI",
|
|
"S_SOMO": "1_R_S_SOMO",
|
|
"S_TONGSIN": "1_R_S_TONGSIN",
|
|
"S_SEGUM": "1_R_S_SEGUM",
|
|
"S_PEGI": "1_R_S_PEGI",
|
|
"S_DOSEO": "1_R_S_DOSEO",
|
|
"S_JIGUP": "1_R_S_JIGUP",
|
|
}
|
|
REV_KEYS = (
|
|
"KANNO",
|
|
"SANBO",
|
|
"KOBO",
|
|
"KUNBO",
|
|
"SLVBO",
|
|
"YUNBO",
|
|
"TBUGUM",
|
|
"ANJUN",
|
|
"KITA",
|
|
"HWAN",
|
|
"EQIP",
|
|
)
|
|
|
|
|
|
def _num(kv: dict, key: str, default: float = 0.0) -> float:
|
|
try:
|
|
s = str(kv.get(key, "")).strip().replace(",", "")
|
|
return float(s) if s else default
|
|
except ValueError:
|
|
return default
|
|
|
|
|
|
def add_amounts(kv: dict) -> list[dict]:
|
|
"""ADD_AMT_<단계>_<행>_<칸> — 저장 단계 1~4 = 화면 단계 3~6(일반관리비 앞 · 이윤 뒤 · 도급 앞 · 총공사비 앞)."""
|
|
out = []
|
|
for stage in range(1, 5):
|
|
for i in range(1, int(_num(kv, f"ADD_CNT_{stage}")) + 1):
|
|
row = f"{stage}_{i:02d}"
|
|
out.append(
|
|
{
|
|
"stage": stage,
|
|
"name": kv.get(f"ADD_NAME_{row}", ""),
|
|
"amount": _num(kv, f"ADD_AMT_{row}_1"),
|
|
"vat": _num(kv, f"ADD_BUGA_{row}") == 1,
|
|
}
|
|
)
|
|
return out
|
|
|
|
|
|
def build_kanjub_config(kv: dict) -> dict:
|
|
jab_type = int(_num(kv, "JAB_TYPE"))
|
|
cal_actl = int(_num(kv, "CAL_ACTL"))
|
|
scheme = ("SA" if jab_type == 1 else "TA") if cal_actl == 1 else ("S" if jab_type == 1 else "T")
|
|
tot_jeol = int(_num(kv, "1_I_TOT_JEOL"))
|
|
return {
|
|
"scheme": scheme,
|
|
"indirectTruncDigits": 0,
|
|
"anjunBaseAdd": _num(kv, "1_C_ANJUN_G"),
|
|
"anjunGovVatExcluded": True,
|
|
"anjunCap12": True,
|
|
"vatMode": "supply_10",
|
|
"totJeolDigits": -tot_jeol,
|
|
"enableProfitEndAdj": tot_jeol > 0,
|
|
"iyunManualAdj": 0 if tot_jeol > 0 else _num(kv, "1_C_IYUN_M"),
|
|
"govMat": _num(kv, "1_C_KWANGUP") if "1_C_KWANGUP" in kv else None,
|
|
"govFee": _num(kv, "1_C_T_JODAL") if "1_C_T_JODAL" in kv else None,
|
|
"govRoundMode": "up",
|
|
"govRoundDigits": -int(_num(kv, "1_I_KWN_JEOLSA", 3)),
|
|
"addAmounts": add_amounts(kv),
|
|
"rates": {k: _num(kv, v) for k, v in RATE_KEYS.items()},
|
|
"revModes": {
|
|
k: ("carry_original" if k in ("KUNBO", "SLVBO", "YUNBO") else "recalculated")
|
|
for k in REV_KEYS
|
|
},
|
|
}
|