Tasks can have forms and they are returned correctly.

This commit is contained in:
Dan Funk 2019-12-19 11:58:51 -05:00
parent bc9bfb658e
commit bb6ab4b8e8
6 changed files with 131 additions and 22 deletions

View File

@ -2,6 +2,7 @@ import logging
import os
import connexion
from flask_cors import CORS
from flask_marshmallow import Marshmallow
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
@ -26,6 +27,7 @@ ma = Marshmallow(app)
from crc import models
connexion_app.add_api('api.yml')
cors = CORS(connexion_app.app)
@app.cli.command()
def load_example_data():

View File

@ -3,7 +3,7 @@ from flask_marshmallow import Schema
from crc import db, ma
from crc.models import WorkflowModel, WorkflowSchema, StudySchema, StudyModel, WorkflowSpecSchema, WorkflowSpecModel, \
WorkflowStatus
WorkflowStatus, Task, TaskSchema
from crc.workflow_processor import WorkflowProcessor
@ -61,11 +61,24 @@ def add_workflow_to_study(study_id, body):
workflow_spec_id=workflow_spec_model.id)
db.session.add(workflow)
db.session.commit()
return get_study_workflows(study_id)
def get_workflow(workflow_id):
return db.session.query(WorkflowModel).filter_by(id=workflow_id).first()
schema = WorkflowSchema()
workflow = db.session.query(WorkflowModel).filter_by(id=workflow_id).first()
return schema.dump(workflow)
def get_tasks(workflow_id):
workflow = db.session.query(WorkflowModel).filter_by(id=workflow_id).first()
processor = WorkflowProcessor(workflow.workflow_spec_id, workflow.bpmn_workflow_json)
spiff_tasks = processor.get_ready_user_tasks()
tasks = []
for st in spiff_tasks:
tasks.append(Task.from_spiff(st))
return TaskSchema(many=True).dump(tasks)
def get_task(workflow_id, task_id):
workflow = db.session.query(WorkflowModel).filter_by(id=workflow_id).first()
return workflow.bpmn_workflow().get_task(task_id)

View File

@ -192,7 +192,35 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/Error"
/workflow/{workflow_id}/tasks:
get:
operationId: crc.api.get_tasks
summary: Return a list of all tasks for this workflow
tags:
- Workflows and Tasks
parameters:
- name: workflow_id
in: path
required: true
description: The id of the workflow
schema:
type: integer
format: int32
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Task"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
# /v1.0/workflow/0/task/0
/workflow/{workflow_id}/task/{task_id}:
get:
@ -265,19 +293,10 @@ paths:
components:
schemas:
Study:
required:
- id
- title
- last_updated
- pb_status
- pi
- sponsor
- ind_number
properties:
id:
type: string
format: string
example: AB1234
type: integer
example: 1234
title:
type: string
example: The impact of fried pickles on beer consumption in bipedal software developers.
@ -285,11 +304,11 @@ components:
type: string
format: date_time
example: "2019-12-25T09:12:33.001Z"
pb_status:
protocol_builder_status:
type: string
enum: [started, done]
enum: [out_of_date, in_process, complete, updating]
example: done
pi:
primary_investigator_id:
type: string
example: dhf8r
sponsor:
@ -356,16 +375,20 @@ components:
type: string
type:
type: string
status:
type: string
form:
$ref: "#/components/schemas/Form"
example:
{
id: study_identification,
name: "Study Identification",
type: form,
state: "ready",
type: "form",
form: {
key: "oncology_form",
field: {
id: adult_oncology,
id: "is_adult_patient",
type: enum,
label: "Is this study treating adult oncology patients?",
options: ["yes", "no"],

View File

@ -1,10 +1,12 @@
import enum
from SpiffWorkflow import Task
from flask_marshmallow.sqla import ModelSchema
from marshmallow import post_load, fields, Schema
from marshmallow_enum import EnumField
from sqlalchemy import func
from crc import db
from crc import db, ma
class ProtocolBuilderStatus(enum.Enum):
@ -56,10 +58,58 @@ class WorkflowModel(db.Model):
study_id = db.Column(db.Integer, db.ForeignKey('study.id'))
workflow_spec_id = db.Column(db.Integer, db.ForeignKey('workflow_spec.id'))
class WorkflowSchema(ModelSchema):
class Meta:
model = WorkflowModel
status = EnumField(WorkflowStatus)
class Task:
def __init__(self, id, name, type, state, form):
self.id = id
self.name = name
self.type = type
self.state = state
self.form = form
@classmethod
def from_spiff(cls, spiff_task):
instance = cls(spiff_task.id,
spiff_task.task_spec.name,
spiff_task.get_state_name(),
"task",
{})
if hasattr(spiff_task.task_spec, "form"):
instance.type = "form"
instance.form = spiff_task.task_spec.form
return instance
class OptionSchema(ma.Schema):
class Meta:
fields = ["id", "name"]
class FieldSchema(ma.Schema):
class Meta:
fields = ["id", "type", "label", "defaultValue", "options"]
options = fields.List(fields.Nested(OptionSchema))
class FormSchema(ma.Schema):
class Meta:
fields = ["key", "fields"]
fields = fields.List(fields.Nested(FieldSchema))
class TaskSchema(ma.Schema):
class Meta:
fields = ["id", "name", "type", "state", "form"]
form = fields.Nested(FormSchema)
@post_load
def make_task(self, data, **kwargs):
return Task(**data)

View File

@ -67,7 +67,7 @@ class WorkflowProcessor:
self.bpmn_workflow.do_engine_steps()
def serialize(self):
return self.bpmn_workflow.serialize(JSONSerializer())
return self._serializer.serialize_workflow(self.bpmn_workflow)
def next_user_tasks(self):
return self.bpmn_workflow.get_ready_user_tasks()
@ -77,3 +77,6 @@ class WorkflowProcessor:
def get_data(self):
return self.bpmn_workflow.data
def get_ready_user_tasks(self):
return self.bpmn_workflow.get_ready_user_tasks()

View File

@ -4,7 +4,9 @@ import unittest
from sqlalchemy import func
from crc import db
from crc.models import StudyModel, StudySchema, WorkflowSpecModel, WorkflowSpecSchema, WorkflowModel, WorkflowStatus
from crc.models import StudyModel, StudySchema, WorkflowSpecModel, WorkflowSpecSchema, WorkflowModel, WorkflowStatus, \
WorkflowSchema, TaskSchema
from crc.workflow_processor import WorkflowProcessor
from tests.base_test import BaseTest
@ -62,3 +64,19 @@ class TestStudy(BaseTest, unittest.TestCase):
self.assertIsNotNone(workflow.bpmn_workflow_json)
self.assertEqual(spec.id, workflow.workflow_spec_id)
json_data = json.loads(rv.get_data(as_text=True))
workflows = WorkflowSchema(many=True).load(json_data, session=db.session)
self.assertEqual(workflows[0].id, workflow.id)
def test_get_current_user_tasks(self):
self.load_example_data()
study = db.session.query(StudyModel).first()
spec = db.session.query(WorkflowSpecModel).filter_by(id='random_fact').first()
self.app.post('/v1.0/study/%i/workflows' % study.id, content_type="application/json",
data=json.dumps(WorkflowSpecSchema().dump(spec)))
rv = self.app.get('/v1.0/workflow/%i/tasks' % study.id, content_type="application/json")
self.assert_success(rv)
json_data = json.loads(rv.get_data(as_text=True))
tasks = TaskSchema(many=True).load(json_data)
self.assertEqual("Task_User_Select_Type", tasks[0].name)
self.assertEqual(3, len(tasks[0].form["fields"][0]["options"]))