Ejemplo n.º 1
0
def set_current_task(workflow_id, task_id):
    workflow_model = session.query(WorkflowModel).filter_by(
        id=workflow_id).first()
    processor = WorkflowProcessor(workflow_model)
    task_id = uuid.UUID(task_id)
    spiff_task = processor.bpmn_workflow.get_task(task_id)
    _verify_user_and_role(processor, spiff_task)
    user_uid = g.user.uid
    if spiff_task.state != spiff_task.COMPLETED and spiff_task.state != spiff_task.READY:
        raise ApiError(
            "invalid_state",
            "You may not move the token to a task who's state is not "
            "currently set to COMPLETE or READY.")

    # Only reset the token if the task doesn't already have it.
    if spiff_task.state == spiff_task.COMPLETED:
        spiff_task.reset_token(
            reset_data=True
        )  # Don't try to copy the existing data back into this task.

    processor.save()
    WorkflowService.log_task_action(user_uid, processor, spiff_task,
                                    WorkflowService.TASK_ACTION_TOKEN_RESET)
    WorkflowService.update_task_assignments(processor)

    workflow_api_model = WorkflowService.processor_to_workflow_api(
        processor, spiff_task)
    return WorkflowApiSchema().dump(workflow_api_model)
Ejemplo n.º 2
0
def get_workflow_from_spec(spec_id):
    workflow_model = WorkflowService.get_workflow_from_spec(spec_id, g.user)
    processor = WorkflowProcessor(workflow_model)

    processor.do_engine_steps()
    processor.save()
    WorkflowService.update_task_assignments(processor)

    workflow_api_model = WorkflowService.processor_to_workflow_api(processor)
    return WorkflowApiSchema().dump(workflow_api_model)
Ejemplo n.º 3
0
    def test_total_tasks_updated(self, mock_docs):
        """Assure that as a users progress is available when getting a list of studies for that user."""
        app.config['PB_ENABLED'] = True
        docs_response = self.protocol_builder_response('required_docs.json')
        mock_docs.return_value = json.loads(docs_response)

        user = self.create_user_with_study_and_workflow()

        # The load example data script should set us up a user and at least one study, one category, and one workflow.
        studies = StudyService.get_studies_for_user(user)
        self.assertTrue(len(studies) == 1)
        self.assertTrue(len(studies[0].categories) == 1)
        self.assertTrue(len(studies[0].categories[0].workflows) == 1)

        workflow = next(iter(
            studies[0].categories[0].workflows))  # Workflows is a set.

        # workflow should not be started, and it should have 0 completed tasks, and 0 total tasks.
        self.assertEqual(WorkflowStatus.not_started, workflow.status)
        self.assertEqual(0, workflow.total_tasks)
        self.assertEqual(0, workflow.completed_tasks)

        # Initialize the Workflow with the workflow processor.
        workflow_model = db.session.query(WorkflowModel).filter(
            WorkflowModel.id == workflow.id).first()
        processor = WorkflowProcessor(workflow_model)

        # Assure the workflow is now started, and knows the total and completed tasks.
        studies = StudyService.get_studies_for_user(user)
        workflow = next(iter(
            studies[0].categories[0].workflows))  # Workflows is a set.
        #        self.assertEqual(WorkflowStatus.user_input_required, workflow.status)
        self.assertTrue(workflow.total_tasks > 0)
        self.assertEqual(0, workflow.completed_tasks)
        self.assertIsNotNone(workflow.spec_version)

        # Complete a task
        task = processor.next_task()
        processor.complete_task(task)
        processor.save()

        # Assure the workflow has moved on to the next task.
        studies = StudyService.get_studies_for_user(user)
        workflow = next(iter(
            studies[0].categories[0].workflows))  # Workflows is a set.
        self.assertEqual(1, workflow.completed_tasks)

        # Get approvals
        approvals = StudyService.get_approvals(studies[0].id)
        self.assertGreater(len(approvals), 0)
        self.assertIsNotNone(approvals[0]['display_order'])
