diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/calculate_cost_item_resource_value.py b/src/ifcopenshell-python/ifcopenshell/api/cost/calculate_cost_item_resource_value.py index fcdd4084ce..e1eb12db85 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/cost/calculate_cost_item_resource_value.py +++ b/src/ifcopenshell-python/ifcopenshell/api/cost/calculate_cost_item_resource_value.py @@ -101,12 +101,11 @@ def calculate_cost_item_resource_value(file: ifcopenshell.file, cost_item: ifcop for resource in resources: cost, unit = ifcopenshell.util.resource.get_cost(resource) - # TODO: cost is never None because get_cost always returns a float. if cost is None: # Concept to standardise - Not defined in schema, but this makes manual scheduling of resources 10x faster and less duplicate data. parent_cost = ifcopenshell.util.resource.get_parent_cost(resource) - assert parent_cost - cost, unit = parent_cost + if parent_cost: + cost, unit = parent_cost quantity = ifcopenshell.util.resource.get_quantity(resource) if cost is None: continue diff --git a/src/ifcopenshell-python/ifcopenshell/util/resource.py b/src/ifcopenshell-python/ifcopenshell/util/resource.py index 2df15e7a63..f518a09125 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/resource.py +++ b/src/ifcopenshell-python/ifcopenshell/util/resource.py @@ -139,22 +139,18 @@ def get_nested_resources(resource: ifcopenshell.entity_instance) -> list[ifcopen return [object for rel in resource.IsNestedBy or [] for object in rel.RelatedObjects] -def get_cost(resource: ifcopenshell.entity_instance) -> tuple[float, Union[str, None]]: - base_costs = getattr(resource, "BaseCosts", []) - costs = ( - [ifcopenshell.util.cost.calculate_applied_value(resource, cost_value) for cost_value in base_costs] - if base_costs - else [] - ) - cost = sum(costs) - unit_basis = ( - next((cost_value.UnitBasis for cost_value in base_costs if cost_value.UnitBasis), None) if base_costs else None - ) - unit = ( - unit_basis.UnitComponent.Name - if unit_basis and unit_basis.UnitComponent.is_a("IfcConversionBasedUnit") - else None - ) +def get_cost(resource: ifcopenshell.entity_instance) -> tuple[Union[float, None], Union[str, None]]: + """Get cost data for IfcConstructionResource. + + :return: a tuple of cost and unit. + """ + cost, unit = None, None + if base_costs := resource.BaseCosts: + costs = [ifcopenshell.util.cost.calculate_applied_value(resource, cost_value) for cost_value in base_costs] + cost = sum(costs) + unit_basis = next((unit_basis for cost_value in base_costs if (unit_basis := cost_value.UnitBasis)), None) + if unit_basis and (unit_component := unit_basis.UnitComponent).is_a("IfcConversionBasedUnit"): + unit = unit_component.Name return cost, unit @@ -167,7 +163,7 @@ def get_quantity(resource: ifcopenshell.entity_instance) -> float: return 1.0 if quantity is None else quantity[3] -def get_parent_cost(resource: ifcopenshell.entity_instance) -> Union[tuple[float, Union[str, None]], None]: +def get_parent_cost(resource: ifcopenshell.entity_instance) -> Union[tuple[Union[float, None], Union[str, None]], None]: if not (nests := resource.Nests): return else: