From 382e028b903be0fb9588e601343e10b93ea620ef Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Wed, 22 May 2024 13:40:22 +0500 Subject: [PATCH] csv to cost schedule - support more cases of 0 quantity #4704 Before - https://i.imgur.com/CYwSGxY.png After - https://i.imgur.com/Wbe6Ij6.png I'll attach example .csv and .ifc in #4704 What changed: 1) If query was provided but it didn't found any elements, then it will still autoassign quantity = 0 instead of cost item end up without quantities at all (which has a different meaning in ifc). Works both with Property provided and without it. 2) If provided quantity = 0, it will now load as quantity = 0 instead of not creating any quantities at all. 3) You can provide both Query and Quantity and they all will be added to the cost item. E.g. if Quantity = 15, Query = "IfcWall", Property="Prop" and there are 3 walls in the model each having Prop = 25 then final quantity will be 15+25*3=90. Previously Quantity would take the priority and the result would be just = 15. Though this is still doesn't work with counting quantities due behaviour in cost.assign_cost_item_quantity. E.g. if Quantity = 7, Query = "IfcWall", Property="" (to make sure it will just count them) and there are 3 walls in the model then final quantity will be not 7+3=10 but just = 3, as query will take the priority here. --- src/ifc5d/ifc5d/csv2ifc.py | 28 +++++++++++++------ .../api/cost/assign_cost_item_quantity.py | 4 +++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/ifc5d/ifc5d/csv2ifc.py b/src/ifc5d/ifc5d/csv2ifc.py index 8483d34dd4..3bdaa0d93c 100644 --- a/src/ifc5d/ifc5d/csv2ifc.py +++ b/src/ifc5d/ifc5d/csv2ifc.py @@ -173,24 +173,30 @@ class Csv2Ifc: cost_value.UnitBasis = self.file.createIfcMeasureWithUnit(value_component, unit_component) - if not self.is_schedule_of_rates and cost_item["Quantity"]: - quantity_class = ifcopenshell.util.unit.get_symbol_quantity_class(cost_item["Unit"]) + quantity = None + quantity_class = ifcopenshell.util.unit.get_symbol_quantity_class(cost_item["Unit"]) + if not cost_item["assignments"]["PropertyName"] or cost_item["assignments"]["PropertyName"].upper() == "COUNT": + prop_name = "" + else: + prop_name = cost_item["assignments"]["PropertyName"] + + if not self.is_schedule_of_rates and cost_item["Quantity"] is not None: quantity = ifcopenshell.api.run( "cost.add_cost_item_quantity", self.file, cost_item=cost_item["ifc"], ifc_class=quantity_class ) # 3 IfcPhysicalSimpleQuantity Value quantity[3] = cost_item["Quantity"] + if prop_name: + quantity.Name = prop_name if cost_item["assignments"]["Query"]: - if ( - not cost_item["assignments"]["PropertyName"] - or cost_item["assignments"]["PropertyName"].upper() == "COUNT" - ): - prop_name = "" - else: - prop_name = cost_item["assignments"]["PropertyName"] results = ifcopenshell.util.selector.filter_elements(self.file, cost_item["assignments"]["Query"]) results = [r for r in results if has_property(self.file, r, prop_name)] + # NOTE: currently we do not support count quantities that have + # both defined quantity in .csv "Quantity" column + # and some query in "Query" column. + # If query is provided it will override the defined value + # due current behaviour in cost.assign_cost_item_quantity. if results: ifcopenshell.api.run( "cost.assign_cost_item_quantity", @@ -199,6 +205,10 @@ class Csv2Ifc: products=results, prop_name=prop_name, ) + elif not quantity: + quantity = ifcopenshell.api.run( + "cost.add_cost_item_quantity", self.file, cost_item=cost_item["ifc"], ifc_class=quantity_class + ) self.create_cost_items(cost_item["children"], cost_item["ifc"]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_quantity.py b/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_quantity.py index bf5b412a21..ae0643acae 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_quantity.py +++ b/src/ifcopenshell-python/ifcopenshell/api/cost/assign_cost_item_quantity.py @@ -44,6 +44,10 @@ def assign_cost_item_quantity( cost item and the product, so it is not necessary to use ifcopenshell.api.control.assign_control. + If cost item has just 1 quantity and it's IfcQuantityCount, API will + assume that quantity is used for counting controlled objects + and it will recalculate the quantity value at the end of the API call. + :param cost_item: The IfcCostItem to assign parametric quantities to :type cost_item: ifcopenshell.entity_instance :param products: The IfcObjects to assign parametric quantities to