Fixes to editing task times

This commit is contained in:
Dion Moult
2021-04-20 17:11:06 +10:00
parent 544d6ee695
commit 6d9770542f
7 changed files with 241 additions and 139 deletions
@@ -36,9 +36,9 @@ classes = (
operator.AssignSuccessor, operator.AssignSuccessor,
operator.UnassignPredecessor, operator.UnassignPredecessor,
operator.UnassignSuccessor, operator.UnassignSuccessor,
operator.AddTaskTime,
operator.EnableEditingTaskTime, operator.EnableEditingTaskTime,
operator.DisableEditingTaskTime, operator.DisableEditingTaskTime,
operator.EditTaskTime,
prop.WorkPlan, prop.WorkPlan,
prop.BIMWorkPlanProperties, prop.BIMWorkPlanProperties,
prop.Task, prop.Task,
@@ -1,6 +1,8 @@
import bpy import bpy
import json import json
import ifcopenshell.api import ifcopenshell.api
from datetime import datetime
from dateutil.parser import parse
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.sequence.data import Data from ifcopenshell.api.sequence.data import Data
@@ -232,6 +234,16 @@ class EnableEditingTasks(bpy.types.Operator):
new.ifc_definition_id = related_object_id new.ifc_definition_id = related_object_id
new.name = task["Name"] or "Unnamed" new.name = task["Name"] or "Unnamed"
new.identification = task["Identification"] or "X" new.identification = task["Identification"] or "X"
if task["TaskTime"]:
task_time = Data.task_times[task["TaskTime"]]
new.start = self.canonicalise_time(task_time["ScheduleStart"])
new.finish = self.canonicalise_time(task_time["ScheduleFinish"])
# TODO: duration
new.duration = "-"
else:
new.start = "-"
new.finish = "-"
new.duration = "-"
new.is_expanded = related_object_id not in self.contracted_tasks new.is_expanded = related_object_id not in self.contracted_tasks
new.level_index = level_index new.level_index = level_index
if task["RelatedObjects"]: if task["RelatedObjects"]:
@@ -240,6 +252,11 @@ class EnableEditingTasks(bpy.types.Operator):
for related_object_id in task["RelatedObjects"]: for related_object_id in task["RelatedObjects"]:
self.create_new_task_li(related_object_id, level_index + 1) self.create_new_task_li(related_object_id, level_index + 1)
def canonicalise_time(self, time):
if not time:
return "-"
return time.strftime("%d/%m/%y")
class DisableEditingWorkSchedule(bpy.types.Operator): class DisableEditingWorkSchedule(bpy.types.Operator):
bl_idname = "bim.disable_editing_work_schedule" bl_idname = "bim.disable_editing_work_schedule"
@@ -481,16 +498,12 @@ class EnableEditingTaskTime(bpy.types.Operator):
def execute(self, context): def execute(self, context):
props = context.scene.BIMWorkScheduleProperties props = context.scene.BIMWorkScheduleProperties
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
task_time_id = Data.tasks[self.task]["TaskTime"] or self.add_task_time().id()
while len(props.task_time_attributes) > 0: while len(props.task_time_attributes) > 0:
props.task_time_attributes.remove(0) props.task_time_attributes.remove(0)
if self.file.by_id(self.task).TaskTime:
task_time_id = self.file.by_id(self.task).TaskTime.id()
else:
task_time = ifcopenshell.api.run("sequence.add_task_time", self.file)
self.file.by_id(self.task).TaskTime = task_time
task_time_id = task_time.id()
Data.load(self.file)
data = Data.task_times[task_time_id] data = Data.task_times[task_time_id]
for attribute in IfcStore.get_schema().declaration_by_name("IfcTaskTime").all_attributes(): for attribute in IfcStore.get_schema().declaration_by_name("IfcTaskTime").all_attributes():
@@ -503,18 +516,82 @@ class EnableEditingTaskTime(bpy.types.Operator):
new.is_optional = attribute.optional() new.is_optional = attribute.optional()
new.data_type = data_type new.data_type = data_type
if data_type == "string": if data_type == "string":
new.string_value = "" if new.is_null else data[attribute.name()] if isinstance(data[attribute.name()], datetime):
new.string_value = "" if new.is_null else data[attribute.name()].isoformat()
else:
new.string_value = "" if new.is_null else data[attribute.name()]
elif data_type == "boolean": elif data_type == "boolean":
new.bool_value = False if new.is_null else data[attribute.name()] new.bool_value = False if new.is_null else data[attribute.name()]
elif data_type == "integer": elif data_type == "float":
new.int_value = 0 if new.is_null else data[attribute.name()] new.float_value = 0.0 if new.is_null else data[attribute.name()]
elif data_type == "enum": elif data_type == "enum":
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute)) new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
if data[attribute.name()]: if data[attribute.name()]:
new.enum_value = data[attribute.name()] new.enum_value = data[attribute.name()]
props.active_task_time_id = IfcStore.get_file().by_id(self.task).TaskTime.id() props.active_task_time_id = task_time_id
props.active_task_id = self.task
return {"FINISHED"} return {"FINISHED"}
def add_task_time(self):
task_time = ifcopenshell.api.run("sequence.add_task_time", self.file, task=self.file.by_id(self.task))
Data.load(IfcStore.get_file())
return task_time
class DisableEditingTaskTime(bpy.types.Operator):
bl_idname = "bim.disable_editing_task_time"
bl_label = "Disable Editing Task Time"
def execute(self, context):
context.scene.BIMWorkScheduleProperties.active_task_time_id = 0
bpy.ops.bim.disable_editing_task()
return {"FINISHED"}
class EditTaskTime(bpy.types.Operator):
bl_idname = "bim.edit_task_time"
bl_label = "Edit Task Time"
def execute(self, context):
props = context.scene.BIMWorkScheduleProperties
attributes = {}
for attribute in props.task_time_attributes:
if attribute.is_null:
attributes[attribute.name] = None
else:
if attribute.data_type == "string":
attributes[attribute.name] = attribute.string_value
elif attribute.data_type == "boolean":
attributes[attribute.name] = attribute.bool_value
elif attribute.data_type == "float":
attributes[attribute.name] = attribute.float_value
elif attribute.data_type == "enum":
attributes[attribute.name] = attribute.enum_value
attributes = self.convert_strings_to_date_times(attributes)
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"sequence.edit_task_time",
self.file,
**{"task_time": self.file.by_id(props.active_task_time_id), "attributes": attributes}
)
Data.load(IfcStore.get_file())
bpy.ops.bim.disable_editing_task_time()
bpy.ops.bim.enable_editing_tasks(work_schedule=props.active_work_schedule_id)
return {"FINISHED"}
def convert_strings_to_date_times(self, attributes):
for key, value in attributes.items():
if not value:
continue
if "Start" in key or "Finish" in key or key == "StatusTime":
try:
attributes[key] = parse(value)
except:
attributes[key] = None
return attributes
class EnableEditingTask(bpy.types.Operator): class EnableEditingTask(bpy.types.Operator):
bl_idname = "bim.enable_editing_task" bl_idname = "bim.enable_editing_task"
@@ -551,15 +628,6 @@ class EnableEditingTask(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class DisableEditingTaskTime(bpy.types.Operator):
bl_idname = "bim.disable_editing_task_time"
bl_label = "Disable Editing Task Time"
def execute(self, context):
context.scene.BIMWorkScheduleProperties.active_task_time_id = 0
return {"FINISHED"}
class DisableEditingTask(bpy.types.Operator): class DisableEditingTask(bpy.types.Operator):
bl_idname = "bim.disable_editing_task" bl_idname = "bim.disable_editing_task"
bl_label = "Disable Editing Task" bl_label = "Disable Editing Task"
@@ -670,20 +738,3 @@ class UnassignSuccessor(bpy.types.Operator):
) )
Data.load(self.file) Data.load(self.file)
return {"FINISHED"} return {"FINISHED"}
class AddTaskTime(bpy.types.Operator):
bl_idname = "bim.add_task_time"
bl_label = "Add Task Time"
task: bpy.props.IntProperty()
def execute(self, context):
props = context.scene.BIMWorkScheduleProperties
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"sequence.add_task_time",
self.file,
task = self.file.by_id(self.task),
)
Data.load(self.file)
return {"FINISHED"}
@@ -3,6 +3,7 @@ import ifcopenshell.api
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.sequence.data import Data from ifcopenshell.api.sequence.data import Data
from blenderbim.bim.prop import StrProperty, Attribute from blenderbim.bim.prop import StrProperty, Attribute
from dateutil.parser import parse
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from bpy.props import ( from bpy.props import (
PointerProperty, PointerProperty,
@@ -47,20 +48,53 @@ def updateTaskIdentification(self, context):
attribute = context.scene.BIMWorkScheduleProperties.task_attributes.get("Identification") attribute = context.scene.BIMWorkScheduleProperties.task_attributes.get("Identification")
attribute.string_value = self.identification attribute.string_value = self.identification
def updateTaskTimeScheduleStart(self, context):
if self.schedule_start == "X": def updateTaskTimeStart(self, context):
updateTaskTimeDateTime(self, context, "start")
def updateTaskTimeFinish(self, context):
updateTaskTimeDateTime(self, context, "finish")
def updateTaskTimeDateTime(self, context, startfinish):
def canonicalise_time(time):
if not time:
return "-"
return time.strftime("%d/%m/%y")
startfinish_key = "Schedule" + startfinish.capitalize()
startfinish_value = getattr(self, startfinish)
if startfinish_value == "-":
return return
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
props = context.scene.BIMWorkScheduleProperties props = context.scene.BIMWorkScheduleProperties
try:
startfinish_datetime = parse(startfinish_value)
except:
setattr(self, startfinish, "-")
return
task = self.file.by_id(self.ifc_definition_id)
if task.TaskTime:
task_time = task.TaskTime
else:
task_time = ifcopenshell.api.run("sequence.add_task_time", self.file, task=task)
Data.load(IfcStore.get_file())
if Data.task_times[task_time.id()][startfinish_key] == startfinish_datetime:
return
ifcopenshell.api.run( ifcopenshell.api.run(
"sequence.edit_task_time", "sequence.edit_task_time",
self.file, self.file,
**{"task": self.file.by_id(self.ifc_definition_id), "attributes": {"ScheduleStart": self.schedule_start}} **{"task_time": task_time, "attributes": {startfinish_key: startfinish_datetime}}
) )
Data.load(IfcStore.get_file()) Data.load(IfcStore.get_file())
if props.active_task_id == self.ifc_definition_id: setattr(self, startfinish, canonicalise_time(startfinish_datetime))
attribute = context.scene.BIMWorkScheduleProperties.task_attributes.get("ScheduleStart")
attribute.string_value = self.schedule_start
class Task(PropertyGroup): class Task(PropertyGroup):
name: StringProperty(name="Name", update=updateTaskName) name: StringProperty(name="Name", update=updateTaskName)
@@ -69,9 +103,10 @@ class Task(PropertyGroup):
has_children: BoolProperty(name="Has Children") has_children: BoolProperty(name="Has Children")
is_expanded: BoolProperty(name="Is Expanded") is_expanded: BoolProperty(name="Is Expanded")
level_index: IntProperty(name="Level Index") level_index: IntProperty(name="Level Index")
schedule_duration: StringProperty(name="Duration") duration: StringProperty(name="Duration")
schedule_start: StringProperty(name="Schedule Start ", update=updateTaskTimeScheduleStart) start: StringProperty(name="Start", update=updateTaskTimeStart)
schedule_finish: StringProperty(name="Schedule Finish ") finish: StringProperty(name="Finish", update=updateTaskTimeFinish)
class WorkPlan(PropertyGroup): class WorkPlan(PropertyGroup):
name: StringProperty(name="Name") name: StringProperty(name="Name")
@@ -136,65 +136,39 @@ class BIM_PT_work_schedules(Panel):
"active_task_index", "active_task_index",
) )
if self.props.active_task_id: if self.props.active_task_id:
for attribute in self.props.task_attributes: self.draw_editable_task_attributes_ui()
row = self.layout.row(align=True) if self.props.active_task_time_id:
if attribute.data_type == "string": self.draw_editable_task_time_attributes_ui()
row.prop(attribute, "string_value", text=attribute.name)
elif attribute.data_type == "boolean":
row.prop(attribute, "bool_value", text=attribute.name)
elif attribute.data_type == "integer":
row.prop(attribute, "int_value", text=attribute.name)
elif attribute.data_type == "enum":
row.prop(attribute, "enum_value", text=attribute.name)
if attribute.is_optional:
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
def draw_editable_task_attributes_ui(self):
for attribute in self.props.task_attributes:
row = self.layout.row(align=True)
if attribute.data_type == "string":
row.prop(attribute, "string_value", text=attribute.name)
elif attribute.data_type == "boolean":
row.prop(attribute, "bool_value", text=attribute.name)
elif attribute.data_type == "integer":
row.prop(attribute, "int_value", text=attribute.name)
elif attribute.data_type == "enum":
row.prop(attribute, "enum_value", text=attribute.name)
if attribute.is_optional:
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
class BIM_UL_tasks(UIList): def draw_editable_task_time_attributes_ui(self):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname): for attribute in self.props.task_time_attributes:
if item: row = self.layout.row(align=True)
props = context.scene.BIMWorkScheduleProperties if attribute.data_type == "string":
row = layout.row(align=True) row.prop(attribute, "string_value", text=attribute.name)
for i in range(0, item.level_index): elif attribute.data_type == "boolean":
row.label(text="", icon="BLANK1") row.prop(attribute, "bool_value", text=attribute.name)
if item.has_children: elif attribute.data_type == "integer":
if item.is_expanded: row.prop(attribute, "int_value", text=attribute.name)
row.operator( elif attribute.data_type == "float":
"bim.contract_task", text="", emboss=False, icon="DISCLOSURE_TRI_DOWN" row.prop(attribute, "float_value", text=attribute.name)
).task = item.ifc_definition_id elif attribute.data_type == "enum":
else: row.prop(attribute, "enum_value", text=attribute.name)
row.operator( if attribute.is_optional:
"bim.expand_task", text="", emboss=False, icon="DISCLOSURE_TRI_RIGHT" row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
).task = item.ifc_definition_id
else:
row.label(text="", icon="DOT")
row.prop(item, "identification", emboss=False, text="")
row.prop(item, "name", emboss=False, text="")
row.prop(item, "schedule_start", emboss=False, text="Start Time")
row.prop(item, "schedule_finish", emboss=False, text="Finish Time")
row.prop(item, "schedule_duration", emboss=False, text="Duration")
if props.active_task_id == item.ifc_definition_id:
row.operator("bim.edit_task", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_task", text="", icon="CANCEL")
elif props.active_task_id:
if props.active_task_id in Data.tasks[item.ifc_definition_id]["IsPredecessorTo"]:
row.operator("bim.unassign_predecessor", text="", icon="BACK", emboss=False).task = item.ifc_definition_id
else:
row.operator("bim.assign_predecessor", text="", icon="TRACKING_BACKWARDS", emboss=False).task = item.ifc_definition_id
if props.active_task_id in Data.tasks[item.ifc_definition_id]["IsSuccessorFrom"]:
row.operator("bim.unassign_successor", text="", icon="FORWARD", emboss=False).task = item.ifc_definition_id
else:
row.operator("bim.assign_successor", text="", icon="TRACKING_FORWARDS", emboss=False).task = item.ifc_definition_id
row.operator("bim.add_task", text="", icon="ADD").task = item.ifc_definition_id
row.operator("bim.remove_task", text="", icon="X").task = item.ifc_definition_id
else:
row.operator("bim.enable_editing_task_time", text="", icon="TIME").task = item.ifc_definition_id
row.operator("bim.add_task", text="", icon="ADD").task = item.ifc_definition_id
row.operator("bim.enable_editing_task", text="", icon="GREASEPENCIL").task = item.ifc_definition_id
row.operator("bim.remove_task", text="", icon="X").task = item.ifc_definition_id
class BIM_PT_work_calendars(Panel): class BIM_PT_work_calendars(Panel):
@@ -259,3 +233,62 @@ class BIM_UL_work_calendars(UIList):
op = row.operator("bim.enable_editing_work_calendar", text="", icon="GREASEPENCIL") op = row.operator("bim.enable_editing_work_calendar", text="", icon="GREASEPENCIL")
op.work_calendar = item.ifc_definition_id op.work_calendar = item.ifc_definition_id
row.operator("bim.remove_work_calendar", text="", icon="X").work_calendar = item.ifc_definition_id row.operator("bim.remove_work_calendar", text="", icon="X").work_calendar = item.ifc_definition_id
class BIM_UL_tasks(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if item:
props = context.scene.BIMWorkScheduleProperties
row = layout.row(align=True)
for i in range(0, item.level_index):
row.label(text="", icon="BLANK1")
if item.has_children:
if item.is_expanded:
row.operator(
"bim.contract_task", text="", emboss=False, icon="DISCLOSURE_TRI_DOWN"
).task = item.ifc_definition_id
else:
row.operator(
"bim.expand_task", text="", emboss=False, icon="DISCLOSURE_TRI_RIGHT"
).task = item.ifc_definition_id
else:
row.label(text="", icon="DOT")
row.prop(item, "identification", emboss=False, text="")
row.prop(item, "name", emboss=False, text="")
row.prop(item, "start", emboss=False, text="")
row.prop(item, "finish", emboss=False, text="")
row.prop(item, "duration", emboss=False, text="")
if props.active_task_id == item.ifc_definition_id:
if props.active_task_time_id:
row.operator("bim.edit_task_time", text="", icon="CHECKMARK")
else:
row.operator("bim.edit_task", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_task", text="", icon="CANCEL")
elif props.active_task_id:
if props.active_task_id in Data.tasks[item.ifc_definition_id]["IsPredecessorTo"]:
row.operator(
"bim.unassign_predecessor", text="", icon="BACK", emboss=False
).task = item.ifc_definition_id
else:
row.operator(
"bim.assign_predecessor", text="", icon="TRACKING_BACKWARDS", emboss=False
).task = item.ifc_definition_id
if props.active_task_id in Data.tasks[item.ifc_definition_id]["IsSuccessorFrom"]:
row.operator(
"bim.unassign_successor", text="", icon="FORWARD", emboss=False
).task = item.ifc_definition_id
else:
row.operator(
"bim.assign_successor", text="", icon="TRACKING_FORWARDS", emboss=False
).task = item.ifc_definition_id
row.operator("bim.add_task", text="", icon="ADD").task = item.ifc_definition_id
row.operator("bim.remove_task", text="", icon="X").task = item.ifc_definition_id
else:
row.operator("bim.enable_editing_task_time", text="", icon="TIME").task = item.ifc_definition_id
row.operator("bim.add_task", text="", icon="ADD").task = item.ifc_definition_id
row.operator("bim.enable_editing_task", text="", icon="GREASEPENCIL").task = item.ifc_definition_id
row.operator("bim.remove_task", text="", icon="X").task = item.ifc_definition_id
@@ -7,31 +7,11 @@ class Usecase:
self.file = file self.file = file
self.settings = { self.settings = {
"task": None, "task": None,
"name": "Unnamed",
"duration_type": "NOTDEFINED",
"schedule_duration": None,
"schedule_start_time": datetime.now(),
"schedule_finish_time": datetime.now() + timedelta(days=5),
} }
for key, value in settings.items(): for key, value in settings.items():
self.settings[key] = value self.settings[key] = value
def execute(self): def execute(self):
task_time = self.file.create_entity("IfcTaskTime", **{"Name": self.settings["name"]}) task_time = self.file.create_entity("IfcTaskTime")
task_time.DurationType = self.settings["duration_type"] self.settings["task"].TaskTime = task_time
task_time.ScheduleStart = ifcopenshell.util.date.datetime2ifc(self.settings["schedule_start_time"], "IfcDateTime")
duration = self.settings["schedule_duration"]
if duration:
task_time.ScheduleDuration = ifcopenshell.util.date.datetime2ifc(duration, "IfcTime")
task_time.ScheduleFinish = ifcopenshell.util.date.datetime2ifc(
self.settings["schedule_start"] + duration,
"IfcDateTime"
)
else:
duration = self.settings["schedule_finish_time"] - self.settings["schedule_start_time"]
# task_time.ScheduleDuration = ifcopenshell.util.date.datetime2ifc(duration.days, "IfcTime")
task_time.ScheduleFinish = ifcopenshell.util.date.datetime2ifc(self.settings["schedule_finish_time"], "IfcDateTime")
task = self.settings["task"]
if task:
task.TaskTime = task_time
return task_time return task_time
@@ -15,6 +15,7 @@ class Data:
cls.work_schedules = {} cls.work_schedules = {}
cls.work_calendars = {} cls.work_calendars = {}
cls.tasks = {} cls.tasks = {}
cls.task_times = {}
@classmethod @classmethod
def load(cls, file): def load(cls, file):
@@ -81,10 +82,7 @@ class Data:
data["IsPredecessorTo"] = [] data["IsPredecessorTo"] = []
data["IsSuccessorFrom"] = [] data["IsSuccessorFrom"] = []
if task.TaskTime: if task.TaskTime:
data["TaskTime"] = task.TaskTime data["TaskTime"] = data["TaskTime"].id()
data["ScheduleStart"] = task.TaskTime.ScheduleStart
data["ScheduleFinish"] = task.TaskTime.ScheduleFinish
data["ScheduleDuration"] = task.TaskTime.ScheduleDuration
for rel in task.IsNestedBy: for rel in task.IsNestedBy:
[data["RelatedObjects"].append(o.id()) for o in rel.RelatedObjects if o.is_a("IfcTask")] [data["RelatedObjects"].append(o.id()) for o in rel.RelatedObjects if o.is_a("IfcTask")]
[data["IsPredecessorTo"].append(rel.RelatedProcess.id()) for rel in task.IsPredecessorTo or []] [data["IsPredecessorTo"].append(rel.RelatedProcess.id()) for rel in task.IsPredecessorTo or []]
@@ -96,11 +94,10 @@ class Data:
cls.task_times = {} cls.task_times = {}
for task_time in cls._file.by_type("IfcTaskTime"): for task_time in cls._file.by_type("IfcTaskTime"):
data = task_time.get_info() data = task_time.get_info()
data["ScheduleStart"] = ifcopenshell.util.date.ifc2datetime(data["ScheduleStart"]) for key, value in data.items():
data["ScheduleFinish"] = ifcopenshell.util.date.ifc2datetime(data["ScheduleFinish"]) if not value:
data["EarlyStart"] = ifcopenshell.util.date.ifc2datetime(data["EarlyStart"]) continue
data["EarlyFinish"] = ifcopenshell.util.date.ifc2datetime(data["EarlyFinish"]) if "Start" in key or "Finish" in key or key == "StatusTime":
data["LateStart"] = ifcopenshell.util.date.ifc2datetime(data["LateStart"]) data[key] = ifcopenshell.util.date.ifc2datetime(value)
data["LateFinish"] = ifcopenshell.util.date.ifc2datetime(data["LateFinish"]) # TODO parse duration
data["EarlyFinish"] = ifcopenshell.util.date.ifc2datetime(data["EarlyFinish"])
cls.task_times[task_time.id()] = data cls.task_times[task_time.id()] = data
@@ -1,10 +1,16 @@
import ifcopenshell.util.date
class Usecase: class Usecase:
def __init__(self, file, **settings): def __init__(self, file, **settings):
self.file = file self.file = file
self.settings = {"task": None, "attributes": {}} self.settings = {"task_time": None, "attributes": {}}
for key, value in settings.items(): for key, value in settings.items():
self.settings[key] = value self.settings[key] = value
def execute(self): def execute(self):
for name, value in self.settings["attributes"].items(): for name, value in self.settings["attributes"].items():
setattr(self.settings["task"].TaskTime, name, value) if "Start" in name or "Finish" in name or name == "StatusTime":
if value:
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
setattr(self.settings["task_time"], name, value)