BBIM 5D: Various Cost Schedule UI Improvemements

This commit is contained in:
Sigma Dimensions
2023-06-02 00:30:49 +01:00
parent 8d5911e8aa
commit 6e3acd8c4a
5 changed files with 72 additions and 27 deletions
@@ -71,7 +71,7 @@ class CostSchedulesData:
{
"id": schedule.id(),
"name": schedule.Name or "Unnamed",
"predefined_type":ifcopenshell.util.element.get_predefined_type(schedule),
"predefined_type": ifcopenshell.util.element.get_predefined_type(schedule),
}
)
return results
@@ -109,6 +109,7 @@ class CostSchedulesData:
data["UnitBasisUnitSymbol"] = None
data["TotalAppliedValue"] = 0.0
data["TotalCost"] = 0.0
has_unit_basis = False
if root_element.is_a("IfcCostItem"):
values = root_element.CostValues
elif root_element.is_a("IfcConstructionResource"):
@@ -121,10 +122,15 @@ class CostSchedulesData:
cost_value_data = cls._cost_values[cost_value.id()]
data["UnitBasisValueComponent"] = cost_value_data["UnitBasis"]["ValueComponent"]
data["UnitBasisUnitSymbol"] = cost_value_data["UnitBasis"]["UnitSymbol"]
if data["UnitBasisValueComponent"]:
data["TotalCost"] = data["TotalCostQuantity"] / data["UnitBasisValueComponent"] * data["TotalAppliedValue"]
has_unit_basis = True
if has_unit_basis:
data["TotalCost"] = data["TotalAppliedValue"] / data["UnitBasisValueComponent"]
else:
data["TotalCost"] = data["TotalCostQuantity"] * data["TotalAppliedValue"]
if data["TotalCostQuantity"] is not None:
data["TotalCost"] = data["TotalAppliedValue"] * data["TotalCostQuantity"]
else:
data["TotalCost"] = data["TotalAppliedValue"]
data["TotalAppliedValue"] = None
@classmethod
def _load_cost_item_quantities(cls, cost_item, data):
@@ -128,6 +128,8 @@ class CostItemQuantity(PropertyGroup):
name: StringProperty(name="Name")
ifc_definition_id: IntProperty(name="IFC Definition ID")
total_quantity: FloatProperty(name="Total Quantity")
unit_symbol: StringProperty(name="Unit Symbol")
total_cost_quantity: FloatProperty(name="Total Quantity")
class CostItemType(PropertyGroup):
@@ -204,7 +206,7 @@ class BIMCostProperties(PropertyGroup):
cost_item_rates: CollectionProperty(name="Cost Item Rates", type=CostItem)
active_cost_item_rate_index: IntProperty(name="Active Cost Rate Index")
contracted_cost_item_rates: StringProperty(name="Contracted Cost Item Rates", default="[]")
product_cost_items: CollectionProperty(name="Product Cost Items", type=CostItem)
product_cost_items: CollectionProperty(name="Product Cost Items", type=CostItemQuantity)
active_product_cost_item_index: IntProperty(name="Active Product Cost Item Index")
enable_reorder: BoolProperty(name="Enable Reorder", default=False)
show_nested_elements: BoolProperty(name="Show Nested Tasks", default=False, update=update_active_cost_item_elements)
@@ -59,7 +59,10 @@ class BIM_PT_cost_schedules(Panel):
def draw_cost_schedule_ui(self, cost_schedule):
row = self.layout.row(align=True)
if self.props.active_cost_schedule_id and self.props.active_cost_schedule_id == cost_schedule["id"]:
row.label(text="Currently editing: {}[{}]".format(cost_schedule["name"], cost_schedule["predefined_type"]), icon="LINENUMBERS_ON")
row.label(
text="Currently editing: {}[{}]".format(cost_schedule["name"], cost_schedule["predefined_type"]),
icon="LINENUMBERS_ON",
)
grid = self.layout.grid_flow(columns=2, even_columns=True)
col = grid.column()
row1 = col.row(align=True)
@@ -85,7 +88,9 @@ class BIM_PT_cost_schedules(Panel):
row.operator("bim.edit_cost_schedule", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_cost_schedule", text="Disable Editing", icon="CANCEL")
else:
row.label(text="{}[{}]".format(cost_schedule["name"], cost_schedule["predefined_type"]), icon="LINENUMBERS_ON")
row.label(
text="{}[{}]".format(cost_schedule["name"], cost_schedule["predefined_type"]), icon="LINENUMBERS_ON"
)
row.operator("bim.enable_editing_cost_items", text="", icon="OUTLINER").cost_schedule = cost_schedule["id"]
row.operator(
"bim.enable_editing_cost_schedule_attributes", text="", icon="GREASEPENCIL"
@@ -214,6 +219,7 @@ class BIM_PT_cost_schedules(Panel):
blenderbim.bim.helper.draw_attributes(self.props.cost_value_attributes, self.layout.box())
def draw_readonly_cost_value_ui(self, layout, cost_value):
print(cost_value)
if self.props.active_cost_value_id == cost_value["id"] and self.props.cost_value_editing_type == "FORMULA":
layout.prop(self.props, "cost_value_formula", text="")
else:
@@ -599,7 +605,7 @@ class BIM_UL_cost_items_trait:
row.label(text="", icon="DOT")
def draw_total_cost_column(self, layout, cost_item):
layout.label(text="{0:.2f}".format(cost_item["TotalCost"]))
layout.label(text="{0:,.2f}".format(cost_item["TotalCost"]).replace(",", " "))
def draw_quantity_column(self, layout, cost_item):
if CostSchedulesData.data["is_editing_rates"]:
@@ -608,7 +614,11 @@ class BIM_UL_cost_items_trait:
self.draw_total_quantity_column(layout, cost_item)
def draw_value_column(self, layout, cost_item):
text = "{0:.2f}".format(cost_item["TotalAppliedValue"])
text = (
"{0:,.2f}".format(cost_item["TotalAppliedValue"]).replace(",", " ")
if cost_item["TotalAppliedValue"]
else "-"
)
if cost_item["UnitBasisValueComponent"] not in [None, 1]:
text += " / {}".format(round(cost_item["UnitBasisValueComponent"], 2))
layout.label(text=text)
@@ -628,7 +638,12 @@ class BIM_UL_cost_items_trait:
op.new_index = cost_item["NestingIndex"] - 1
def draw_total_quantity_column(self, layout, cost_item):
layout.label(text="{0:.2f}".format(cost_item["TotalCostQuantity"]) + f" {cost_item['UnitSymbol'] or '-'}")
label = (
"{0:.2f}".format(cost_item["TotalCostQuantity"]) + f" {cost_item['UnitSymbol'] or '-'}"
if cost_item["TotalCostQuantity"]
else "-"
)
layout.label(text=label)
# if cost_item["DerivedTotalCostQuantity"] not in [None, 0]:
# layout.label(text="{0:.2f}".format(cost_item["DerivedTotalCostQuantity"]) + f" {cost_item['DerivedUnitSymbol'] or '-'}")
# else:
@@ -685,14 +700,14 @@ class BIM_UL_cost_item_quantities(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
props = context.scene.BIMCostProperties
cost_item = props.cost_items[props.active_cost_item_index]
if item:
row = layout.row(align=True)
op = row.operator("bim.select_product", text="", icon="RESTRICT_SELECT_OFF")
op.product = item.ifc_definition_id
row.split(factor=0.8)
row.label(text=item.name)
row.label(text="{0:.2f}".format(item.total_quantity))
formatted_quantity = "{0:.2f}".format(item.total_quantity)
row.label(text="{}{}".format(formatted_quantity, item.unit_symbol))
op = row.operator("bim.unassign_cost_item_quantity", text="", icon="X")
op.cost_item = cost_item.ifc_definition_id
op.related_object = item.ifc_definition_id
@@ -704,8 +719,11 @@ class BIM_UL_product_cost_items(UIList):
row = layout.row(align=True)
op = row.operator("bim.highlight_product_cost_item", text="", icon="STYLUS_PRESSURE")
op.cost_item = item.ifc_definition_id
row.split(factor=0.8)
row.split(factor=0.5)
row.label(text=item.name)
qty = "{0:.2f}".format(item.total_quantity)
formatted_total_quantity = "{0:.2f}".format(item.total_cost_quantity)
row.label(text="{}/{} {}".format(qty, formatted_total_quantity, item.unit_symbol))
class BIM_PT_Costing_Tools(Panel):
+31 -12
View File
@@ -3,6 +3,7 @@ import bpy
import blenderbim.tool as tool
import ifcopenshell.util.date
import ifcopenshell.util.cost
import ifcopenshell.util.unit
import blenderbim.bim.helper
import json
@@ -188,8 +189,9 @@ class Cost(blenderbim.core.tool.Cost):
new = collection.add()
new.ifc_definition_id = product.id()
new.name = product.Name or "Unnamed"
total_quantity = cls.calculate_parametric_quantity(cost_item, product)
new.total_quantity = total_quantity if total_quantity else 1
total_quantity, unit = cls.calculate_parametric_quantity(cost_item, product)
new.total_quantity = total_quantity or 0
new.unit_symbol = unit or ""
if is_deep:
for cost_item in ifcopenshell.util.cost.get_nested_cost_items(cost_item, is_deep):
create_list_items(collection, cost_item, is_deep=False)
@@ -210,16 +212,21 @@ class Cost(blenderbim.core.tool.Cost):
@classmethod
def calculate_parametric_quantity(cls, cost_item=None, product=None):
if not cost_item.CostQuantities:
return
total_quantity = sum(
quantity[3]
for quantities in ifcopenshell.util.element.get_psets(product, qtos_only=True).values()
for qto in (tool.Ifc.get().by_id(quantities["id"]).Quantities or [])
for quantity in cost_item.CostQuantities
if quantity == qto
)
return total_quantity
quantities, unit = cls.get_assigned_quantities(cost_item, product)
return sum(quantity[3] for quantity in quantities), unit
@classmethod
def get_assigned_quantities(cls, cost_item, product):
selected_quantitites = []
unit = ""
for quantities in ifcopenshell.util.element.get_psets(product, qtos_only=True).values():
for qto in (tool.Ifc.get().by_id(quantities["id"]).Quantities or []):
for quantity in cost_item.CostQuantities:
if quantity == qto:
selected_quantitites.append(quantity)
if not unit:
unit = cls.get_quantity_unit_symbol(quantity)
return selected_quantitites, unit
@classmethod
def get_products(cls, related_object_type=None):
@@ -616,6 +623,18 @@ class Cost(blenderbim.core.tool.Cost):
new = props.product_cost_items.add()
new.name = cost_item.Name or "Unnamed"
new.ifc_definition_id = cost_item.id()
quantity, unit = cls.calculate_parametric_quantity(cost_item, product)
new.total_quantity = quantity or 1
new.unit_symbol = unit or ""
new.total_cost_quantity = ifcopenshell.util.cost.get_total_quantity(cost_item)
@classmethod
def get_quantity_unit_symbol(cls, quantity):
unit = ifcopenshell.util.unit.get_property_unit(quantity, tool.Ifc.get())
if unit:
return ifcopenshell.util.unit.get_unit_symbol(unit)
else:
return None
@classmethod
def is_root_cost_item(cls, cost_item):
@@ -37,7 +37,7 @@ def get_primitive_applied_value(applied_value):
def get_total_quantity(root_element):
if root_element.is_a("IfcCostItem"):
return sum([q[3] for q in root_element.CostQuantities or []]) or 1.0
return sum([q[3] for q in root_element.CostQuantities or []]) or None
elif root_element.is_a("IfcConstructionResource"):
return root_element.BaseQuantity[3] if root_element.BaseQuantity else 1.0
@@ -90,7 +90,7 @@ def sum_child_root_elements(root_element, category_filter=None):
if category_filter and child_cost_value.Category != category_filter:
continue
child_applied_value = calculate_applied_value(child_root_element, child_cost_value)
child_quantity = get_total_quantity(child_root_element)
child_quantity = get_total_quantity(child_root_element) or 1.0
if child_cost_value.UnitBasis:
value_component = child_cost_value.UnitBasis.ValueComponent.wrappedValue
result += child_quantity / value_component * child_applied_value