From 8e279ea86294cf08f5483c41c060627a27b3b2b9 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 4 Jun 2021 15:21:48 +1000 Subject: [PATCH] Improved date calculations during import and editing ensure that start / finish dates are always on working days. --- .../blenderbim/bim/module/sequence/prop.py | 2 +- .../api/sequence/edit_task_time.py | 42 +++++++++++-------- src/ifcp6/ifcp6/p62ifc.py | 20 ++++----- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/sequence/prop.py b/src/blenderbim/blenderbim/bim/module/sequence/prop.py index 47e7e0146b..0271c9320c 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/prop.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/prop.py @@ -126,7 +126,7 @@ def updateTaskduration(self, context): ) Data.load(IfcStore.get_file()) if props.active_task_id == self.ifc_definition_id: - attribute = props.task_attributes.get("Duration") + attribute = props.task_time_attributes.get("Duration") attribute.string_value = self.duration bpy.ops.bim.load_task_properties(task=props.active_task_id) diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_task_time.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_task_time.py index e4c3f8118a..976442ab75 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_task_time.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_task_time.py @@ -12,11 +12,27 @@ class Usecase: def execute(self): # If the user specifies both an end date and a duration, the duration takes priority - if "ScheduleDuration" in self.settings["attributes"].keys() and "ScheduleFinish" in self.settings["attributes"].keys(): + if ( + "ScheduleDuration" in self.settings["attributes"].keys() + and "ScheduleFinish" in self.settings["attributes"].keys() + ): del self.settings["attributes"]["ScheduleFinish"] - if "ActualDuration" in self.settings["attributes"].keys() and "ActualFinish" in self.settings["attributes"].keys(): + if ( + "ActualDuration" in self.settings["attributes"].keys() + and "ActualFinish" in self.settings["attributes"].keys() + ): del self.settings["attributes"]["ActualFinish"] + duration_type = self.settings["attributes"].get("DurationType", self.settings["task_time"].DurationType) + if "ScheduleFinish" in self.settings["attributes"]: + self.settings["attributes"]["ScheduleFinish"] = ifcopenshell.util.sequence.get_soonest_working_day( + self.settings["attributes"]["ScheduleFinish"], duration_type, self.get_calendar() + ) + if "ScheduleStart" in self.settings["attributes"]: + self.settings["attributes"]["ScheduleStart"] = ifcopenshell.util.sequence.get_soonest_working_day( + self.settings["attributes"]["ScheduleStart"], duration_type, self.get_calendar() + ) + for name, value in self.settings["attributes"].items(): if value: if "Start" in name or "Finish" in name or name == "StatusTime": @@ -37,21 +53,13 @@ class Usecase: self.calculate_duration() def calculate_finish(self): - start = ifcopenshell.util.date.ifc2datetime(self.settings["task_time"].ScheduleStart) - current_date = datetime.date(start.year, start.month, start.day) - duration = ifcopenshell.util.date.ifc2datetime(self.settings["task_time"].ScheduleDuration).days - - calendar = self.get_calendar() - - while duration >= 0: - if self.settings["task_time"].DurationType == "ELAPSEDTIME" or not calendar: - duration -= 1 - elif ifcopenshell.util.sequence.is_working_day(current_date, calendar): - duration -= 1 - current_date += datetime.timedelta(days=1) - - current_date -= datetime.timedelta(days=1) - self.settings["task_time"].ScheduleFinish = ifcopenshell.util.date.datetime2ifc(current_date, "IfcDateTime") + finish_date = ifcopenshell.util.sequence.get_finish_date( + ifcopenshell.util.date.ifc2datetime(self.settings["task_time"].ScheduleStart), + ifcopenshell.util.date.ifc2datetime(self.settings["task_time"].ScheduleDuration), + self.settings["task_time"].DurationType, + self.get_calendar(), + ) + self.settings["task_time"].ScheduleFinish = ifcopenshell.util.date.datetime2ifc(finish_date, "IfcDateTime") def calculate_duration(self): start = ifcopenshell.util.date.ifc2datetime(self.settings["task_time"].ScheduleStart) diff --git a/src/ifcp6/ifcp6/p62ifc.py b/src/ifcp6/ifcp6/p62ifc.py index be3052bceb..d4021a746f 100644 --- a/src/ifcp6/ifcp6/p62ifc.py +++ b/src/ifcp6/ifcp6/p62ifc.py @@ -70,7 +70,7 @@ class P62Ifc: exceptions = {} holiday_or_exceptions = calendar.find("pr:HolidayOrExceptions", self.ns) holiday_or_exception = [] - if holiday_or_exceptions: + if holiday_or_exceptions is not None: holiday_or_exception = holiday_or_exceptions.findall("pr:HolidayOrException", self.ns) for exception in holiday_or_exception: d = datetime.datetime.fromisoformat(exception.find("pr:Date", self.ns).text).date() @@ -337,6 +337,15 @@ class P62Ifc: ) task_time = ifcopenshell.api.run("sequence.add_task_time", self.file, task=activity["ifc"]) calendar = self.calendars[activity["CalendarObjectId"]] + # Seems intermittently crashy - can we investigate for larger files? + ifcopenshell.api.run( + "control.assign_control", + self.file, + **{ + "relating_control": calendar["ifc"], + "related_object": activity["ifc"], + }, + ) ifcopenshell.api.run( "sequence.edit_task_time", self.file, @@ -353,15 +362,6 @@ class P62Ifc: else None, }, ) - # Seems intermittently crashy - can we investigate for larger files? - ifcopenshell.api.run( - "control.assign_control", - self.file, - **{ - "relating_control": calendar["ifc"], - "related_object": activity["ifc"], - }, - ) def create_rel_sequences(self): self.sequence_type_map = {