68 lines
2.5 KiB
Python
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,
|
|
) |