Example #1
0
    def test_register_for_a_transition(self):
        self.initialize_standard_scenario()

        self.test_args = None
        self.test_kwargs = None

        def test_callback(*args, **kwargs):
            self.test_args = args
            self.test_kwargs = kwargs

        objects = TestModelObjectFactory.create_batch(2)
        objects[0].river.my_field.hook_post_transition(test_callback, source_state=self.state2, destination_state=self.state3)

        self.assertIsNone(self.test_args)
        self.assertIsNone(self.test_kwargs)

        objects[0].river.my_field.approve(as_user=self.user1)

        self.assertIsNone(self.test_args)
        self.assertIsNone(self.test_kwargs)

        objects[0].river.my_field.approve(as_user=self.user2)

        self.assertIsNone(self.test_args)
        self.assertIsNone(self.test_kwargs)

        objects[0].river.my_field.approve(as_user=self.user3)

        self.assertEqual((objects[0], "my_field"), self.test_args)
        self.assertDictEqual(
            {
                'transition_approval': TransitionApproval.objects.get(object_id=objects[0].pk, source_state=self.state2, destination_state=self.state3,
                                                                      permissions__in=Permission.objects.filter(user=self.user3))
            }, self.test_kwargs)
Example #2
0
    def test_register(self):
        objects = TestModelObjectFactory.create_batch(2)

        self.assertEqual(0, Callback.objects.count())
        self.assertFalse(
            '%s.%s_object%sfield%s' %
            (PostTransitionHooking.__module__, PostTransitionHooking.__name__,
             objects[1].pk, 'my_field') in self.handler_backend.callbacks)

        self.handler_backend.register(PostTransitionHooking, test_callback,
                                      objects[1], self.field_name)

        self.assertEqual(
            1,
            Callback.objects.filter(hash='%s.%s_object%s_field_name%s' %
                                    (PostTransitionHooking.__module__,
                                     PostTransitionHooking.__name__,
                                     objects[1].pk, self.field_name)).count())
        self.assertTrue(
            '%s.%s_object%s_field_name%s' %
            (PostTransitionHooking.__module__, PostTransitionHooking.__name__,
             objects[1].pk, self.field_name) in self.handler_backend.callbacks)
        self.assertEqual(
            test_callback.__name__,
            list(self.handler_backend.callbacks.values())[0].__name__)
Example #3
0
    def test_get_handlers_in_multiprocessing(self):
        objects = TestModelObjectFactory.create_batch(2)

        from multiprocessing import Process, Queue

        Callback.objects.update_or_create(
            hash='%s.%s_object%s_field_name%s' %
            (PostTransitionHooking.__module__, PostTransitionHooking.__name__,
             objects[1].pk, self.field_name),
            defaults={
                'method':
                '%s.%s' % (test_callback.__module__, test_callback.__name__),
                'hooking_cls':
                '%s.%s' % (PostTransitionHooking.__module__,
                           PostTransitionHooking.__name__),
            })

        def worker2(q):
            handlers = self.handler_backend.get_callbacks(
                PostTransitionHooking, objects[1], self.field_name)
            q.put([f.__name__ for f in handlers])

        q = Queue()
        p2 = Process(target=worker2, args=(q, ))

        p2.start()

        handlers = q.get(timeout=1)
        self.assertEqual(1, len(handlers))
        self.assertEqual(test_callback.__name__, handlers[0])
Example #4
0
    def initialize_circular_scenario(self):
        from river.models.factories import \
            TransitionObjectFactory, \
            UserObjectFactory, \
            PermissionObjectFactory, \
            ProceedingMetaObjectFactory, \
            StateObjectFactory

        TransitionObjectFactory.reset_sequence(0)
        ProceedingMetaObjectFactory.reset_sequence(0)
        StateObjectFactory.reset_sequence(0)
        TestModel.objects.all().delete()

        self.content_type = ContentType.objects.get_for_model(TestModel)
        self.permissions = PermissionObjectFactory.create_batch(4)
        self.user1 = UserObjectFactory(user_permissions=[self.permissions[0]])
        self.user2 = UserObjectFactory(user_permissions=[self.permissions[1]])
        self.user3 = UserObjectFactory(user_permissions=[self.permissions[2]])
        self.user4 = UserObjectFactory(user_permissions=[self.permissions[3]])


        self.open_state = StateObjectFactory(
            label='open'
        )
        self.in_progress_state = StateObjectFactory(
            label='in-progress'
        )

        self.resolved_state = StateObjectFactory(
            label='resolved'
        )
        self.re_opened_state = StateObjectFactory(
            label='re-opened'
        )

        self.closed_state = StateObjectFactory(
            label='closed'
        )

        self.transitions = [
            TransitionObjectFactory(source_state=self.open_state, destination_state=self.in_progress_state),
            TransitionObjectFactory(source_state=self.in_progress_state,
                                    destination_state=self.resolved_state),
            TransitionObjectFactory(source_state=self.resolved_state,
                                    destination_state=self.re_opened_state),
            TransitionObjectFactory(source_state=self.resolved_state, destination_state=self.closed_state),
            TransitionObjectFactory(source_state=self.re_opened_state, destination_state=self.in_progress_state)]

        self.proceeding_metas = ProceedingMetaObjectFactory.create_batch(
            5,
            content_type=self.content_type,
            transition=factory.Sequence(lambda n: self.transitions[n]),
            order=0
        )

        for n, proceeding_meta in enumerate(self.proceeding_metas):
            proceeding_meta.permissions.add(self.permissions[n] if n < len(self.permissions) else self.permissions[0])

        self.objects = TestModelObjectFactory.create_batch(2)
Example #5
0
 def test_get_waiting_approvals_slowness_test(self):
     self.initialize_standard_scenario()
     self.objects = TestModelObjectFactory.create_batch(100)
     before = datetime.now()
     for o in self.objects:
         o.river.my_field.get_available_states(as_user=self.user1)
     after = datetime.now()
     self.assertLess(after - before, timedelta(seconds=2))
Example #6
0
    def test_get_handlers(self):
        object = TestModelObjectFactory.create_batch(1)[0]

        self.handler_backend.register(PostTransitionHooking, test_handler,
                                      object, self.field_name)
        callbacks = self.handler_backend.get_callbacks(PostTransitionHooking,
                                                       object, self.field_name)
        self.assertEqual(1, len(callbacks))

        self.assertEqual(test_handler.__name__, callbacks[0].__name__)
 def test_get_proceedings_object_waiting_for_approval_slow_test(self):
     self.initialize_normal_scenario()
     self.objects = TestModelObjectFactory.create_batch(100)
     for o in self.objects:
         ObjectService.register_object(o)
     before = datetime.now()
     for o in self.objects:
         ProceedingService.get_available_proceedings(o, [o.my_field], user=self.user1)
     after = datetime.now()
     self.assertLess(after - before, timedelta(seconds=2))
Example #8
0
    def initialize_circular_scenario(self):
        from river.models.factories import \
            TransitionObjectFactory, \
            UserObjectFactory, \
            PermissionObjectFactory, \
            ProceedingMetaObjectFactory, \
            StateObjectFactory

        TransitionObjectFactory.reset_sequence(0)
        ProceedingMetaObjectFactory.reset_sequence(0)
        StateObjectFactory.reset_sequence(0)
        TestModel.objects.all().delete()

        self.content_type = ContentType.objects.get_for_model(TestModel)
        self.permissions = PermissionObjectFactory.create_batch(4)
        self.user1 = UserObjectFactory(user_permissions=[self.permissions[0]])
        self.user2 = UserObjectFactory(user_permissions=[self.permissions[1]])
        self.user3 = UserObjectFactory(user_permissions=[self.permissions[2]])
        self.user4 = UserObjectFactory(user_permissions=[self.permissions[3]])

        self.field = 'my_field'

        self.open_state = StateObjectFactory(label='open')
        self.in_progress_state = StateObjectFactory(label='in-progress')

        self.resolved_state = StateObjectFactory(label='resolved')
        self.re_opened_state = StateObjectFactory(label='re-opened')

        self.closed_state = StateObjectFactory(label='closed')

        self.transitions = [
            TransitionObjectFactory(source_state=self.open_state,
                                    destination_state=self.in_progress_state),
            TransitionObjectFactory(source_state=self.in_progress_state,
                                    destination_state=self.resolved_state),
            TransitionObjectFactory(source_state=self.resolved_state,
                                    destination_state=self.re_opened_state),
            TransitionObjectFactory(source_state=self.resolved_state,
                                    destination_state=self.closed_state),
            TransitionObjectFactory(source_state=self.re_opened_state,
                                    destination_state=self.in_progress_state)
        ]

        self.proceeding_metas = ProceedingMetaObjectFactory.create_batch(
            5,
            content_type=self.content_type,
            field=self.field,
            transition=factory.Sequence(lambda n: self.transitions[n]),
            order=0)

        for n, proceeding_meta in enumerate(self.proceeding_metas):
            proceeding_meta.permissions.add(self.permissions[n] if n < len(
                self.permissions) else self.permissions[0])

        self.objects = TestModelObjectFactory.create_batch(2)