Ejemplo n.º 4
0
def get_workflow(workflow_id, do_engine_steps=True):
    """Retrieve workflow based on workflow_id, and return it in the last saved State.
       If do_engine_steps is False, return the workflow without running any engine tasks or logging any events. """
    workflow_model: WorkflowModel = session.query(WorkflowModel).filter_by(
        id=workflow_id).first()
    processor = WorkflowProcessor(workflow_model)

    if do_engine_steps:
        processor.do_engine_steps()
        processor.save()
        WorkflowService.update_task_assignments(processor)

    workflow_api_model = WorkflowService.processor_to_workflow_api(processor)
    return WorkflowApiSchema().dump(workflow_api_model)
 def test_timer_event(self):
     workflow = self.create_workflow('timer_event')
     processor = WorkflowProcessor(workflow)
     processor.do_engine_steps()
     task = processor.next_task()
     processor.complete_task(task)
     tasks = processor.get_ready_user_tasks()
     self.assertEqual(tasks, [])
     processor.save()
     time.sleep(.3)  # our timer is at .25 sec so we have to wait for it
     # get done waiting
     WorkflowService.do_waiting()
     wf = db.session.query(WorkflowModel).filter(
         WorkflowModel.id == workflow.id).first()
     self.assertTrue(wf.status != WorkflowStatus.waiting)
    def test_waiting_event_error(self):
        workflow = self.create_workflow('timer_event_error')
        processor = WorkflowProcessor(workflow)
        processor.do_engine_steps()
        processor.save()
        time.sleep(.3)  # our timer is at .25 sec so we have to wait for it
        # get done waiting
        wf = db.session.query(WorkflowModel).filter(
            WorkflowModel.id == workflow.id).first()
        self.assertTrue(wf.status == WorkflowStatus.waiting)
        with self.assertLogs('crc', level='ERROR') as cm:
            WorkflowService.do_waiting()
            self.assertEqual(1, len(cm.output))
            self.assertRegex(cm.output[0], f"workflow #%i" % workflow.id)
            self.assertRegex(cm.output[0], f"study #%i" % workflow.study_id)

        self.assertTrue(wf.status == WorkflowStatus.erroring)
Ejemplo n.º 7
0
    def test_load_irb_from_db(self, mock_study_service):
        # This depends on getting a list of investigators back from the protocol builder.
        mock_study_service.return_value = self.mock_investigator_response

        self.load_example_data()
        workflow_spec_model = self.create_workflow("irb_api_personnel")
        study = session.query(StudyModel).first()
        processor = WorkflowProcessor(workflow_spec_model)
        processor.do_engine_steps()
        task_list = processor.get_ready_user_tasks()
        processor.complete_task(task_list[0])
        processor.do_engine_steps()
        nav_list = processor.bpmn_workflow.get_flat_nav_list()
        processor.save()
        # reload after save
        processor = WorkflowProcessor(workflow_spec_model)
        nav_list2 = processor.bpmn_workflow.get_flat_nav_list()
        self.assertEqual(nav_list, nav_list2)
Ejemplo n.º 8
0
def update_task(workflow_id, task_id, body, terminate_loop=None):
    workflow_model = session.query(WorkflowModel).filter_by(
        id=workflow_id).first()
    if workflow_model is None:
        raise ApiError("invalid_workflow_id",
                       "The given workflow id is not valid.",
                       status_code=404)

    elif workflow_model.study is None:
        raise ApiError("invalid_study",
                       "There is no study associated with the given workflow.",
                       status_code=404)

    processor = WorkflowProcessor(workflow_model)
    task_id = uuid.UUID(task_id)
    spiff_task = processor.bpmn_workflow.get_task(task_id)
    _verify_user_and_role(processor, spiff_task)
    if not spiff_task:
        raise ApiError("empty_task",
                       "Processor failed to obtain task.",
                       status_code=404)
    if spiff_task.state != spiff_task.READY:
        raise ApiError(
            "invalid_state",
            "You may not update a task unless it is in the READY state. "
            "Consider calling a token reset to make this task Ready.")

    if terminate_loop:
        spiff_task.terminate_loop()
    spiff_task.update_data(body)
    processor.complete_task(spiff_task)
    processor.do_engine_steps()
    processor.save()

    # Log the action, and any pending task assignments in the event of lanes in the workflow.
    WorkflowService.log_task_action(g.user.uid, processor, spiff_task,
                                    WorkflowService.TASK_ACTION_COMPLETE)
    WorkflowService.update_task_assignments(processor)

    workflow_api_model = WorkflowService.processor_to_workflow_api(processor)
    return WorkflowApiSchema().dump(workflow_api_model)