mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +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.LoadCostItemElementQuantities,
|
||||
operator.LoadCostItemQuantities,
|
||||
operator.ShowAssignedCostRate,
|
||||
operator.LoadCostItemResourceQuantities,
|
||||
operator.LoadCostItemTaskQuantities,
|
||||
operator.LoadCostItemTypes,
|
||||
|
||||
@@ -110,6 +110,7 @@ class CostSchedulesData:
|
||||
cls._load_cost_item_quantities(cost_item, data)
|
||||
cls._load_cost_values(cost_item, data)
|
||||
cls._load_nesting_index(cost_item, data)
|
||||
cls._load_assigned_cost_rate(cost_item, data)
|
||||
results[cost_item.id()] = data
|
||||
return results
|
||||
|
||||
@@ -154,7 +155,12 @@ class CostSchedulesData:
|
||||
else:
|
||||
data["TotalCost"] = data["TotalAppliedValue"] * cost_quantity
|
||||
if is_sum:
|
||||
#pass If it is None it doesn't allow me to assign a cost rate composed by sum
|
||||
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
|
||||
def _load_cost_item_quantities(cls, cost_item: ifcopenshell.entity_instance, data: CostItem) -> None:
|
||||
@@ -248,6 +254,8 @@ class CostSchedulesData:
|
||||
) -> None:
|
||||
value_data = cost_value.get_info()
|
||||
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"]:
|
||||
data = cost_value.UnitBasis.get_info()
|
||||
data["ValueComponent"] = data["ValueComponent"].wrappedValue
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
# pyright: reportUnnecessaryTypeIgnoreComment=error
|
||||
|
||||
import bpy
|
||||
import textwrap
|
||||
import ifcopenshell.api
|
||||
import bonsai.tool as tool
|
||||
from bpy_extras.io_utils import ImportHelper, ExportHelper
|
||||
@@ -607,6 +608,33 @@ class LoadCostItemQuantities(bpy.types.Operator):
|
||||
core.load_cost_item_quantities(tool.Cost)
|
||||
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):
|
||||
bl_idname = "bim.load_cost_item_element_quantities"
|
||||
@@ -658,7 +686,10 @@ class AssignCostValue(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
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:
|
||||
split2.label(text=column.name)
|
||||
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):
|
||||
if item:
|
||||
@@ -684,6 +686,8 @@ class BIM_UL_cost_items_trait:
|
||||
|
||||
if self.props.change_cost_item_parent:
|
||||
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
|
||||
|
||||
@@ -723,6 +727,18 @@ class BIM_UL_cost_items_trait:
|
||||
layout.label(text=label)
|
||||
else:
|
||||
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):
|
||||
if cost_item["TotalAppliedValue"]:
|
||||
|
||||
@@ -193,9 +193,18 @@ def load_cost_item_resource_quantities(cost: tool.Cost) -> None:
|
||||
|
||||
|
||||
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:
|
||||
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:
|
||||
|
||||
@@ -228,6 +228,7 @@ class Cost:
|
||||
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_assigned_rate_cost_item(cls, cost_item): pass
|
||||
def get_cost_item_attributes(cls, cost_item): pass
|
||||
def get_cost_item_products(cls): pass
|
||||
def get_cost_item_quantity_attributes(cls): pass
|
||||
|
||||
@@ -835,6 +835,12 @@ class Cost(bonsai.core.tool.Cost):
|
||||
]
|
||||
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
|
||||
def load_product_cost_items(cls, product: ifcopenshell.entity_instance) -> None:
|
||||
props = cls.get_cost_props()
|
||||
|
||||
Reference in New Issue
Block a user