Example #9
0
    def test_get_callbacks(self):
        objects = TestModelObjectFactory.create_batch(2)

        self.handler_backend.register(PostTransitionHooking, test_callback,
                                      objects[1], self.field_name)
        handlers = self.handler_backend.get_callbacks(PostTransitionHooking,
                                                      objects[1],
                                                      self.field_name)
        self.assertEqual(1, len(handlers))

        self.assertEqual(test_callback.__name__, handlers[0].__name__)
    def setUp(self):
        from river.models.factories import ProceedingMetaObjectFactory, StateObjectFactory

        self.state1 = StateObjectFactory()
        self.state2 = StateObjectFactory()
        self.state3 = StateObjectFactory()
        self.content_type = ContentType.objects.get_for_model(TestModel)

        self.proceeding_meta = ProceedingMetaObjectFactory(
            content_type=self.content_type,
            transition__source_state=self.state1,
            transition__destination_state=self.state2)
        self.object = TestModelObjectFactory().model
    def setUp(self):
        from river.models.factories import ApprovementMetaObjectFactory, StateObjectFactory

        self.state1 = StateObjectFactory()
        self.state2 = StateObjectFactory()
        self.state3 = StateObjectFactory()
        self.content_type = ContentType.objects.get_for_model(TestModel)

        self.approvement_meta = ApprovementMetaObjectFactory(
            transition__content_type=self.content_type,
            transition__source_state=self.state1,
            transition__destination_state=self.state2)
        self.object = TestModelObjectFactory().model
        self.field = "my_field"
Example #12
0
    def test_register(self):
        objects = TestModelObjectFactory.create_batch(2)

        self.assertFalse(
            '%s.%s_object%s_field_name%s' %
            (PostTransitionHooking.__module__, PostTransitionHooking.__name__,
             objects[1].pk, self.field_name) in self.handler_backend.callbacks)
        self.handler_backend.register(PostTransitionHooking, test_handler,
                                      objects[1], self.field_name)
        self.assertTrue(
            '%s.%s_object%s_field_name%s' %
            (PostTransitionHooking.__module__, PostTransitionHooking.__name__,
             objects[1].pk, self.field_name) in self.handler_backend.callbacks)
        self.assertEqual(
            test_handler.__name__,
            list(self.handler_backend.callbacks.values())[0].__name__)
    def setUp(self):
        from river.models.factories import \
            TransitionObjectFactory, \
            UserObjectFactory, \
            PermissionObjectFactory, \
            ApprovementMetaObjectFactory, \
            StateObjectFactory

        TransitionObjectFactory.reset_sequence(0)
        ApprovementMetaObjectFactory.reset_sequence(0)
        StateObjectFactory.reset_sequence(0)
        TestModel.objects.all().delete()

        self.content_type = ContentType.objects.get_for_model(TestModel)
        self.permissions = PermissionObjectFactory.create_batch(4)
        self.user1 = UserObjectFactory(user_permissions=[self.permissions[0]])
        self.user2 = UserObjectFactory(user_permissions=[self.permissions[1]])
        self.user3 = UserObjectFactory(user_permissions=[self.permissions[2]])
        self.user4 = UserObjectFactory(user_permissions=[self.permissions[3]])

        self.field = 'my_field'
        self.states = StateObjectFactory.create_batch(
            9,
            label=factory.Sequence(lambda n: "s%s" % str(n + 1) if n <= 4 else
                                   ("s4.%s" % str(n - 4)
                                    if n <= 6 else "s5.%s" % str(n - 6))))
        self.transitions = TransitionObjectFactory.create_batch(
            8,
            content_type=self.content_type,
            field=self.field,
            source_state=factory.Sequence(lambda n: self.states[
                n] if n <= 2 else (self.states[n - 1]) if n <= 4 else (
                    self.states[n - 2] if n <= 6 else self.states[4])),
            destination_state=factory.Sequence(lambda n: self.states[n + 1]))

        self.approvement_metas = ApprovementMetaObjectFactory.create_batch(
            9,
            transition=factory.Sequence(lambda n: self.transitions[n] if n <= 1
                                        else self.transitions[n - 1]),
            order=factory.Sequence(lambda n: 1 if n == 2 else 0))

        for n, approvement_meta in enumerate(self.approvement_metas):
            approvement_meta.permissions.add(
                self.permissions[n] if n <= 3 else self.permissions[3])

        self.objects = TestModelObjectFactory.create_batch(2)
Example #14
0
    def initialize_normal_scenario(self):
        from river.models.factories import \
            TransitionObjectFactory, \
            UserObjectFactory, \
            PermissionObjectFactory, \
            ProceedingMetaObjectFactory, \
            StateObjectFactory

        TransitionObjectFactory.reset_sequence(0)
        ProceedingMetaObjectFactory.reset_sequence(0)
        StateObjectFactory.reset_sequence(0)
        TestModel.objects.all().delete()

        self.content_type = ContentType.objects.get_for_model(TestModel)
        self.permissions = PermissionObjectFactory.create_batch(4)
        self.user1 = UserObjectFactory(user_permissions=[self.permissions[0]])
        self.user2 = UserObjectFactory(user_permissions=[self.permissions[1]])
        self.user3 = UserObjectFactory(user_permissions=[self.permissions[2]])
        self.user4 = UserObjectFactory(user_permissions=[self.permissions[3]])

        self.states = StateObjectFactory.create_batch(
            9,
            label=factory.Sequence(
                lambda n: "s%s" % str(n + 1) if n <= 4 else ("s4.%s" % str(n - 4) if n <= 6 else "s5.%s" % str(n - 6)))
        )
        self.transitions = TransitionObjectFactory.create_batch(8,
                                                                source_state=factory.Sequence(
                                                                    lambda n: self.states[n] if n <= 2 else (
                                                                        self.states[n - 1]) if n <= 4 else (
                                                                        self.states[n - 2] if n <= 6 else self.states[
                                                                            4])),
                                                                destination_state=factory.Sequence(
                                                                    lambda n: self.states[n + 1]))

        self.proceeding_metas = ProceedingMetaObjectFactory.create_batch(
            9,
            content_type=self.content_type,
            transition=factory.Sequence(lambda n: self.transitions[n] if n <= 1 else self.transitions[n - 1]),
            order=factory.Sequence(lambda n: 1 if n == 2 else 0)
        )

        for n, proceeding_meta in enumerate(self.proceeding_metas):
            proceeding_meta.permissions.add(self.permissions[n] if n <= 3 else self.permissions[3])

        self.objects = TestModelObjectFactory.create_batch(2)
Example #15
0
    def test_get_waiting_transition_approvals_without_skip(self):
        self.initialize_standard_scenario()
        object = TestModelObjectFactory.create_batch(1)[0]

        transition_approvals = object.river.my_field.get_available_approvals(
            as_user=self.user1)
        self.assertEqual(1, transition_approvals.count())

        transition_approvals = object.river.my_field.get_available_approvals(
            as_user=self.user2)
        self.assertEqual(0, transition_approvals.count())

        transition_approvals = object.river.my_field.get_available_approvals(
            as_user=self.user3)
        self.assertEqual(0, transition_approvals.count())

        transition_approvals = object.river.my_field.get_available_approvals(
            as_user=self.user4)
        self.assertEqual(0, transition_approvals.count())
Example #16
0
    def test_get_on_approval_objects(self):
        self.initialize_standard_scenario()
        objects = TestModelObjectFactory.create_batch(2)

        on_approval_objects = TestModel.river.my_field.get_on_approval_objects(
            as_user=self.user1)
        self.assertEqual(2, on_approval_objects.count())
        self.assertEqual(objects[0], on_approval_objects[0])

        on_approval_objects = TestModel.river.my_field.get_on_approval_objects(
            as_user=self.user2)
        self.assertEqual(0, on_approval_objects.count())

        on_approval_objects = TestModel.river.my_field.get_on_approval_objects(
            as_user=self.user3)
        self.assertEqual(0, on_approval_objects.count())

        on_approval_objects = TestModel.river.my_field.get_on_approval_objects(
            as_user=self.user4)
        self.assertEqual(0, on_approval_objects.count())
Example #17
0
    def test_register_for_an_object(self):
        objects = TestModelObjectFactory.create_batch(2)

        self.test_args = None
        self.test_kwargs = None

        def test_callback(*args, **kwargs):
            self.test_args = args
            self.test_kwargs = kwargs

        objects[0].river.my_field.hook_post_complete(test_callback)

        self.assertIsNone(self.test_args)
        self.assertIsNone(self.test_kwargs)

        objects[0].river.my_field.approve(as_user=self.user1)

        self.assertIsNone(self.test_args)
        self.assertIsNone(self.test_kwargs)

        # Proceeded but no transition
        objects[0].river.my_field.approve(as_user=self.user2)

        self.assertIsNone(self.test_args)
        self.assertIsNone(self.test_kwargs)

        objects[0].river.my_field.approve(as_user=self.user3)

        self.assertIsNone(self.test_args)
        self.assertIsNone(self.test_kwargs)

        objects[0].river.my_field.approve(as_user=self.user4, next_state=self.state4)

        self.assertIsNone(self.test_args)
        self.assertIsNone(self.test_kwargs)

        objects[0].river.my_field.approve(as_user=self.user4, next_state=self.state41)

        self.assertEqual((objects[0], "my_field"), self.test_args)
