Merge pull request #375 from sartography/study-info-adds-463
Study info adds #463
This commit is contained in:
commit
e672d46dd0
|
@ -53,6 +53,8 @@ class StudyModel(db.Model):
|
||||||
enrollment_date = db.Column(db.DateTime(timezone=True), nullable=True)
|
enrollment_date = db.Column(db.DateTime(timezone=True), nullable=True)
|
||||||
#events = db.relationship("TaskEventModel")
|
#events = db.relationship("TaskEventModel")
|
||||||
events_history = db.relationship("StudyEvent", cascade="all, delete, delete-orphan")
|
events_history = db.relationship("StudyEvent", cascade="all, delete, delete-orphan")
|
||||||
|
short_name = db.Column(db.String, nullable=True)
|
||||||
|
proposal_name = db.Column(db.String, nullable=True)
|
||||||
|
|
||||||
def update_from_protocol_builder(self, pbs: ProtocolBuilderStudy):
|
def update_from_protocol_builder(self, pbs: ProtocolBuilderStudy):
|
||||||
self.title = pbs.TITLE
|
self.title = pbs.TITLE
|
||||||
|
@ -168,7 +170,7 @@ class CategorySchema(ma.Schema):
|
||||||
class Study(object):
|
class Study(object):
|
||||||
|
|
||||||
def __init__(self, title, short_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="",
|
id=None, status=None, irb_status=None, short_name=None, proposal_name=None, comment="",
|
||||||
sponsor="", ind_number="", categories=[],
|
sponsor="", ind_number="", categories=[],
|
||||||
files=[], approvals=[], enrollment_date=None, events_history=[],
|
files=[], approvals=[], enrollment_date=None, events_history=[],
|
||||||
last_activity_user="",last_activity_date =None,create_user_display="", **argsv):
|
last_activity_user="",last_activity_date =None,create_user_display="", **argsv):
|
||||||
|
@ -192,6 +194,8 @@ class Study(object):
|
||||||
self.files = files
|
self.files = files
|
||||||
self.enrollment_date = enrollment_date
|
self.enrollment_date = enrollment_date
|
||||||
self.events_history = events_history
|
self.events_history = events_history
|
||||||
|
self.short_name = short_name
|
||||||
|
self.proposal_name = proposal_name
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_model(cls, study_model: StudyModel):
|
def from_model(cls, study_model: StudyModel):
|
||||||
|
@ -253,13 +257,15 @@ class StudySchema(ma.Schema):
|
||||||
files = fields.List(fields.Nested(FileSchema), dump_only=True)
|
files = fields.List(fields.Nested(FileSchema), dump_only=True)
|
||||||
enrollment_date = fields.Date(allow_none=True)
|
enrollment_date = fields.Date(allow_none=True)
|
||||||
events_history = fields.List(fields.Nested('StudyEventSchema'), dump_only=True)
|
events_history = fields.List(fields.Nested('StudyEventSchema'), dump_only=True)
|
||||||
|
short_name = fields.String(allow_none=True)
|
||||||
|
proposal_name = fields.String(allow_none=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Study
|
model = Study
|
||||||
additional = ["id", "title", "short_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",
|
"sponsor", "ind_number", "files", "enrollment_date",
|
||||||
"create_user_display", "last_activity_date","last_activity_user",
|
"create_user_display", "last_activity_date", "last_activity_user",
|
||||||
"events_history"]
|
"events_history", "short_name", "proposal_name"]
|
||||||
unknown = INCLUDE
|
unknown = INCLUDE
|
||||||
|
|
||||||
@marshmallow.post_load
|
@marshmallow.post_load
|
||||||
|
|
|
@ -44,6 +44,10 @@ update_study(title=PIComputingID.label, short_title="Really Short Name")
|
||||||
study.title = kwargs[arg]
|
study.title = kwargs[arg]
|
||||||
elif arg.lower() == "short_title":
|
elif arg.lower() == "short_title":
|
||||||
study.short_title = kwargs[arg]
|
study.short_title = kwargs[arg]
|
||||||
|
elif arg.lower() == "short_name":
|
||||||
|
study.short_name = kwargs[arg]
|
||||||
|
elif arg.lower() == "proposal_name":
|
||||||
|
study.proposal_name = kwargs[arg]
|
||||||
elif arg.lower() == "pi":
|
elif arg.lower() == "pi":
|
||||||
study.primary_investigator_id = kwargs[arg]
|
study.primary_investigator_id = kwargs[arg]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
"""new study info data points
|
||||||
|
|
||||||
|
Revision ID: 9afbd55082a0
|
||||||
|
Revises: 981156283cb9
|
||||||
|
Create Date: 2021-09-17 10:31:05.094062
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '9afbd55082a0'
|
||||||
|
down_revision = '981156283cb9'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.add_column('study', sa.Column('short_name', sa.String(), nullable=True))
|
||||||
|
op.add_column('study', sa.Column('proposal_name', sa.String(), nullable=True))
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_column('study', 'short_name')
|
||||||
|
op.drop_column('study', 'proposal_name')
|
|
@ -0,0 +1,85 @@
|
||||||
|
<?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_3435c8d" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
|
||||||
|
<bpmn:process id="Process_3435c8d" isExecutable="true">
|
||||||
|
<bpmn:startEvent id="StartEvent_1">
|
||||||
|
<bpmn:outgoing>Flow_0g8e1jy</bpmn:outgoing>
|
||||||
|
</bpmn:startEvent>
|
||||||
|
<bpmn:sequenceFlow id="Flow_0g8e1jy" sourceRef="StartEvent_1" targetRef="Activity_GetData" />
|
||||||
|
<bpmn:userTask id="Activity_GetData" name="Get Data" camunda:formKey="GetDataForm">
|
||||||
|
<bpmn:extensionElements>
|
||||||
|
<camunda:formData>
|
||||||
|
<camunda:formField id="short_name" label="Short Name" type="string" />
|
||||||
|
<camunda:formField id="proposal_name" label="Proposal Name" type="string" />
|
||||||
|
</camunda:formData>
|
||||||
|
</bpmn:extensionElements>
|
||||||
|
<bpmn:incoming>Flow_0g8e1jy</bpmn:incoming>
|
||||||
|
<bpmn:outgoing>Flow_09flr91</bpmn:outgoing>
|
||||||
|
</bpmn:userTask>
|
||||||
|
<bpmn:sequenceFlow id="Flow_09flr91" sourceRef="Activity_GetData" targetRef="Activity_UpdateStudy" />
|
||||||
|
<bpmn:scriptTask id="Activity_UpdateStudy" name="Update Study">
|
||||||
|
<bpmn:incoming>Flow_09flr91</bpmn:incoming>
|
||||||
|
<bpmn:outgoing>Flow_0xf0u0k</bpmn:outgoing>
|
||||||
|
<bpmn:script>update_study(short_name=short_name, proposal_name=proposal_name)</bpmn:script>
|
||||||
|
</bpmn:scriptTask>
|
||||||
|
<bpmn:sequenceFlow id="Flow_0xf0u0k" sourceRef="Activity_UpdateStudy" targetRef="Activity_GetStudyInfo" />
|
||||||
|
<bpmn:scriptTask id="Activity_GetStudyInfo" name="Get Study Info">
|
||||||
|
<bpmn:incoming>Flow_0xf0u0k</bpmn:incoming>
|
||||||
|
<bpmn:outgoing>Flow_0tzamxo</bpmn:outgoing>
|
||||||
|
<bpmn:script>study_info = study_info("info")</bpmn:script>
|
||||||
|
</bpmn:scriptTask>
|
||||||
|
<bpmn:sequenceFlow id="Flow_0tzamxo" sourceRef="Activity_GetStudyInfo" targetRef="Activity_DisplayInfo" />
|
||||||
|
<bpmn:manualTask id="Activity_DisplayInfo" name="Display Study Info">
|
||||||
|
<bpmn:documentation># Info
|
||||||
|
{{ study_info }}
|
||||||
|
</bpmn:documentation>
|
||||||
|
<bpmn:incoming>Flow_0tzamxo</bpmn:incoming>
|
||||||
|
<bpmn:outgoing>Flow_0x5ex3d</bpmn:outgoing>
|
||||||
|
</bpmn:manualTask>
|
||||||
|
<bpmn:endEvent id="Event_05xjsir">
|
||||||
|
<bpmn:incoming>Flow_0x5ex3d</bpmn:incoming>
|
||||||
|
</bpmn:endEvent>
|
||||||
|
<bpmn:sequenceFlow id="Flow_0x5ex3d" sourceRef="Activity_DisplayInfo" targetRef="Event_05xjsir" />
|
||||||
|
</bpmn:process>
|
||||||
|
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||||
|
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_3435c8d">
|
||||||
|
<bpmndi:BPMNEdge id="Flow_0x5ex3d_di" bpmnElement="Flow_0x5ex3d">
|
||||||
|
<di:waypoint x="850" y="177" />
|
||||||
|
<di:waypoint x="912" y="177" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_0tzamxo_di" bpmnElement="Flow_0tzamxo">
|
||||||
|
<di:waypoint x="690" y="177" />
|
||||||
|
<di:waypoint x="750" y="177" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_0xf0u0k_di" bpmnElement="Flow_0xf0u0k">
|
||||||
|
<di:waypoint x="530" y="177" />
|
||||||
|
<di:waypoint x="590" y="177" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_09flr91_di" bpmnElement="Flow_09flr91">
|
||||||
|
<di:waypoint x="370" y="177" />
|
||||||
|
<di:waypoint x="430" y="177" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_0g8e1jy_di" bpmnElement="Flow_0g8e1jy">
|
||||||
|
<di:waypoint x="215" y="177" />
|
||||||
|
<di:waypoint x="270" y="177" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||||
|
<dc:Bounds x="179" y="159" width="36" height="36" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_06lg3xc_di" bpmnElement="Activity_GetData">
|
||||||
|
<dc:Bounds x="270" y="137" width="100" height="80" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_0ulzpsr_di" bpmnElement="Activity_UpdateStudy">
|
||||||
|
<dc:Bounds x="430" y="137" width="100" height="80" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_15xfbrf_di" bpmnElement="Activity_GetStudyInfo">
|
||||||
|
<dc:Bounds x="590" y="137" width="100" height="80" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_1yteq9j_di" bpmnElement="Activity_DisplayInfo">
|
||||||
|
<dc:Bounds x="750" y="137" width="100" height="80" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Event_05xjsir_di" bpmnElement="Event_05xjsir">
|
||||||
|
<dc:Bounds x="912" y="159" width="36" height="36" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
</bpmndi:BPMNPlane>
|
||||||
|
</bpmndi:BPMNDiagram>
|
||||||
|
</bpmn:definitions>
|
|
@ -14,9 +14,12 @@ class TestUpdateStudyScript(BaseTest):
|
||||||
processor = WorkflowProcessor(workflow)
|
processor = WorkflowProcessor(workflow)
|
||||||
task = processor.next_task()
|
task = processor.next_task()
|
||||||
details = Box({
|
details = Box({
|
||||||
"label": "My New Title",
|
"title": "My New Title",
|
||||||
"short": "My New Short Title",
|
"short_title": "My New Short Title",
|
||||||
"value": "dhf8r"})
|
"pi": "dhf8r",
|
||||||
|
"short_name": "My Short Name",
|
||||||
|
"proposal_name": "My Proposal Name"
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
script = UpdateStudy()
|
script = UpdateStudy()
|
||||||
|
@ -26,9 +29,14 @@ class TestUpdateStudyScript(BaseTest):
|
||||||
# evaluated before they are passed to the script -
|
# evaluated before they are passed to the script -
|
||||||
# this allows us to do a lot more things like strings, functions, etc.
|
# this allows us to do a lot more things like strings, functions, etc.
|
||||||
# and it makes the arguments less confusing to use.
|
# and it makes the arguments less confusing to use.
|
||||||
script.do_task(task, workflow.study_id, workflow.id, title = details.label,
|
script.do_task(task, workflow.study_id, workflow.id,
|
||||||
short_title = details.short,
|
title=details.title,
|
||||||
pi = details.value)
|
short_title=details.short_title,
|
||||||
self.assertEqual("My New Title", workflow.study.title)
|
pi=details.pi,
|
||||||
self.assertEqual("My New Short Title", workflow.study.short_title)
|
short_name=details.short_name,
|
||||||
self.assertEqual("dhf8r", workflow.study.primary_investigator_id)
|
proposal_name=details.proposal_name)
|
||||||
|
self.assertEqual(details.title, workflow.study.title)
|
||||||
|
self.assertEqual(details.short_title, workflow.study.short_title)
|
||||||
|
self.assertEqual(details.pi, workflow.study.primary_investigator_id)
|
||||||
|
self.assertEqual(details.short_name, workflow.study.short_name)
|
||||||
|
self.assertEqual(details.proposal_name, workflow.study.proposal_name)
|
||||||
|
|
|
@ -33,6 +33,25 @@ class TestStudyInfoScript(BaseTest):
|
||||||
self.assertEqual(study_info['primary_investigator_id'], second_task.data['info']['primary_investigator_id'])
|
self.assertEqual(study_info['primary_investigator_id'], second_task.data['info']['primary_investigator_id'])
|
||||||
self.assertIn(study_info['title'], second_task.documentation)
|
self.assertIn(study_info['title'], second_task.documentation)
|
||||||
|
|
||||||
|
def test_info_script_updated_study_info(self):
|
||||||
|
self.load_example_data()
|
||||||
|
short_name = "My Short Name"
|
||||||
|
proposal_name = "My Proposal Name"
|
||||||
|
workflow = self.create_workflow('update_study_info')
|
||||||
|
workflow_api = self.get_workflow_api(workflow)
|
||||||
|
task = workflow_api.next_task
|
||||||
|
|
||||||
|
workflow_api = self.complete_form(workflow, task, {'short_name': short_name, 'proposal_name': proposal_name})
|
||||||
|
task = workflow_api.next_task
|
||||||
|
# The workflow calls study_info('info') and puts the result in Element Documentation
|
||||||
|
# I create a dictionary of that info with `eval` to make the asserts easier to read
|
||||||
|
study_info = eval(task.documentation)
|
||||||
|
|
||||||
|
self.assertIn('short_name', study_info.keys())
|
||||||
|
self.assertEqual(short_name, study_info['short_name'])
|
||||||
|
self.assertIn('proposal_name', study_info.keys())
|
||||||
|
self.assertIn(proposal_name, study_info['proposal_name'])
|
||||||
|
|
||||||
@patch('crc.services.protocol_builder.requests.get')
|
@patch('crc.services.protocol_builder.requests.get')
|
||||||
def test_info_script_investigators(self, mock_get):
|
def test_info_script_investigators(self, mock_get):
|
||||||
app.config['PB_ENABLED'] = True
|
app.config['PB_ENABLED'] = True
|
||||||
|
|
Loading…
Reference in New Issue