Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pesticide liaison workflow #401

Merged
merged 87 commits into from
May 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
b00ab1f
changed position of sbc selection in add exam popup
nitheesh-aot Mar 9, 2020
a84e465
added location and invigilator select in the non-sbc exams
nitheesh-aot Mar 12, 2020
74c9e40
Invite minimal (#370)
ozamani9 Mar 12, 2020
b65fc84
fix quicktrans issue
ozamani9 Mar 13, 2020
d5a88fb
Merge pull request #371 from ozamani9/invite_omid
jhmccoll Mar 13, 2020
0de6e17
posting exam with latest body
nitheesh-aot Mar 14, 2020
a28a147
Phase 3 (#368)
sjrumsby Feb 28, 2020
67e35f9
Update requirements temporarily
gil0109 Mar 3, 2020
ffd6de8
changed position of sbc selection in add exam popup
nitheesh-aot Mar 9, 2020
d003059
added location and invigilator select in the non-sbc exams
nitheesh-aot Mar 12, 2020
603b683
posting exam with latest body
nitheesh-aot Mar 14, 2020
0c7f0a1
Merge branch 'pesticide_liaison_workflow' of https://github.com/nithe…
nitheesh-aot Mar 17, 2020
77b6771
saving group exam - inprogress
nitheesh-aot Mar 18, 2020
929023f
group exam posting to bcmp
nitheesh-aot Mar 19, 2020
a51558b
individual and group exam in the proper format
nitheesh-aot Mar 20, 2020
05260a2
ui issues for group exam modal fixed
nitheesh-aot Mar 21, 2020
d7ab930
fixed banner showing after refreshing once exams added
nitheesh-aot Mar 21, 2020
61a1d01
bug fixes for saving non-pesticide exams
nitheesh-aot Mar 22, 2020
6c0dd52
modified post exam function to separate bcmp request
nitheesh-aot Mar 22, 2020
7d2e9b2
emergency fix added click once to check in button
ozamani9 Mar 23, 2020
8f12aa6
Merge pull request #374 from ozamani9/appointment_fix_emer
jhmccoll Mar 23, 2020
61a6e21
emergency fix added click once to submit button
ozamani9 Mar 23, 2020
fa98730
emergency fix added click once to submit button and added spinners to…
ozamani9 Mar 23, 2020
10050cb
emergency fix added click once to submit button, remove spinner logic
ozamani9 Mar 23, 2020
445c714
emergency fix added click once to buttons on check in modal and add a…
ozamani9 Mar 23, 2020
63aa735
Merge pull request #375 from ozamani9/appointment_fix_emer
jhmccoll Mar 23, 2020
6953381
separated api call for bcmp exam posting
nitheesh-aot Mar 24, 2020
5642a89
request exam button api integration
nitheesh-aot Mar 24, 2020
8e03f12
Code to put spinner in Appointments, when selecting a service (#376)
ChrisDMac Mar 25, 2020
020e705
scheduling for group exam - ui
nitheesh-aot Mar 25, 2020
784584a
new parameter added for identifying pesticide exams
nitheesh-aot Mar 25, 2020
e2fe25c
Update package-lock.json to fix vulnerabilities
ChrisDMac Mar 25, 2020
6d6ed6a
Put in code to handle double clicks, turn on/off spinner
ChrisDMac Mar 25, 2020
dcefaca
Update the version.
ChrisDMac Mar 25, 2020
ddb8269
Merge pull request #377 from ChrisDMac/fix_doubleclick
jhmccoll Mar 25, 2020
30ae9de
Revert package-lock.json, see if works in IE.
ChrisDMac Mar 25, 2020
47c9b9a
Merge pull request #378 from ChrisDMac/revert_packagelock
jhmccoll Mar 25, 2020
c854ed6
ui changes for add invigilator to group exam modal
nitheesh-aot Mar 26, 2020
86238cd
add invigilator group exam modal submit
nitheesh-aot Mar 27, 2020
8bfdec5
exam download as pdf
nitheesh-aot Mar 27, 2020
a8c694b
download an updated received date exam
nitheesh-aot Mar 27, 2020
0529694
Mender update (#379)
gil0109 Mar 29, 2020
2b8cc85
upload exam api changes
nitheesh-aot Mar 29, 2020
62902df
upload exam modal changes
nitheesh-aot Mar 29, 2020
097921c
$ sign if exam fee not paid but printed
nitheesh-aot Mar 30, 2020
98a6381
disable submit for pesticide till job id is generated
nitheesh-aot Mar 30, 2020
086e1a2
offsite invigilators rest added
nitheesh-aot Mar 31, 2020
c2dc07a
pesticide offsite invigilators list added
nitheesh-aot Mar 31, 2020
cb8be02
updated minio url expiry to 7 days
nitheesh-aot Mar 31, 2020
b7a849c
email to offsite invigilators after creating exam
nitheesh-aot Mar 31, 2020
46179a4
return exam if uploaded
nitheesh-aot Mar 31, 2020
1278d69
Put in logging for debugging session errors
ChrisDMac Mar 31, 2020
6c33343
Merge pull request #380 from ChrisDMac/debug_sids
jhmccoll Mar 31, 2020
d402f5a
receipt send status in the edit exam modal
nitheesh-aot Apr 1, 2020
fdf7657
awaiting receipt filter
nitheesh-aot Apr 1, 2020
de7006c
awaiting upload filter
nitheesh-aot Apr 1, 2020
c96f649
UI for pesticide final step
nitheesh-aot Apr 1, 2020
f36fd23
Use websocket transport for smartboard (#381)
ChrisDMac Apr 1, 2020
8384666
event id from bcmp job id
nitheesh-aot Apr 2, 2020
9d651cd
exam_type variable issue fixed
nitheesh-aot Apr 2, 2020
1a745c1
db migration for new columns
nitheesh-aot Apr 2, 2020
2198e9f
job id issue fixed
nitheesh-aot Apr 2, 2020
075a831
Update requirements.txt
nitheesh-aot Apr 2, 2020
87e7d90
Update exam_bcmp.py
nitheesh-aot Apr 2, 2020
90ca8be
replaced flask-restplus
nitheesh-aot Apr 2, 2020
eaddee6
updated config file
nitheesh-aot Apr 4, 2020
6cdcd3d
clear data in modal, group exam, hide add shadow invigilator
nitheesh-aot Apr 5, 2020
a8fd1d8
bug fixes
nitheesh-aot Apr 5, 2020
ae0176d
fixed exam date change issue
nitheesh-aot Apr 5, 2020
e6c6257
bcmp base url to env
nitheesh-aot Apr 5, 2020
927cecf
non sbc table status correction
nitheesh-aot Apr 5, 2020
b4f5bec
await upload filter fix
nitheesh-aot Apr 6, 2020
36acf6a
pest exam date default days corrected
nitheesh-aot Apr 7, 2020
8798eee
expiry date invalid fix
nitheesh-aot Apr 7, 2020
17fc910
bcmp to env
nitheesh-aot Apr 7, 2020
e5ba55e
bcmp manual job id breaking issue fixed
nitheesh-aot Apr 7, 2020
9ae415a
loading for await upload
nitheesh-aot Apr 8, 2020
efd868f
exam not ready message persisting issue
nitheesh-aot Apr 9, 2020
b689661
filter fix
nitheesh-aot Apr 9, 2020
1df8b8c
indication for upload
nitheesh-aot Apr 9, 2020
2a5fc5a
loading and disable request exam btn
nitheesh-aot Apr 9, 2020
4845acf
event id editable for pest exams
nitheesh-aot Apr 10, 2020
ec05284
invigilator id edit fix
nitheesh-aot Apr 10, 2020
5fd0ebc
updated minio to baseconfig
nitheesh-aot Apr 18, 2020
2a05a37
filter fixes
nitheesh-aot Apr 19, 2020
3128552
Merge branch 'master' of github.com:bcgov/queue-management into pesti…
nitheesh-aot Apr 19, 2020
72864cc
flask_marshmallow to 0.11.0
nitheesh-aot Apr 28, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions api/app/models/bookings/exam.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class Exam(Base):
payee_email = db.Column(db.String(50), nullable=True)
payee_name = db.Column(db.String(50), nullable=True)
payee_phone = db.Column(db.String(50), nullable=True)
candidates_list = db.Column(db.JSON, nullable=True)
is_pesticide = db.Column(db.Integer, nullable=True, default=0)

booking = db.relationship("Booking")
exam_type = db.relationship("ExamType")
Expand Down
14 changes: 13 additions & 1 deletion api/app/resources/bookings/booking/booking_post.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,23 @@ def post(self):
db.session.add(booking)
db.session.commit()

else:
elif type(i_id) == int:

booking.invigilators.append(Invigilator.query.filter_by(invigilator_id=i_id).first_or_404())
db.session.add(booking)
db.session.commit()

elif type(i_id) == list:

if len(i_id) == 0:
db.session.add(booking)
db.session.commit()

else:
for value in i_id:
booking.invigilators.append(Invigilator.query.filter_by(invigilator_id=value).first_or_404())
db.session.add(booking)
db.session.commit()

result = self.booking_schema.dump(booking)

Expand Down
80 changes: 80 additions & 0 deletions api/app/resources/bookings/exam/exam_bcmp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'''Copyright 2018 Province of British Columbia

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.'''

import logging
import copy
import json
from flask import request, g
from flask_restx import Resource
from app.models.theq import CSR, Office
from app.models.bookings import ExamType, Invigilator
from app.schemas.bookings import ExamSchema, CandidateSchema
from qsystem import api, api_call_with_retry, db, oidc
from app.utilities.bcmp_service import BCMPService

from app.resources.bookings.exam.exam_post import ExamPost

@api.route("/exams/bcmp/", methods=["POST"])
class ExamBcmpPost(Resource):

exam_schema = ExamSchema()
bcmp_service = BCMPService()

@oidc.accept_token(require_token=True)
@api_call_with_retry
def post(self):

csr = CSR.find_by_username(g.oidc_token_info['username'])

json_data = request.get_json()

exam, warning = self.exam_schema.load(json_data)

print("json_data: ")
print(json_data)

if warning:
logging.warning("WARNING: %s", warning)
return {"message": warning}, 422

if not (exam.office_id == csr.office_id or csr.liaison_designate == 1):
return {"The Exam Office ID and CSR Office ID do not match!"}, 403

formatted_data = ExamPost.format_data(self, json_data, exam)
exam = formatted_data["exam"]

invigilator = None
if exam.invigilator_id:
invigilator = Invigilator.query.filter_by(invigilator_id=exam.invigilator_id).first()

bcmp_response = None
if json_data["ind_or_group"] == "individual":

exam_fees = json_data["fees"]

logging.info("Creating individual pesticide exam")
bcmp_response = self.bcmp_service.create_individual_exam(exam, exam_fees, invigilator, formatted_data["pesticide_office"], g.oidc_token_info)

else:

logging.info("Creating Group pesticide exam")
bcmp_response = self.bcmp_service.create_group_exam_bcmp(exam, formatted_data["candidates_list_bcmp"], invigilator, formatted_data["pesticide_office"], g.oidc_token_info)


if bcmp_response:
return {"bcmp_job_id": bcmp_response['jobId'],
"errors": {}}, 201
else:
return {"message": "create_group_exam_bcmp failed",
"error": bcmp_response}, 403
34 changes: 30 additions & 4 deletions api/app/resources/bookings/exam/exam_bulk_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,54 @@
limitations under the License.'''

import logging
import json
from flask import g
from flask_restplus import Resource
from flask_restx import Resource
from sqlalchemy import exc
from app.models.bookings import Exam
from app.schemas.bookings import ExamSchema
from app.models.theq import CSR
from app.utilities.bcmp_service import BCMPService
from qsystem import api, oidc
from qsystem import api, oidc, db


@api.route("/exams/bcmp_status/", methods=["POST"])
class ExamList(Resource):
bcmp_service = BCMPService()
exam_schema = ExamSchema()

@oidc.accept_token(require_token=True)
def post(self):
csr = CSR.find_by_username(g.oidc_token_info['username'])

try:
exams = Exam.query.filter_by(upload_received_ind=0).filter(Exam.bcmp_job_id.isnot(None))
self.bcmp_service.bulk_check_exam_status(exams)
bcmp_response = self.bcmp_service.bulk_check_exam_status(exams)

return {}, 200
job_ids = []
for job in bcmp_response["jobs"]:
if job["jobStatus"] == "RESPONSE_UPLOADED":
job_ids.append(job["jobId"])

print("job_ids to update: ")
print(job_ids)

exams_tobe_updated = None

if len(job_ids) != 0:
exams_tobe_updated = Exam.query.filter(Exam.bcmp_job_id.in_(job_ids))

for exam in exams_tobe_updated:
exam_upd, warn = self.exam_schema.load({'upload_received_ind': 1}, instance=exam, partial=True)
db.session.add(exam_upd)

try:
db.session.commit()
except:
db.session.rollback()
raise

return {"exams_updated": exams_tobe_updated}, 200

except exc.SQLAlchemyError as error:
logging.error(error, exc_info=True)
Expand Down
12 changes: 6 additions & 6 deletions api/app/resources/bookings/exam/exam_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
limitations under the License.'''

from flask import g, Response
from flask_restplus import Resource
from flask_restx import Resource
import io
import logging
import urllib
Expand All @@ -40,11 +40,11 @@ def get(self, exam_id):
if not (exam.office_id == csr.office_id or csr.liaison_designate == 1):
return {"The Exam Office ID and CSR Office ID do not match!"}, 403

status = self.bcmp_service.check_exam_status(exam)
print(status)
job = self.bcmp_service.check_exam_status(exam)
print(job)

if status == 'PACKAGE_GENERATED':
package_url = status["jobProperties"]["EXAM_PACKAGE_URL"]
if job['jobStatus'] == 'PACKAGE_GENERATED':
package_url = job["jobProperties"]["EXAM_PACKAGE_URL"]
req = urllib.request.Request(package_url)
response = urllib.request.urlopen(req).read()
exam_file = io.BytesIO(response)
Expand All @@ -58,7 +58,7 @@ def get(self, exam_id):
"Content-Type": "application/pdf"
})
else:
return {'message': 'API is down'}, 400
return {'message': 'Package not yet generated', 'status': job['jobStatus']}, 400
# test_url = 'http://www.pdf995.com/samples/pdf.pdf'
# req = urllib.request.Request(test_url)
# response = urllib.request.urlopen(req).read()
Expand Down
2 changes: 1 addition & 1 deletion api/app/resources/bookings/exam/exam_email_invigilator.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
limitations under the License.'''

from flask import g, request
from flask_restplus import Resource
from flask_restx import Resource
import logging
from sqlalchemy import exc
from app.models.theq import CSR
Expand Down
120 changes: 85 additions & 35 deletions api/app/resources/bookings/exam/exam_post.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@
limitations under the License.'''

import logging
import copy
import json
from flask import request, g
from flask_restx import Resource
from app.models.theq import CSR, Office
from flask_restplus import Resource
from app.models.bookings import ExamType
from app.schemas.bookings import ExamSchema
from flask_restx import Resource
from app.models.bookings import ExamType, Invigilator
from app.schemas.bookings import ExamSchema, CandidateSchema
from qsystem import api, api_call_with_retry, db, oidc
from app.utilities.bcmp_service import BCMPService


@api.route("/exams/", methods=["POST"])
class ExamPost(Resource):

Expand All @@ -33,46 +34,34 @@ class ExamPost(Resource):
@api_call_with_retry
def post(self):

is_bcmp_req = True if request.args.get('bcmp_pesticide') else False

print("is_bcmp_req: ")
print(is_bcmp_req)

csr = CSR.find_by_username(g.oidc_token_info['username'])

json_data = request.get_json()

exam, warning = self.exam_schema.load(json_data)

print("json_data: ")
print(json_data)

if warning:
logging.warning("WARNING: %s", warning)
return {"message": warning}, 422
print("+=+=+=+= NAME: %s +=+=+=+=" % exam.examinee_name)

exam_type = ExamType.query.filter_by(exam_type_id=exam.exam_type_id).first()

if not exam_type:
exam_type = ExamType.query.filter_by(pesticide_exam_ind=1, group_exam_ind=1).first()
exam.exam_type = exam_type

if exam_type.pesticide_exam_ind:
if not exam_type.group_exam_ind:
logging.info("Create BCMP exam since this is a pesticide exam")

if json_data["sbc_managed"] != "sbc":
print("Setting non-SBC shit")
pesticide_office = Office.query.filter_by(office_name="Pesticide Offsite").first()
exam.office_id = pesticide_office.office_id

if exam_type.group_exam_ind:
logging.info("Creating group pesticide exam")
bcmp_response = self.bcmp_service.create_group_exam(exam)
else:
logging.info("Creating individual pesticide exam")
bcmp_response = self.bcmp_service.create_individual_exam(exam, exam_type)

if bcmp_response:
exam.bcmp_job_id = bcmp_response['jobId']
else:
print("Do the group exam shit here")
else:
if not (exam.office_id == csr.office_id or csr.liaison_designate == 1):
return {"The Exam Office ID and CSR Office ID do not match!"}, 403

if not (exam.office_id == csr.office_id or csr.liaison_designate == 1):
return {"The Exam Office ID and CSR Office ID do not match!"}, 403

if exam.is_pesticide:
formatted_data = self.format_data(json_data, exam)
exam = formatted_data["exam"]
job = self.bcmp_service.check_exam_status(exam)
print(job)
if job and job['jobProperties'] and job['jobProperties']['JOB_ID']:
exam.event_id = job['jobProperties']['JOB_ID']

db.session.add(exam)
db.session.commit()
Expand All @@ -81,3 +70,64 @@ def post(self):

return {"exam": result.data,
"errors": result.errors}, 201



## formating data to save on bcmp
def format_data(self, json_data, exam):

candidates_list_bcmp = []

pesticide_office = None
if json_data["sbc_managed"] == "sbc":
pesticide_office = Office.query.filter_by(office_id=exam.office_id).first()
else:
pesticide_office = Office.query.filter_by(office_name="Pesticide Offsite").first()
exam.office_id = pesticide_office.office_id

if json_data["ind_or_group"] == "individual":

exam_type = ExamType.query.filter_by(exam_type_id=exam.exam_type_id).first()

if not exam_type:
exam_type = ExamType.query.filter_by(pesticide_exam_ind=1, group_exam_ind=1).first()
exam.exam_type = exam_type

else:
logging.info("For Group Exams")

exam_type = ExamType.query.filter_by(exam_type_name="Group Pesticide Exam").first()
if exam_type:
exam.exam_type_id = exam_type.exam_type_id
exam.exam_type = exam_type

if json_data["candidates"]:
candidates = json_data["candidates"]
candidates_list = []
for candidate in candidates:
candidate_temp = {}
candidate_temp["examinee_name"] = candidate["name"]
candidate_temp["examinee_email"] = candidate["email"]
candidate_temp["exam_type_id"] = candidate["exam_type_id"]
candidate_temp["fees"] = candidate["fees"]
candidate_temp["payee_ind"] = 1 if (candidate["billTo"] == "candidate") else 0
candidate_temp["receipt"] = candidate["receipt"]
candidate_temp["receipt_number"] = candidate["receipt"]
candidate_temp["payee_name"] = candidate["payeeName"]
candidate_temp["payee_email"] = candidate["payeeEmail"]
candidates_list.append(candidate_temp)
# for bcmp service
candidates_bcmp = copy.deepcopy(candidate_temp)
exam_type = ExamType.query.filter_by(exam_type_id=candidate["exam_type_id"]).first()
if exam_type.exam_type_name:
candidates_bcmp["exam_type"] = exam_type.exam_type_name
candidates_list_bcmp.append(candidates_bcmp)

exam.candidates_list = candidates_list

return {
'exam': exam,
'candidates_list_bcmp': candidates_list_bcmp,
'pesticide_office': pesticide_office,
}

12 changes: 9 additions & 3 deletions api/app/resources/bookings/exam/exam_transfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
limitations under the License.'''

from flask import g
from flask_restplus import Resource
from flask_restx import Resource
import logging
from sqlalchemy import exc
from app.models.theq import CSR
Expand All @@ -37,8 +37,14 @@ def post(self, exam_id):
if not (exam.office_id == csr.office_id or csr.liaison_designate == 1):
return {"The Exam Office ID and CSR Office ID do not match!"}, 403

self.bcmp_service.send_exam_to_bcmp(exam)
return {}
bcmp_response = self.bcmp_service.send_exam_to_bcmp(exam)

if bcmp_response:
return {"bcmp": bcmp_response,
"errors": {}}, 202
else:
return {"message": "create_group_exam_bcmp failed",
"error": bcmp_response}, 403

except exc.SQLAlchemyError as error:
logging.error(error, exc_info=True)
Expand Down
Loading