Merge pull request #376 from sartography/bug/468_missing_file_date

fixes #448 - Missing  file date
This commit is contained in:
Dan Funk 2021-09-22 15:29:32 -04:00 committed by GitHub
commit deff293fff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 69 additions and 41 deletions

View File

@ -1,13 +1,15 @@
import enum
import urllib
import flask
from marshmallow import INCLUDE, EXCLUDE, Schema
from marshmallow.fields import Method
from marshmallow_enum import EnumField
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema
from sqlalchemy import func, Index
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import deferred, relationship
from crc import db, ma
from crc import db, ma, app
from crc.models.data_store import DataStoreModel
@ -144,9 +146,17 @@ class FileSchema(Schema):
fields = ["id", "name", "is_status", "is_reference", "content_type",
"primary", "primary_process_id", "workflow_spec_id", "workflow_id",
"irb_doc_code", "last_modified", "latest_version", "type", "size", "data_store",
"document", "user_uid"]
"document", "user_uid", "url"]
unknown = INCLUDE
type = EnumField(FileType)
url = Method("get_url")
def get_url(self, obj):
token = 'not_available'
if hasattr(flask.g, 'user'):
token = flask.g.user.encode_auth_token()
return (app.config['APPLICATION_ROOT'] + 'file/' +
str(obj.id) + '/download?auth_token=' + urllib.parse.quote_plus(token))
class LookupFileModel(db.Model):

View File

@ -14,7 +14,7 @@ from crc import db, session, app
from crc.api.common import ApiError
from crc.models.data_store import DataStoreModel
from crc.models.email import EmailModel
from crc.models.file import FileModel, File
from crc.models.file import FileModel, File, FileSchema
from crc.models.ldap import LdapSchema
from crc.models.protocol_builder import ProtocolBuilderStudy, ProtocolBuilderStatus
@ -294,15 +294,10 @@ class StudyService(object):
token = 'not_available'
if hasattr(flask.g, 'user'):
token = flask.g.user.encode_auth_token()
for file in doc_files:
file_data = {'file_id': file.id,
'name': file.name,
'url': app.config['APPLICATION_ROOT'] +
'file/' + str(file.id) +
'/download?auth_token=' +
urllib.parse.quote_plus(token),
'workflow_id': file.workflow_id
}
for file_model in doc_files:
file = File.from_models(file_model, FileService.get_file_data(file_model.id), [])
file_data = FileSchema().dump(file)
del file_data['document']
data = db.session.query(DataStoreModel).filter(DataStoreModel.file_id == file.id).all()
data_store_data = {}
for d in data:

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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1j7idla" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1j7idla" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.10.0">
<bpmn:process id="Process_18biih5" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>SequenceFlow_1pnq3kg</bpmn:outgoing>
@ -16,7 +16,7 @@
<bpmn:outgoing>Flow_0z7kamo</bpmn:outgoing>
<bpmn:script>filelist = list(documents.keys())
fileid = documents['UVACompl_PRCAppr'].files[0]['file_id']
fileid = documents['UVACompl_PRCAppr'].files[0]['id']
fileurl = documents['UVACompl_PRCAppr'].files[0]['url']
@ -43,6 +43,22 @@ file_data_set(file_id=fileid,key='test',value='me')</bpmn:script>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_18biih5">
<bpmndi:BPMNEdge id="Flow_02bgcrp_di" bpmnElement="Flow_02bgcrp">
<di:waypoint x="860" y="117" />
<di:waypoint x="962" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_15mmymi_di" bpmnElement="Flow_15mmymi">
<di:waypoint x="690" y="117" />
<di:waypoint x="760" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0z7kamo_di" bpmnElement="Flow_0z7kamo">
<di:waypoint x="530" y="117" />
<di:waypoint x="590" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1xqewuk_di" bpmnElement="Flow_1xqewuk">
<di:waypoint x="370" y="117" />
<di:waypoint x="430" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_1pnq3kg_di" bpmnElement="SequenceFlow_1pnq3kg">
<di:waypoint x="215" y="117" />
<di:waypoint x="270" y="117" />
@ -53,34 +69,18 @@ file_data_set(file_id=fileid,key='test',value='me')</bpmn:script>
<bpmndi:BPMNShape id="Activity_01ekdl8_di" bpmnElement="Task_Has_Bananas">
<dc:Bounds x="270" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1xqewuk_di" bpmnElement="Flow_1xqewuk">
<di:waypoint x="370" y="117" />
<di:waypoint x="430" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Activity_0g5namy_di" bpmnElement="Activity_0yikdu7">
<dc:Bounds x="430" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1pdyoyv_di" bpmnElement="Event_1pdyoyv">
<dc:Bounds x="962" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_0z7kamo_di" bpmnElement="Flow_0z7kamo">
<di:waypoint x="530" y="117" />
<di:waypoint x="590" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_15mmymi_di" bpmnElement="Flow_15mmymi">
<di:waypoint x="690" y="117" />
<di:waypoint x="760" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Activity_0ma7ela_di" bpmnElement="Activity_19x6e2e">
<dc:Bounds x="590" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0oaeqxs_di" bpmnElement="Activity_0oaeqxs">
<dc:Bounds x="760" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_02bgcrp_di" bpmnElement="Flow_02bgcrp">
<di:waypoint x="860" y="117" />
<di:waypoint x="962" y="117" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -156,7 +156,7 @@ class TestStudyService(BaseTest):
self.assertEqual("not_started", docs["UVACompl_PRCAppr"]['status'])
self.assertEqual(1, docs["UVACompl_PRCAppr"]['count'])
self.assertIsNotNone(docs["UVACompl_PRCAppr"]['files'][0])
self.assertIsNotNone(docs["UVACompl_PRCAppr"]['files'][0]['file_id'])
self.assertIsNotNone(docs["UVACompl_PRCAppr"]['files'][0]['id'])
self.assertEqual(workflow.id, docs["UVACompl_PRCAppr"]['files'][0]['workflow_id'])
def test_get_all_studies(self):