Example #18
0
    def test_get_available_states(self):
        self.initialize_standard_scenario()
        object = TestModelObjectFactory.create_batch(1)[0]
        available_states = object.river.my_field.get_available_states()
        self.assertEqual(1, available_states.count())
        self.assertEqual(self.state2, available_states[0])

        available_states = object.river.my_field.get_available_states(
            as_user=self.user1)
        self.assertEqual(1, available_states.count())
        self.assertEqual(self.state2, available_states[0])

        available_states = object.river.my_field.get_available_states(
            as_user=self.user2)
        self.assertEqual(0, available_states.count())

        available_states = object.river.my_field.get_available_states(
            as_user=self.user3)
        self.assertEqual(0, available_states.count())

        available_states = object.river.my_field.get_available_states(
            as_user=self.user4)
        self.assertEqual(0, available_states.count())
Example #19
0
    def test_register_in_multiprocessing(self):
        objects = TestModelObjectFactory.create_batch(2)

        from multiprocessing import Process, Queue

        self.handler_backend.register(PostTransitionHooking, test_callback,
                                      objects[1], self.field_name)
        self.assertEqual(1, Callback.objects.count())

        def worker2(q):
            second_handler_backend = load_callback_backend()
            handlers = second_handler_backend.get_callbacks(
                PostTransitionHooking, objects[1], self.field_name)
            q.put([f.__name__ for f in handlers])

        q = Queue()
        p2 = Process(target=worker2, args=(q, ))

        p2.start()

        handlers = q.get(timeout=1)
        self.assertEqual(1, len(handlers))
        self.assertEqual(test_callback.__name__, handlers[0])
Example #20
0
    def test_get_waiting_transition_approvals_with_skip(self):
        self.initialize_standard_scenario()
        object = TestModelObjectFactory.create_batch(1)[0]

        transition_approvals = object.river.my_field.get_available_approvals(
            as_user=self.user1)
        self.assertEqual(1, transition_approvals.count())
        self.assertEqual(self.state2,
                         transition_approvals[0].destination_state)

        TransitionApproval.objects.filter(
            workflow_object=object,
            field_name="my_field",
            destination_state=self.state2).update(skip=True)

        transition_approvals = object.river.my_field.get_available_approvals(
            as_user=self.user2)
        self.assertEqual(1, transition_approvals.count())
        self.assertEqual(self.state3,
                         transition_approvals[0].destination_state)

        TransitionApproval.objects.filter(
            workflow_object=object,
            field_name="my_field",
            destination_state=self.state3).update(skip=True)

        transition_approvals = object.river.my_field.get_available_approvals(
            as_user=self.user4)
        self.assertEqual(2, transition_approvals.count())
        self.assertEqual(self.state4,
                         transition_approvals[0].destination_state)
        self.assertEqual(self.state5,
                         transition_approvals[1].destination_state)

        TransitionApproval.objects.filter(
            workflow_object=object,
            field_name="my_field",
            destination_state=self.state4).update(skip=True)

        transition_approvals = object.river.my_field.get_available_approvals(
            as_user=self.user4)
        self.assertEqual(3, transition_approvals.count())
        self.assertEqual(self.state5,
                         transition_approvals[0].destination_state)
        self.assertEqual(self.state41,
                         transition_approvals[1].destination_state)
        self.assertEqual(self.state42,
                         transition_approvals[2].destination_state)

        TransitionApproval.objects.filter(
            workflow_object=object,
            field_name="my_field",
            destination_state=self.state4).update(skip=False)

        TransitionApproval.objects.filter(
            workflow_object=object,
            field_name="my_field",
            destination_state=self.state5).update(skip=True)

        transition_approvals = object.river.my_field.get_available_approvals(
            as_user=self.user4)
        self.assertEqual(3, transition_approvals.count())
        self.assertEqual(self.state4,
                         transition_approvals[0].destination_state)
        self.assertEqual(self.state51,
                         transition_approvals[1].destination_state)
        self.assertEqual(self.state52,
                         transition_approvals[2].destination_state)

        TransitionApproval.objects.filter(
            workflow_object=object,
            field_name="my_field",
            destination_state__in=[self.state4, self.state5]).update(skip=True)

        transition_approvals = object.river.my_field.get_available_approvals(
            as_user=self.user4)
        self.assertEqual(4, transition_approvals.count())
        self.assertEqual(self.state41,
                         transition_approvals[0].destination_state)
        self.assertEqual(self.state42,
                         transition_approvals[1].destination_state)
        self.assertEqual(self.state51,
                         transition_approvals[2].destination_state)
        self.assertEqual(self.state52,
                         transition_approvals[3].destination_state)

        TransitionApproval.objects.filter(
            workflow_object=object,
            field_name="my_field",
            destination_state__in=[self.state41,
                                   self.state51]).update(skip=True)

        transition_approvals = object.river.my_field.get_available_approvals(
            as_user=self.user4)
        self.assertEqual(2, transition_approvals.count())
        self.assertEqual(self.state42,
                         transition_approvals[0].destination_state)
        self.assertEqual(self.state52,
                         transition_approvals[1].destination_state)
