Files
Aislo/B08_wf5_Quantity/B08_wf5_Quantity_Engine_UnitCost.py
T
2026-07-25 19:09:57 +09:00

68 lines
2.5 KiB
Python

from decimal import Decimal
from B08_wf5_Quantity.B08_wf5_Quantity_Engine_Formula import round_amount
from B08_wf5_Quantity.B08_wf5_Quantity_Schema_UnitCost import (
CostResult,
EquipmentRate,
UnitCost,
)
def _calculate(components, mode: str, unit: int) -> CostResult:
buckets = {"LABOR": Decimal(0), "MATERIAL": Decimal(0), "EXPENSE": Decimal(0)}
trace = []
for component in sorted(components, key=lambda row: row.sort_order):
amount = component.quantity * component.unit_price
buckets[component.cost_type] += amount
trace.append(
{
"reference_id": component.reference_id,
"quantity": str(component.quantity),
"unit_price": str(component.unit_price),
"amount": str(amount),
"cost_type": component.cost_type,
}
)
labor = round_amount(buckets["LABOR"], mode, unit)
material = round_amount(buckets["MATERIAL"], mode, unit)
expense = round_amount(buckets["EXPENSE"], mode, unit)
return CostResult(
labor=labor,
material=material,
expense=expense,
total=labor + material + expense,
trace=trace,
)
def calculate_unit_cost(model: UnitCost) -> CostResult:
if not model.components:
raise ValueError(f"{model.name}: 구성요소가 없습니다.")
return _calculate(model.components, model.rounding_mode, model.rounding_unit)
def calculate_equipment_rate(model: EquipmentRate) -> CostResult:
if model.annual_hours <= 0:
raise ValueError(f"{model.name}: 연간 가동시간이 필요합니다.")
if not model.components:
raise ValueError(f"{model.name}: 연료·운전·정비 구성요소가 없습니다.")
component_cost = _calculate(model.components, "FLOOR", 1)
hourly_ownership = round_amount(model.equipment_price / model.annual_hours, "FLOOR", 1)
expense = component_cost.expense + hourly_ownership
trace = [
{
"component_type": "EQUIPMENT_OWNERSHIP",
"equipment_price": str(model.equipment_price),
"annual_hours": str(model.annual_hours),
"amount": str(hourly_ownership),
"cost_type": "EXPENSE",
},
*component_cost.trace,
]
return CostResult(
labor=component_cost.labor,
material=component_cost.material,
expense=expense,
total=component_cost.labor + component_cost.material + expense,
trace=trace,
)