Files
Aislo/B08_wf5_Quantity/B08_wf5_Quantity_Engine_CostBasis.py
T

19 lines
1.4 KiB
Python

from decimal import Decimal
from B08_wf5_Quantity.B08_wf5_Quantity_Engine_Formula import evaluate, round_amount
from B08_wf5_Quantity.B08_wf5_Quantity_Schema_CostBasis import CostBasis
from B08_wf5_Quantity.B08_wf5_Quantity_Schema_UnitCost import CostResult
def calculate_cost_basis(model: CostBasis) -> CostResult:
variables={v.code:v.value for v in model.variables if v.value is not None}
missing=[v.label for v in model.variables if v.required and v.value is None]
if missing: raise ValueError("필수 산출변수 미입력: "+", ".join(missing))
buckets={"LABOR":Decimal(0),"MATERIAL":Decimal(0),"EXPENSE":Decimal(0)}; trace=[]
for component in sorted(model.components,key=lambda row:row.sort_order):
quantity=evaluate(component.quantity_expression,variables)
if quantity<0: raise ValueError(f"{component.reference_name}: 구성수량이 음수입니다.")
amount=quantity*component.unit_price; buckets[component.cost_type]+=amount
trace.append({"reference_id":component.reference_id,"expression":component.quantity_expression,
"quantity":str(quantity),"unit_price":str(component.unit_price),"amount":str(amount)})
labor=round_amount(buckets["LABOR"],"FLOOR",1); material=round_amount(buckets["MATERIAL"],"FLOOR",1)
expense=round_amount(buckets["EXPENSE"],"FLOOR",1)
return CostResult(labor=labor,material=material,expense=expense,total=labor+material+expense,trace=trace)