| 72 | return relationships |
| 73 | |
| 74 | def parse_task_xml(self, project): |
| 75 | if self.project["MinutesPerDay"]: |
| 76 | hours_per_day = int(self.project["MinutesPerDay"]) / 60 |
| 77 | else: |
| 78 | hours_per_day = 8 |
| 79 | |
| 80 | for task in project.find("pr:Tasks", self.ns): |
| 81 | task_id = task.find("pr:UID", self.ns).text |
| 82 | task_index_level = task.find("pr:OutlineLevel", self.ns).text |
| 83 | wbs_id = task.find("pr:WBS", self.ns).text |
| 84 | relationships = self.parse_relationship_xml(task) |
| 85 | outline_level = int(task.find("pr:OutlineLevel", self.ns).text) |
| 86 | |
| 87 | if outline_level != 0: |
| 88 | parent_task = self.tasks[self.outline_parents[outline_level - 1]] |
| 89 | parent_task["subtasks"].append(task_id) |
| 90 | self.outline_level = outline_level |
| 91 | self.outline_parents[outline_level] = task_id |
| 92 | |
| 93 | # Microsoft Project stores durations in terms of hours. |
| 94 | duration = ifcopenshell.util.date.ifc2datetime(task.find("pr:Duration", self.ns).text) |
| 95 | hours = duration.days * 24 |
| 96 | hours += duration.seconds / 60 / 60 |
| 97 | # Let's convert it into days, where days is the appropriate hours per day |
| 98 | duration = timedelta(days=hours / float(hours_per_day)) |
| 99 | |
| 100 | self.tasks[task_id] = { |
| 101 | "Name": task.find("pr:Name", self.ns).text, |
| 102 | "OutlineNumber": task.find("pr:OutlineNumber", self.ns).text, |
| 103 | "OutlineLevel": outline_level, |
| 104 | "Start": datetime.datetime.fromisoformat(task.find("pr:Start", self.ns).text), |
| 105 | "Finish": datetime.datetime.fromisoformat(task.find("pr:Finish", self.ns).text), |
| 106 | "Duration": duration, |
| 107 | "Priority": task.find("pr:Priority", self.ns).text, |
| 108 | "CalendarUID": task.find("pr:CalendarUID", self.ns).text, |
| 109 | "PredecessorTasks": relationships if relationships else None, |
| 110 | "subtasks": [], |
| 111 | "ifc": None, |
| 112 | } |
| 113 | |
| 114 | # retrieve optional columns |
| 115 | # If first column = "all" then retrieve all columns |
| 116 | if len(self.optionalColumns) and self.optionalColumns[0] == "all": |
| 117 | self.optionalColumns = [child.tag.split("}")[1] for child in task] |
| 118 | |
| 119 | for column in self.optionalColumns: |
| 120 | if not self.tasks[task_id].get(column): |
| 121 | self.tasks[task_id][column] = ( |
| 122 | task.find(f"pr:{column}", self.ns).text if task.find(f"pr:{column}", self.ns) else None |
| 123 | ) |
| 124 | |
| 125 | def parse_calendar_xml(self, project): |
| 126 | def parse_working_times(day): |