diff --git a/crc/models/study.py b/crc/models/study.py index 967a964d..1e536a56 100644 --- a/crc/models/study.py +++ b/crc/models/study.py @@ -53,6 +53,8 @@ class StudyModel(db.Model): enrollment_date = db.Column(db.DateTime(timezone=True), nullable=True) #events = db.relationship("TaskEventModel") 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): self.title = pbs.TITLE @@ -168,7 +170,7 @@ class CategorySchema(ma.Schema): class Study(object): 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=[], files=[], approvals=[], enrollment_date=None, events_history=[], last_activity_user="",last_activity_date =None,create_user_display="", **argsv): @@ -192,6 +194,8 @@ class Study(object): self.files = files self.enrollment_date = enrollment_date self.events_history = events_history + self.short_name = short_name + self.proposal_name = proposal_name @classmethod def from_model(cls, study_model: StudyModel): @@ -253,13 +257,15 @@ class StudySchema(ma.Schema): files = fields.List(fields.Nested(FileSchema), dump_only=True) enrollment_date = fields.Date(allow_none=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: model = Study 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"] + "create_user_display", "last_activity_date", "last_activity_user", + "events_history", "short_name", "proposal_name"] unknown = INCLUDE @marshmallow.post_load diff --git a/crc/scripts/update_study.py b/crc/scripts/update_study.py index 340665e0..f3412a39 100644 --- a/crc/scripts/update_study.py +++ b/crc/scripts/update_study.py @@ -44,6 +44,10 @@ update_study(title=PIComputingID.label, short_title="Really Short Name") study.title = kwargs[arg] elif arg.lower() == "short_title": 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": study.primary_investigator_id = kwargs[arg] else: diff --git a/migrations/versions/9afbd55082a0_new_study_info_data_points.py b/migrations/versions/9afbd55082a0_new_study_info_data_points.py new file mode 100644 index 00000000..9a0a1e89 --- /dev/null +++ b/migrations/versions/9afbd55082a0_new_study_info_data_points.py @@ -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') diff --git a/tests/data/update_study_info/update_study_info.bpmn b/tests/data/update_study_info/update_study_info.bpmn new file mode 100644 index 00000000..ccaa7b05 --- /dev/null +++ b/tests/data/update_study_info/update_study_info.bpmn @@ -0,0 +1,85 @@ + + + + + Flow_0g8e1jy + + + + + + + + + + Flow_0g8e1jy + Flow_09flr91 + + + + Flow_09flr91 + Flow_0xf0u0k + update_study(short_name=short_name, proposal_name=proposal_name) + + + + Flow_0xf0u0k + Flow_0tzamxo + study_info = study_info("info") + + + + # Info +{{ study_info }} + + Flow_0tzamxo + Flow_0x5ex3d + + + Flow_0x5ex3d + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/study/test_update_study_script.py b/tests/study/test_update_study_script.py index 36d516d9..62444dd4 100644 --- a/tests/study/test_update_study_script.py +++ b/tests/study/test_update_study_script.py @@ -14,9 +14,12 @@ class TestUpdateStudyScript(BaseTest): processor = WorkflowProcessor(workflow) task = processor.next_task() details = Box({ - "label": "My New Title", - "short": "My New Short Title", - "value": "dhf8r"}) + "title": "My New Title", + "short_title": "My New Short Title", + "pi": "dhf8r", + "short_name": "My Short Name", + "proposal_name": "My Proposal Name" + }) script = UpdateStudy() @@ -26,9 +29,14 @@ class TestUpdateStudyScript(BaseTest): # 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) + script.do_task(task, workflow.study_id, workflow.id, + title=details.title, + short_title=details.short_title, + pi=details.pi, + short_name=details.short_name, + 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) diff --git a/tests/test_study_info_script.py b/tests/test_study_info_script.py index 18ac77a9..f5bd92c6 100644 --- a/tests/test_study_info_script.py +++ b/tests/test_study_info_script.py @@ -33,6 +33,25 @@ class TestStudyInfoScript(BaseTest): self.assertEqual(study_info['primary_investigator_id'], second_task.data['info']['primary_investigator_id']) 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') def test_info_script_investigators(self, mock_get): app.config['PB_ENABLED'] = True