mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-12 06:32:09 +00:00
You can now customise cost category columns in the cost schedule tree
This commit is contained in:
@@ -19,6 +19,8 @@ classes = (
|
|||||||
operator.DisableEditingCostSchedule,
|
operator.DisableEditingCostSchedule,
|
||||||
operator.DisableEditingCostItemQuantity,
|
operator.DisableEditingCostItemQuantity,
|
||||||
operator.DisableEditingCostItemValue,
|
operator.DisableEditingCostItemValue,
|
||||||
|
operator.AddCostColumn,
|
||||||
|
operator.RemoveCostColumn,
|
||||||
operator.AddCostItem,
|
operator.AddCostItem,
|
||||||
operator.AddSummaryCostItem,
|
operator.AddSummaryCostItem,
|
||||||
operator.ExpandCostItem,
|
operator.ExpandCostItem,
|
||||||
@@ -38,6 +40,7 @@ classes = (
|
|||||||
prop.BIMCostProperties,
|
prop.BIMCostProperties,
|
||||||
ui.BIM_PT_cost_schedules,
|
ui.BIM_PT_cost_schedules,
|
||||||
ui.BIM_UL_cost_items,
|
ui.BIM_UL_cost_items,
|
||||||
|
ui.BIM_UL_cost_columns,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -673,3 +673,32 @@ class ImportCostScheduleCsv(bpy.types.Operator, ImportHelper):
|
|||||||
Data.load(IfcStore.get_file())
|
Data.load(IfcStore.get_file())
|
||||||
print("Import finished in {:.2f} seconds".format(time.time() - start))
|
print("Import finished in {:.2f} seconds".format(time.time() - start))
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class AddCostColumn(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.add_cost_column"
|
||||||
|
bl_label = "Add Cost Column"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
name: bpy.props.StringProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
self.props = context.scene.BIMCostProperties
|
||||||
|
new = self.props.columns.add()
|
||||||
|
new.name = self.name
|
||||||
|
Data.set_categories([c.name for c in self.props.columns])
|
||||||
|
Data.load(IfcStore.get_file())
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveCostColumn(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.remove_cost_column"
|
||||||
|
bl_label = "Remove Cost Column"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
name: bpy.props.StringProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
self.props = context.scene.BIMCostProperties
|
||||||
|
self.props.columns.remove(self.props.columns.find(self.name))
|
||||||
|
Data.set_categories([c.name for c in self.props.columns])
|
||||||
|
Data.load(IfcStore.get_file())
|
||||||
|
return {"FINISHED"}
|
||||||
|
|||||||
@@ -105,3 +105,7 @@ class BIMCostProperties(PropertyGroup):
|
|||||||
cost_category: StringProperty(name="Cost Category")
|
cost_category: StringProperty(name="Cost Category")
|
||||||
active_cost_item_value_id: IntProperty(name="Active Cost Item Value Id")
|
active_cost_item_value_id: IntProperty(name="Active Cost Item Value Id")
|
||||||
cost_value_attributes: CollectionProperty(name="Cost Value Attributes", type=Attribute)
|
cost_value_attributes: CollectionProperty(name="Cost Value Attributes", type=Attribute)
|
||||||
|
cost_column: StringProperty(name="Cost Column")
|
||||||
|
should_show_column_ui: BoolProperty(name="Should Show Column UI", default=False)
|
||||||
|
columns: CollectionProperty(name="Columns", type=StrProperty)
|
||||||
|
active_column_index: IntProperty(name="Active Column Index")
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ class BIM_PT_cost_schedules(Panel):
|
|||||||
if self.props.active_cost_schedule_id and self.props.active_cost_schedule_id == cost_schedule_id:
|
if self.props.active_cost_schedule_id and self.props.active_cost_schedule_id == cost_schedule_id:
|
||||||
op = row.operator("bim.select_cost_schedule_products", icon="RESTRICT_SELECT_OFF", text="")
|
op = row.operator("bim.select_cost_schedule_products", icon="RESTRICT_SELECT_OFF", text="")
|
||||||
op.cost_schedule = cost_schedule_id
|
op.cost_schedule = cost_schedule_id
|
||||||
|
row.prop(self.props, "should_show_column_ui", text="", icon="SHORTDISPLAY")
|
||||||
if self.props.is_editing == "COST_SCHEDULE":
|
if self.props.is_editing == "COST_SCHEDULE":
|
||||||
row.operator("bim.edit_cost_schedule", text="", icon="CHECKMARK")
|
row.operator("bim.edit_cost_schedule", text="", icon="CHECKMARK")
|
||||||
elif self.props.is_editing == "COST_ITEMS":
|
elif self.props.is_editing == "COST_ITEMS":
|
||||||
@@ -53,8 +54,16 @@ class BIM_PT_cost_schedules(Panel):
|
|||||||
if self.props.is_editing == "COST_SCHEDULE":
|
if self.props.is_editing == "COST_SCHEDULE":
|
||||||
self.draw_editable_cost_schedule_ui()
|
self.draw_editable_cost_schedule_ui()
|
||||||
elif self.props.is_editing == "COST_ITEMS":
|
elif self.props.is_editing == "COST_ITEMS":
|
||||||
|
if self.props.should_show_column_ui:
|
||||||
|
self.draw_column_ui()
|
||||||
self.draw_editable_cost_item_ui(cost_schedule_id)
|
self.draw_editable_cost_item_ui(cost_schedule_id)
|
||||||
|
|
||||||
|
def draw_column_ui(self):
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.prop(self.props, "cost_column", text="")
|
||||||
|
row.operator("bim.add_cost_column", text="", icon="ADD").name = self.props.cost_column
|
||||||
|
self.layout.template_list("BIM_UL_cost_columns", "", self.props, "columns", self.props, "active_column_index")
|
||||||
|
|
||||||
def draw_editable_cost_schedule_ui(self):
|
def draw_editable_cost_schedule_ui(self):
|
||||||
for attribute in self.props.cost_schedule_attributes:
|
for attribute in self.props.cost_schedule_attributes:
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
@@ -266,6 +275,10 @@ class BIM_UL_cost_items(UIList):
|
|||||||
op = row.operator("bim.enable_editing_cost_item_values", text="", icon="DISC")
|
op = row.operator("bim.enable_editing_cost_item_values", text="", icon="DISC")
|
||||||
op.cost_item = item.ifc_definition_id
|
op.cost_item = item.ifc_definition_id
|
||||||
row.label(text="{0:.2f}".format(cost_item["TotalAppliedValue"]))
|
row.label(text="{0:.2f}".format(cost_item["TotalAppliedValue"]))
|
||||||
|
|
||||||
|
for column in props.columns:
|
||||||
|
row.label(text=str(cost_item["CategoryValues"].get(column.name, "-")))
|
||||||
|
|
||||||
row.label(text="{0:.2f}".format(cost_item["TotalCostValue"]), icon="CON_TRANSLIKE")
|
row.label(text="{0:.2f}".format(cost_item["TotalCostValue"]), icon="CON_TRANSLIKE")
|
||||||
|
|
||||||
if context.active_object:
|
if context.active_object:
|
||||||
@@ -297,3 +310,12 @@ class BIM_UL_cost_items(UIList):
|
|||||||
).cost_item = item.ifc_definition_id
|
).cost_item = item.ifc_definition_id
|
||||||
row.operator("bim.add_cost_item", text="", icon="ADD").cost_item = item.ifc_definition_id
|
row.operator("bim.add_cost_item", text="", icon="ADD").cost_item = item.ifc_definition_id
|
||||||
row.operator("bim.remove_cost_item", text="", icon="X").cost_item = item.ifc_definition_id
|
row.operator("bim.remove_cost_item", text="", icon="X").cost_item = item.ifc_definition_id
|
||||||
|
|
||||||
|
|
||||||
|
class BIM_UL_cost_columns(UIList):
|
||||||
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||||
|
props = context.scene.BIMCostProperties
|
||||||
|
if item:
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(item, "name", emboss=False, text="")
|
||||||
|
row.operator("bim.remove_cost_column", text="", icon="X").name = item.name
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ class Data:
|
|||||||
cost_items = {}
|
cost_items = {}
|
||||||
physical_quantities = {}
|
physical_quantities = {}
|
||||||
cost_values = {}
|
cost_values = {}
|
||||||
|
categories = []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def purge(cls):
|
def purge(cls):
|
||||||
@@ -16,6 +17,11 @@ class Data:
|
|||||||
cls.cost_items = {}
|
cls.cost_items = {}
|
||||||
cls.physical_quantities = {}
|
cls.physical_quantities = {}
|
||||||
cls.cost_values = {}
|
cls.cost_values = {}
|
||||||
|
cls.categories = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_categories(cls, categories):
|
||||||
|
cls.categories = categories
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, file):
|
def load(cls, file):
|
||||||
@@ -81,14 +87,15 @@ class Data:
|
|||||||
data["CostValues"] = []
|
data["CostValues"] = []
|
||||||
data["TotalCostValue"] = 0.0
|
data["TotalCostValue"] = 0.0
|
||||||
data["TotalAppliedValue"] = 0.0
|
data["TotalAppliedValue"] = 0.0
|
||||||
|
data["CategoryValues"] = {}
|
||||||
for cost_value in cost_item.CostValues or []:
|
for cost_value in cost_item.CostValues or []:
|
||||||
cls.load_cost_item_value(cost_item, cost_value)
|
cls.load_cost_item_value(data, cost_item, cost_value)
|
||||||
data["CostValues"].append(cost_value.id())
|
data["CostValues"].append(cost_value.id())
|
||||||
data["TotalAppliedValue"] += cls.cost_values[cost_value.id()]["AppliedValue"]
|
data["TotalAppliedValue"] += cls.cost_values[cost_value.id()]["AppliedValue"]
|
||||||
data["TotalCostValue"] = data["TotalCostQuantity"] * data["TotalAppliedValue"]
|
data["TotalCostValue"] = data["TotalCostQuantity"] * data["TotalAppliedValue"]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_cost_item_value(cls, cost_item, cost_value):
|
def load_cost_item_value(cls, cost_item_data, cost_item, cost_value):
|
||||||
value_data = cost_value.get_info()
|
value_data = cost_value.get_info()
|
||||||
del value_data["AppliedValue"]
|
del value_data["AppliedValue"]
|
||||||
del value_data["UnitBasis"]
|
del value_data["UnitBasis"]
|
||||||
@@ -98,9 +105,14 @@ class Data:
|
|||||||
value_data["FixedUntilDate"] = ifcopenshell.util.date.ifc2datetime(value_data["FixedUntilDate"])
|
value_data["FixedUntilDate"] = ifcopenshell.util.date.ifc2datetime(value_data["FixedUntilDate"])
|
||||||
value_data["Components"] = [c.id() for c in value_data["Components"] or []]
|
value_data["Components"] = [c.id() for c in value_data["Components"] or []]
|
||||||
value_data["AppliedValue"] = cls.calculate_applied_value(cost_item, cost_value)
|
value_data["AppliedValue"] = cls.calculate_applied_value(cost_item, cost_value)
|
||||||
|
|
||||||
|
if cost_value.Category not in [None, "*"]:
|
||||||
|
cost_item_data["CategoryValues"].setdefault(cost_value.Category, 0)
|
||||||
|
cost_item_data["CategoryValues"][cost_value.Category] += value_data["AppliedValue"]
|
||||||
|
|
||||||
cls.cost_values[cost_value.id()] = value_data
|
cls.cost_values[cost_value.id()] = value_data
|
||||||
for component in cost_value.Components or []:
|
for component in cost_value.Components or []:
|
||||||
cls.load_cost_item_value(cost_item, component)
|
cls.load_cost_item_value(cost_item_data, cost_item, component)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def calculate_applied_value(cls, cost_item, cost_value, category_filter=None):
|
def calculate_applied_value(cls, cost_item, cost_value, category_filter=None):
|
||||||
|
|||||||
Reference in New Issue
Block a user