Merge pull request #253 from sartography/220-short-study-name

Add short_title to study, change update_study task to use kw argument…
This commit is contained in:
Dan Funk 2021-03-02 13:37:24 -05:00 committed by GitHub
commit 9c31d69c12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 74 additions and 38 deletions

View File

@ -40,6 +40,7 @@ class StudyModel(db.Model):
__tablename__ = 'study'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String)
short_title = db.Column(db.String, nullable=True)
last_updated = db.Column(db.DateTime(timezone=True), default=func.now())
status = db.Column(db.Enum(StudyStatus))
irb_status = db.Column(db.Enum(IrbStatus))
@ -161,7 +162,7 @@ class CategorySchema(ma.Schema):
class Study(object):
def __init__(self, title, last_updated, primary_investigator_id, user_uid,
def __init__(self, title, short_title, last_updated, primary_investigator_id, user_uid,
id=None, status=None, irb_status=None, comment="",
sponsor="", hsr_number="", ind_number="", categories=[],
files=[], approvals=[], enrollment_date=None, events_history=[],
@ -172,6 +173,7 @@ class Study(object):
self.last_activity_date = last_activity_date
self.last_activity_user = last_activity_user
self.title = title
self.short_title = short_title
self.last_updated = last_updated
self.status = status
self.irb_status = irb_status
@ -243,6 +245,7 @@ class StudySchema(ma.Schema):
protocol_builder_status = EnumField(StudyStatus, by_value=True)
status = EnumField(StudyStatus, by_value=True)
hsr_number = fields.String(allow_none=True)
short_title = fields.String(allow_none=True)
sponsor = fields.String(allow_none=True)
ind_number = fields.String(allow_none=True)
files = fields.List(fields.Nested(FileSchema), dump_only=True)
@ -251,7 +254,7 @@ class StudySchema(ma.Schema):
class Meta:
model = Study
additional = ["id", "title", "last_updated", "primary_investigator_id", "user_uid",
additional = ["id", "title", "short_title", "last_updated", "primary_investigator_id", "user_uid",
"sponsor", "ind_number", "files", "enrollment_date",
"create_user_display", "last_activity_date","last_activity_user",
"events_history"]

View File

@ -186,6 +186,7 @@ Returns information specific to the protocol.
"info": {
"id": 12,
"title": "test",
"short_title": "tst",
"primary_investigator_id":21,
"user_uid": "dif84",
"sponsor": "sponsor",

View File

@ -15,44 +15,37 @@ class mock_study:
class UpdateStudy(Script):
argument_error_message = "You must supply at least one argument to the " \
"update_study task, in the form [study_field]:[value]",
"update_study task, in the form [study_field]=[value]",
def get_description(self):
return """
Allows you to set specific attributes on the Study model by mapping them to
values in the task data. Should be called with the value to set (either title, or pi)
followed by a ":" and then the value to use in dot notation.
values in the task data. Should be called with the value to set (either title, short_title, or pi)
Example:
UpdateStudy title:PIComputingID.label pi:PIComputingID.value
update_study(title=PIComputingID.label, short_title="Really Short Name")
"""
def do_task_validate_only(self, task, study_id, workflow_id, *args, **kwargs):
study = mock_study
self.__update_study(task, study, *args)
self.__update_study(task, study, *args, **kwargs)
def do_task(self, task, study_id, workflow_id, *args, **kwargs):
study = db.session.query(StudyModel).filter(StudyModel.id == study_id).first()
self.__update_study(task, study, *args)
self.__update_study(task, study, *args, **kwargs)
db.session.add(study)
def __update_study(self, task, study, *args):
if len(args) < 1:
def __update_study(self, task, study, *args, **kwargs):
if len(kwargs.keys()) < 1:
raise ApiError.from_task("missing_argument", self.argument_error_message,
task=task)
for arg in args:
try:
field, value_lookup = arg.split(':')
except:
raise ApiError.from_task("invalid_argument", self.argument_error_message,
task=task)
value = task.workflow.script_engine.evaluate_expression(task, value_lookup)
if field.lower() == "title":
study.title = value
elif field.lower() == "pi":
study.primary_investigator_id = value
for arg in kwargs.keys():
if arg.lower() == "title":
study.title = kwargs[arg]
elif arg.lower() == "short_title":
study.short_title = kwargs[arg]
elif arg.lower() == "pi":
study.primary_investigator_id = kwargs[arg]
else:
raise ApiError.from_task("invalid_argument", self.argument_error_message,
task=task)

View File

@ -36,7 +36,7 @@ class StudyService(object):
studies = []
for study_model in db_studies:
studies.append(StudyService.get_study(study_model.id, study_model))
studies.append(StudyService.get_study(study_model.id, study_model,do_status=False))
return studies
@staticmethod
@ -51,7 +51,7 @@ class StudyService(object):
return studies
@staticmethod
def get_study(study_id, study_model: StudyModel = None):
def get_study(study_id, study_model: StudyModel = None, do_status=True):
"""Returns a study model that contains all the workflows organized by category.
IMPORTANT: This is intended to be a lightweight call, it should never involve
loading up and executing all the workflows in a study to calculate information."""
@ -81,6 +81,7 @@ class StudyService(object):
if study.status != StudyStatus.abandoned:
# this line is taking 99% of the time that is used in get_study.
# see ticket #196
if do_status:
status = StudyService.__get_study_status(study_model)
study.warnings = StudyService.__update_status_of_workflow_meta(workflow_metas, status)

View File

@ -0,0 +1,28 @@
"""empty message
Revision ID: f28ee3722c49
Revises: cb892916166a
Create Date: 2021-03-02 08:30:22.879266
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'f28ee3722c49'
down_revision = 'cb892916166a'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('study', sa.Column('short_title', sa.String(), nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('study', 'short_title')
# ### end Alembic commands ###

View File

@ -1,5 +1,5 @@
<?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_0a9entn" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.3">
<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_0a9entn" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.0">
<bpmn:process id="Process_1dagb7t" name="TestMessage" isExecutable="true">
<bpmn:startEvent id="StartEvent_1" name="Start">
<bpmn:outgoing>Flow_0xym55y</bpmn:outgoing>
@ -7,7 +7,7 @@
<bpmn:sequenceFlow id="Flow_16q1uec" name="TestMessageFlow" sourceRef="Event_TokenReset" targetRef="Activity_TestMessage" />
<bpmn:scriptTask id="Activity_TestMessage" name="Test Message" camunda:resultVariable="test_message">
<bpmn:incoming>Flow_16q1uec</bpmn:incoming>
<bpmn:script>update_study("title:'New Title'")
<bpmn:script>update_study(title='New Title')
print('New Title')</bpmn:script>
</bpmn:scriptTask>
<bpmn:userTask id="Activity_GetData" name="GetData" camunda:formKey="FirstTaskForm">

View File

@ -1,5 +1,5 @@
<?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_0a9entn" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.2.0">
<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_0a9entn" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.0">
<bpmn:process id="Process_1dagb7t" name="TestMessage" isExecutable="true">
<bpmn:startEvent id="StartEvent_1" name="Start">
<bpmn:outgoing>Flow_0xym55y</bpmn:outgoing>
@ -7,7 +7,7 @@
<bpmn:sequenceFlow id="Flow_16q1uec" name="TestMessageFlow" sourceRef="Event_TokenReset" targetRef="Activity_TestMessage" />
<bpmn:scriptTask id="Activity_TestMessage" name="Test Message" camunda:resultVariable="test_message">
<bpmn:incoming>Flow_16q1uec</bpmn:incoming>
<bpmn:script>update_study("title:'New Title'")
<bpmn:script>update_study(title='New Title')
print('New Title')</bpmn:script>
</bpmn:scriptTask>
<bpmn:sequenceFlow id="Flow_0xym55y" sourceRef="StartEvent_1" targetRef="Activity_Hello" />
@ -58,7 +58,7 @@ print('New Title')</bpmn:script>
<bpmn:scriptTask id="Activity_CancelMessage" name="Cancel Message" camunda:resultVariable="cancel_message">
<bpmn:documentation>&lt;H1&gt;Cancel Message&lt;/H1&gt;</bpmn:documentation>
<bpmn:incoming>Flow_13xidv2</bpmn:incoming>
<bpmn:script>update_study("title:'Second Title'")
<bpmn:script>update_study(title='Second Title')
print('Second Title')</bpmn:script>
</bpmn:scriptTask>
</bpmn:process>

View File

@ -2,7 +2,7 @@ from tests.base_test import BaseTest
from crc.scripts.update_study import UpdateStudy
from crc.services.workflow_processor import WorkflowProcessor
from box import Box
class TestUpdateStudyScript(BaseTest):
@ -12,12 +12,22 @@ class TestUpdateStudyScript(BaseTest):
workflow = self.create_workflow('empty_workflow')
processor = WorkflowProcessor(workflow)
task = processor.next_task()
task.data = {"details": {
details = Box({
"label": "My New Title",
"value": "dhf8r"}
}
"short": "My New Short Title",
"value": "dhf8r"})
script = UpdateStudy()
script.do_task(task, workflow.study_id, workflow.id, "title:details.label", "pi:details.value")
# note that we changed where the argument gets evaluated
# previsously, it took the arguments and then evaluated them within the script
# now, it evaluates the arugments in the context of the main script so they get
# evaluated before they are passed to the script -
# this allows us to do a lot more things like strings, functions, etc.
# and it makes the arguments less confusing to use.
script.do_task(task, workflow.study_id, workflow.id, title = details.label,
short_title = details.short,
pi = details.value)
self.assertEqual("My New Title", workflow.study.title)
self.assertEqual("My New Short Title", workflow.study.short_title)
self.assertEqual("dhf8r", workflow.study.primary_investigator_id)

View File

@ -26,7 +26,7 @@ class TestMessageEvent(BaseTest):
headers=self.logged_in_headers(),
content_type="application/json")
# set_current_task should call the interupt (signal) task
# set_current_task should call the interrupt (signal) task
# which should run the script in our task
#
# test to see if our changes made it to the DB