Example #21
0
    def test_proceed(self):
        self.initialize_standard_scenario()
        object = TestModelObjectFactory.create_batch(1)[0]

        # ####################
        # STATE 1 - STATE 2
        # Only User1(2001) can proceed and after his proceed state must be changed to STATE 2
        # ###################

        # Proceeded by user has no required permission for this transition

        try:
            object.river.my_field.approve(as_user=self.user2)
            self.fail('Exception was expected')
        except RiverException as e:
            self.assertEqual(
                str(e),
                'There is no available state for destination for the user.')
            self.assertEqual(ErrorCode.NO_AVAILABLE_NEXT_STATE_FOR_USER,
                             e.code)

        try:
            object.river.my_field.approve(as_user=self.user3)
            self.fail('Exception was expected')
        except RiverException as e:
            self.assertEqual(
                str(e),
                'There is no available state for destination for the user.')
            self.assertEqual(ErrorCode.NO_AVAILABLE_NEXT_STATE_FOR_USER,
                             e.code)

        try:
            object.river.my_field.approve(as_user=self.user4)
            self.fail('Exception was expected')
        except RiverException as e:
            self.assertEqual(
                str(e),
                'There is no available state for destination for the user.')
            self.assertEqual(ErrorCode.NO_AVAILABLE_NEXT_STATE_FOR_USER,
                             e.code)

        self.assertEqual(self.state1, object.my_field)

        object.river.my_field.approve(as_user=self.user1)

        self.assertEqual(self.state2, object.my_field)

        transition_approvals = TransitionApproval.objects.filter(
            workflow_object=object,
            status=APPROVED,
            source_state=self.state1,
            destination_state=self.state2)
        self.assertEqual(1, transition_approvals.count())
        self.assertIsNotNone(transition_approvals[0].transactioner)
        self.assertEqual(self.user1, transition_approvals[0].transactioner)
        self.assertIsNotNone(transition_approvals[0].transaction_date)

        # ####################
        # STATE 2 - STATE 3
        # User2(2002) is first proceeder and User3(2003) is second proceeder. This must be done with turn. After proceeding is done, state is gonna be changed to STATE 3
        # ####################

        # Proceeded by user has no required permission for this transition
        try:
            object.river.my_field.approve(as_user=self.user1)
            self.fail('Exception was expected')
        except RiverException as e:
            self.assertEqual(
                str(e),
                'There is no available state for destination for the user.')
            self.assertEqual(ErrorCode.NO_AVAILABLE_NEXT_STATE_FOR_USER,
                             e.code)

        try:
            object.river.my_field.approve(as_user=self.user4)
            self.fail('Exception was expected')
        except RiverException as e:
            self.assertEqual(
                str(e),
                'There is no available state for destination for the user.')
            self.assertEqual(ErrorCode.NO_AVAILABLE_NEXT_STATE_FOR_USER,
                             e.code)

        # Turn is User2(2002)s, not User3(2003)s. After User2(2002) proceeded, User3(2003) can proceed.
        try:
            object.river.my_field.approve(as_user=self.user3)
            self.fail('Exception was expected')
        except RiverException as e:
            self.assertEqual(
                str(e),
                'There is no available state for destination for the user.')
            self.assertEqual(ErrorCode.NO_AVAILABLE_NEXT_STATE_FOR_USER,
                             e.code)

        # Proceeded by two user has required permission for this transition to get next state (order is user2(2002),user3(2003)).
        object.river.my_field.approve(as_user=self.user2)
        self.assertEqual(self.state2, object.my_field)

        transition_approvals = TransitionApproval.objects.filter(
            workflow_object=object,
            status=APPROVED,
            source_state=self.state2,
            destination_state=self.state3)
        self.assertEqual(1, transition_approvals.count())
        self.assertIsNotNone(transition_approvals[0].transactioner)
        self.assertEqual(self.user2, transition_approvals[0].transactioner)
        self.assertIsNotNone(transition_approvals[0].transaction_date)

        try:
            object.river.my_field.approve(as_user=self.user2)
            self.fail('Exception was expected')
        except RiverException as e:
            self.assertEqual(
                str(e),
                'There is no available state for destination for the user.')
            self.assertEqual(ErrorCode.NO_AVAILABLE_NEXT_STATE_FOR_USER,
                             e.code)

            object.river.my_field.approve(as_user=self.user3)
        self.assertEqual(self.state3, object.my_field)

        transition_approvals = TransitionApproval.objects.filter(
            workflow_object=object,
            status=APPROVED,
            source_state=self.state2,
            destination_state=self.state3)
        self.assertEqual(2, transition_approvals.count())
        self.assertIsNotNone(transition_approvals[0].transactioner)
        self.assertIsNotNone(transition_approvals[1].transactioner)
        self.assertEqual(self.user2, transition_approvals[0].transactioner)
        self.assertEqual(self.user3, transition_approvals[1].transactioner)
        self.assertIsNotNone(transition_approvals[0].transaction_date)
        self.assertIsNotNone(transition_approvals[1].transaction_date)

        # ####################
        # STATE 3 - STATE 4 or STATE 5
        # Only User4(2004) can proceed by giving the exact next state and after his proceed with his state must be changed to STATE 4 or STATE 5
        # ###################

        # Proceeded by user has no required permission for this transition
        try:
            object.river.my_field.approve(as_user=self.user1)
            self.fail('Exception was expected')
        except RiverException as e:
            self.assertEqual(
                str(e),
                'There is no available state for destination for the user.')
            self.assertEqual(ErrorCode.NO_AVAILABLE_NEXT_STATE_FOR_USER,
                             e.code)

        # Proceeded by user has no required permission for this transition
        try:
            object.river.my_field.approve(as_user=self.user2)
            self.fail('Exception was expected')
        except RiverException as e:
            self.assertEqual(
                str(e),
                'There is no available state for destination for the user.')
            self.assertEqual(ErrorCode.NO_AVAILABLE_NEXT_STATE_FOR_USER,
                             e.code)

        # Proceeded by user has no required permission for this transition
        try:
            object.river.my_field.approve(as_user=self.user3)
            self.fail('Exception was expected')
        except RiverException as e:
            self.assertEqual(
                str(e),
                'There is no available state for destination for the user.')
            self.assertEqual(ErrorCode.NO_AVAILABLE_NEXT_STATE_FOR_USER,
                             e.code)

        # There are STATE 4 and STATE 5 as next. State must be given to switch
        try:
            object.river.my_field.approve(as_user=self.user4)
            self.fail('Exception was expected')
        except RiverException as e:
            self.assertEqual(
                str(e),
                'State must be given when there are multiple states for destination'
            )
            self.assertEqual(ErrorCode.NEXT_STATE_IS_REQUIRED, e.code)

        # There are STATE 4 and STATE 5 as next. State among STATE 4 and STATE 5 must be given to switch, not other state
        try:
            object.river.my_field.approve(as_user=self.user4,
                                          next_state=self.state3)
            self.fail('Exception was expected')
        except RiverException as e:
            self.assertEqual(
                str(e), "Invalid state is given(%s). Valid states is(are) %s" %
                (self.state3.__str__(), ','.join(
                    [ast.__str__() for ast in [self.state4, self.state5]])))
            self.assertEqual(ErrorCode.INVALID_NEXT_STATE_FOR_USER, e.code)

        # There are STATE 4 and STATE 5 as next. After one of them is given to proceeding, the state must be switch to it immediately.
        object.river.my_field.approve(as_user=self.user4,
                                      next_state=self.state5)
        self.assertEqual(self.state5, object.my_field)

        transition_approvals = TransitionApproval.objects.filter(
            workflow_object=object,
            status=APPROVED,
            source_state=self.state3,
            destination_state=self.state5)
        self.assertEqual(1, transition_approvals.count())
        self.assertIsNotNone(transition_approvals[0].transactioner)
        self.assertEqual(self.user4, transition_approvals[0].transactioner)
        self.assertIsNotNone(transition_approvals[0].transaction_date)
