From e6747b258cb7dac2975c67903355df31bb767ef6 Mon Sep 17 00:00:00 2001 From: falken10 Date: Tue, 24 Jun 2025 19:08:09 +0200 Subject: [PATCH] Remove CostSchedulesMapping and added csv_filepaths to data.py --- src/bonsai/bonsai/bim/module/cost/__init__.py | 1 - src/bonsai/bonsai/bim/module/cost/data.py | 28 ++++++++++++++ src/bonsai/bonsai/bim/module/cost/operator.py | 38 +++++++++++++------ src/bonsai/bonsai/bim/module/cost/prop.py | 12 ------ src/bonsai/bonsai/bim/module/cost/ui.py | 26 ++----------- 5 files changed, 58 insertions(+), 47 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/cost/__init__.py b/src/bonsai/bonsai/bim/module/cost/__init__.py index 8f53f85015..5152cbdf04 100644 --- a/src/bonsai/bonsai/bim/module/cost/__init__.py +++ b/src/bonsai/bonsai/bim/module/cost/__init__.py @@ -84,7 +84,6 @@ classes = ( prop.CostItem, prop.CostItemQuantity, prop.CostItemType, - prop.CostSchedulesMapping, prop.ScheduleColumn, prop.BIMCostProperties, ui.BIM_PT_cost_schedules, diff --git a/src/bonsai/bonsai/bim/module/cost/data.py b/src/bonsai/bonsai/bim/module/cost/data.py index 7d631eaf40..ac05c5001b 100644 --- a/src/bonsai/bonsai/bim/module/cost/data.py +++ b/src/bonsai/bonsai/bim/module/cost/data.py @@ -56,9 +56,37 @@ class CostSchedulesData: "cost_values": cls.cost_values(), "quantity_types": cls.quantity_types(), "currency": cls.currency(), + "csv_filepaths": cls.get_csv_filepaths(), # Add this line } cls.is_loaded = True + @classmethod + def get_csv_filepaths(cls) -> dict[int, str]: + """Get CSV filepaths for cost schedules from document references.""" + filepaths = {} + ifc_file = tool.Ifc.get() + cost_docs_document = next( + ( + document + for document in ifc_file.by_type("IfcDocumentInformation") + if document.Name == "BBIM_Cost_Documents" + ), + None, + ) + + if cost_docs_document: + references = tool.Document.get_document_references(cost_docs_document) + for reference in references: + if reference.Description and "Cost Schedule ID:" in reference.Description: + schedule_id_str = reference.Description.split("Cost Schedule ID:")[1].strip() + try: + schedule_id = int(schedule_id_str) + filepaths[schedule_id] = reference.Location + except ValueError: + pass + + return filepaths + @classmethod def currency(cls) -> Union[Currency, None]: unit = tool.Unit.get_project_currency_unit() diff --git a/src/bonsai/bonsai/bim/module/cost/operator.py b/src/bonsai/bonsai/bim/module/cost/operator.py index f7706ab603..bdf1743f77 100644 --- a/src/bonsai/bonsai/bim/module/cost/operator.py +++ b/src/bonsai/bonsai/bim/module/cost/operator.py @@ -566,29 +566,31 @@ class ImportCostScheduleCsv(bpy.types.Operator, ImportHelper, tool.Ifc.Operator) def _execute(self, context): from pathlib import Path - + from bonsai.bim.module.cost.data import CostSchedulesData + store_path = self.filepath if self.use_relative_path: store_path = tool.Ifc.get_uri(self.filepath, use_relative_path=True) - + resolved_path = Path(tool.Ifc.resolve_uri(self.filepath)) if not resolved_path.exists(): self.report({"ERROR"}, f"File does not exist: '{store_path}' (resolved to '{resolved_path}')") return {"CANCELLED"} - + cost_schedule = core.import_cost_schedule_csv(tool.Cost, str(resolved_path), self.is_schedule_of_rates) if cost_schedule: core.add_csv_filepath(tool.Cost, store_path, self.is_schedule_of_rates, cost_schedule) + CostSchedulesData.is_loaded = False + return {"FINISHED"} return {"CANCELLED"} - + def draw(self, context): row = self.layout.row() row.prop(self, "is_schedule_of_rates") row = self.layout.row() row.prop(self, "use_relative_path") - class RefreshCostScheduleCsv(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.refresh_cost_schedule_csv" bl_label = "Refresh Cost Schedule CSV" @@ -601,42 +603,54 @@ class RefreshCostScheduleCsv(bpy.types.Operator, tool.Ifc.Operator): if not props.active_cost_schedule_id: cls.poll_message_set("No active cost schedule") return False + + file_path = tool.Cost.get_cost_schedule_csv_filepath(props.active_cost_schedule_id) + if not file_path: + cls.poll_message_set("No CSV file associated with this cost schedule") + return False + return True def _execute(self, context): from pathlib import Path - + from bonsai.bim.module.cost.data import CostSchedulesData + props = tool.Cost.get_cost_props() cost_schedule_id = props.active_cost_schedule_id - + file_path = tool.Cost.get_cost_schedule_csv_filepath(cost_schedule_id) + if not file_path: + self.report({"ERROR"}, "No CSV file associated with this cost schedule") + return {"CANCELLED"} + resolved_path = Path(tool.Ifc.resolve_uri(file_path)) if not resolved_path.exists(): self.report({"ERROR"}, f"File does not exist: '{file_path}' (resolved to '{resolved_path}')") return {"CANCELLED"} - + tool.Cost.delete_all_cost_items() - + cost_schedule = tool.Ifc.get_entity_by_id(cost_schedule_id) is_schedule_of_rates = tool.Cost.is_schedule_of_rates_csv(cost_schedule_id) try: from ifc5d.csv2ifc import Csv2Ifc - + csv2ifc = Csv2Ifc() csv2ifc.csv = str(resolved_path) csv2ifc.file = tool.Ifc.get() csv2ifc.cost_schedule = cost_schedule csv2ifc.is_schedule_of_rates = is_schedule_of_rates csv2ifc.refresh() - + tool.Cost.load_cost_schedule_tree() + CostSchedulesData.is_loaded = False + return {"FINISHED"} except Exception as e: self.report({"ERROR"}, f"Error refreshing CSV: {str(e)}") return {"CANCELLED"} - class AddCostColumn(bpy.types.Operator): bl_idname = "bim.add_cost_column" bl_label = "Add Cost Column" diff --git a/src/bonsai/bonsai/bim/module/cost/prop.py b/src/bonsai/bonsai/bim/module/cost/prop.py index fd10660720..9ecea280ce 100644 --- a/src/bonsai/bonsai/bim/module/cost/prop.py +++ b/src/bonsai/bonsai/bim/module/cost/prop.py @@ -174,16 +174,6 @@ class CostItemQuantity(PropertyGroup): unit_symbol: str total_cost_quantity: float - -class CostSchedulesMapping(PropertyGroup): - cost_schedule_id: IntProperty(name="cost_schedule_id") - csv_filepath: StringProperty(name="filepath") - - if TYPE_CHECKING: - cost_schedule_id: int - csv_filepath: str - - class CostItemType(PropertyGroup): name: StringProperty(name="Name") ifc_definition_id: IntProperty(name="IFC Definition ID") @@ -289,7 +279,6 @@ class BIMCostProperties(PropertyGroup): custom_currency: StringProperty( name="Custom Currency", default="USD", description="Custom Currency in ISO 4217 format" ) - cost_schedule_files: CollectionProperty(name="Cost Schedule Files", type=CostSchedulesMapping) if TYPE_CHECKING: cost_schedule_predefined_types: str @@ -344,7 +333,6 @@ class BIMCostProperties(PropertyGroup): show_cost_item_operators: bool currency: str custom_currency: str - cost_schedule_files: bpy.types.bpy_prop_collection_idprop[CostSchedulesMapping] @property def active_cost_item(self) -> Union[CostItem, None]: diff --git a/src/bonsai/bonsai/bim/module/cost/ui.py b/src/bonsai/bonsai/bim/module/cost/ui.py index 8a81368d9e..98997abffd 100644 --- a/src/bonsai/bonsai/bim/module/cost/ui.py +++ b/src/bonsai/bonsai/bim/module/cost/ui.py @@ -76,28 +76,10 @@ class BIM_PT_cost_schedules(Panel): col = row0.column() col.label(text="Linked CSV:") row_1 = col.row(align=True) - - ifc_file = tool.Ifc.get() - cost_docs_document = next( - ( - document - for document in ifc_file.by_type("IfcDocumentInformation") - if document.Name == "BBIM_Cost_Documents" - ), - None, - ) - - file_path = None - if cost_docs_document: - references = tool.Document.get_document_references(cost_docs_document) - for reference in references: - if ( - reference.Description - and f"Cost Schedule ID: {self.props.active_cost_schedule_id}" in reference.Description - ): - file_path = reference.Location - break - + + csv_filepaths = CostSchedulesData.data["csv_filepaths"] + file_path = csv_filepaths.get(self.props.active_cost_schedule_id) + if file_path: row_1.label(text=file_path) row_1.operator("bim.refresh_cost_schedule_csv", icon="FILE_REFRESH", text="")