From 0ea0b0a2335d9aec28067a4344bd6a69fa7195d5 Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Thu, 25 Mar 2021 13:06:52 -0400 Subject: [PATCH 01/10] added form validation for study_details --- pb/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pb/__init__.py b/pb/__init__.py index fd821d4..b8d0bd1 100644 --- a/pb/__init__.py +++ b/pb/__init__.py @@ -463,7 +463,7 @@ def study_details(study_id): action = BASE_HREF + "/study_details/" + study_id title = "Edit Study Details for Study #" + study_id details = "Numeric fields can be 1 for true, 0 or false, or Null if not applicable." - if request.method == 'POST': + if request.method == 'POST' and form.validate(): form.populate_obj(study_details) db.session.add(study_details) db.session.commit() From eb4ca6fda4328c2f03c62c86cb4cc28399856909 Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Thu, 25 Mar 2021 13:07:42 -0400 Subject: [PATCH 02/10] Sorted the fields in the study_details form to match real Protocol Builder --- pb/forms.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/pb/forms.py b/pb/forms.py index f9c0425..69c48ce 100644 --- a/pb/forms.py +++ b/pb/forms.py @@ -36,6 +36,26 @@ class StudySponsorForm(FlaskForm): class StudyDetailsForm(ModelForm, FlaskForm): class Meta: model = StudyDetails + only = ['IS_IND', 'IND_1', 'IND_2', 'IND_3', 'IS_UVA_IND', 'IS_IDE', 'IDE', + 'IS_UVA_IDE', 'IS_CHART_REVIEW', 'IS_RADIATION', 'GCRC_NUMBER', 'IS_GCRC', + 'IS_PRC_DSMP', 'IS_PRC', 'PRC_NUMBER', 'IS_IBC', 'IBC_NUMBER', + 'IS_SPONSOR_TRACKING', 'SPONSOR_TRACKING', 'SPONSORS_PROTOCOL_REVISION_DATE', + 'IS_SPONSOR_MONITORING', 'IS_DSMB', 'IS_COMPLETE_NON_IRB_REGULATORY', + 'IS_AUX', 'IS_SPONSOR', 'IS_GRANT', 'IS_COMMITTEE_CONFLICT', 'DSMB', + 'DSMB_FREQUENCY', 'IS_DB', 'IS_UVA_DB', 'IS_CENTRAL_REG_DB', + 'IS_CONSENT_WAIVER', 'IS_HGT', 'IS_GENE_TRANSFER', 'IS_TISSUE_BANKING', + 'IS_SURROGATE_CONSENT', 'IS_ADULT_PARTICIPANT', 'IS_MINOR_PARTICIPANT', + 'IS_MINOR', 'IS_BIOMEDICAL', 'IS_QUALITATIVE', 'IS_PI_SCHOOL', + 'IS_PRISONERS_POP', 'IS_PREGNANT_POP', 'IS_FETUS_POP', + 'IS_MENTAL_IMPAIRMENT_POP', 'IS_ELDERLY_POP', 'IS_OTHER_VULNERABLE_POP', + 'OTHER_VULNERABLE_DESC', 'IS_MULTI_SITE', 'IS_UVA_LOCATION', + 'NON_UVA_LOCATION', 'MULTI_SITE_LOCATIONS', 'IS_OUTSIDE_CONTRACT', + 'IS_UVA_PI_MULTI', 'IS_NOT_PRC_WAIVER', 'IS_INSIDE_CONTRACT', + 'IS_CANCER_PATIENT', 'UPLOAD_COMPLETE', 'IS_FUNDING_SOURCE', + 'IS_CODED_RESEARCH', 'IS_OUTSIDE_SPONSOR', 'IS_PI_INITIATED', + 'IS_ENGAGED_RESEARCH', 'IS_APPROVED_DEVICE', 'IS_FINANCIAL_CONFLICT', + 'IS_NOT_CONSENT_WAIVER', 'IS_FOR_CANCER_CENTER', 'IS_REVIEW_BY_CENTRAL_IRB', + 'IRBREVIEWERADMIN', 'IS_UVA_COLLABANALYSIS'] class ConfirmDeleteForm(FlaskForm): From 9d839bb85c0bc29537998b7148a6e82afe21dabf Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Thu, 25 Mar 2021 13:11:27 -0400 Subject: [PATCH 03/10] Changed to match real Protocol Builder - Removed `Scientific Contact` from Investigator types - Changed study_details SPONSORS_PROTOCOL_REVISION_DATE data type from integer to date - Added 8 new fields to study_details --- pb/models.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pb/models.py b/pb/models.py index 0404930..2b17bc7 100644 --- a/pb/models.py +++ b/pb/models.py @@ -100,7 +100,6 @@ class Investigator(db.Model): Investigator(INVESTIGATORTYPE="AS_C", INVESTIGATORTYPEFULL="Additional Study Coordinators"), Investigator(INVESTIGATORTYPE="DEPT_CH", INVESTIGATORTYPEFULL="Department Chair"), Investigator(INVESTIGATORTYPE="IRBC", INVESTIGATORTYPEFULL="IRB Coordinator"), - Investigator(INVESTIGATORTYPE="SCI", INVESTIGATORTYPEFULL="Scientific Contact"), ] return types @@ -185,7 +184,7 @@ class StudyDetails(db.Model): PRC_NUMBER = db.Column(db.String, nullable=True) IS_IBC = db.Column(db.Integer, nullable=True) IBC_NUMBER = db.Column(db.String, nullable=True) - SPONSORS_PROTOCOL_REVISION_DATE = db.Column(db.Integer, nullable=True) + SPONSORS_PROTOCOL_REVISION_DATE = db.Column(db.Date, nullable=True) IS_SPONSOR_MONITORING = db.Column(db.Integer, nullable=True) IS_AUX = db.Column(db.Integer, nullable=True) IS_SPONSOR = db.Column(db.Integer, nullable=True) @@ -232,6 +231,15 @@ class StudyDetails(db.Model): IS_FOR_CANCER_CENTER = db.Column(db.Integer, nullable=True) IS_REVIEW_BY_CENTRAL_IRB = db.Column(db.Integer, nullable=True) IRBREVIEWERADMIN = db.Column(db.String, nullable=True) + IS_SPONSOR_TRACKING = db.Column(db.Integer, nullable=True) + SPONSOR_TRACKING = db.Column(db.Integer, nullable=True) + IS_DSMB = db.Column(db.Integer, nullable=True) + IS_COMPLETE_NON_IRB_REGULATORY = db.Column(db.Integer, nullable=True) + IS_INSIDE_CONTRACT = db.Column(db.Integer, nullable=True) + IS_CODED_RESEARCH = db.Column(db.Integer, nullable=True) + IS_OUTSIDE_SPONSOR = db.Column(db.Integer, nullable=True) + IS_UVA_COLLABANALYSIS = db.Column(db.Integer, nullable=True) + class StudyDetailsSchema(ma.SQLAlchemyAutoSchema): From ab776ea47d60fe9cb8f2c7b8eb7bc85daab5918b Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Thu, 25 Mar 2021 13:12:03 -0400 Subject: [PATCH 04/10] Migration for study_details db changes --- migrations/versions/6cd52db404f6_.py | 42 ++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 migrations/versions/6cd52db404f6_.py diff --git a/migrations/versions/6cd52db404f6_.py b/migrations/versions/6cd52db404f6_.py new file mode 100644 index 0000000..1863a91 --- /dev/null +++ b/migrations/versions/6cd52db404f6_.py @@ -0,0 +1,42 @@ +"""empty message + +Revision ID: 6cd52db404f6 +Revises: 9493f29b0898 +Create Date: 2021-03-24 10:04:28.215143 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '6cd52db404f6' +down_revision = '9493f29b0898' +branch_labels = None +depends_on = None + + +def upgrade(): + op.add_column('study_details', sa.Column('IS_SPONSOR_TRACKING', sa.Integer(), nullable=True)) + op.add_column('study_details', sa.Column('SPONSOR_TRACKING', sa.Integer(), nullable=True)) + op.add_column('study_details', sa.Column('IS_DSMB', sa.Integer(), nullable=True)) + op.add_column('study_details', sa.Column('IS_COMPLETE_NON_IRB_REGULATORY', sa.Integer(), nullable=True)) + op.add_column('study_details', sa.Column('IS_INSIDE_CONTRACT', sa.Integer(), nullable=True)) + op.add_column('study_details', sa.Column('IS_CODED_RESEARCH', sa.Integer(), nullable=True)) + op.add_column('study_details', sa.Column('IS_OUTSIDE_SPONSOR', sa.Integer(), nullable=True)) + op.add_column('study_details', sa.Column('IS_UVA_COLLABANALYSIS', sa.Integer(), nullable=True)) + op.drop_column('study_details', 'SPONSORS_PROTOCOL_REVISION_DATE') + op.add_column('study_details', sa.Column('SPONSORS_PROTOCOL_REVISION_DATE', sa.Date(), nullable=True)) + + +def downgrade(): + op.drop_column('study_details', 'IS_SPONSOR_TRACKING') + op.drop_column('study_details', 'SPONSOR_TRACKING') + op.drop_column('study_details', 'IS_DSMB') + op.drop_column('study_details', 'IS_COMPLETE_NON_IRB_REGULATORY') + op.drop_column('study_details', 'IS_INSIDE_CONTRACT') + op.drop_column('study_details', 'IS_CODED_RESEARCH') + op.drop_column('study_details', 'IS_OUTSIDE_SPONSOR') + op.drop_column('study_details', 'IS_UVA_COLLABANALYSIS') + op.drop_column('study_details', 'SPONSORS_PROTOCOL_REVISION_DATE') + op.add_column('study_details', sa.Column('SPONSORS_PROTOCOL_REVISION_DATE', sa.Integer(), nullable=True)) From 5371d204e547e27c670c968225ea0ab559c05926 Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Thu, 25 Mar 2021 13:14:17 -0400 Subject: [PATCH 05/10] Added db.drop_all() to the tearDownClass class. Now we always start tests with a new DB I tried to add some tests for form validation, but ran into a problem with the csrf_token. The tests couldn't find it. This is not a problem using the form for real. It would be nice to figure this out. --- tests/test_sanity.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/test_sanity.py b/tests/test_sanity.py index 5250219..dd3326d 100644 --- a/tests/test_sanity.py +++ b/tests/test_sanity.py @@ -25,7 +25,7 @@ class Sanity_Check_Test(unittest.TestCase): @classmethod def tearDownClass(cls): - pass + db.drop_all() def setUp(self): ExampleDataLoader().clean_db() @@ -164,3 +164,19 @@ class Sanity_Check_Test(unittest.TestCase): study = self.add_study(title=title) self.assertEqual(title, study.TITLE) + # def test_study_details_validation(self): + # + # test_study = self.add_study() + # data = {'IS_IND': 1, 'IND_1': 1234} + # r = self.app.post(f'/study_details/{test_study.STUDYID}', data=data, follow_redirects=False) + # self.assertNotIn('Form did not validate!', r.data.decode('utf-8')) + # + # print('test_study_details_validation') + # + # def test_study_details_validation_fail(self): + # test_study = self.add_study() + # data = {'IS_IND': 1, 'IND_1': 1234, 'IS_IDE': 'b'} + # r = self.app.post(f'/study_details/{test_study.STUDYID}', data=data, follow_redirects=False) + # self.assertIn('Form did not validate!', r.data.decode('utf-8')) + # + # print('test_study_details_validation_fail') From 4834c029d930429560564ce8d1a4cb40db9468b0 Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Tue, 30 Mar 2021 10:48:36 -0400 Subject: [PATCH 06/10] Added form to upload study_details csv file --- templates/form.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/templates/form.html b/templates/form.html index 50beb78..c48c8cb 100644 --- a/templates/form.html +++ b/templates/form.html @@ -14,6 +14,16 @@

{{ title }}

{{ details|safe }}

+ +{% if 'Edit Study Details' in title %} +
Upload CSV
+
+ {{ form.csrf_token() }} + + +
+{% endif %} +
{{ form.csrf_token() }} From a1f2b98ecf54693c4e68573173d84918a930cd83 Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Tue, 30 Mar 2021 10:53:56 -0400 Subject: [PATCH 07/10] Added code to process uploaded study_details csv file Modified study_details method to accommodate the csv upload Added imports for csv, TextIOWrapper Removed unused imports for date, re --- pb/__init__.py | 76 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/pb/__init__.py b/pb/__init__.py index b8d0bd1..556ac5f 100644 --- a/pb/__init__.py +++ b/pb/__init__.py @@ -1,8 +1,8 @@ +import csv import datetime import os -import re import yaml -from datetime import date +from io import TextIOWrapper import connexion from flask_cors import CORS @@ -453,26 +453,78 @@ def _update_study(study, form): db.session.commit() +def _allowed_file(filename): + allowed_extensions = ['csv', 'xls', 'xlsx'] + return '.' in filename and \ + filename.rsplit('.', 1)[1].lower() in allowed_extensions + + +def process_csv_study_details(study_id, csv_file): + study_details = db.session.query(StudyDetails).filter(StudyDetails.STUDYID == study_id).first() + csv_file.seek(0) + data = csv.DictReader(TextIOWrapper(csv_file)) + for row in data: + if data.line_num == 2: + + for key in row.keys(): + if key != 'STUDYID': + if hasattr(study_details, key): + if key in row.keys(): + val = row[key] + print(key, val) + if key == 'SPONSORS_PROTOCOL_REVISION_DATE': + print(type(val)) + if val == '': + val = None + if val == 'null': + val = None + setattr(study_details, key, val) + + session.add(study_details) + session.commit() + + @app.route('/study_details/', methods=['GET', 'POST']) def study_details(study_id): + study_details = db.session.query(StudyDetails).filter(StudyDetails.STUDYID == study_id).first() if not study_details: study_details = StudyDetails(STUDYID=study_id) form = StudyDetailsForm(request.form, obj=study_details) - if request.method == 'GET': - action = BASE_HREF + "/study_details/" + study_id - title = "Edit Study Details for Study #" + study_id - details = "Numeric fields can be 1 for true, 0 or false, or Null if not applicable." - if request.method == 'POST' and form.validate(): - form.populate_obj(study_details) - db.session.add(study_details) - db.session.commit() - flash('Study updated successfully!', 'success') - return redirect_home() + + action = BASE_HREF + "/study_details/" + study_id + title = "Edit Study Details for Study #" + study_id + details = "Numeric fields can be 1 for true, 0 or false, or Null if not applicable." + + if request.method == 'POST': + # update study details with csv file + if 'file' in request.files: + file = request.files['file'] + if file.filename == '': + flash('No file selected', 'failure') + return redirect(action) + elif file and _allowed_file(file.filename): + process_csv_study_details(study_id, file) + flash('CSV file uploaded', 'success') + return redirect_home() + else: + flash('There was a problem processing your file', 'failure') + return redirect(action) + + # update study details from the form + elif form.validate(): + form.populate_obj(study_details) + db.session.add(study_details) + db.session.commit() + flash('Study updated successfully!', 'success') + return redirect_home() + + # display the study details form return render_template( 'form.html', form=form, action=action, + csv_action=action, title=title, details=details, description_map=description_map, From c260e6a4657ca8b218fccf2133aa3d5d86004852 Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Tue, 30 Mar 2021 10:56:23 -0400 Subject: [PATCH 08/10] Added new fields for study_details Changed some field types Removed 2 unused documents from required documents list Changed the name of required documents from Required to Documents --- pb/forms.py | 6 +++--- pb/models.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pb/forms.py b/pb/forms.py index 69c48ce..e5ea96e 100644 --- a/pb/forms.py +++ b/pb/forms.py @@ -10,7 +10,7 @@ class StudyForm(FlaskForm): STUDYID = HiddenField() TITLE = StringField('Title', [validators.DataRequired()]) NETBADGEID = StringField('User UVA Computing Id', [validators.DataRequired()]) - requirements = SelectMultipleField("Requirements", + requirements = SelectMultipleField("Documents", render_kw={'class': 'multi'}, choices=[(rd.AUXDOCID, rd.AUXDOC) for rd in RequiredDocument.all()]) HSRNUMBER = StringField('HSR Number') @@ -55,7 +55,7 @@ class StudyDetailsForm(ModelForm, FlaskForm): 'IS_CODED_RESEARCH', 'IS_OUTSIDE_SPONSOR', 'IS_PI_INITIATED', 'IS_ENGAGED_RESEARCH', 'IS_APPROVED_DEVICE', 'IS_FINANCIAL_CONFLICT', 'IS_NOT_CONSENT_WAIVER', 'IS_FOR_CANCER_CENTER', 'IS_REVIEW_BY_CENTRAL_IRB', - 'IRBREVIEWERADMIN', 'IS_UVA_COLLABANALYSIS'] + 'IRBREVIEWERADMIN', 'IS_UVA_COLLABANALYSIS', 'REVIEW_TYPE', 'REVIEWTYPENAME'] class ConfirmDeleteForm(FlaskForm): @@ -120,7 +120,7 @@ class StudyTable(Table): NETBADGEID = Col('User') DATE_MODIFIED = DatetimeCol('Last Update', "medium") Q_COMPLETE = BoolCol('Complete?') - requirements = NestedTableCol('Requirements', RequirementsTable) + requirements = NestedTableCol('Documents', RequirementsTable) investigators = NestedTableCol('Investigators', InvestigatorsTable) sponsors = NestedTableCol('Sponsors', SponsorsTable) delete = LinkCol( diff --git a/pb/models.py b/pb/models.py index 2b17bc7..bb99a90 100644 --- a/pb/models.py +++ b/pb/models.py @@ -136,11 +136,9 @@ class RequiredDocument(db.Model): RequiredDocument(AUXDOCID=21, AUXDOC="New Medical Device Form"), RequiredDocument(AUXDOCID=22, AUXDOC="SOM CTO Review regarding need for IDE"), RequiredDocument(AUXDOCID=23, AUXDOC="SOM CTO Review regarding need for IND"), - RequiredDocument(AUXDOCID=24, AUXDOC="InfoSec Approval"), RequiredDocument(AUXDOCID=25, AUXDOC="Scientific Pre-review Documentation"), RequiredDocument(AUXDOCID=26, AUXDOC="IBC Number"), RequiredDocument(AUXDOCID=32, AUXDOC="IDS - Investigational Drug Service Approval"), - RequiredDocument(AUXDOCID=33, AUXDOC="Data Security Plan"), RequiredDocument(AUXDOCID=36, AUXDOC="RDRC Approval "), RequiredDocument(AUXDOCID=40, AUXDOC="SBS/IRB Approval-FERPA"), RequiredDocument(AUXDOCID=41, AUXDOC="HIRE Standard Radiation Language"), @@ -190,7 +188,7 @@ class StudyDetails(db.Model): IS_SPONSOR = db.Column(db.Integer, nullable=True) IS_GRANT = db.Column(db.Integer, nullable=True) IS_COMMITTEE_CONFLICT = db.Column(db.Integer, nullable=True) - DSMB = db.Column(db.Integer, nullable=True) + DSMB = db.Column(db.String, nullable=True) DSMB_FREQUENCY = db.Column(db.Integer, nullable=True) IS_DB = db.Column(db.Integer, nullable=True) IS_UVA_DB = db.Column(db.Integer, nullable=True) @@ -239,6 +237,8 @@ class StudyDetails(db.Model): IS_CODED_RESEARCH = db.Column(db.Integer, nullable=True) IS_OUTSIDE_SPONSOR = db.Column(db.Integer, nullable=True) IS_UVA_COLLABANALYSIS = db.Column(db.Integer, nullable=True) + REVIEW_TYPE = db.Column(db.Integer, nullable=True) + REVIEWTYPENAME = db.Column(db.String, nullable=True) From a2ddfaf03b2d137b720053e2517a88984bf2ea0d Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Tue, 30 Mar 2021 10:56:49 -0400 Subject: [PATCH 09/10] Migration script for new db columns --- migrations/versions/93a1e2ce38dc_.py | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 migrations/versions/93a1e2ce38dc_.py diff --git a/migrations/versions/93a1e2ce38dc_.py b/migrations/versions/93a1e2ce38dc_.py new file mode 100644 index 0000000..2eccb84 --- /dev/null +++ b/migrations/versions/93a1e2ce38dc_.py @@ -0,0 +1,30 @@ +"""empty message + +Revision ID: 93a1e2ce38dc +Revises: 6cd52db404f6 +Create Date: 2021-03-29 15:06:32.100287 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '93a1e2ce38dc' +down_revision = '6cd52db404f6' +branch_labels = None +depends_on = None + + +def upgrade(): + op.drop_column('study_details', 'DSMB') + op.add_column('study_details', sa.Column('DSMB', sa.VARCHAR, nullable=True)) + op.add_column('study_details', sa.Column('REVIEW_TYPE', sa.Integer, nullable=True)) + op.add_column('study_details', sa.Column('REVIEWTYPENAME', sa.VARCHAR, nullable=True)) + + +def downgrade(): + op.drop_column('study_details', 'DSMB') + op.add_column('study_details', sa.Column('DSMB', sa.Integer, nullable=True)) + op.drop_column('study_details', 'REVIEW_TYPE') + op.drop_column('study_details', 'REVIEWTYPENAME') From f4bd576a72efaf1d7d1576a7eda8982d7a19d963 Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Tue, 30 Mar 2021 11:00:40 -0400 Subject: [PATCH 10/10] Sample csv file for testing the file upload feature Attempt at testing the file upload feature. Test fails because SQLite doesn't accept the date as a string. NEED TO FIND A SOLUTION FOR THIS --- tests/data/ExampleStudyID15370.csv | 2 ++ tests/test_sanity.py | 8 ++++++++ 2 files changed, 10 insertions(+) create mode 100644 tests/data/ExampleStudyID15370.csv diff --git a/tests/data/ExampleStudyID15370.csv b/tests/data/ExampleStudyID15370.csv new file mode 100644 index 0000000..bf96968 --- /dev/null +++ b/tests/data/ExampleStudyID15370.csv @@ -0,0 +1,2 @@ +STUDYID,UVA_STUDY_TRACKING,IS_IND,IND_1,IND_2,IND_3,IS_UVA_IND,IS_IDE,IDE,IS_UVA_IDE,IS_CHART_REVIEW,IS_RADIATION,GCRC_NUMBER,IS_GCRC,IS_PRC_DSMP,IS_PRC,PRC_NUMBER,IS_IBC,IBC_NUMBER,IS_SPONSOR_TRACKING,SPONSOR_TRACKING,SPONSORS_PROTOCOL_REVISION_DATE,IS_SPONSOR_MONITORING,IS_DSMB,IS_COMPLETE_NON_IRB_REGULATORY,IS_AUX,IS_SPONSOR,IS_GRANT,IS_COMMITTEE_CONFLICT,DSMB,DSMB_FREQUENCY,IS_DB,IS_UVA_DB,IS_CENTRAL_REG_DB,IS_CONSENT_WAIVER,IS_HGT,IS_GENE_TRANSFER,IS_TISSUE_BANKING,IS_SURROGATE_CONSENT,IS_ADULT_PARTICIPANT,IS_MINOR_PARTICIPANT,IS_MINOR,IS_BIOMEDICAL,IS_QUALITATIVE,IS_PI_SCHOOL,IS_PRISONERS_POP,IS_PREGNANT_POP,IS_FETUS_POP,IS_MENTAL_IMPAIRMENT_POP,IS_ELDERLY_POP,IS_OTHER_VULNERABLE_POP,OTHER_VULNERABLE_DESC,IS_MULTI_SITE,IS_UVA_LOCATION,NON_UVA_LOCATION,MULTI_SITE_LOCATIONS,IS_OUTSIDE_CONTRACT,IS_UVA_PI_MULTI,IS_NOT_PRC_WAIVER,IS_INSIDE_CONTRACT,IS_CANCER_PATIENT,UPLOAD_COMPLETE,IS_FUNDING_SOURCE,IS_CODED_RESEARCH,IS_OUTSIDE_SPONSOR,IS_PI_INITIATED,IS_ENGAGED_RESEARCH,IS_APPROVED_DEVICE,IS_FINANCIAL_CONFLICT,IS_NOT_CONSENT_WAIVER,IS_FOR_CANCER_CENTER,IS_REVIEW_BY_CENTRAL_IRB,IRBREVIEWERADMIN,IS_UVA_COLLABANALYSIS +15370,,0,abc,def,ghi,,1,1234,1,0,,,,1,,,,,1,123456,2019-01-01T00:00:00,1,1,,1,1,1,0,UVA Cancer Center,4,,,1,0,0,0,,,,,,1,0,1,,,,,,,,1,0,"Martha Jefferson Hospital, Augusta Health Medical Center, Rockingham Memorial Hospital",,1,,,1,1,,,,1,1,,1,1,0,,1,,1 \ No newline at end of file diff --git a/tests/test_sanity.py b/tests/test_sanity.py index dd3326d..8b20d77 100644 --- a/tests/test_sanity.py +++ b/tests/test_sanity.py @@ -164,6 +164,14 @@ class Sanity_Check_Test(unittest.TestCase): study = self.add_study(title=title) self.assertEqual(title, study.TITLE) + # def test_update_study_from_csv(self): + # study = self.add_study() + # f = open('tests/data/ExampleStudyID15370.csv', 'rb') + # r = self.app.post(f'/study_details/{study.STUDYID}', data={'file': [f]}, follow_redirects=False) + # + # print(r) + # print('test_update_study_from_csv') + # def test_study_details_validation(self): # # test_study = self.add_study()