View File

@ -1,3 +1,6 @@
import io
import json
from tests.base_test import BaseTest
from crc.scripts.study_info import StudyInfo
from crc import app
@ -13,15 +16,15 @@ class TestStudyInfoScript(BaseTest):
def do_work(self, info_type):
app.config['PB_ENABLED'] = True
self.load_example_data()
workflow = self.create_workflow('study_info_script')
workflow_api = self.get_workflow_api(workflow)
self.workflow = self.create_workflow('study_info_script')
self.workflow_api = self.get_workflow_api(self.workflow)
# grab study_info directly from script
study_info = StudyInfo().do_task(workflow_api.study_id, workflow.study.id, workflow.id, info_type)
study_info = StudyInfo().do_task(self.workflow_api.study_id, self.workflow.study.id, self.workflow.id, info_type)
# grab study info through a workflow
first_task = workflow_api.next_task
self.complete_form(workflow, first_task, {'which': info_type})
workflow_api = self.get_workflow_api(workflow)
first_task = self.workflow_api.next_task
self.complete_form(self.workflow, first_task, {'which': info_type})
workflow_api = self.get_workflow_api(self.workflow)
second_task = workflow_api.next_task
return study_info, second_task
@ -81,9 +84,29 @@ class TestStudyInfoScript(BaseTest):
self.assertEqual(response['IND_2'], second_task.data['info']['IND_2'])
self.assertEqual(response['IND_3'], second_task.data['info']['IND_3'])
# def test_info_script_documents(self):
# study_info, second_task = self.do_work(info_type='documents')
# self.assertEqual(study_info, second_task.data['info'])
def test_info_script_documents(self):
study_info, second_task = self.do_work(info_type='documents')
self.assertEqual(study_info, second_task.data['info'])
self.assertEqual(0, len(study_info['Grant_App']['files']), "Grant_App has not files yet.")
# Add a grant app file
data = {'file': (io.BytesIO(b"abcdef"), 'random_fact.svg')}
rv = self.app.post('/v1.0/file?study_id=%i&workflow_id=%s&task_spec_name=%s&form_field_key=%s' %
(self.workflow.study_id, self.workflow.id, second_task.name, 'Grant_App'), data=data, follow_redirects=True,
content_type='multipart/form-data', headers=self.logged_in_headers())
self.assert_success(rv)
file_data = json.loads(rv.get_data(as_text=True))
# Now get the study info again.
study_info = StudyInfo().do_task(self.workflow_api.study_id, self.workflow.study.id, self.workflow.id,
'documents')
# The data should contain a file.
self.assertEqual(1, len(study_info['Grant_App']['files']), "Grant_App has exactly one file.")
# This file data returned should be the same as what we get back about the file when we uploaded it,
# but the details on the document should be removed, because that would be recursive.
del file_data['document']
self.assertEqual(file_data, study_info['Grant_App']['files'][0])
@patch('crc.services.protocol_builder.requests.get')
def test_info_script_sponsors(self, mock_get):