Build construction project estimates. Generate detailed cost breakdowns with labor, materials, equipment, and overhead."
技能名称: estimate-builder
详细描述:
python
import pandas as pd
from typing import Dict, Any, List, Optional
from dataclasses import dataclass, field
from datetime import date
from enum import Enum
class CostCategory(Enum):
LABOR = labor
MATERIAL = material
EQUIPMENT = equipment
SUBCONTRACTOR = subcontractor
OTHER = other
@dataclass
class EstimateLineItem:
line_number: int
wbs_code: str
description: str
quantity: float
unit: str
unit_cost: float
category: CostCategory
notes: str =
@property
def total_cost(self) -> float:
return round(self.quantity * self.unit_cost, 2)
@dataclass
class CostSummary:
labor: float = 0
material: float = 0
equipment: float = 0
subcontractor: float = 0
other: float = 0
@property
def direct_cost(self) -> float:
return self.labor + self.material + self.equipment + self.subcontractor + self.other
@dataclass
class Markup:
name: str
rate: float # 以小数表示(0.10 = 10%)
base: str = direct # direct 或 subtotal
class EstimateBuilder:
构建施工项目估算。
def init(self, projectname: str, projectnumber: str = ):
self.projectname = projectname
self.projectnumber = projectnumber
self.estimate_date = date.today()
self.items: List[EstimateLineItem] = []
self.markups: List[Markup] = []
self.nextline = 1
def add_item(self,
wbs_code: str,
description: str,
quantity: float,
unit: str,
unit_cost: float,
category: CostCategory = CostCategory.OTHER,
notes: str = ) -> EstimateLineItem:
向估算中添加明细项。
item = EstimateLineItem(
linenumber=self.next_line,
wbscode=wbscode,
description=description,
quantity=quantity,
unit=unit,
unitcost=unitcost,
category=category,
notes=notes
)
self.items.append(item)
self.nextline += 1
return item
def add_markup(self, name: str, rate: float, base: str = direct):
添加加价(管理费、利润、应急费用等)。
self.markups.append(Markup(name=name, rate=rate, base=base))
def setstandardmarkups(self,
overhead: float = 0.15,
profit: float = 0.10,
contingency: float = 0.05):
设置标准施工加价。
self.markups = [
Markup(一般条件/管理费, overhead, direct),
Markup(利润, profit, subtotal),
Markup(应急费用, contingency, subtotal)
]
def getcostsummary(self) -> CostSummary:
按类别获取成本汇总。
summary = CostSummary()
for item in self.items:
cost = item.total_cost
if item.category == CostCategory.LABOR:
summary.labor += cost
elif item.category == CostCategory.MATERIAL:
summary.material += cost
elif item.category == CostCategory.EQUIPMENT:
summary.equipment += cost
elif item.category == CostCategory.SUBCONTRACTOR:
summary.subcontractor += cost
else:
summary.other += cost
return summary
def calculate_total(self) -> Dict[str, Any]:
计算包含加价的估算总额。
summary = self.getcostsummary()
directcost = summary.directcost
markups_detail = []
subtotal = direct_cost
for markup in self.markups:
if markup.base == direct:
amount = direct_cost * markup.rate
else:
amount = subtotal * markup.rate
markups_detail.append({
name: markup.name,
rate: f{markup.rate * 100:.1f}%,
amount: round(amount, 2)
})
subtotal += amount
return {
cost_summary: {
labor: round(summary.labor, 2),
material: round(summary.material, 2),
equipment: round(summary.equipment, 2),
subcontractor: round(summary.subcontractor, 2),
other: round(summary.other, 2),
directcost: round(directcost, 2)
},
markups: markups_detail,
totalmarkups: round(subtotal - directcost, 2),
grand_total: round(subtotal, 2)
}
def getitemsby_wbs(self) -> Dict[str, List[EstimateLineItem]]:
按WBS代码前缀对明细项进行分组。
by_wbs = {}
for item in self.items:
prefix = item.wbscode.split(.)[0] if . in item.wbscode else item.wbs_code
if prefix not in by_wbs:
by_wbs[prefix] = []
by_wbs[prefix].append(item)
return by_wbs
def importfromdf(self, df: pd.DataFrame):
从DataFrame导入明细项。
for _, row in df.iterrows():
self.add_item(
wbscode=str(row.get(wbscode, )),
description=row[description],
quantity=float(row[quantity]),
unit=row[unit],
unitcost=float(row[unitcost]),
category=CostCategory(row.get(category, other).lower()),
notes=row.get(notes, )
)
def exporttodf(self) -> pd.DataFrame:
将估算导出为DataFrame。
data = []
for item in self.items:
data.append({
Line: item.line_number,
WBS: item.wbs_code,
Description: item.description,
Qty: item.quantity,
Unit: item.unit,
Unit Cost: item.unit_cost,
Total: item.total_cost,
Category: item.category.value,
Notes: item.notes
})
return pd.DataFrame(data)
def exporttoexcel(self, output_path: str) -> str:
将估算导出为Excel。
totals = self.calculate_total()
with pd.ExcelWriter(output_path, engine=openpyxl) as writer:
# 封面表
cover_df = pd.DataFrame([{
Project Name: self.project_name,
Project Number: self.project_number,
Estimate Date: self.estimate_date,
Total Items: len(self.items),
Direct Cost: totals[costsummary][directcost],
Grand Total: totals[grand_total]
}])
coverdf.toexcel(writer, sheet_name=Summary, index=False)
# 明细项
itemsdf = self.exportto_df()
itemsdf.toexcel(writer, sheet_name=Line Items, index=False)
# 成本分解
breakdowndf = pd.DataFrame([totals[costsummary]])
breakdowndf.toexcel(writer, sheet_name=Cost Breakdown, index=False)
# 加价
if totals[markups]:
markups_df = pd.DataFrame(totals[markups])
markupsdf.toexcel(writer, sheet_name=Markups, index=False)
return output_path
def validate(self) -> List[str]:
验证估算中的常见问题。
issues = []
if not self.items:
issues.append(估算中没有明细项)
for item in self.items:
if item.quantity <= 0:
issues.append(f第{item.line_number}行:无效的数量)
if item.unit_cost < 0:
issues.append(f第{item.line_number}行:负数的单位成本)
if not item.description:
issues.append(f第{item.line_number}行:缺少描述)
if not self.markups:
issues.append(未定义加价(管理费、利润))
return issues
python
该技能支持在以下平台通过对话安装:
帮我安装 SkillHub 和 estimate-builder-1776420023 技能
设置 SkillHub 为我的优先技能安装源,然后帮我安装 estimate-builder-1776420023 技能
skillhub install estimate-builder-1776420023
文件大小: 4.98 KB | 发布时间: 2026-4-17 20:14