diff --git a/src/blenderbim/blenderbim/bim/module/qto/ui.py b/src/blenderbim/blenderbim/bim/module/qto/ui.py index 6386859d88..43e5e0b584 100644 --- a/src/blenderbim/blenderbim/bim/module/qto/ui.py +++ b/src/blenderbim/blenderbim/bim/module/qto/ui.py @@ -16,10 +16,11 @@ # You should have received a copy of the GNU General Public License # along with BlenderBIM Add-on. If not, see . -from bpy.types import Panel +import bpy +from blenderbim.bim.module.qto.data import QtoData -class BIM_PT_qto_utilities(Panel): +class BIM_PT_qto_utilities(bpy.types.Panel): bl_idname = "BIM_PT_qto_utilities" bl_label = "Quantity Take-off" bl_options = {"DEFAULT_CLOSED"} @@ -28,6 +29,9 @@ class BIM_PT_qto_utilities(Panel): bl_category = "BlenderBIM" def draw(self, context): + if not QtoData.is_loaded: + QtoData.load() + layout = self.layout props = context.scene.BIMQtoProperties @@ -51,9 +55,34 @@ class BIM_PT_qto_utilities(Panel): row.prop(props, "qto_name", text="") row.prop(props, "prop_name", text="") row.operator("bim.quantify_objects", icon="COPYDOWN", text="") - + row = layout.row(align=True) row.operator("bim.assign_objects_base_qto") row = layout.row(align=True) row.operator("bim.calculate_all_quantities", icon="MOD_EDGESPLIT") + + if context.selected_objects: + row = layout.row(align=True) + row.label(text=f"Relating Cost Item:") + + if QtoData.data['has_cost_item']: + for relating_cost_item in QtoData.data['relating_cost_items']: + row.label(text=f"\n") + row = layout.row(align=True) + row.label(text=f"Cost item name:") + row.label(text=f"{relating_cost_item['cost_item_name']}") + row = layout.row(align=True) + row.label(text=f"Quantity name:") + row.label(text=f"{relating_cost_item['quantity_name']}") + row = layout.row(align=True) + row.label(text=f"Quantity value:") + row.label(text=f"{relating_cost_item['quantity_value']}") + row = layout.row(align=True) + row.label(text=f"Quantity type:") + row.label(text=f"{relating_cost_item['quantity_type']}") + row = layout.row(align=True) + else: + row = layout.row(align=True) + row.label(text = f"No cost item related") + diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index 39d3b5e3b5..e4b4444f58 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -518,6 +518,7 @@ class Qto: def add_product_base_qto(cls, product): pass def get_new_calculated_quantity(cls, qto_name, quantity_name, object): pass def get_new_guessed_quantity(cls, object, qto_name, quantity_name, ): pass + def get_related_cost_item_quantities(cls, product): pass @interface @@ -625,7 +626,7 @@ class Sequence: def get_recurrence_pattern_attributes(cls, recurrence_pattern): pass def get_recurrence_pattern_times(cls): pass def get_rel_sequence_attributes(cls): pass - + def get_selected_resource(cls): pass def get_start_date(cls): pass def get_task_attribute_value(cls, attribute_name): pass diff --git a/src/blenderbim/blenderbim/tool/qto.py b/src/blenderbim/blenderbim/tool/qto.py index 290354d5ae..2dbf11e285 100644 --- a/src/blenderbim/blenderbim/tool/qto.py +++ b/src/blenderbim/blenderbim/tool/qto.py @@ -127,3 +127,54 @@ class Qto(blenderbim.core.tool.Qto): ): continue return rel.RelatingPropertyDefinition + + @classmethod + def get_related_cost_item_quantities(cls, product): + """_summary_: Returns the related cost item and related quantities of the product + + :param ifc-instance product: ifc instance + :type product: ifcopenshell.entity_instance.entity_instance + + :return list of dictionaries in the form [ + { + "cost_item_id" : XX, + "cost_item_name" : XX, + "quantity_id" : XX, + "quantity_name" : XX, + "quantity_value" : XX, + "quantity_type" : XX + }] + :rtype list + + Example: + + .. code::Python + import blenderbim.tool as tool + + relating_cost_items = tool.Qto.relating_cost_items(my_beautiful_wall) + for relating_cost_item in relating_cost_items: + print(f"RELATING COST ITEM NAME: {relating_cost_item["cost_item_name"]}") + print(f"RELATING COST QUANTITY NAME: {relating_cost_item["quantity_name"]}") + ... + """ + quantities = cls.get_base_qto(product).Quantities + model = tool.Ifc.get() + cost_items = model.by_type("IfcCostItem") + result = [] + + for cost_item in cost_items: + cost_item_quantities = cost_item.CostQuantities if cost_item.CostQuantities is not None else [] + for cost_item_quantity in cost_item_quantities: + for quantity in quantities: + if quantity == cost_item_quantity: + result.append( + { + "cost_item_id" : cost_item.id(), + "cost_item_name" : cost_item.Name, + "quantity_id" : quantity.id(), + "quantity_name" : quantity.Name, + "quantity_value" : quantity[3], + "quantity_type" : quantity.is_a(), + } + ) + return result diff --git a/src/blenderbim/test/tool/test_qto.py b/src/blenderbim/test/tool/test_qto.py index 382c02a2c9..e5fe515d3e 100644 --- a/src/blenderbim/test/tool/test_qto.py +++ b/src/blenderbim/test/tool/test_qto.py @@ -142,3 +142,19 @@ class TestGetBaseQto(test.bim.bootstrap.NewFile): product = tool.Ifc.get_entity(wall_obj) assert not subject.get_base_qto(product) == True +class TestGetRelatedCostItemQuantities(test.bim.bootstrap.NewFile): + def test_run(self): + ifc = ifcopenshell.file() + tool.Ifc.set(ifc) + wall = ifc.createIfcWall() + product = tool.Ifc.get_entity(wall) + schedule = ifcopenshell.api.run("cost.add_cost_schedule", ifc) + item = ifcopenshell.api.run("cost.add_cost_item", ifc, cost_schedule=schedule) + ifcopenshell.api.run("cost.edit_cost_item", ifc, cost_item=item, attributes={"Name": "Foo"}) + qto = ifcopenshell.api.run("pset.add_qto", ifc, product=wall, name="Qto_WallBaseQuantities") + ifcopenshell.api.run("pset.edit_qto", ifc, qto=qto, properties={"NetVolume": 42.0}) + ifcopenshell.api.run("cost.assign_cost_item_quantity", ifc, cost_item=item, products=[wall], prop_name="NetVolume") + assert subject.get_related_cost_item_quantities(wall)[0]['cost_item_name'] == "Foo" + assert subject.get_related_cost_item_quantities(wall)[0]['quantity_name'] == "NetVolume" + assert subject.get_related_cost_item_quantities(wall)[0]['quantity_value'] == 42 + assert subject.get_related_cost_item_quantities(wall)[0]['quantity_type'] == "IfcQuantityVolume"