Files
Aislo/B08_wf5_Quantity/B08_wf5_Quantity_Engine_Final.py
T

48 lines
2.4 KiB
Python

from B08_wf5_Quantity.B08_wf5_Quantity_Engine_Indirect import calculate_indirect
from B08_wf5_Quantity.B08_wf5_Quantity_Schema_Basis import RatePolicy
from B08_wf5_Quantity.B08_wf5_Quantity_Schema_Calculation import CostTotals, FinalCost
_RESERVED = ("GENERAL_ADMIN", "PROFIT", "VAT", "PROCUREMENT_FEE")
def calculate_final_cost(totals: CostTotals, policies: list[RatePolicy]) -> FinalCost:
context = {"LABOR": totals.labor, "MATERIAL": totals.material, "EXPENSE": totals.expense,
"DIRECT_COST": totals.direct_cost, "GOVERNMENT_MATERIAL": totals.government_material}
ordered = sorted(policies, key=lambda row: row.sort_order)
overhead = [row for row in ordered if row.rule_code not in _RESERVED]
results, context = calculate_indirect(overhead, context)
net_cost = totals.direct_cost + sum(row.result_amount for row in results)
context["NET_COST"] = net_cost
general_rows, context = _stage(ordered, "GENERAL_ADMIN", context)
results += general_rows
general = context.get("GENERAL_ADMIN", 0)
context["AFTER_GENERAL"] = net_cost + general
profit_rows, context = _stage(ordered, "PROFIT", context)
results += profit_rows
profit = context.get("PROFIT", 0)
total_cost = net_cost + general + profit
context["TOTAL_COST"] = total_cost
vat_rows, context = _stage(ordered, "VAT", context)
results += vat_rows
vat = context.get("VAT", 0)
contract_cost = total_cost + vat
context["CONTRACT_COST"] = contract_cost
fee_rows, context = _stage(ordered, "PROCUREMENT_FEE", context)
results += fee_rows
fee = context.get("PROCUREMENT_FEE", 0)
total_project_cost = contract_cost + totals.government_material + fee
context["TOTAL_PROJECT_COST"] = total_project_cost
return FinalCost(direct_cost=totals.direct_cost, net_cost=net_cost, general_admin=general,
profit=profit, total_cost=total_cost, vat=vat, contract_cost=contract_cost,
government_material=totals.government_material, procurement_fee=fee,
total_project_cost=total_project_cost, indirect_results=results,
trace={"excluded_amount": totals.excluded_amount, "context": context})
def _stage(policies: list[RatePolicy], code: str, context: dict[str, int]):
selected = [row for row in policies if row.rule_code == code]
if not selected:
return [], context
return calculate_indirect(selected, context)