48 lines
2.4 KiB
Python
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) |