Example #22
0
    def test_cycle_proceedings(self):
        self.initialize_circular_scenario()
        object = TestModelObjectFactory.create_batch(1)[0]

        # No Cycle
        self.assertFalse(object.river.my_field._cycle_proceedings())
        object.river.my_field.approve(as_user=self.user1,
                                      next_state=self.in_progress_state,
                                      god_mod=True)
        self.assertEqual(
            5,
            TransitionApproval.objects.filter(object_id=object.pk).count())

        # No Cycle
        self.assertFalse(object.river.my_field._cycle_proceedings())
        object.river.my_field.approve(as_user=self.user2,
                                      next_state=self.resolved_state,
                                      god_mod=True)
        self.assertEqual(
            5,
            TransitionApproval.objects.filter(object_id=object.pk).count())

        # State is re-opened and cycle is detected. Transition in-progress to resolved proceeding is cloned
        self.assertFalse(object.river.my_field._cycle_proceedings())
        object.river.my_field.approve(as_user=self.user3,
                                      next_state=self.re_opened_state,
                                      god_mod=True)
        self.assertEqual(
            6,
            TransitionApproval.objects.filter(object_id=object.pk).count())

        self.assertEqual(
            TransitionApprovalMeta.objects.get(
                source_state=self.in_progress_state,
                destination_state=self.resolved_state),
            TransitionApproval.objects.filter(
                object_id=object.pk).latest('date_created').meta)

        # There will be no cycling even if the method is invoked. Because cycling is done in proceeding.
        self.assertFalse(object.river.my_field._cycle_proceedings())
        self.assertEqual(
            6,
            TransitionApproval.objects.filter(object_id=object.pk).count())

        # State is in-progress and cycle is detected. Transition resolved to re-opened proceeding is cloned
        object.river.my_field.approve(as_user=self.user3,
                                      next_state=self.in_progress_state,
                                      god_mod=True)
        self.assertEqual(
            7,
            TransitionApproval.objects.filter(object_id=object.pk).count())
        self.assertEqual(
            TransitionApprovalMeta.objects.get(
                source_state=self.resolved_state,
                destination_state=self.re_opened_state),
            TransitionApproval.objects.filter(
                object_id=object.pk).latest('date_created').meta)

        # State is resolved and cycle is detected. Transition re-opened to in-progress proceeding is cloned
        object.river.my_field.approve(as_user=self.user3,
                                      next_state=self.resolved_state,
                                      god_mod=True)
        self.assertEqual(
            8,
            TransitionApproval.objects.filter(object_id=object.pk).count())
        self.assertEqual(
            TransitionApprovalMeta.objects.get(
                source_state=self.re_opened_state,
                destination_state=self.in_progress_state),
            TransitionApproval.objects.filter(
                object_id=object.pk).latest('date_created').meta)

        # State is re-opened and cycle is detected. Transition  in-progress to resolved proceeding is cloned
        self.assertFalse(object.river.my_field._cycle_proceedings())
        object.river.my_field.approve(as_user=self.user3,
                                      next_state=self.re_opened_state,
                                      god_mod=True)
        self.assertEqual(
            9,
            TransitionApproval.objects.filter(object_id=object.pk).count())
        self.assertEqual(
            TransitionApprovalMeta.objects.get(
                source_state=self.in_progress_state,
                destination_state=self.resolved_state),
            TransitionApproval.objects.filter(
                object_id=object.pk).latest('date_created').meta)

        # State is in-progress and cycle is detected. Transition resolved to re-opened proceeding is cloned
        object.river.my_field.approve(as_user=self.user3,
                                      next_state=self.in_progress_state,
                                      god_mod=True)
        self.assertEqual(
            10,
            TransitionApproval.objects.filter(object_id=object.pk).count())
        self.assertEqual(
            TransitionApprovalMeta.objects.get(
                source_state=self.resolved_state,
                destination_state=self.re_opened_state),
            TransitionApproval.objects.filter(
                object_id=object.pk).latest('date_created').meta)

        # State is resolved and cycle is detected. Transition re-opened to in-progress proceeding is cloned
        object.river.my_field.approve(as_user=self.user3,
                                      next_state=self.resolved_state,
                                      god_mod=True)
        self.assertEqual(
            11,
            TransitionApproval.objects.filter(object_id=object.pk).count())
        self.assertEqual(
            TransitionApprovalMeta.objects.get(
                source_state=self.re_opened_state,
                destination_state=self.in_progress_state),
            TransitionApproval.objects.filter(
                object_id=object.pk).latest('date_created').meta)

        # No Cycle for closed state.
        object.river.my_field.approve(as_user=self.user4,
                                      next_state=self.closed_state,
                                      god_mod=True)
        self.assertEqual(
            11,
            TransitionApproval.objects.filter(object_id=object.pk).count())