Merge pull request #430 from sartography/study-status-scripts-556

Study status scripts #556
This commit is contained in:
Dan Funk 2021-12-08 10:36:53 -05:00 committed by GitHub
commit b28ddef842
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 294 additions and 0 deletions

View File

@ -0,0 +1,18 @@
from crc import session
from crc.models.study import StudyModel
from crc.scripts.script import Script
class GetStudyStatus(Script):
def get_description(self):
return """Get the status of the current study.
Status can be one of `in_progress`, `hold`, `open_for_enrollment`, or `abandoned`."""
def do_task_validate_only(self, task, study_id, workflow_id, *args, **kwargs):
return self.do_task(task, study_id, workflow_id, *args, **kwargs)
def do_task(self, task, study_id, workflow_id, *args, **kwargs):
study_status = session.query(StudyModel.status).filter(StudyModel.id == study_id).scalar()
if study_status:
return study_status.value

View File

@ -0,0 +1,69 @@
from crc import session
from crc.api.common import ApiError
from crc.models.study import StudyModel, StudyStatus
from crc.scripts.script import Script
class SetStudyStatus(Script):
def get_description(self):
return """Set the status of the current study.
Status can be one of `in_progress`, `hold`, `open_for_enrollment`, or `abandoned`."""
def do_task_validate_only(self, task, study_id, workflow_id, *args, **kwargs):
if 'new_status' in kwargs.keys() or len(args) > 0:
if 'new_status' in kwargs.keys():
new_status = kwargs['new_status']
else:
new_status = args[0]
try:
study_status = getattr(StudyStatus, new_status)
except AttributeError as ae:
raise ApiError.from_task(code='invalid_argument',
message=f"We could not find a status matching `{new_status}`. Original message: {ae}",
task=task)
return study_status.value
else:
raise ApiError.from_task(code='missing_argument',
message='You must include the new status when calling `set_study_status` script. '
'The new status must be one of `in_progress`, `hold`, `open_for_enrollment`, or `abandoned`.',
task=task)
def do_task(self, task, study_id, workflow_id, *args, **kwargs):
# Get new status
if 'new_status' in kwargs.keys() or len(args) > 0:
if 'new_status' in kwargs.keys():
new_status = kwargs['new_status']
else:
new_status = args[0]
# Get StudyStatus object for new_status
try:
study_status = getattr(StudyStatus, new_status)
# Invalid argument
except AttributeError as ae:
raise ApiError.from_task(code='invalid_argument',
message=f"We could not find a status matching `{new_status}`. Original message: {ae}"
'The new status must be one of `in_progress`, `hold`, `open_for_enrollment`, or `abandoned`.',
task=task)
# Set new status
study_model = session.query(StudyModel).filter(StudyModel.id == study_id).first()
study_model.status = study_status
session.commit()
return study_model.status.value
# Missing argument
else:
raise ApiError.from_task(code='missing_argument',
message='You must include the new status when calling `set_study_status` script. '
'The new status must be one of `in_progress`, `hold`, `open_for_enrollment`, or `abandoned`.',
task=task)

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1mi5jsa" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.2.0">
<bpmn:process id="Process_19squur" name="Study Status" isExecutable="true">
<bpmn:startEvent id="StartEvent_1" name="Start">
<bpmn:outgoing>Flow_1iqprcz</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_1iqprcz" sourceRef="StartEvent_1" targetRef="Activity_GetStudyStatus" />
<bpmn:scriptTask id="Activity_GetStudyStatus" name="Get Study Status">
<bpmn:incoming>Flow_1iqprcz</bpmn:incoming>
<bpmn:outgoing>Flow_0npc38l</bpmn:outgoing>
<bpmn:script>study_status = get_study_status()</bpmn:script>
</bpmn:scriptTask>
<bpmn:endEvent id="Event_005hgvx" name="Display Study Status">
<bpmn:documentation># Study Status
{{ study_status }}</bpmn:documentation>
<bpmn:incoming>Flow_0npc38l</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_0npc38l" sourceRef="Activity_GetStudyStatus" targetRef="Event_005hgvx" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_19squur">
<bpmndi:BPMNEdge id="Flow_1iqprcz_di" bpmnElement="Flow_1iqprcz">
<di:waypoint x="215" y="117" />
<di:waypoint x="270" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0npc38l_di" bpmnElement="Flow_0npc38l">
<di:waypoint x="370" y="117" />
<di:waypoint x="432" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="99" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="186" y="142" width="24" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_07bvb7w_di" bpmnElement="Activity_GetStudyStatus">
<dc:Bounds x="270" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_005hgvx_di" bpmnElement="Event_005hgvx">
<dc:Bounds x="432" y="99" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="417" y="142" width="68" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_00dbd41" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.2.0">
<bpmn:process id="Process_SetStudyStatus" name="Set Study Status" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_0c77bdh</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:userTask id="Activity_GetSelectedStatus" name="Get Selected Status" camunda:formKey="SelectStudyStatus">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="selected_status" label="Select Study Status" type="enum">
<camunda:value id="in_progress" name="In Progress" />
<camunda:value id="hold" name="Hold" />
<camunda:value id="open_for_enrollment" name="Open For Enrollment" />
<camunda:value id="abandoned" name="Abandoned" />
<camunda:value id="asdf" name="asdf" />
</camunda:formField>
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>Flow_1e9oiuw</bpmn:incoming>
<bpmn:outgoing>Flow_0q0rtvj</bpmn:outgoing>
</bpmn:userTask>
<bpmn:sequenceFlow id="Flow_0q0rtvj" sourceRef="Activity_GetSelectedStatus" targetRef="Activity_SetSelectedStatus" />
<bpmn:scriptTask id="Activity_SetSelectedStatus" name="Set Selected Status">
<bpmn:incoming>Flow_0q0rtvj</bpmn:incoming>
<bpmn:outgoing>Flow_0ana8xt</bpmn:outgoing>
<bpmn:script>returned_status = set_study_status(selected_status)</bpmn:script>
</bpmn:scriptTask>
<bpmn:sequenceFlow id="Flow_0ana8xt" sourceRef="Activity_SetSelectedStatus" targetRef="Activity_GetNewStatus" />
<bpmn:manualTask id="Activity_DisplayStatus" name="Display Status">
<bpmn:documentation># Study Status
## Original Status
{{ original_status }}
## Selected Status
{{ selected_status }}
## Returned Status
{{ returned_status }}
## New Status
{{ new_status }}</bpmn:documentation>
<bpmn:incoming>Flow_0nckhhn</bpmn:incoming>
<bpmn:outgoing>Flow_14s6jnt</bpmn:outgoing>
</bpmn:manualTask>
<bpmn:endEvent id="Event_1wm8dmt">
<bpmn:incoming>Flow_14s6jnt</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_14s6jnt" sourceRef="Activity_DisplayStatus" targetRef="Event_1wm8dmt" />
<bpmn:sequenceFlow id="Flow_0c77bdh" sourceRef="StartEvent_1" targetRef="Activity_GetOriginalStatus" />
<bpmn:sequenceFlow id="Flow_1e9oiuw" sourceRef="Activity_GetOriginalStatus" targetRef="Activity_GetSelectedStatus" />
<bpmn:scriptTask id="Activity_GetOriginalStatus" name="Get Original Status">
<bpmn:incoming>Flow_0c77bdh</bpmn:incoming>
<bpmn:outgoing>Flow_1e9oiuw</bpmn:outgoing>
<bpmn:script>original_status = get_study_status()</bpmn:script>
</bpmn:scriptTask>
<bpmn:sequenceFlow id="Flow_0nckhhn" sourceRef="Activity_GetNewStatus" targetRef="Activity_DisplayStatus" />
<bpmn:scriptTask id="Activity_GetNewStatus" name="Get New Status">
<bpmn:incoming>Flow_0ana8xt</bpmn:incoming>
<bpmn:outgoing>Flow_0nckhhn</bpmn:outgoing>
<bpmn:script>new_status = get_study_status()</bpmn:script>
</bpmn:scriptTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_SetStudyStatus">
<bpmndi:BPMNEdge id="Flow_0nckhhn_di" bpmnElement="Flow_0nckhhn">
<di:waypoint x="847" y="117" />
<di:waypoint x="913" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1e9oiuw_di" bpmnElement="Flow_1e9oiuw">
<di:waypoint x="349" y="117" />
<di:waypoint x="415" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0c77bdh_di" bpmnElement="Flow_0c77bdh">
<di:waypoint x="188" y="117" />
<di:waypoint x="249" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_14s6jnt_di" bpmnElement="Flow_14s6jnt">
<di:waypoint x="1013" y="117" />
<di:waypoint x="1072" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0ana8xt_di" bpmnElement="Flow_0ana8xt">
<di:waypoint x="681" y="117" />
<di:waypoint x="747" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0q0rtvj_di" bpmnElement="Flow_0q0rtvj">
<di:waypoint x="515" y="117" />
<di:waypoint x="581" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="152" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0xpoc9f_di" bpmnElement="Activity_GetSelectedStatus">
<dc:Bounds x="415" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0ef9nv4_di" bpmnElement="Activity_SetSelectedStatus">
<dc:Bounds x="581" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0tpv5xw_di" bpmnElement="Activity_DisplayStatus">
<dc:Bounds x="913" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1wm8dmt_di" bpmnElement="Event_1wm8dmt">
<dc:Bounds x="1072" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_18rnj9i_di" bpmnElement="Activity_GetOriginalStatus">
<dc:Bounds x="249" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0h090bt_di" bpmnElement="Activity_GetNewStatus">
<dc:Bounds x="747" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -0,0 +1,11 @@
from tests.base_test import BaseTest
class TestGetStudyStatus(BaseTest):
def test_get_study_status(self):
workflow = self.create_workflow('get_study_status')
workflow_api = self.get_workflow_api(workflow)
task = workflow_api.next_task
self.assertEqual(task.data['study_status'], workflow.study.status.value)

View File

@ -0,0 +1,35 @@
from tests.base_test import BaseTest
class TestSetStudyStatus(BaseTest):
def test_set_study_status_validation(self):
self.load_example_data()
spec_model = self.load_test_spec('set_study_status')
rv = self.app.get('/v1.0/workflow-specification/%s/validate' % spec_model.id, headers=self.logged_in_headers())
self.assertEqual([], rv.json)
def test_set_study_status(self):
workflow = self.create_workflow('set_study_status')
workflow_api = self.get_workflow_api(workflow)
task = workflow_api.next_task
original_status = task.data['original_status']
self.assertEqual('in_progress', original_status)
workflow_api = self.complete_form(workflow, task, {'selected_status': 'hold'})
task = workflow_api.next_task
self.assertEqual('Activity_DisplayStatus', task.name)
self.assertEqual('hold', task.data['selected_status'])
self.assertEqual('hold', task.data['new_status'])
def test_set_study_status_fail(self):
self.load_example_data()
workflow = self.create_workflow('set_study_status')
workflow_api = self.get_workflow_api(workflow)
task = workflow_api.next_task
with self.assertRaises(AssertionError):
self.complete_form(workflow, task, {'selected_status': 'asdf'})