Files
Aislo/B09_Estimation/B09_Estimation_CostSheet_Forms.py

177 lines
8.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""원가계산서 4형식 중 나머지 셋 — **서식 차례만** (수공 S · 실적일반 TA · 실적수공 SA).
근거: STmate 분석 `12_원가계산_4형식과_RATE표_복원.md` §4~6 (DFM 복원 서식) ·
`35_형식과_단계의_공통과_차이.md` §1·§2 (공통 사슬 · 형식별 차이 · 12번 정정 반영).
⚠ **금액을 안 낸다** — 2026-09-14 요율표 셋 결론(PLAN 7장): 실적형 제비율 `RATE_RA`·`RATE_RA1` 은
**임도 미적용**(100억 미만 · 예정가격작성기준 §37②) · 수공 세부 경비 `RateB` 는 **법정 요율 없음**
(업체 실측 대상 §34① — 설계자 입력 칸) · 실적 안전표 `An_A` 는 고시 편입(제4조·별표1)이나 실적형
자체가 임도 미적용. 줄마다 무엇이 막혔는지만 적는다.
**0 원으로 채우지 않는다** — 0 원은 「없다」가 아니라 「공짜」로 읽혀 총액이 조용히 작아진다.
⚠ 35번 §5 미확인은 「확인 대기」로 세운다 — 지금 남은 것은 **실적형 이윤 밑수** 하나다.
실적수공 안전관리비는 2026-09-14 코덱스가 STmate 원문에서 **있음**을 확인해 별도내역으로 내렸다.
"""
from __future__ import annotations
from typing import Any
#: 줄 상태 — 화면이 그대로 보인다.
COMMON = "공통 요율 — 일반형식과 같은 표(형식 전체가 서면 금액이 섬)"
SEPARATE = "별도내역 — 요율이 아니라 따로 산출한 금액"
RATE_B = (
"법정 요율 없음 — 값을 넣어 주십시오(업체 실측 대상 · 예정가격작성기준 §34①) · 수공 세부 경비"
"(STmate RateB) · 입력 칸은 수공형식 금액 셈과 함께 섬"
)
RATE_RA = (
"임도 미적용 — 100억 미만(예정가격작성기준 §37②) · 표준시장단가(실적공사비) 제비율"
"(STmate RATE_RA·RATE_RA1)"
)
RATE_AN_A = (
"임도 미적용 — 실적형 형식 전체가 100억 미만 임도에 안 씀(§37②) · 요율 자체는 고시 편입"
"(건설업 산업안전보건관리비 계상 및 사용기준 제4조·별표1)"
)
TOTAL = "합계 — 위 줄이 다 서야 섬"
PENDING_PROFIT = "확인 대기 — 실적형 이윤 밑수가 복원식과 화면 문구가 충돌(35번 §5-1)"
DIRECT = "설계내역서 합계에서 옴"
_SUGONG_EXPENSES = (
"수도광열비",
"복리후생비",
"소모품·사무용품비",
"여비·교통비·통신비",
"세금·공과금",
"폐기물처리비",
"도서인쇄비",
"지급수수료",
)
FORM_LABELS = {
"general": "일반형식",
"sugong": "수공형식",
"actual_general": "실적일반",
"actual_sugong": "실적수공",
}
def _r(mark: str, label: str, formula: str, status: str, level: int) -> dict[str, Any]:
return {
"key": "",
"mark": mark,
"label": label,
"level": level,
"formula": formula,
"rate_percent": None,
"amount_krw": None,
"note": status,
"total": level == 0,
"blocked": status not in (COMMON, DIRECT),
}
def _sugong() -> list[dict[str, Any]]:
"""수공 S — 12번 §4.1."""
rows = [
_r("1.", "순공사원가(가+나+다)", "", TOTAL, 0),
_r("가.", "순공사비", "", DIRECT, 1),
_r("나.", "간접노무비", "직접노무비 × 율", COMMON, 1),
_r("다.", "경 비", "", TOTAL, 1),
_r("1)", "산재보험료", "(직접노무비+간접노무비) × 율", COMMON, 2),
_r("2)", "고용보험료", "(직접노무비+간접노무비) × 율", COMMON, 2),
_r("3)", "건강보험료", "직접노무비 × 율", COMMON, 2),
_r("4)", "장기요양보험료", "건강보험료 × 율", COMMON, 2),
_r("5)", "연금보험료", "직접노무비 × 율", COMMON, 2),
_r("6)", "퇴직공제부금비", "직접노무비 × 율", COMMON, 2),
_r("7)", "산업안전보건관리비", "(재료비+직접노무비+도급자관급자재) × 율", COMMON, 2),
_r("8)", "안전관리비", "", SEPARATE, 2),
_r("9)", "품질관리비", "", SEPARATE, 2),
]
rows += [
_r(f"{10 + i})", name, "(직노·노무·재료 중 고른 밑수) × 율", RATE_B, 2)
for i, name in enumerate(_SUGONG_EXPENSES)
]
rows += [
_r("18)", "공사이행 수수료", "[기초액 + (직공비−기준액) × 율] × 공기", COMMON, 2),
_r("19)", "하도대금 수수료", "(재료비+직노+산출경비) × 율", COMMON, 2),
_r("20)", "환 경 보 전 비", "(재료비+직노+산출경비) × 율", COMMON, 2),
_r("21)", "건설기계 대여금", "(재료비+직노+산출경비) × 율", COMMON, 2),
_r("22)", "석면분담금", "(직노+간노) × 율", COMMON, 2),
_r("23)", "임금채권부담금", "(직노+간노) × 율", COMMON, 2),
_r(
"2.",
"일반관리비",
"(순공사비+간접노무비+경비) × 율 — 밑수에 수공 경비가 들어 미산출",
RATE_B,
1,
),
_r("3.", "이 윤", "(순공사원가+일반관리비−재료비) × 율 — 밑수 미산출", RATE_B, 1),
_r("4.", "공급가액", "", TOTAL, 0),
_r("5.", "도급공사비", "", TOTAL, 0),
_r("6.", "총공사비", "", TOTAL, 0),
]
return rows
def _actual(sugong: bool) -> list[dict[str, Any]]:
"""실적일반 TA(§5 · 35번 정정) / 실적수공 SA(§6)."""
labor_base = "(직접노무비+간접노무비)" if sugong else "노무비"
rows = [
_r("1.", "직접공사비", "", DIRECT, 0),
_r("2.", "간접공사비", "", TOTAL, 0),
_r("1)", "간접노무비", "직접노무비 × 율", RATE_RA, 1),
_r("2)", "산재보험료", f"{labor_base} × 율", COMMON, 1),
_r("3)", "고용보험료", f"{labor_base} × 율", COMMON, 1),
_r("4)", "건강보험료", "직접노무비 × 율", COMMON, 1),
_r("5)", "장기요양보험료", "건강보험료 × 율", COMMON, 1),
_r("6)", "연금보험료", "직접노무비 × 율", COMMON, 1),
_r("7)", "퇴직공제부금비", "직접노무비 × 율", COMMON, 1),
_r("8)", "산업안전보건관리비", "(직접공사비+도급자관급자재) × 율", RATE_AN_A, 1),
# TA·SA 둘 다 별도내역 — SA 도 있음이 확인됨(2026-09-14 코덱스, 35번 §5-2 풀림).
_r("9)", "안전관리비", "", SEPARATE, 1),
_r("10)", "품질관리비", "", SEPARATE, 1),
]
if sugong:
rows += [
_r(f"{11 + i})", name, "(직노·노무·재료 중 고른 밑수) × 율", RATE_B, 1)
for i, name in enumerate(_SUGONG_EXPENSES)
]
guarantee_base = "(재료비+직노+산출경비)"
tail = 19
else:
rows.append(_r("11)", "기타경비", "직접공사비 × 율", RATE_RA, 1))
guarantee_base = "직접공사비"
tail = 12
rows += [
_r(f"{tail})", "공사이행 수수료", "[기초액 + (직공비−기준액) × 율] × 공기", COMMON, 1),
_r(f"{tail + 1})", "하도대금 수수료", f"{guarantee_base} × 율", COMMON, 1),
_r(f"{tail + 2})", "환 경 보 전 비", "(재료비+직노+산출경비) × 율", COMMON, 1),
_r(f"{tail + 3})", "건설기계 대여금", f"{guarantee_base} × 율", COMMON, 1),
_r(f"{tail + 4})", "석면분담금", f"{labor_base} × 율", COMMON, 1),
_r(f"{tail + 5})", "임금채권부담금", f"{labor_base} × 율", COMMON, 1),
_r(
"3.",
"일반관리비",
"(직접공사비+간접노무비) × 율"
if sugong
else "(직접공사비+간접공사비+관리품목자재) × 율",
RATE_RA,
0,
),
_r("4.", "이 윤", "", PENDING_PROFIT, 0),
_r("5.", "공급가액", "", TOTAL, 0),
_r("6.", "도급공사비", "", TOTAL, 0),
_r("7.", "총공사비", "", TOTAL, 0),
]
return rows
def form_rows(form: str) -> list[dict[str, Any]]:
"""형식별 서식 줄(금액 없음). 일반형식은 엔진이 셈하므로 여기 없음."""
if form == "sugong":
return _sugong()
if form == "actual_general":
return _actual(sugong=False)
if form == "actual_sugong":
return _actual(sugong=True)
raise ValueError(f"서식이 없는 형식입니다: {form}")