Skip to content

Commit 399ddcf

Browse files
committed
Fix auto close function
1 parent 8652627 commit 399ddcf

3 files changed

Lines changed: 33 additions & 33 deletions

File tree

opengever/task/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535

3636
TASK_STATE_IN_PROGRESS = 'task-state-in-progress'
3737

38+
TASK_STATE_RESOLVED = 'task-state-resolved'
39+
40+
TASK_STATE_REJECTED = 'task-state-rejected'
41+
3842
FINAL_TASK_STATES = [
3943
'task-state-tested-and-closed',
4044
'task-state-cancelled',

opengever/task/task.py

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
from opengever.task import TASK_STATE_IN_PROGRESS
3535
from opengever.task import TASK_STATE_OPEN
3636
from opengever.task import TASK_STATE_PLANNED
37+
from opengever.task import TASK_STATE_REJECTED
38+
from opengever.task import TASK_STATE_RESOLVED
3739
from opengever.task import TASK_STATE_SKIPPED
3840
from opengever.task import util
3941
from opengever.task.interfaces import ITaskSettings
@@ -47,6 +49,7 @@
4749
from persistent.dict import PersistentDict
4850
from persistent.list import PersistentList
4951
from plone import api
52+
from plone.api.exc import InvalidParameterError
5053
from plone.app.textfield import RichText
5154
from plone.autoform import directives as form
5255
from plone.dexterity.content import Container
@@ -907,14 +910,6 @@ def _set_review_state(self, review_state):
907910
self.sync()
908911
self.reindexObject()
909912

910-
def get_available_transitions(self):
911-
wftool = api.portal.get_tool("portal_workflow")
912-
actions = wftool.listActionInfos(object=self)
913-
return [
914-
action['id'] for action in actions
915-
if action['category'] == 'workflow'
916-
]
917-
918913
def force_finish_task(self):
919914
"""This method is used to forcefully close a task, including all its subtasks,
920915
when a dossier is being closed and active tasks still exist.
@@ -924,32 +919,32 @@ def force_finish_task(self):
924919
Rather than preventing the dossier from closing, we force each task into a
925920
valid terminal state based on its current state.
926921
927-
# This method is recursive, ensuring that all subtasks are also finished in the same way,
922+
This method is recursive, ensuring that all subtasks are also finished in the same way,
928923
"""
929-
state = api.content.get_state(self)
930-
transitions = self.get_available_transitions()
924+
if api.content.get_state(self) == TASK_STATE_REJECTED:
925+
api.content.transition(obj=self, transition='task-transition-rejected-open')
926+
927+
if api.content.get_state(self) == TASK_STATE_OPEN:
928+
api.content.transition(obj=self, transition='task-transition-open-cancelled')
929+
# Cancel a task will automatically cancel all subtasks.
930+
return
931931

932932
for subtask in self.objectValues():
933933
if ITask.providedBy(subtask):
934934
subtask.force_finish_task()
935935

936-
if state == TASK_STATE_OPEN:
937-
api.content.transition(obj=self, transition='task-transition-open-cancelled')
938-
939-
elif state == TASK_STATE_IN_PROGRESS:
940-
if 'task-transition-in-progress-resolved' in transitions:
941-
api.content.transition(obj=self, transition='task-transition-in-progress-resolved')
942-
# refresh transitions after state change
943-
transitions = self.get_available_transitions()
944-
945-
if 'task-transition-resolved-tested-and-closed' in transitions:
936+
if api.content.get_state(self) == TASK_STATE_IN_PROGRESS:
937+
# Depending on the task type, some transitions are not possible. We
938+
# do not try to understand the businesslogic here and naivily do
939+
# the expected transitions.
940+
try:
941+
# We first try to directly close it.
946942
api.content.transition(obj=self, transition='task-transition-resolved-tested-and-closed')
943+
except InvalidParameterError:
944+
# If it does not work, we try to resolve it first.
945+
api.content.transition(obj=self, transition='task-transition-in-progress-resolved')
947946

948-
if 'task-transition-in-progress-cancelled' in transitions:
949-
api.content.transition(obj=self, transition='task-transition-in-progress-cancelled')
950-
transitions = self.get_available_transitions()
951-
952-
elif state == 'task-state-resolved':
947+
if api.content.get_state(self) == TASK_STATE_RESOLVED:
953948
api.content.transition(obj=self, transition='task-transition-resolved-tested-and-closed')
954949

955950

opengever/task/tests/test_task.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ def test_force_update_resolved_main_task_without_subtasks(self, browser):
743743

744744
@browsing
745745
def test_force_finish_task_open_with_subtask(self, browser):
746-
self.login(self.dossier_responsible)
746+
self.login(self.dossier_responsible, browser)
747747

748748
dossier = create(Builder('dossier'))
749749
main_task = create(
@@ -802,6 +802,7 @@ def test_force_finish_task_open_with_subtask(self, browser):
802802

803803
main_task.force_finish_task()
804804

805+
# If the main task is cancelled, every subtask will be cancelled as well
805806
self.assertEqual('task-state-cancelled', api.content.get_state(main_task))
806807
self.assertEqual('task-state-cancelled', api.content.get_state(subtask1))
807808
self.assertEqual('task-state-cancelled', api.content.get_state(subtask2))
@@ -810,7 +811,7 @@ def test_force_finish_task_open_with_subtask(self, browser):
810811

811812
@browsing
812813
def test_force_finish_task_in_progress_with_subtask(self, browser):
813-
self.login(self.dossier_responsible)
814+
self.login(self.dossier_responsible, browser)
814815

815816
dossier = create(Builder('dossier'))
816817
main_task = create(
@@ -869,15 +870,15 @@ def test_force_finish_task_in_progress_with_subtask(self, browser):
869870

870871
main_task.force_finish_task()
871872

872-
self.assertEqual('task-state-cancelled', api.content.get_state(main_task))
873-
self.assertEqual('task-state-cancelled', api.content.get_state(subtask1))
874-
self.assertEqual('task-state-cancelled', api.content.get_state(subtask2))
873+
self.assertEqual('task-state-tested-and-closed', api.content.get_state(main_task))
874+
self.assertEqual('task-state-tested-and-closed', api.content.get_state(subtask1))
875+
self.assertEqual('task-state-tested-and-closed', api.content.get_state(subtask2))
875876
self.assertEqual('task-state-cancelled', api.content.get_state(subtask3))
876877
self.assertEqual('task-state-cancelled', api.content.get_state(subtask4))
877878

878879
@browsing
879880
def test_force_finish_task_resolved_with_subtask(self, browser):
880-
self.login(self.dossier_responsible)
881+
self.login(self.dossier_responsible, browser)
881882

882883
dossier = create(Builder('dossier'))
883884
main_task = create(
@@ -940,4 +941,4 @@ def test_force_finish_task_resolved_with_subtask(self, browser):
940941
self.assertEqual('task-state-tested-and-closed', api.content.get_state(subtask1))
941942
self.assertEqual('task-state-tested-and-closed', api.content.get_state(subtask2))
942943
self.assertEqual('task-state-cancelled', api.content.get_state(subtask3))
943-
self.assertEqual('task-state-rejected', api.content.get_state(subtask4))
944+
self.assertEqual('task-state-cancelled', api.content.get_state(subtask4))

0 commit comments

Comments
 (0)