· BillOfQuantities.py 733 → 597 · 새 _BillOfQuantities_Input.py 162 (인계 자료형 HandoffWorkItem·HandoffMaterial · parse_handoff · _decimal · BillError · 공급구분·미확정 상수) · Engine_Cost.py 725 → 609 · 새 _Engine_Cost_Input.py 136 (CostInput 한 벌 · DEFAULT_ITEMS) 반올림 두 함수(floor_won·ceil_thousand)는 엔진 것이라 도로 옮겨 둠 · 쓰던 이름은 그대로 — 본 모듈이 다시 내보내(noqa: E402,F401) from …BillOfQuantities import HandoffWorkItem · from …Engine_Cost import CostInput 가 종전대로 돎 · ruff — 새 파일 둘 다 깨끗 · 본 모듈 둘은 HEAD 와 같은 수(옮기며 안 늘음) ⚠ UnitPrice.py 1403 은 아직 남음 — 따로 배정 필요. 전체 시험 2102 통과 · 28 건너뜀 · 1 xfail. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Prk9BCHG1EMAywk9k8wegA
137 lines
8.7 KiB
Python
137 lines
8.7 KiB
Python
"""B09 원가계산 — ⑤ 공사원가계산서 **입력 한 벌**(`CostInput`).
|
|
|
|
`B09_Estimation_Engine_Cost` 가 700줄에 닿아 **그대로 옮겨 온 자리**다
|
|
(2026-09-15 · 순수 분리 — 글자 한 자 안 고쳤다). 계산 사슬은 그쪽에 그대로 있다.
|
|
|
|
⚠ 쓰던 자리가 안 바뀌도록 엔진이 다시 내보낸다 —
|
|
`from ...Engine_Cost import CostInput` 가 그대로 돈다.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from decimal import Decimal
|
|
from typing import Any
|
|
|
|
_ZERO = Decimal(0)
|
|
|
|
#: 기본으로 켜는 비목 = **그 해 요율 데이터에 있는 것 전부**.
|
|
#: 사용자 확정(2026-09-07, PLAN 8-14): 실무 서류에 없다고 빼지 않는다.
|
|
DEFAULT_ITEMS = "ALL_AVAILABLE"
|
|
|
|
|
|
@dataclass
|
|
class CostInput:
|
|
"""원가계산 입력. 금액은 전부 원 단위 `Decimal`."""
|
|
|
|
direct_material_krw: Decimal
|
|
direct_labor_krw: Decimal
|
|
direct_expense_krw: Decimal
|
|
indirect_material_krw: Decimal = _ZERO
|
|
|
|
#: 구간 판정용 공종·기간. `work_type` 값은 요율 데이터의 표기를 그대로 쓴다.
|
|
work_type_indirect_labor: str = "civil"
|
|
work_type_safety: str = "civil"
|
|
duration_days: int = 183
|
|
pension_year: int = 2026
|
|
|
|
#: 관급자재 — **순자재대**와 조달수수료를 나눠 받는다(순환 정의 방지, 원가계산_체계 §1).
|
|
#: ⚠ `owner_supplied_material_krw` 는 **수수료를 뺀 순자재대**다. 실무 서류의
|
|
#: 「관급자재대」는 이미 `순자재대 + 수수료` 를 천원 올림한 값이므로 그대로 넣으면 안 된다
|
|
#: (2026-09-07 실측 정정 — 울진 순자재대 69,474,220 + 수수료 375,160 = 69,849,380 →
|
|
#: 천원 올림 69,850,000). 안전관리비 관급항도 **순자재대만** 쓴다.
|
|
owner_supplied_material_krw: Decimal = _ZERO
|
|
procurement_fee_krw: Decimal = _ZERO
|
|
include_fee_in_owner_material_total: bool = True
|
|
|
|
#: 안전관리비 대상액에 들어가는 **도급자설치 관급금액**. None 이면 관급 전액.
|
|
owner_supplied_for_safety_krw: Decimal | None = None
|
|
#: 그 금액이 부가세 포함인가 — 포함이면 1.1 로 나눈다.
|
|
#: ⚠ 근거는 **실무**다 — 고시(산업안전보건관리비 계상 및 사용기준) 제4조① 단서는 「해당
|
|
#: 재료비를 **대상액에 포함**」까지만 적고 부가세를 말하지 않는다. ÷1.1 은 부가세 제외
|
|
#: 환산이며, 실무 원가계산서 **6건이 모두** 「관급재/1.1」로 적었다(2026-09-14 전수 확인).
|
|
owner_supplied_includes_vat: bool = True
|
|
#: 규모 구간 판정에 쓸 **추정가격**. 주면 그 값으로 한 번만 판정한다.
|
|
#: 없으면 직접공사비를 씨앗으로 **반복 수렴**한다 (`calculate_cost` 참조).
|
|
#: 근거 — 국가계약법 시행령 제7조 1호 「공사계약의 경우에는 관급자재로 공급될
|
|
#: 부분의 가격을 제외한 금액」. 우리 계산의 그 값은 **총원가**(부가세 전, 관급 밖).
|
|
estimated_price_krw: Decimal | None = None
|
|
|
|
#: 이윤 수동 조정액 — 설계자 명시 입력일 때만. 프로그램이 스스로 채우지 않는다.
|
|
profit_adjustment_krw: Decimal = _ZERO
|
|
#: 조정액 줄 산식 칸 — 비면 「설계자 명시 입력」. 절사 자동보정이 제 이름을 적는 자리.
|
|
profit_adjustment_label: str = ""
|
|
|
|
#: 폐기물처리비 — 요율이 아니라 **실비**(수량 × 처리단가).
|
|
#: ⭐ 2026-09-14 판정 — **비목은 경비**(예정가격작성기준 제19조③18호)라 순공사원가에 들고
|
|
#: **일반관리비·이윤 밑수에 든다.** 빠지면 총액이 조용히 작아진다.
|
|
#: ⚠ 법정경비 밑수(직접공사비·노무비)에는 안 넣는다 — 그 밑수는 요율 데이터가 정한 합이다.
|
|
waste_disposal_krw: Decimal = _ZERO
|
|
#: 분리발주 — 켜면 공사와 따로 발주하는 용역이라 **총원가 밖**, 총공사비에만 더한다
|
|
#: (거창 원가계산서 `총공사비 = 도급액 + 관급자재대 + 폐기물처리비` 모양). 기본 꺼짐.
|
|
waste_separate_order: bool = False
|
|
#: 폐기물처리비 자리 — `expense`(기본 · 법 문언: 경비 · 일반관리비·이윤 밑수 안) ·
|
|
#: `after_profit`(실무 관행: 이윤 뒤 · 총원가 안 · 부가세 안 · 승률 밖 — 울진소광·실정보고).
|
|
#: 분리발주(`waste_separate_order`)가 켜지면 그쪽이 먼저(총원가 밖).
|
|
waste_placement: str = "expense"
|
|
|
|
#: ── 기준 입력 10·11·12 (규칙은 `Engine_Cost_Options`) — 기본값은 종전 계산과 같음 ──
|
|
#: 원가계산 형식 — 일반관리비 밑수가 형식마다 다름(지금은 `general` 만).
|
|
form: str = "general"
|
|
#: 10. 일반관리비 — 요율 표 이름((주)공사 / 전문공사).
|
|
overhead_class: str = "civil_landscape_industrial"
|
|
#: 일반 형식 일반관리비 밑수에 더하는 관리품목 자재대.
|
|
overhead_managed_material_krw: Decimal = _ZERO
|
|
#: 12. 부가세 방식(`VAT_MODES`) · 산림조합-면세품이면 면세품 금액.
|
|
vat_mode: str = "supply"
|
|
tax_exempt_material_krw: Decimal = _ZERO
|
|
#: 11. 절사 — `grand_total`(총공사비에서 조정) · `supply`(공급가액) · `none`·빈 값은 안 자름.
|
|
#: ⭐ 2026-09-14 **기본이 켜짐** — 근거 산림청고시 제2025-82호 「금액의 단위표준」
|
|
#: 「설계서의 총액 · 원 · 1,000 · 미만버림」.
|
|
#: 실무 6건이 여섯 다 `000` 으로 끝나는 것이 증거.
|
|
#: ⚠ 2026-09-08 「조용히 깎지 않음」 합의의 정신은 살린다 — 깎은 몫과
|
|
#: **까닭(고시 번호)** 을 이윤 조정액 줄과 결과 메모에 적고,
|
|
#: 설계자가 `none` 으로 **끌 수 있게** 둔다.
|
|
cut_basis: str = "grand_total"
|
|
cut_unit_krw: int = 1000
|
|
#: 4. 고용보험 등급 — `auto`(추정금액 구간) · `none`(없음) · `1`~`7`(등급 직접).
|
|
employment_insurance_grade: str = "auto"
|
|
#: 5. 퇴직공제부금비 — `auto`(추정금액 1억 이상) · `apply`(적용) · `none`(미적용).
|
|
#: ⚠ STmate 는 토목·준설·건축·기타로 가르나 현행 제비율(2026-04-13)은 공종 구분 없이 2.3% —
|
|
#: 율이 안 갈리는 구분은 칸으로 안 세움.
|
|
retirement_mutual_aid_mode: str = "auto"
|
|
#: 13. 사급비 위치 — `material`(재료비에 포함) 뿐. 사급은 이미 내역 재료비에 들어 오므로
|
|
#: 계산에 안 씀(실무 거창·영월 · STmate 기본). 다른 자리는 사급 금액 칸이 설 때 엶.
|
|
private_material_position: str = "material"
|
|
#: 14. 낙찰방식 — `not_comprehensive`(종합심사 외) · `comprehensive`(종합심사 대상) · `turnkey`.
|
|
#: 하도급대금 지급보증 요율 줄만 고름.
|
|
bid_method: str = "not_comprehensive"
|
|
#: 하도급대금 지급보증수수료 — `off`(기본) · `on`. 실무 여섯 건에 줄 없음 · 건설산업기본법
|
|
#: 제34조 대상이면 켬(「대상 아님」인지 「안 적음」인지는 실무로 못 가름).
|
|
subcontract_guarantee: str = "off"
|
|
#: 15. 이행보증 — `general`(일반계약: 추정가격 300억 이상만) ·
|
|
#: `lowest_price_tech`(최저가·기술제안: 규모 무관).
|
|
performance_guarantee_mode: str = "general"
|
|
#: 16. 적용기준 — `national`·`local`·`moi`. 계산에 안 씀: 현행 조달청 표 한 벌뿐 · 국가/지방
|
|
#: 구간 차이(예정가격작성기준 제20조 표)는 원문 이미지라 미확인 · 행자부 표 없음. 칸만 받음.
|
|
contract_law_basis: str = ""
|
|
#: 프로젝트 요율 덮어쓰기(`RateOverride` 한 줄씩, 사유 포함) — 발주처별 별도요율.
|
|
rate_overrides: tuple[dict[str, Any], ...] = ()
|
|
|
|
#: 환경보전비 공종 (`rate_environment.all_work_types` 의 값).
|
|
#: TODO(미결 PLAN 9-6): 임도가 「도로 0.9 %」인지 「기타 토목 0.8 %」인지 미확정.
|
|
#: 잠정 = 도로(0.9 %). 요율 데이터가 `pending` 을 달고 있어 결과 줄에 경고가 붙는다.
|
|
environment_work_type: str = "civil_road"
|
|
#: 건설기계대여대금 지급보증 공종.
|
|
equipment_guarantee_work_type: str = "civil_general"
|
|
#: 하도급대금 지급보증 — 30억 이상 구간이 공종으로 갈린다(토목·산업설비 / 건축).
|
|
subcontract_guarantee_variant: str = "integrated_civil_or_industrial"
|
|
|
|
#: 켤 비목. 기본은 「그 해 요율 데이터에 있는 것 전부」.
|
|
enabled_items: tuple[str, ...] | str = DEFAULT_ITEMS
|
|
|
|
#: 요율 데이터 파일명. **연도를 갈아끼우는 자리.**
|
|
rate_file_name: str = "rates_2026.json"
|
|
#: 매니페스트 밖 요율 파일(옛 연도 재현 검산 전용). 주면 이쪽이 우선.
|
|
rate_file_path: str | None = None
|