mirror of
https://github.com/sartography/protocol-builder-mock.git
synced 2025-02-28 15:20:35 +00:00
WIP: Adds sponsor model, mock sponsors list, and form for adding sponsors to a study.
This commit is contained in:
parent
86101375b2
commit
be441a7c53
45
example_data.py
Normal file
45
example_data.py
Normal file
@ -0,0 +1,45 @@
|
||||
import csv
|
||||
from pb import db, session
|
||||
from pb.models import Sponsor
|
||||
|
||||
|
||||
class ExampleDataLoader:
|
||||
@staticmethod
|
||||
def clean_db():
|
||||
session.flush() # Clear out any transactions before deleting it all to avoid spurious errors.
|
||||
for table in reversed(db.metadata.sorted_tables):
|
||||
session.execute(table.delete())
|
||||
session.commit()
|
||||
session.flush()
|
||||
|
||||
def load_all(self):
|
||||
self.load_sponsors()
|
||||
# self.load_studies()
|
||||
# self.load_investigators()
|
||||
|
||||
def load_sponsors(self):
|
||||
# Load sponsors from csv
|
||||
with open('./pb/static/csv/sponsors.csv') as csv_file:
|
||||
data = csv.reader(csv_file, delimiter=',')
|
||||
first_line = True
|
||||
sponsors = []
|
||||
for row in data:
|
||||
# Skip first line, which will be the column headings
|
||||
if first_line:
|
||||
# row[0]: SPONSOR_ID
|
||||
# row[1]: SP_NAME
|
||||
# row[2]: SP_MAILING_ADDRESS
|
||||
# row[3]: SP_TYPE
|
||||
first_line = False
|
||||
elif int(row[0] or -1) is not -1:
|
||||
print('row', row)
|
||||
new_sponsor = Sponsor(SPONSOR_ID=int(row[0]), SP_NAME=row[1], SP_MAILING_ADDRESS=row[2], SP_TYPE=row[3])
|
||||
new_sponsor.SP_TYPE_GROUP_NAME = Sponsor.get_type_group_name(new_sponsor.SP_TYPE)
|
||||
sponsors.append(new_sponsor)
|
||||
|
||||
session.add_all(sponsors)
|
||||
session.commit()
|
||||
|
||||
|
||||
|
||||
|
49
migrations/versions/ffba4886d280_.py
Normal file
49
migrations/versions/ffba4886d280_.py
Normal file
@ -0,0 +1,49 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: ffba4886d280
|
||||
Revises: d3592c4e8a39
|
||||
Create Date: 2020-08-12 14:06:05.072787
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'ffba4886d280'
|
||||
down_revision = 'd3592c4e8a39'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('sponsor',
|
||||
sa.Column('SPONSOR_ID', sa.Integer(), nullable=False),
|
||||
sa.Column('SP_NAME', sa.String(), nullable=True),
|
||||
sa.Column('SP_MAILING_ADDRESS', sa.String(), nullable=True),
|
||||
sa.Column('SP_PHONE', sa.String(), nullable=True),
|
||||
sa.Column('SP_FAX', sa.String(), nullable=True),
|
||||
sa.Column('SP_EMAIL', sa.String(), nullable=True),
|
||||
sa.Column('SP_HOMEPAGE', sa.String(), nullable=True),
|
||||
sa.Column('COMMONRULEAGENCY', sa.Boolean(), nullable=True),
|
||||
sa.Column('SP_TYPE', sa.String(), nullable=True),
|
||||
sa.Column('SP_TYPE_GROUP_NAME', sa.String(), nullable=True),
|
||||
sa.PrimaryKeyConstraint('SPONSOR_ID')
|
||||
)
|
||||
op.create_table('study_sponsor',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('SS_STUDY', sa.Integer(), nullable=True),
|
||||
sa.Column('SPONSOR_ID', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['SPONSOR_ID'], ['sponsor.SPONSOR_ID'], ),
|
||||
sa.ForeignKeyConstraint(['SS_STUDY'], ['study.STUDYID'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('study_sponsor')
|
||||
op.drop_table('sponsor')
|
||||
# ### end Alembic commands ###
|
@ -59,6 +59,11 @@ origins_re = [r"^https?:\/\/%s(.*)" % o.replace('.', '\.') for o in app.config['
|
||||
cors = CORS(connexion_app.app, origins=origins_re)
|
||||
|
||||
db = SQLAlchemy(app)
|
||||
""":type: sqlalchemy.orm.SQLAlchemy"""
|
||||
|
||||
session = db.session
|
||||
""":type: sqlalchemy.orm.Session"""
|
||||
|
||||
migrate = Migrate(app, db)
|
||||
ma = Marshmallow(app)
|
||||
|
||||
@ -115,6 +120,21 @@ def has_no_empty_params(rule):
|
||||
return len(defaults) >= len(arguments)
|
||||
|
||||
|
||||
@app.cli.command()
|
||||
def load_example_data():
|
||||
"""Load example data into the database."""
|
||||
from example_data import ExampleDataLoader
|
||||
ExampleDataLoader().clean_db()
|
||||
ExampleDataLoader().load_all()
|
||||
|
||||
|
||||
@app.cli.command()
|
||||
def load_example_sponsors():
|
||||
"""Load example data into the database."""
|
||||
from example_data import ExampleDataLoader
|
||||
ExampleDataLoader().load_sponsors()
|
||||
|
||||
|
||||
@app.route('/site_map')
|
||||
def site_map():
|
||||
links = []
|
||||
@ -130,9 +150,9 @@ def site_map():
|
||||
# **************************
|
||||
# WEB FORMS
|
||||
# **************************
|
||||
from pb.forms import StudyForm, StudyTable, InvestigatorForm, StudyDetailsForm, ConfirmDeleteForm
|
||||
from pb.forms import StudyForm, StudyTable, InvestigatorForm, StudyDetailsForm, ConfirmDeleteForm, StudySponsorForm
|
||||
from pb.models import Study, RequiredDocument, Investigator, StudySchema, RequiredDocumentSchema, InvestigatorSchema, \
|
||||
StudyDetails, StudyDetailsSchema
|
||||
StudyDetails, StudyDetailsSchema, StudySponsor, Sponsor
|
||||
|
||||
|
||||
@app.route('/', methods=['GET', 'POST'])
|
||||
@ -256,6 +276,69 @@ def del_investigator(inv_id):
|
||||
return redirect_home()
|
||||
|
||||
|
||||
@app.route('/study_sponsor/<study_id>', methods=['GET', 'POST'])
|
||||
def new_study_sponsor(study_id):
|
||||
form = StudySponsorForm(request.form)
|
||||
action = BASE_HREF + "/study_sponsor/" + study_id
|
||||
title = "Add StudySponsor to Study " + study_id
|
||||
form.SPONSOR_IDS.choices = [(s.SPONSOR_ID, s.SP_NAME) for s in db.session.query(Sponsor).all()]
|
||||
if request.method == 'POST':
|
||||
study_sponsor = StudySponsor(STUDYID=study_id)
|
||||
study_sponsor.NETBADGEID = form.NETBADGEID.data
|
||||
study_sponsor.set_type(form.INVESTIGATORTYPE.data)
|
||||
db.session.add(study_sponsor)
|
||||
db.session.commit()
|
||||
flash('StudySponsor created successfully!', 'success')
|
||||
return redirect_home()
|
||||
|
||||
return render_template(
|
||||
'form.html',
|
||||
form=form,
|
||||
action=action,
|
||||
title=title,
|
||||
description_map={},
|
||||
base_href=BASE_HREF
|
||||
)
|
||||
|
||||
|
||||
@app.route('/del_study_sponsor/<study_sponsor_id>', methods=['GET', 'POST'])
|
||||
def del_study_sponsor(study_sponsor_id):
|
||||
study_sponsor_id = int(study_sponsor_id)
|
||||
study_sponsor_model = db.session.query(StudySponsor).filter(StudySponsor.id == study_sponsor_id).first()
|
||||
if study_sponsor_model is None:
|
||||
flash('StudySponsor not found.', 'warn')
|
||||
return redirect_home()
|
||||
|
||||
uid = study_sponsor_model.NETBADGEID
|
||||
study_id = int(study_sponsor_model.STUDYID)
|
||||
form = ConfirmDeleteForm(request.form, obj=study_sponsor_model)
|
||||
|
||||
if request.method == 'GET':
|
||||
action = BASE_HREF + "/del_study_sponsor/%i" % study_sponsor_id
|
||||
title = "Delete StudySponsor #%i?" % study_sponsor_id
|
||||
details = "Are you sure you want to delete StudySponsor '%s' from Study %i?" % (uid, study_id)
|
||||
|
||||
return render_template(
|
||||
'form.html',
|
||||
form=form,
|
||||
action=action,
|
||||
title=title,
|
||||
details=details,
|
||||
description_map=description_map,
|
||||
base_href=BASE_HREF
|
||||
)
|
||||
|
||||
if request.method == 'POST':
|
||||
if form.confirm and form.confirm.data:
|
||||
db.session.query(StudySponsor).filter(StudySponsor.id == study_sponsor_id).delete()
|
||||
db.session.commit()
|
||||
flash('StudySponsor %s deleted from Study %i.' % (uid, study_id), 'success')
|
||||
else:
|
||||
flash('Delete canceled.', 'info')
|
||||
|
||||
return redirect_home()
|
||||
|
||||
|
||||
@app.route('/del_study/<study_id>', methods=['GET', 'POST'])
|
||||
def del_study(study_id):
|
||||
study_id = int(study_id)
|
||||
|
20
pb/forms.py
20
pb/forms.py
@ -23,6 +23,11 @@ class InvestigatorForm(FlaskForm):
|
||||
INVESTIGATORTYPE = SelectField("InvestigatorType", choices=[(i.INVESTIGATORTYPE, i.INVESTIGATORTYPEFULL) for i in Investigator.all_types()])
|
||||
|
||||
|
||||
class StudySponsorForm(FlaskForm):
|
||||
STUDY_ID = HiddenField()
|
||||
SPONSOR_IDS = SelectMultipleField("Sponsor", coerce=int, validators=[validators.DataRequired()])
|
||||
|
||||
|
||||
class StudyDetailsForm(ModelForm, FlaskForm):
|
||||
class Meta:
|
||||
model = StudyDetails
|
||||
@ -46,6 +51,15 @@ class InvestigatorsTable(Table):
|
||||
th_html_attrs={'class': 'mat-icon text-center', 'title': 'Delete Investigator'}
|
||||
)
|
||||
|
||||
class SponsorsTable(Table):
|
||||
SPONSOR_ID = Col('Sponsor Id')
|
||||
SP_TYPE = Col('Type')
|
||||
delete = LinkCol(
|
||||
'delete', 'del_sponsor', url_kwargs=dict(inv_id='id'),
|
||||
anchor_attrs={'class': 'btn btn-icon btn-warn', 'title': 'Delete Sponsor'},
|
||||
th_html_attrs={'class': 'mat-icon text-center', 'title': 'Delete Sponsor'}
|
||||
)
|
||||
|
||||
|
||||
class StudyTable(Table):
|
||||
def sort_url(self, col_id, reverse=False):
|
||||
@ -65,6 +79,11 @@ class StudyTable(Table):
|
||||
anchor_attrs={'class': 'btn btn-icon btn-accent', 'title': 'Add Investigator'},
|
||||
th_html_attrs={'class': 'mat-icon text-center', 'title': 'Add Investigator'}
|
||||
)
|
||||
add_sponsor = LinkCol(
|
||||
'add_business', 'new_study_sponsor', url_kwargs=dict(study_id='STUDYID'),
|
||||
anchor_attrs={'class': 'btn btn-icon btn-accent', 'title': 'Add Sponsor'},
|
||||
th_html_attrs={'class': 'mat-icon text-center', 'title': 'Add Sponsor'}
|
||||
)
|
||||
STUDYID = Col('Study Id')
|
||||
TITLE = Col('Title')
|
||||
NETBADGEID = Col('User')
|
||||
@ -72,6 +91,7 @@ class StudyTable(Table):
|
||||
Q_COMPLETE = BoolCol('Complete?')
|
||||
requirements = NestedTableCol('Requirements', RequirementsTable)
|
||||
investigators = NestedTableCol('Investigators', InvestigatorsTable)
|
||||
sponsors = NestedTableCol('Sponsors', SponsorsTable)
|
||||
delete = LinkCol(
|
||||
'delete', 'del_study', url_kwargs=dict(study_id='STUDYID'),
|
||||
anchor_attrs={'class': 'btn btn-icon btn-warn', 'title': 'Delete Study'},
|
||||
|
60
pb/models.py
60
pb/models.py
@ -1,3 +1,4 @@
|
||||
from marshmallow import fields
|
||||
from sqlalchemy import func
|
||||
from pb import db, ma
|
||||
|
||||
@ -11,6 +12,7 @@ class Study(db.Model):
|
||||
DATE_MODIFIED = db.Column(db.DateTime(timezone=True), default=func.now())
|
||||
requirements = db.relationship("RequiredDocument", backref="study", lazy='dynamic')
|
||||
investigators = db.relationship("Investigator", backref="study", lazy='dynamic')
|
||||
sponsors = db.relationship("StudySponsor", backref="study", lazy='dynamic')
|
||||
study_details = db.relationship("StudyDetails", uselist=False, backref="study")
|
||||
|
||||
|
||||
@ -178,3 +180,61 @@ class StudyDetailsSchema(ma.SQLAlchemyAutoSchema):
|
||||
model = StudyDetails
|
||||
load_instance = True
|
||||
include_relationships = False
|
||||
|
||||
|
||||
class Sponsor(db.Model):
|
||||
SPONSOR_ID = db.Column(db.Integer, primary_key=True)
|
||||
SP_NAME = db.Column(db.String, nullable=True)
|
||||
SP_MAILING_ADDRESS = db.Column(db.String, nullable=True)
|
||||
SP_PHONE = db.Column(db.String, nullable=True)
|
||||
SP_FAX = db.Column(db.String, nullable=True)
|
||||
SP_EMAIL = db.Column(db.String, nullable=True)
|
||||
SP_HOMEPAGE = db.Column(db.String, nullable=True)
|
||||
COMMONRULEAGENCY = db.Column(db.Boolean, nullable=True)
|
||||
SP_TYPE = db.Column(db.String, nullable=True)
|
||||
SP_TYPE_GROUP_NAME = db.Column(db.String, nullable=True)
|
||||
|
||||
@staticmethod
|
||||
def all_types():
|
||||
types = [
|
||||
Sponsor(SP_TYPE="Federal", SP_TYPE_GROUP_NAME="Government"),
|
||||
Sponsor(SP_TYPE="Foundation/Not for Profit", SP_TYPE_GROUP_NAME="Other External Funding"),
|
||||
Sponsor(SP_TYPE="Incoming Sub Award", SP_TYPE_GROUP_NAME="Government"),
|
||||
Sponsor(SP_TYPE="Industry", SP_TYPE_GROUP_NAME="Industry"),
|
||||
Sponsor(SP_TYPE="Internal/Departmental/Gift", SP_TYPE_GROUP_NAME="Internal Funding"),
|
||||
Sponsor(SP_TYPE="No Funding", SP_TYPE_GROUP_NAME="Internal Funding"),
|
||||
Sponsor(SP_TYPE="Other Colleges and Universities", SP_TYPE_GROUP_NAME="Other External Funding"),
|
||||
Sponsor(SP_TYPE="State", SP_TYPE_GROUP_NAME="Government"),
|
||||
]
|
||||
return types
|
||||
|
||||
@staticmethod
|
||||
def get_type_group_name(self, type_code):
|
||||
for t in self.all_types():
|
||||
if t.SP_TYPE == type_code:
|
||||
return t.SP_TYPE_GROUP_NAME
|
||||
|
||||
|
||||
class SponsorSchema(ma.Schema):
|
||||
class Meta:
|
||||
fields = ("SPONSOR_ID", "SP_NAME", "SP_MAILING_ADDRESS",
|
||||
"SP_PHONE", "SP_FAX", "SP_EMAIL", "SP_HOMEPAGE",
|
||||
"COMMONRULEAGENCY", "SP_TYPE")
|
||||
|
||||
|
||||
class StudySponsor(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
SS_STUDY = db.Column(db.Integer, db.ForeignKey('study.STUDYID'))
|
||||
SPONSOR_ID = db.Column(db.Integer, db.ForeignKey('sponsor.SPONSOR_ID'))
|
||||
study = db.relationship("Study")
|
||||
sponsor = db.relationship("Sponsor")
|
||||
|
||||
|
||||
class StudySponsorSchema(ma.Schema):
|
||||
class Meta:
|
||||
fields = ("SS_STUDY", "SPONSOR_ID", "SP_NAME", "SP_TYPE", "SP_TYPE_GROUP_NAME", "COMMONRULEAGENCY")
|
||||
|
||||
SP_TYPE = fields.Function(lambda obj: obj.sponsor.SP_TYPE)
|
||||
SP_NAME = fields.Function(lambda obj: obj.sponsor.SP_NAME)
|
||||
SP_TYPE_GROUP_NAME = fields.Function(lambda obj: obj.sponsor.SP_TYPE_GROUP_NAME)
|
||||
COMMONRULEAGENCY = fields.Function(lambda obj: obj.sponsor.COMMONRULEAGENCY)
|
||||
|
3497
pb/static/csv/sponsors.csv
Normal file
3497
pb/static/csv/sponsors.csv
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user