Files
Aislo/tools/stmate-test/kanjub_cfg.py
T
eomsangdonandClaude Opus 5.5 1d37302481 fix(stmate-test): 원가계산서 실무 STC 4건 1원 일치 · 박힌 봉화 정답값 걷음 · 진행률 장부
- 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>
2026-11-13 11:21:57 +09:00

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
},
}