diff --git a/src/mlx/jira_juggler.py b/src/mlx/jira_juggler.py index f5ba44e..429aca4 100644 --- a/src/mlx/jira_juggler.py +++ b/src/mlx/jira_juggler.py @@ -624,6 +624,7 @@ def link_to_preceding_task(tasks, weeklymax=5.0, current_date=datetime.now()): weeklymax (float): Number of allocated workdays per week current_date (datetime.datetime): Offset-naive datetime to treat as the current date """ + key_to_task_map = {task.key: task for task in tasks} current_date_str = to_juggler_date(current_date) unresolved_tasks = {} for task in tasks: @@ -640,17 +641,22 @@ def link_to_preceding_task(tasks, weeklymax=5.0, current_date=datetime.now()): if assignee in unresolved_tasks: # link to a preceding unresolved task preceding_task = unresolved_tasks[assignee][-1] depends_property.append_value(to_identifier(preceding_task.key)) - else: # first unresolved task for assignee: set start time - start_time = current_date_str - if task.issue.fields.timespent: - effort_property = task.properties['effort'] - effort_property.value += task.issue.fields.timespent / JugglerTaskEffort.FACTOR - days_spent = task.issue.fields.timespent // 3600 / 8 - weekends = calculate_weekends(current_date, days_spent, weeklymax) - days_per_weekend = min(2, 7 - weeklymax) - start_time = f"%{{{start_time} - {days_spent + weekends * days_per_weekend}d}}" - time_property.name = 'start' - time_property.value = start_time + else: # first unresolved task for assignee: set start time unless it depends on an unresolved task + for key in depends_property.value: + if not key_to_task_map[key].is_resolved: + break + else: + start_time = current_date_str + if task.issue.fields.timespent: + effort_property = task.properties['effort'] + effort_property.value += task.issue.fields.timespent / JugglerTaskEffort.FACTOR + days_spent = task.issue.fields.timespent // 3600 / 8 + weekends = calculate_weekends(current_date, days_spent, weeklymax) + days_per_weekend = min(2, 7 - weeklymax) + start_time = f"%{{{start_time} - {days_spent + weekends * days_per_weekend}d}}" + time_property.name = 'start' + time_property.value = start_time + unresolved_tasks.setdefault(assignee, []).append(task) def sort_tasks_on_sprint(self, tasks, sprint_field_name): diff --git a/tests/test_jira_juggler.py b/tests/test_jira_juggler.py index 0f62476..21d2a54 100644 --- a/tests/test_jira_juggler.py +++ b/tests/test_jira_juggler.py @@ -509,10 +509,16 @@ def test_depend_on_preceding(self, jira_mock): [self.ESTIMATE1, None, None], self.DEPENDS1, status="Open"), + self._mock_jira_issue('Last-assignee', + self.SUMMARY3, + self.ASSIGNEE3, + [self.ESTIMATE1, None, None], + [self.KEY1, self.KEY2], + status="Open"), ], []] issues = juggler.juggle(depend_on_preceding=True, weeklymax=1.0, current_date=parser.isoparse('2021-08-23T13:30')) jira_mock_object.search_issues.assert_has_calls([call(self.QUERY, maxResults=dut.JIRA_PAGE_SIZE, startAt=0, expand='changelog')]) - self.assertEqual(4, len(issues)) + self.assertEqual(5, len(issues)) self.assertEqual(self.ASSIGNEE1, issues[0].properties['allocate'].value) self.assertEqual(self.ESTIMATE1 / self.SECS_PER_DAY, issues[0].properties['effort'].value) self.assertEqual(' end 2021-08-18-18:00-+0200\n', str(issues[0].properties['time'])) @@ -530,6 +536,9 @@ def test_depend_on_preceding(self, jira_mock): self.assertEqual('', str(issues[3].properties['depends'])) self.assertEqual(' start 2021-08-23-13:00\n', str(issues[3].properties['time'])) # start on current date + self.assertEqual(' depends !Issue1, !Issue2\n', str(issues[4].properties['depends'])) + self.assertEqual('', str(issues[4].properties['time'])) # no start date as it depends on an unresolved task + def _mock_jira_issue(self, key, summary, assignee='', estimates=[], depends=[], histories=[], status="Open", email=''): ''' Helper function to create a mocked Jira issue