Merge pull request #135 from sartography/feature/multi_instance_titles
* Modifying the StudyInfo script to return both "investigators" and "…
This commit is contained in:
commit
ec40cfabda
|
@ -14,7 +14,7 @@ class StudyInfo(Script):
|
|||
"""Please see the detailed description that is provided below. """
|
||||
|
||||
pb = ProtocolBuilderService()
|
||||
type_options = ['info', 'investigators', 'details', 'approvals', 'documents', 'protocol']
|
||||
type_options = ['info', 'investigators', 'roles', 'details', 'approvals', 'documents', 'protocol']
|
||||
|
||||
# This is used for test/workflow validation, as well as documentation.
|
||||
example_data = {
|
||||
|
@ -106,11 +106,20 @@ Returns the basic information such as the id and title
|
|||
### Investigators ###
|
||||
Returns detailed information about related personnel.
|
||||
The order returned is guaranteed to match the order provided in the investigators.xslx reference file.
|
||||
If possible, detailed information is added in from LDAP about each personnel based on their user_id.
|
||||
Detailed information is added in from LDAP about each personnel based on their user_id.
|
||||
```
|
||||
{investigators_example}
|
||||
```
|
||||
|
||||
### Investigator Roles ###
|
||||
Returns a list of all investigator roles, populating any roles with additional information available from
|
||||
the Protocol Builder and LDAP. Its basically just like Investigators, but it includes all the roles, rather
|
||||
that just those that were set in Protocol Builder.
|
||||
```
|
||||
{investigators_example}
|
||||
```
|
||||
|
||||
|
||||
### Details ###
|
||||
Returns detailed information about variable keys read in from the Protocol Builder.
|
||||
|
||||
|
@ -161,6 +170,12 @@ Returns information specific to the protocol.
|
|||
"INVESTIGATORTYPEFULL": "Primary Investigator",
|
||||
"NETBADGEID": "dhf8r"
|
||||
},
|
||||
"roles":
|
||||
{
|
||||
"INVESTIGATORTYPE": "PI",
|
||||
"INVESTIGATORTYPEFULL": "Primary Investigator",
|
||||
"NETBADGEID": "dhf8r"
|
||||
},
|
||||
"details":
|
||||
{
|
||||
"IS_IND": 0,
|
||||
|
@ -198,6 +213,8 @@ Returns information specific to the protocol.
|
|||
self.add_data_to_task(task, {cmd: schema.dump(study)})
|
||||
if cmd == 'investigators':
|
||||
self.add_data_to_task(task, {cmd: StudyService().get_investigators(study_id)})
|
||||
if cmd == 'roles':
|
||||
self.add_data_to_task(task, {cmd: StudyService().get_investigators(study_id, all=True)})
|
||||
if cmd == 'details':
|
||||
self.add_data_to_task(task, {cmd: self.pb.get_study_details(study_id)})
|
||||
if cmd == 'approvals':
|
||||
|
|
|
@ -182,7 +182,7 @@ class StudyService(object):
|
|||
return documents
|
||||
|
||||
@staticmethod
|
||||
def get_investigators(study_id):
|
||||
def get_investigators(study_id, all=False):
|
||||
|
||||
# Loop through all known investigator types as set in the reference file
|
||||
inv_dictionary = FileService.get_reference_data(FileService.INVESTIGATOR_LIST, 'code')
|
||||
|
@ -199,6 +199,8 @@ class StudyService(object):
|
|||
else:
|
||||
inv_dictionary[i_type]['user_id'] = None
|
||||
|
||||
if not all:
|
||||
inv_dictionary = dict(filter(lambda elem: elem[1]['user_id'] is not None, inv_dictionary.items()))
|
||||
return inv_dictionary
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -207,8 +207,10 @@ class WorkflowService(object):
|
|||
if spiff_task:
|
||||
nav_item['task'] = WorkflowService.spiff_task_to_api_task(spiff_task, add_docs_and_forms=False)
|
||||
nav_item['title'] = nav_item['task'].title # Prefer the task title.
|
||||
|
||||
else:
|
||||
nav_item['task'] = None
|
||||
|
||||
if not 'is_decision' in nav_item:
|
||||
nav_item['is_decision'] = False
|
||||
|
||||
|
@ -333,10 +335,12 @@ class WorkflowService(object):
|
|||
# otherwise strip off the first word of the task, as that should be following
|
||||
# a BPMN standard, and should not be included in the display.
|
||||
if task.properties and "display_name" in task.properties:
|
||||
task.title = task.properties['display_name']
|
||||
try:
|
||||
task.title = spiff_task.workflow.script_engine.evaluate_expression(spiff_task, task.properties['display_name'])
|
||||
except Exception as e:
|
||||
app.logger.info("Failed to set title on task due to type error." + str(e))
|
||||
elif task.title and ' ' in task.title:
|
||||
task.title = task.title.partition(' ')[2]
|
||||
|
||||
return task
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
<camunda:formData>
|
||||
<camunda:formField id="email" label="Email Address:" type="string" />
|
||||
</camunda:formData>
|
||||
<camunda:properties>
|
||||
<camunda:property name="display_name" value="investigator.label" />
|
||||
</camunda:properties>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>SequenceFlow_1p568pp</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0ugjw69</bpmn:outgoing>
|
||||
|
|
|
@ -182,8 +182,8 @@ class TestStudyApi(BaseTest):
|
|||
self.assertGreater(num_db_studies_after, num_db_studies_before)
|
||||
self.assertEqual(num_abandoned, 1)
|
||||
self.assertEqual(num_open, 1)
|
||||
self.assertEqual(num_active, 1)
|
||||
self.assertEqual(num_incomplete, 1)
|
||||
self.assertEqual(num_active, 2)
|
||||
self.assertEqual(num_incomplete, 0)
|
||||
self.assertEqual(len(json_data), num_db_studies_after)
|
||||
self.assertEqual(num_open + num_active + num_incomplete + num_abandoned, num_db_studies_after)
|
||||
|
||||
|
|
|
@ -183,7 +183,7 @@ class TestStudyService(BaseTest):
|
|||
|
||||
|
||||
@patch('crc.services.protocol_builder.ProtocolBuilderService.get_investigators') # mock_docs
|
||||
def test_get_personnel(self, mock_docs):
|
||||
def test_get_personnel_roles(self, mock_docs):
|
||||
self.load_example_data()
|
||||
|
||||
# mock out the protocol builder
|
||||
|
@ -191,7 +191,7 @@ class TestStudyService(BaseTest):
|
|||
mock_docs.return_value = json.loads(docs_response)
|
||||
|
||||
workflow = self.create_workflow('docx') # The workflow really doesnt matter in this case.
|
||||
investigators = StudyService().get_investigators(workflow.study_id)
|
||||
investigators = StudyService().get_investigators(workflow.study_id, all=True)
|
||||
|
||||
self.assertEqual(9, len(investigators))
|
||||
|
||||
|
@ -207,3 +207,22 @@ class TestStudyService(BaseTest):
|
|||
|
||||
# No value is provided for Department Chair
|
||||
self.assertIsNone(investigators['DEPT_CH']['user_id'])
|
||||
|
||||
@patch('crc.services.protocol_builder.ProtocolBuilderService.get_investigators') # mock_docs
|
||||
def test_get_study_personnel(self, mock_docs):
|
||||
self.load_example_data()
|
||||
|
||||
# mock out the protocol builder
|
||||
docs_response = self.protocol_builder_response('investigators.json')
|
||||
mock_docs.return_value = json.loads(docs_response)
|
||||
|
||||
workflow = self.create_workflow('docx') # The workflow really doesnt matter in this case.
|
||||
investigators = StudyService().get_investigators(workflow.study_id, all=False)
|
||||
|
||||
self.assertEqual(3, len(investigators))
|
||||
|
||||
# dhf8r is in the ldap mock data.
|
||||
self.assertEqual("dhf8r", investigators['PI']['user_id'])
|
||||
self.assertEqual("Dan Funk", investigators['PI']['display_name']) # Data from ldap
|
||||
self.assertEqual("Primary Investigator", investigators['PI']['label']) # Data from xls file.
|
||||
self.assertEqual("Always", investigators['PI']['display']) # Data from xls file.
|
||||
|
|
|
@ -322,7 +322,7 @@ class TestTasksApi(BaseTest):
|
|||
self.assertEqual(4, len(navigation)) # Start task, form_task, multi_task, end task
|
||||
self.assertEqual("UserTask", workflow.next_task.type)
|
||||
self.assertEqual(MultiInstanceType.sequential.value, workflow.next_task.multi_instance_type)
|
||||
self.assertEqual(9, workflow.next_task.multi_instance_count)
|
||||
self.assertEqual(3, workflow.next_task.multi_instance_count)
|
||||
|
||||
# Assure that the names for each task are properly updated, so they aren't all the same.
|
||||
self.assertEqual("Primary Investigator", workflow.next_task.properties['display_name'])
|
||||
|
@ -480,17 +480,23 @@ class TestTasksApi(BaseTest):
|
|||
workflow = self.create_workflow('multi_instance_parallel')
|
||||
|
||||
workflow_api = self.get_workflow_api(workflow)
|
||||
self.assertEqual(12, len(workflow_api.navigation))
|
||||
self.assertEqual(6, len(workflow_api.navigation))
|
||||
ready_items = [nav for nav in workflow_api.navigation if nav['state'] == "READY"]
|
||||
self.assertEqual(9, len(ready_items))
|
||||
self.assertEqual(3, len(ready_items))
|
||||
|
||||
self.assertEqual("UserTask", workflow_api.next_task.type)
|
||||
self.assertEqual("MultiInstanceTask",workflow_api.next_task.name)
|
||||
self.assertEqual("more information", workflow_api.next_task.title)
|
||||
self.assertEqual("Primary Investigator", workflow_api.next_task.title)
|
||||
|
||||
for i in random.sample(range(9), 9):
|
||||
for i in random.sample(range(3), 3):
|
||||
task = TaskSchema().load(ready_items[i]['task'])
|
||||
data = workflow_api.next_task.data
|
||||
rv = self.app.put('/v1.0/workflow/%i/task/%s/set_token' % (workflow.id, task.id),
|
||||
headers=self.logged_in_headers(),
|
||||
content_type="application/json")
|
||||
self.assert_success(rv)
|
||||
json_data = json.loads(rv.get_data(as_text=True))
|
||||
workflow = WorkflowApiSchema().load(json_data)
|
||||
data = workflow.next_task.data
|
||||
data['investigator']['email'] = "dhf8r@virginia.edu"
|
||||
self.complete_form(workflow, task, data)
|
||||
#tasks = self.get_workflow_api(workflow).user_tasks
|
||||
|
|
|
@ -146,6 +146,11 @@ class TestWorkflowProcessorMultiInstance(BaseTest):
|
|||
|
||||
api_task = WorkflowService.spiff_task_to_api_task(task)
|
||||
self.assertEqual(MultiInstanceType.parallel, api_task.multi_instance_type)
|
||||
|
||||
# Assure navigation picks up the label of the current element variable.
|
||||
nav = WorkflowService.processor_to_workflow_api(processor, task).navigation
|
||||
self.assertEquals("Primary Investigator", nav[2].title)
|
||||
|
||||
task.update_data({"investigator": {"email": "dhf8r@virginia.edu"}})
|
||||
processor.complete_task(task)
|
||||
processor.do_engine_steps()
|
||||
|
|
Loading…
Reference in New Issue