diff --git a/crc/api.yml b/crc/api.yml
index 09cdc5a3..09b70e4d 100644
--- a/crc/api.yml
+++ b/crc/api.yml
@@ -746,7 +746,7 @@ components:
example: "2019-12-25T09:12:33.001Z"
protocol_builder_status:
type: string
- enum: [out_of_date, in_process, complete, updating]
+ enum: [DRAFT, IN_PROCESS, IN_REVIEW, REVIEW_COMPLETE, INACTIVE]
example: done
user_uid:
type: string
diff --git a/crc/api/study.py b/crc/api/study.py
index 159f8815..3bbd085e 100644
--- a/crc/api/study.py
+++ b/crc/api/study.py
@@ -89,7 +89,13 @@ def update_from_protocol_builder():
# Mark studies as inactive that are no longer in Protocol Builder
for study_id in db_study_ids:
if study_id not in pb_study_ids:
- update_study(study_id=study_id, body={'inactive': True})
+ update_study(
+ study_id=study_id,
+ body={
+ 'inactive': True,
+ 'protocol_builder_status': ProtocolBuilderStatus.INACTIVE.name
+ }
+ )
# Return updated studies
updated_studies = session.query(StudyModel).filter_by(user_uid=user.uid).all()
@@ -158,10 +164,20 @@ def map_pb_study_to_study(pb_study):
if k in prop_map:
study_info[prop_map[k]] = v
- if pb_study['Q_COMPLETE']:
- study_info['protocol_builder_status'] = ProtocolBuilderStatus.complete._value_
- else:
- study_info['protocol_builder_status'] = ProtocolBuilderStatus.in_process._value_
+ # Translate Protocol Builder states to enum values
+ status = ProtocolBuilderStatus.DRAFT
+ pb_details = ProtocolBuilderService.get_study_details(pb_study['STUDYID'])
+ if 'Q_COMPLETE' in pb_study and pb_study['Q_COMPLETE']:
+ if 'UPLOAD_COMPLETE' in pb_details and pb_details['UPLOAD_COMPLETE']:
+ if 'HSRNUMBER' in pb_study and pb_study['HSRNUMBER']:
+ status = ProtocolBuilderStatus.REVIEW_COMPLETE
+ else:
+ status = ProtocolBuilderStatus.IN_REVIEW
+ else:
+ status = ProtocolBuilderStatus.IN_PROCESS
+
+ study_info['protocol_builder_status'] = status.name
+ study_info['inactive'] = False
return study_info
diff --git a/crc/models/protocol_builder.py b/crc/models/protocol_builder.py
index 436e0027..a52a1ea0 100644
--- a/crc/models/protocol_builder.py
+++ b/crc/models/protocol_builder.py
@@ -18,10 +18,11 @@ class ProtocolBuilderInvestigatorType(enum.Enum):
class ProtocolBuilderStatus(enum.Enum):
- out_of_date = "out_of_date"
- in_process = "in_process"
- complete = "complete"
- updating = "updating"
+ DRAFT = 'draft', # !Q_COMPLETE
+ IN_PROCESS = 'in_process', # Q_COMPLETE && !UPLOAD_COMPLETE && !HSRNUMBER
+ IN_REVIEW = 'in_review', # Q_COMPLETE && (!UPLOAD_COMPLETE || !HSRNUMBER)
+ REVIEW_COMPLETE = 'review_complete', # Q_COMPLETE && UPLOAD_COMPLETE && HSRNUMBER
+ INACTIVE = 'inactive', # Not found in PB
class ProtocolBuilderStudy(object):
diff --git a/crc/static/bpmn/crc2_training_session_data_security_plan/crc2_training_session_data_security_plan.bpmn b/crc/static/bpmn/crc2_training_session_data_security_plan/crc2_training_session_data_security_plan.bpmn
index f11e9a4e..453ba1ad 100644
--- a/crc/static/bpmn/crc2_training_session_data_security_plan/crc2_training_session_data_security_plan.bpmn
+++ b/crc/static/bpmn/crc2_training_session_data_security_plan/crc2_training_session_data_security_plan.bpmn
@@ -98,7 +98,7 @@
-
+
@@ -484,78 +484,49 @@ Indicate all the possible formats in which you will transmit your data outside o
SequenceFlow_08rwbhm
SequenceFlow_0uewki3
SequenceFlow_0lere0k
- SequenceFlow_14p4mbl
+ Flow_1h5ufzp
-
Transmission Method of data that will be mailed or faxed (FedEx, UPS, certified mail, etc.) Check all that apply:
-
+
-
-
+
+
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
SequenceFlow_1mnmo6p
SequenceFlow_0lere0k
-
- Data Security Plan Study Team Notes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SequenceFlow_14p4mbl
- SequenceFlow_18ik6tv
- SequenceFlow_02pq2w4
-
-
Flow_0bvraie
-
SequenceFlow_0mgwas4
SequenceFlow_01hl869
- SequenceFlow_18ik6tv
DateTransmittedOutside == True
@@ -566,9 +537,6 @@ Indicate all the possible formats in which you will transmit your data outside o
SequenceFlow_12bv2i4
SequenceFlow_1mnmo6p
-
- DateTransmittedOutside == False
-
#### Collection & storage of research data at UVA
@@ -650,8 +618,8 @@ Submit the step only when you are ready. After you "Submit" the step, the inform
- SequenceFlow_02pq2w4
Flow_1wgcnrc
+ Flow_1h5ufzp
SequenceFlow_1wzlqa1
@@ -693,6 +661,7 @@ Submit the step only when you are ready. After you "Submit" the step, the inform
FormField_DSP_Done == False
+
@@ -841,23 +810,12 @@ Submit the step only when you are ready. After you "Submit" the step, the inform
-
-
-
-
-
-
-
-
+
-
-
-
-
@@ -874,15 +832,6 @@ Submit the step only when you are ready. After you "Submit" the step, the inform
-
-
-
-
-
-
-
-
-
@@ -913,64 +862,68 @@ Submit the step only when you are ready. After you "Submit" the step, the inform
-
-
+
+
-
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
-
-
-
-
+
+
+
+
-
+
-
-
+
+
-
+
-
+
-
-
+
+
-
+
-
-
-
-
+
+
+
+
-
+
+
+
+
+
diff --git a/crc/static/bpmn/crc2_training_session_enter_core_info/crc2_training_session_enter_core_info.bpmn b/crc/static/bpmn/crc2_training_session_enter_core_info/crc2_training_session_enter_core_info.bpmn
index 15346b03..fc90a9de 100644
--- a/crc/static/bpmn/crc2_training_session_enter_core_info/crc2_training_session_enter_core_info.bpmn
+++ b/crc/static/bpmn/crc2_training_session_enter_core_info/crc2_training_session_enter_core_info.bpmn
@@ -14,6 +14,121 @@
+
+ SequenceFlow_0xfv8yt
+ SequenceFlow_1nyebxq
+ SequenceFlow_0s6lscl
+ SequenceFlow_0tl6dtl
+ SequenceFlow_1bdgyx8
+
+
+ SequenceFlow_0vnit5w
+ SequenceFlow_12u08ph
+ SequenceFlow_1049qrj
+ SequenceFlow_1vfbg50
+ SequenceFlow_0skynyx
+
+
+ SequenceFlow_0skynyx
+
+
+ SequenceFlow_0xfv8yt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SequenceFlow_0tl6dtl
+ SequenceFlow_1049qrj
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SequenceFlow_1bdgyx8
+ SequenceFlow_1vfbg50
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SequenceFlow_0s6lscl
+ SequenceFlow_12u08ph
+
@@ -83,163 +198,6 @@
SequenceFlow_1nyebxq
SequenceFlow_0vnit5w
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SequenceFlow_0s6lscl
- SequenceFlow_12u08ph
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SequenceFlow_1bdgyx8
- SequenceFlow_1vfbg50
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SequenceFlow_1oz7y6d
- SequenceFlow_0vbmpyv
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SequenceFlow_0tl6dtl
- SequenceFlow_1049qrj
-
-
- SequenceFlow_0xfv8yt
- SequenceFlow_1nyebxq
- SequenceFlow_0s6lscl
- SequenceFlow_0tl6dtl
- SequenceFlow_1bdgyx8
- SequenceFlow_1oz7y6d
-
-
- SequenceFlow_0vnit5w
- SequenceFlow_12u08ph
- SequenceFlow_1049qrj
- SequenceFlow_1vfbg50
- SequenceFlow_0vbmpyv
- SequenceFlow_0skynyx
-
-
- SequenceFlow_0skynyx
-
-
- SequenceFlow_0xfv8yt
-
@@ -250,13 +208,13 @@
-
+
-
+
-
+
@@ -268,7 +226,7 @@
-
+
@@ -276,63 +234,52 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
diff --git a/crc/static/bpmn/sponsor_funding_source/sponsor_funding_source.bpmn b/crc/static/bpmn/crc2_training_session_sponsor_funding_source/crc2_training_session_sponsor_funding_source.bpmn
similarity index 78%
rename from crc/static/bpmn/sponsor_funding_source/sponsor_funding_source.bpmn
rename to crc/static/bpmn/crc2_training_session_sponsor_funding_source/crc2_training_session_sponsor_funding_source.bpmn
index c3b9d2bd..bcf6f6d9 100644
--- a/crc/static/bpmn/sponsor_funding_source/sponsor_funding_source.bpmn
+++ b/crc/static/bpmn/crc2_training_session_sponsor_funding_source/crc2_training_session_sponsor_funding_source.bpmn
@@ -14,11 +14,7 @@
-
-
+
@@ -26,14 +22,7 @@
-
-
-
-
-
-
-
-
+
@@ -51,10 +40,10 @@
-
+
-
+
diff --git a/example_data.py b/example_data.py
index 793127c3..ddbcd9b0 100644
--- a/example_data.py
+++ b/example_data.py
@@ -10,6 +10,7 @@ from crc.models.user import UserModel
from crc.models.workflow import WorkflowSpecModel
from crc.services.file_service import FileService
from crc.services.workflow_processor import WorkflowProcessor
+from crc.models.protocol_builder import ProtocolBuilderStatus
class ExampleDataLoader:
@@ -41,7 +42,7 @@ class ExampleDataLoader:
id=1,
title='The impact of fried pickles on beer consumption in bipedal software developers.',
last_updated=datetime.datetime.now(),
- protocol_builder_status='in_process',
+ protocol_builder_status=ProtocolBuilderStatus.IN_PROCESS,
primary_investigator_id='dhf8r',
sponsor='Sartography Pharmaceuticals',
ind_number='1234',
@@ -51,7 +52,7 @@ class ExampleDataLoader:
id=2,
title='Requirement of hippocampal neurogenesis for the behavioral effects of soft pretzels',
last_updated=datetime.datetime.now(),
- protocol_builder_status='in_process',
+ protocol_builder_status=ProtocolBuilderStatus.IN_PROCESS,
primary_investigator_id='dhf8r',
sponsor='Makerspace & Co.',
ind_number='5678',
@@ -69,10 +70,11 @@ class ExampleDataLoader:
name="crc2_training_session_data_security_plan",
display_name="CR Connect2 - Training Session - Data Security Plan",
description='Part of Milestone 3 Deliverable')
- self.create_spec(id="sponsor_funding_source",
- name="sponsor_funding_source",
- display_name="Sponsor and/or Funding Source ",
- description='TBD')
+ self.create_spec(id="crc2_training_session_sponsor_funding_source",
+ name="crc2_training_session_sponsor_funding_source",
+ display_name="CR Connect2 - Training Session - Sponsor and/or Funding Source",
+ description='Part of Milestone 3 Deliverable')
+
def create_spec(self, id, name, display_name="", description="", filepath=None):
"""Assumes that a directory exists in static/bpmn with the same name as the given id.
diff --git a/migrations/versions/cb3a03c10a0e_.py b/migrations/versions/1c6e4e179f8e_.py
similarity index 94%
rename from migrations/versions/cb3a03c10a0e_.py
rename to migrations/versions/1c6e4e179f8e_.py
index 0280235c..b6237cb0 100644
--- a/migrations/versions/cb3a03c10a0e_.py
+++ b/migrations/versions/1c6e4e179f8e_.py
@@ -1,8 +1,8 @@
"""empty message
-Revision ID: cb3a03c10a0e
+Revision ID: 1c6e4e179f8e
Revises:
-Create Date: 2020-02-28 11:12:56.150837
+Create Date: 2020-03-03 15:51:45.550681
"""
from alembic import op
@@ -10,7 +10,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
-revision = 'cb3a03c10a0e'
+revision = '1c6e4e179f8e'
down_revision = None
branch_labels = None
depends_on = None
@@ -43,7 +43,7 @@ def upgrade():
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('title', sa.String(), nullable=True),
sa.Column('last_updated', sa.DateTime(timezone=True), nullable=True),
- sa.Column('protocol_builder_status', sa.Enum('out_of_date', 'in_process', 'complete', 'updating', name='protocolbuilderstatus'), nullable=True),
+ sa.Column('protocol_builder_status', sa.Enum('DRAFT', 'IN_PROCESS', 'IN_REVIEW', 'REVIEW_COMPLETE', 'INACTIVE', name='protocolbuilderstatus'), nullable=True),
sa.Column('primary_investigator_id', sa.String(), nullable=True),
sa.Column('sponsor', sa.String(), nullable=True),
sa.Column('hsr_number', sa.String(), nullable=True),
diff --git a/tests/data/pb_responses/user_studies.json b/tests/data/pb_responses/user_studies.json
index 40aa65b3..18a0a00d 100644
--- a/tests/data/pb_responses/user_studies.json
+++ b/tests/data/pb_responses/user_studies.json
@@ -14,5 +14,13 @@
"Q_COMPLETE": true,
"STUDYID": 65432,
"TITLE": "Peanut butter consumption among quiet dogs"
+ },
+ {
+ "DATE_MODIFIED": "2020-02-19T14:24:55.101695",
+ "HSRNUMBER": "45678",
+ "NETBADGEID": "dhf8r",
+ "Q_COMPLETE": true,
+ "STUDYID": 1,
+ "TITLE": "Efficacy of xenomorph bio-augmented circuits on dexterity of cybernetic prostheses"
}
]
diff --git a/tests/test_study_api.py b/tests/test_study_api.py
index 136e38a4..d4ded939 100644
--- a/tests/test_study_api.py
+++ b/tests/test_study_api.py
@@ -1,11 +1,12 @@
import json
from datetime import datetime, timezone
-from unittest.mock import patch
+from unittest.mock import patch, Mock
from crc import session
from crc.models.api_models import WorkflowApiSchema
from crc.models.study import StudyModel, StudyModelSchema
-from crc.models.protocol_builder import ProtocolBuilderStatus
+from crc.models.protocol_builder import ProtocolBuilderStatus, ProtocolBuilderStudyDetailsSchema, \
+ ProtocolBuilderStudySchema
from crc.models.workflow import WorkflowSpecModel, WorkflowSpecModelSchema, WorkflowModel, WorkflowStatus
from tests.base_test import BaseTest
@@ -24,7 +25,7 @@ class TestStudyApi(BaseTest):
"title": "Phase III Trial of Genuine People Personalities (GPP) Autonomous Intelligent Emotional Agents "
"for Interstellar Spacecraft",
"last_updated": datetime.now(tz=timezone.utc),
- "protocol_builder_status": ProtocolBuilderStatus.in_process,
+ "protocol_builder_status": ProtocolBuilderStatus.IN_PROCESS,
"primary_investigator_id": "tricia.marie.mcmillan@heartofgold.edu",
"sponsor": "Sirius Cybernetics Corporation",
"ind_number": "567890",
@@ -49,7 +50,7 @@ class TestStudyApi(BaseTest):
self.load_example_data()
study: StudyModel = session.query(StudyModel).first()
study.title = "Pilot Study of Fjord Placement for Single Fraction Outcomes to Cortisol Susceptibility"
- study.protocol_builder_status = ProtocolBuilderStatus.complete
+ study.protocol_builder_status = ProtocolBuilderStatus.REVIEW_COMPLETE
rv = self.app.put('/v1.0/study/%i' % study.id,
content_type="application/json",
headers=self.logged_in_headers(),
@@ -60,17 +61,19 @@ class TestStudyApi(BaseTest):
self.assertEqual(study.title, db_study.title)
self.assertEqual(study.protocol_builder_status, db_study.protocol_builder_status)
-
- @patch('crc.services.protocol_builder.requests.get')
- def test_get_all_studies(self, mock_get):
+ @patch('crc.services.protocol_builder.ProtocolBuilderService.get_study_details') # mock_details
+ @patch('crc.services.protocol_builder.ProtocolBuilderService.get_studies') # mock_studies
+ def test_get_all_studies(self, mock_studies, mock_details):
self.load_example_data()
db_studies_before = session.query(StudyModel).all()
num_db_studies_before = len(db_studies_before)
- mock_get.return_value.ok = True
- mock_get.return_value.text = self.protocol_builder_response('user_studies.json')
- # pb_response = ProtocolBuilderService.get_studies(self.test_uid)
- # self.assertIsNotNone(pb_response)
+ # Mock Protocol Builder response
+ studies_response = self.protocol_builder_response('user_studies.json')
+ mock_studies.return_value = ProtocolBuilderStudySchema(many=True).loads(studies_response)
+
+ details_response = self.protocol_builder_response('study_details.json')
+ mock_details.return_value = ProtocolBuilderStudyDetailsSchema().loads(details_response)
self.load_example_data()
api_response = self.app.get('/v1.0/study',
@@ -78,11 +81,6 @@ class TestStudyApi(BaseTest):
headers=self.logged_in_headers(),
content_type="application/json")
self.assert_success(api_response)
-
- db_studies_after = session.query(StudyModel).all()
- num_db_studies_after = len(db_studies_after)
- self.assertGreater(num_db_studies_after, num_db_studies_before)
-
json_data = json.loads(api_response.get_data(as_text=True))
api_studies = StudyModelSchema(many=True).load(json_data, session=session)
@@ -95,8 +93,13 @@ class TestStudyApi(BaseTest):
else:
num_active += 1
- self.assertEqual(num_inactive, num_db_studies_before)
- self.assertEqual(num_active, num_db_studies_after - num_db_studies_before)
+ db_studies_after = session.query(StudyModel).all()
+ num_db_studies_after = len(db_studies_after)
+ self.assertGreater(num_db_studies_after, num_db_studies_before)
+ self.assertGreater(num_inactive, 0)
+ self.assertGreater(num_active, 0)
+ self.assertEqual(len(api_studies), num_db_studies_after)
+ self.assertEqual(num_active + num_inactive, num_db_studies_after)
def test_study_api_get_single_study(self):
self.load_example_data()