diff --git a/src/blenderbim/blenderbim/bim/module/cost/ui.py b/src/blenderbim/blenderbim/bim/module/cost/ui.py index 2b9626fc0f..12d5deaecc 100644 --- a/src/blenderbim/blenderbim/bim/module/cost/ui.py +++ b/src/blenderbim/blenderbim/bim/module/cost/ui.py @@ -474,9 +474,10 @@ class BIM_PT_cost_item_rates(Panel): cost_item = self.props.cost_items[self.props.active_cost_item_index] row = self.layout.row(align=True) row.prop(self.props, "schedule_of_rates", text="") - op = row.operator("bim.assign_cost_value", text="", icon="COPYDOWN") - op.cost_item = self.props.cost_items[self.props.active_cost_item_index].ifc_definition_id - op.cost_rate = self.props.cost_item_rates[self.props.active_cost_item_rate_index].ifc_definition_id + if self.props.active_cost_item_rate_index < len(self.props.cost_item_rates): + op = row.operator("bim.assign_cost_value", text="", icon="COPYDOWN") + op.cost_item = self.props.cost_items[self.props.active_cost_item_index].ifc_definition_id + op.cost_rate = self.props.cost_item_rates[self.props.active_cost_item_rate_index].ifc_definition_id self.layout.template_list( "BIM_UL_cost_item_rates", "", @@ -487,7 +488,7 @@ class BIM_PT_cost_item_rates(Panel): ) -class BIM_UL_cost_items_trait(): +class BIM_UL_cost_items_trait: def draw_item(self, context, layout, data, item, icon, active_data, active_propname): if item: self.props = context.scene.BIMCostProperties @@ -503,13 +504,12 @@ class BIM_UL_cost_items_trait(): split2.prop(item, "name", emboss=False, text="") self.draw_quantity_column(split2, cost_item) - - split2.label(text="{0:.2f}".format(cost_item["TotalAppliedValue"])) + self.draw_value_column(split2, cost_item) for column in self.props.columns: split2.label(text=str(cost_item["CategoryValues"].get(column.name, "-"))) - split2.label(text="{0:.2f}".format(cost_item["TotalCostValue"])) + self.draw_total_cost_column(split2, cost_item) # TODO: reimplement "bim.copy_cost_item_values" somewhere with better UX def draw_hierarchy(self, row, item): @@ -524,22 +524,26 @@ class BIM_UL_cost_items_trait(): else: row.label(text="", icon="DOT") + def draw_total_cost_column(self, layout, cost_item): + layout.label(text="{0:.2f}".format(cost_item["TotalCost"])) + def draw_quantity_column(self, layout, cost_item): if Data.cost_schedules[self.props.active_cost_schedule_id]["PredefinedType"] == "SCHEDULEOFRATES": self.draw_uom_column(layout, cost_item) else: self.draw_total_quantity_column(layout, cost_item) - def draw_uom_column(self, layout, cost_item): - text = "-" - if cost_item["CostValues"]: - unit_basis = Data.cost_values[cost_item["CostValues"][0]]["UnitBasis"] - if unit_basis: - text = "{0:.2f}".format(unit_basis["ValueComponent"]) + f" ({unit_basis['UnitSymbol'] or '?'})" + def draw_value_column(self, layout, cost_item): + text = "{0:.2f}".format(cost_item["TotalAppliedValue"]) + if cost_item["UnitBasisValueComponent"] not in [None, 1]: + text += " / {}".format(round(cost_item["UnitBasisValueComponent"], 2)) layout.label(text=text) + def draw_uom_column(self, layout, cost_item): + layout.label(text=cost_item["UnitBasisUnitSymbol"] or "?" if cost_item["UnitBasisValueComponent"] else "-") + def draw_total_quantity_column(self, layout, cost_item): - layout.label(text="{0:.2f}".format(cost_item["TotalCostQuantity"]) + f" ({cost_item['UnitSymbol'] or '?'})") + layout.label(text="{0:.2f}".format(cost_item["TotalCostQuantity"]) + f" {cost_item['UnitSymbol'] or '?'}") class BIM_UL_cost_items(BIM_UL_cost_items_trait, UIList): @@ -559,6 +563,9 @@ class BIM_UL_cost_item_rates(BIM_UL_cost_items_trait, UIList): def draw_quantity_column(self, layout, cost_item): self.draw_uom_column(layout, cost_item) + def draw_total_cost_column(self, layout, cost_item): + pass # No such thing as a total cost in a schedule of rates + class BIM_UL_cost_columns(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/data.py b/src/ifcopenshell-python/ifcopenshell/api/cost/data.py index 138b96c799..fdd8d811ec 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/cost/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/cost/data.py @@ -107,14 +107,25 @@ class Data: @classmethod def load_cost_item_values(cls, cost_item, data): data["CostValues"] = [] - data["TotalCostValue"] = 0.0 - data["TotalAppliedValue"] = 0.0 data["CategoryValues"] = {} + data["UnitBasisValueComponent"] = None + data["UnitBasisUnitSymbol"] = None + data["TotalAppliedValue"] = 0.0 + data["TotalCost"] = 0.0 for cost_value in cost_item.CostValues or []: cls.load_cost_item_value(cost_item, data, cost_value) data["CostValues"].append(cost_value.id()) data["TotalAppliedValue"] += cls.cost_values[cost_value.id()]["AppliedValue"] - data["TotalCostValue"] = data["TotalCostQuantity"] * data["TotalAppliedValue"] + if cost_value.UnitBasis: + 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"] + ) + else: + data["TotalCost"] = data["TotalCostQuantity"] * data["TotalAppliedValue"] @classmethod def load_cost_item_value(cls, cost_item, cost_item_data, cost_value): @@ -187,7 +198,11 @@ class Data: continue child_applied_value = cls.calculate_applied_value(child_cost_item, child_cost_value) child_quantity = cls.get_total_quantity(child_cost_item) - result += child_applied_value * child_quantity + if child_cost_value.UnitBasis: + value_component = child_cost_value.UnitBasis.ValueComponent.wrappedValue + result += child_quantity / value_component * child_applied_value + else: + result += child_quantity * child_applied_value return result @classmethod