mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-23 13:16:25 +00:00
See #6570. More consistent cost rate assignment
Now when a cost rate is assigned to a cost item, it creates also a relation between them, making the relation more consistent. It is also shown in the UI
This commit is contained in:
committed by
Massimo Fabbro
parent
8cb871a6a2
commit
2bef2a0219
@@ -64,6 +64,7 @@ classes = (
|
|||||||
operator.RefreshCostScheduleCsv,
|
operator.RefreshCostScheduleCsv,
|
||||||
operator.LoadCostItemElementQuantities,
|
operator.LoadCostItemElementQuantities,
|
||||||
operator.LoadCostItemQuantities,
|
operator.LoadCostItemQuantities,
|
||||||
|
operator.ShowAssignedCostRate,
|
||||||
operator.LoadCostItemResourceQuantities,
|
operator.LoadCostItemResourceQuantities,
|
||||||
operator.LoadCostItemTaskQuantities,
|
operator.LoadCostItemTaskQuantities,
|
||||||
operator.LoadCostItemTypes,
|
operator.LoadCostItemTypes,
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ class CostSchedulesData:
|
|||||||
cls._load_cost_item_quantities(cost_item, data)
|
cls._load_cost_item_quantities(cost_item, data)
|
||||||
cls._load_cost_values(cost_item, data)
|
cls._load_cost_values(cost_item, data)
|
||||||
cls._load_nesting_index(cost_item, data)
|
cls._load_nesting_index(cost_item, data)
|
||||||
|
cls._load_assigned_cost_rate(cost_item, data)
|
||||||
results[cost_item.id()] = data
|
results[cost_item.id()] = data
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@@ -154,7 +155,12 @@ class CostSchedulesData:
|
|||||||
else:
|
else:
|
||||||
data["TotalCost"] = data["TotalAppliedValue"] * cost_quantity
|
data["TotalCost"] = data["TotalAppliedValue"] * cost_quantity
|
||||||
if is_sum:
|
if is_sum:
|
||||||
|
#pass If it is None it doesn't allow me to assign a cost rate composed by sum
|
||||||
data["TotalAppliedValue"] = None
|
data["TotalAppliedValue"] = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _load_assigned_cost_rate(cls, cost_item: ifcopenshell.entity_instance, data: CostItem) -> None:
|
||||||
|
data["AssignedCostRate"] = tool.Cost.get_cost_item_rate_assignment(cost_item)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _load_cost_item_quantities(cls, cost_item: ifcopenshell.entity_instance, data: CostItem) -> None:
|
def _load_cost_item_quantities(cls, cost_item: ifcopenshell.entity_instance, data: CostItem) -> None:
|
||||||
@@ -248,6 +254,8 @@ class CostSchedulesData:
|
|||||||
) -> None:
|
) -> None:
|
||||||
value_data = cost_value.get_info()
|
value_data = cost_value.get_info()
|
||||||
del value_data["AppliedValue"]
|
del value_data["AppliedValue"]
|
||||||
|
if tool.Cost.get_assigned_rate_cost_item(root_element):
|
||||||
|
root_element = tool.Cost.get_assigned_rate_cost_item(root_element)
|
||||||
if value_data["UnitBasis"]:
|
if value_data["UnitBasis"]:
|
||||||
data = cost_value.UnitBasis.get_info()
|
data = cost_value.UnitBasis.get_info()
|
||||||
data["ValueComponent"] = data["ValueComponent"].wrappedValue
|
data["ValueComponent"] = data["ValueComponent"].wrappedValue
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
# pyright: reportUnnecessaryTypeIgnoreComment=error
|
# pyright: reportUnnecessaryTypeIgnoreComment=error
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
import textwrap
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
from bpy_extras.io_utils import ImportHelper, ExportHelper
|
from bpy_extras.io_utils import ImportHelper, ExportHelper
|
||||||
@@ -607,6 +608,33 @@ class LoadCostItemQuantities(bpy.types.Operator):
|
|||||||
core.load_cost_item_quantities(tool.Cost)
|
core.load_cost_item_quantities(tool.Cost)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
class ShowAssignedCostRate(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.show_assigned_cost_rate"
|
||||||
|
bl_label = "Info about the assigned cost item rate"
|
||||||
|
bl_options = {"REGISTER"}
|
||||||
|
assigned_rate_id: bpy.props.IntProperty()
|
||||||
|
assigned_rate_name: bpy.props.StringProperty()
|
||||||
|
assigned_rate_description: bpy.props.StringProperty()
|
||||||
|
assigned_rate_total_value: bpy.props.FloatProperty()
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
wm = context.window_manager
|
||||||
|
return wm.invoke_props_dialog(self, width=450)
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
#core.load_cost_item_quantities(tool.Cost) IS IT NECESSARY?
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
wrapper = textwrap.TextWrapper(width=80)
|
||||||
|
layout.label(text=f"ID: {self.assigned_rate_id}")
|
||||||
|
layout.label(text=f"Name: {self.assigned_rate_name}")
|
||||||
|
layout.label(text="Description:")
|
||||||
|
for line in wrapper.wrap(str(self.assigned_rate_description)):
|
||||||
|
layout.label(text=line)
|
||||||
|
layout.label(text=f"Value: {self.assigned_rate_total_value}")
|
||||||
|
|
||||||
|
|
||||||
class LoadCostItemElementQuantities(bpy.types.Operator):
|
class LoadCostItemElementQuantities(bpy.types.Operator):
|
||||||
bl_idname = "bim.load_cost_item_element_quantities"
|
bl_idname = "bim.load_cost_item_element_quantities"
|
||||||
@@ -658,7 +686,10 @@ class AssignCostValue(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.assign_cost_value(
|
core.assign_cost_value(
|
||||||
tool.Ifc, cost_item=tool.Ifc.get().by_id(self.cost_item), cost_rate=tool.Ifc.get().by_id(self.cost_rate)
|
tool.Ifc,
|
||||||
|
tool.Cost,
|
||||||
|
cost_item=tool.Ifc.get().by_id(self.cost_item),
|
||||||
|
cost_rate=tool.Ifc.get().by_id(self.cost_rate)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -655,6 +655,8 @@ class BIM_UL_cost_items_trait:
|
|||||||
for column in props.columns:
|
for column in props.columns:
|
||||||
split2.label(text=column.name)
|
split2.label(text=column.name)
|
||||||
split2.label(text="Total Cost")
|
split2.label(text="Total Cost")
|
||||||
|
split2.alignment = "LEFT"
|
||||||
|
split2.label(text="Rate")
|
||||||
|
|
||||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||||
if item:
|
if item:
|
||||||
@@ -684,6 +686,8 @@ class BIM_UL_cost_items_trait:
|
|||||||
|
|
||||||
if self.props.change_cost_item_parent:
|
if self.props.change_cost_item_parent:
|
||||||
self.draw_parent_operator(row, item.ifc_definition_id)
|
self.draw_parent_operator(row, item.ifc_definition_id)
|
||||||
|
|
||||||
|
self.draw_assigned_rate_column(split2, cost_item)
|
||||||
|
|
||||||
# TODO: reimplement "bim.copy_cost_item_values" somewhere with better UX
|
# TODO: reimplement "bim.copy_cost_item_values" somewhere with better UX
|
||||||
|
|
||||||
@@ -723,6 +727,18 @@ class BIM_UL_cost_items_trait:
|
|||||||
layout.label(text=label)
|
layout.label(text=label)
|
||||||
else:
|
else:
|
||||||
layout.label(text="-")
|
layout.label(text="-")
|
||||||
|
|
||||||
|
def draw_assigned_rate_column(self, layout, cost_item):
|
||||||
|
row=layout.row()
|
||||||
|
row.alignment= "LEFT"
|
||||||
|
if cost_item["AssignedCostRate"] is not None:
|
||||||
|
op = row.operator("bim.show_assigned_cost_rate", text="", emboss=False, icon="ZOOM_IN")
|
||||||
|
op.assigned_rate_id = cost_item["AssignedCostRate"].id()
|
||||||
|
op.assigned_rate_name = cost_item["AssignedCostRate"].Name or ""
|
||||||
|
op.assigned_rate_description = cost_item["AssignedCostRate"].Description or ""
|
||||||
|
op.assigned_rate_total_value = CostSchedulesData.data["cost_items"][cost_item["AssignedCostRate"].id()]["TotalAppliedValue"]
|
||||||
|
else:
|
||||||
|
row.label(text="-")
|
||||||
|
|
||||||
def draw_value_column(self, layout, cost_item):
|
def draw_value_column(self, layout, cost_item):
|
||||||
if cost_item["TotalAppliedValue"]:
|
if cost_item["TotalAppliedValue"]:
|
||||||
|
|||||||
@@ -193,9 +193,18 @@ def load_cost_item_resource_quantities(cost: tool.Cost) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def assign_cost_value(
|
def assign_cost_value(
|
||||||
ifc: tool.Ifc, cost_item: ifcopenshell.entity_instance, cost_rate: ifcopenshell.entity_instance
|
ifc: tool.Ifc,
|
||||||
|
cost: tool.Cost,
|
||||||
|
cost_item: ifcopenshell.entity_instance,
|
||||||
|
cost_rate: ifcopenshell.entity_instance
|
||||||
) -> None:
|
) -> None:
|
||||||
ifc.run("cost.assign_cost_value", cost_item=cost_item, cost_rate=cost_rate)
|
ifc.run("cost.assign_cost_value", cost_item=cost_item, cost_rate=cost_rate)
|
||||||
|
existing_cost_rate = cost.get_cost_item_rate_assignment(cost_item)
|
||||||
|
if existing_cost_rate is None:
|
||||||
|
ifc.run("control.assign_control", relating_control=cost_rate, related_object=cost_item)
|
||||||
|
else:
|
||||||
|
ifc.run("control.unassign_control", relating_control=existing_cost_rate, related_object=cost_item)
|
||||||
|
ifc.run("control.assign_control", relating_control=cost_rate, related_object=cost_item)
|
||||||
|
|
||||||
|
|
||||||
def load_schedule_of_rates(cost: tool.Cost, schedule_of_rates: ifcopenshell.entity_instance) -> None:
|
def load_schedule_of_rates(cost: tool.Cost, schedule_of_rates: ifcopenshell.entity_instance) -> None:
|
||||||
|
|||||||
@@ -228,6 +228,7 @@ class Cost:
|
|||||||
def get_active_cost_schedule(cls): pass
|
def get_active_cost_schedule(cls): pass
|
||||||
def get_active_cost_schedule(cls): pass
|
def get_active_cost_schedule(cls): pass
|
||||||
def get_attributes_for_cost_value(cls, cost_type, cost_category): pass
|
def get_attributes_for_cost_value(cls, cost_type, cost_category): pass
|
||||||
|
def get_assigned_rate_cost_item(cls, cost_item): pass
|
||||||
def get_cost_item_attributes(cls, cost_item): pass
|
def get_cost_item_attributes(cls, cost_item): pass
|
||||||
def get_cost_item_products(cls): pass
|
def get_cost_item_products(cls): pass
|
||||||
def get_cost_item_quantity_attributes(cls): pass
|
def get_cost_item_quantity_attributes(cls): pass
|
||||||
|
|||||||
@@ -835,6 +835,12 @@ class Cost(bonsai.core.tool.Cost):
|
|||||||
]
|
]
|
||||||
return bool(cost_items)
|
return bool(cost_items)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_assigned_rate_cost_item(cls, cost_item: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
|
||||||
|
for assignment in cost_item.HasAssignments:
|
||||||
|
if assignment.RelatingControl.is_a() == "IfcCostItem":
|
||||||
|
return assignment.RelatingControl
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_product_cost_items(cls, product: ifcopenshell.entity_instance) -> None:
|
def load_product_cost_items(cls, product: ifcopenshell.entity_instance) -> None:
|
||||||
props = cls.get_cost_props()
|
props = cls.get_cost_props()
|
||||||
|
|||||||
Reference in New Issue
Block a user