def test_getByToken_test(self, mock1): from src.api.appointment import appointment_helper from src.util.util import Auth auth = Auth() # Normal Case payload = {'token': mockhcp.auth_token, 'appointmentId': appointment_token} mock1.return_value = mockappointment.appointment response, status_code = appointment_helper.appointment_get_by_token(payload) self.assertEqual(200, status_code) # Empty token payload = {'token': None, 'appointmentId': appointment_token} response, status_code = appointment_helper.appointment_get_by_token(payload) self.assertEqual(401, status_code) # Wrong token payload = {'token': auth.encode_auth_token('pyy2020', "NURSE"), 'appointmentId': appointment_token} response, status_code = appointment_helper.appointment_get_by_token(payload) self.assertEqual(401, status_code) # Missing token payload = {'appointmentId': appointment_token} response, status_code = appointment_helper.appointment_get_by_token(payload) self.assertEqual(401, status_code) # No appointment id payload = {'token': mockhcp.auth_token, 'appointmentId': None} response, status_code = appointment_helper.appointment_get_by_token(payload) self.assertEqual(401, status_code)
def set_profile_picture(): """ Set HCP Profile Picture Returns: Response: JSON """ # Get Auth Token post_data = request.get_json() auth_token = post_data.get('token') if auth_token: hid, utype = Auth.decode_auth_token(auth_token) pic = post_data.get('profilePicture') res = hcp_set_profile_picture(hcpdb, hid, pic) if res: response_object = {"Success": True, "profilePicture": pic} return make_response(jsonify(response_object)), 200 else: response_object = { 'status': 'fail', 'message': "no response from helper function" } return make_response(jsonify(response_object)), 401 else: response_object = {'status': 'fail', 'message': "invalid_token"} return make_response(jsonify(response_object)), 401
def edit_hcp_profile(): """ Edit existing HCP profile Returns: Response: JSON """ post_data = request.get_json() auth_token = post_data.get('token') if auth_token: hid, utype = Auth.decode_auth_token(auth_token) # Get the ids of the HCPs of patient if utype == "HCP": try: response_object = hcp_edit_profile(hcpdb, hid, post_data) if response_object['Success']: return make_response(jsonify(response_object)), 200 except Exception as e: response_object = { 'status': 'fail', 'message': f'Some error, {e} occurred. Please try again.' } return make_response(jsonify(response_object)), 401 response_object = { 'status': 'fail', 'message': f'Fail to edit HCP profile' } return make_response(jsonify(response_object)), 401
def getbytoken(): """Get Patients by token Returns: Response: JSON """ # get the auth token auth_token = request.get_json().get('token') if auth_token: pid, utype = Auth.decode_auth_token(auth_token) resp, success = pat_get_by_token(pat, pid) if not success: return make_response(resp), 404 response_object = { "id": resp.id, "firstName": resp.firstName, "lastName": resp.lastName, "phone": resp.phone, "email": resp.email, "dateOfBirth": resp.dateOfBirth, "sex": resp.sex, "profilePicture": resp.profilePicture, "height": resp.height, "weight": resp.weight, "drinker": resp.drinker, "smoker": resp.smoker, "health": resp.health } return make_response(jsonify(response_object)), 200 else: response_object = { 'status': 'fail', 'message': 'Invalid token. Provide a valid auth token.' } return make_response(jsonify(response_object)), 401
def notify(): """ Notify patient of appoint Request{ token: string appointment_d: string } :return: Response """ post_data = request.get_json() auth_token = post_data.get('token') if auth_token: hid, utype = Auth.decode_auth_token(auth_token) if utype == "HCP": try: appointment_id = post_data.get('id') res = hcp_notify(appointmentsdb, pat, appointment_id) except Exception as e: return f"Unable to find {post_data.get('id')} because {e}", 400 return make_response(jsonify(res)), 200 else: response_object = {'Success': False, 'message': nonHCP} return make_response(jsonify(response_object)), 401 else: response_object = {'status': 'fail', 'message': invalid_token} return make_response(jsonify(response_object)), 401
def video(post_data): """ Creates JWT Twlio Room token Request: appointmentId: string hcpToken: string? patientToken: string? Response: token: videoId id: AppointmentId date: number duration: number doctor: DoctorId patient: PatientId subject: string """ auth_token = post_data.get('token') if auth_token: pid, _ = Auth.decode_auth_token(auth_token) appointment_id = post_data.get('appointmentId') appointments_output = appointmentsdb.document( str(appointment_id)).get().to_dict() if not (pid == appointments_output['patient'] or pid == appointments_output['doctor']): response_object = { "Success": False, "message": "ID not in appointment, unable to access room" } return response_object, 401 conversation = get_chatroom(str(appointment_id)) try: conversation.participants.create(identity=pid) except TwilioRestException as exc: # do not error if the user is already in the conversation if exc.status != 409: raise token = twilio.access_token(pid) token.add_grant(VideoGrant(room=str(appointment_id))) token.add_grant(ChatGrant(service_sid=conversation.chat_service_sid)) response_object = { "accessToken": token.to_jwt().decode(), "id": appointments_output['id'], "date": appointments_output['date'], "duration": appointments_output['duration'], "doctor": appointments_output['doctor'], "patient": appointments_output['patient'], "subject": appointments_output['subject'], "notes": appointments_output['notes'] } return response_object, 200 else: response_object = { 'Success': False, 'message': 'Failed to verify role' } return response_object, 401
def search(): """ Searches for a Patient from input Returns: Response: JSON """ # Get Auth Token auth_token = request.get_json().get('token') if auth_token: pid, utype = Auth.decode_auth_token(auth_token) text = request.get_json().get('text') if len(text) >= 3: res = pat_search(text) else: response_object = {"Success": False, "Not long enough": text} return make_response(jsonify(response_object)), 400 if res: return make_response(jsonify(res)), 200 else: response_object = { 'status': 'fail', 'message': 'Unable to find patient with query' } return make_response(jsonify(response_object)), 404 else: response_object = {'status': 'fail', 'message': "invalid_token"} return make_response(jsonify(response_object)), 401
def set_health_event(): """ Creates a health event given an HCP token, a patient ID and the criteria of a health event :return: HealthEvent """ post_data = request.get_json() auth_token = post_data.get('token') if auth_token: hid, utype = Auth.decode_auth_token(auth_token) if utype == "HCP": try: pid = post_data.get('id') patient = pat.document(str(pid)).get().to_dict() event = HealthEvent(date=post_data.get('date'), event=post_data.get('event'), remarks=post_data.get('remarks'), status=post_data.get('status')) jsonevent = { "date": event.date, "event": event.event, "remarks": event.remarks, "status": event.status } resp = Patient(id=patient['id'], firstName=patient['firstName'], lastName=patient['lastName'], phone=patient['phone'], email=patient['email'], dateOfBirth=patient['dateOfBirth'], sex=patient['sex'], profilePicture=patient['profilePicture'], height=patient['height'], weight=patient['weight'], drinker=patient['drinker'], smoker=patient['smoker'], calendar=patient['calendar'], doctors=patient['doctors'], health=patient['health']) resp.health.append(jsonevent) listevents = [] for i in resp.health: listevents.append(i) res = hcp_set_record(pat, resp) if res: return make_response(jsonify(jsonevent)), 201 else: return make_response(jsonify(jsonevent)), 401 except Exception as e: return f"Unable to find {post_data.get('id')} because {e}", 404 else: response_object = {'Success': False, 'message': nonHCP} return make_response(jsonify(response_object)), 401 else: response_object = {'status': 'fail', 'message': invalid_token} return make_response(jsonify(response_object)), 401
def appointment_get_by_token(post_data): """ Get the appointment details given appointment ID, request must be from concerned patient or healthcare professional. Request: { token: string appointmentId: string } Response: 200 OK (Appointment object in JSON format) """ auth_token = post_data.get('token') if auth_token: try: pid, utype = Auth.decode_auth_token(auth_token) appointmentid = post_data.get('appointmentId') elements = appointmentid.split(',') if (utype == "HCP") and (str(pid) == str(elements[1])) or ( utype == "PATIENT") and (str(pid) == str(elements[0])): appointments_output = \ appointmentsdb.document(str(appointmentid)).get().to_dict() response_object = { "id": appointments_output['id'], "date": appointments_output['date'], "duration": appointments_output['duration'], "doctor": appointments_output['doctor'], "patient": appointments_output['patient'], "subject": appointments_output['subject'], "notes": appointments_output['notes'], "videoUrl": appointments_output['videoUrl'] } return response_object, 200 else: response_object = { 'status': 'fail', 'message': 'Request not from ' 'concerned patient or healthcare professional.' } return response_object, 401 except Exception as e: return f"An Error Occurred: {e}", 401 else: response_object = { 'status': 'fail', 'message': 'Error in token authentication' } return response_object, 401
def get_records(): """ Based on the supplied patient JWT the health records for that patient will be accessed. :return: List[HealthEvent] """ auth_token = request.get_json().get('token') if auth_token: pid, utype = Auth.decode_auth_token(auth_token) response_object = pat_get_records(pat, pid) return make_response(jsonify(response_object)), 200 else: response_object = { 'status': 'fail', 'message': 'Invalid. Provide a valid auth token.' } return make_response(jsonify(response_object)), 401
def get_all(): """Get Patients Returns: Response: JSON """ auth_token = request.get_json().get('token') if auth_token: hid, utype = Auth.decode_auth_token(auth_token) pats_return = pat_get_all(pat) return jsonify(pats_return), 200 else: response_object = { 'status': 'fail', 'message': 'Provide a valid auth token.' } return make_response(jsonify(response_object)), 401
def get_all(): """ Get all HCPs Returns: List[HCP] :return: """ auth_token = request.get_json().get('token') if auth_token: hid, utype = Auth.decode_auth_token(auth_token) hcps_return = hcp_get_all(hcpdb) return jsonify(hcps_return), 200 else: response_object = {'status': 'fail', 'message': invalid_token} return make_response(jsonify(response_object)), 401
def getpatients(): """ Get Patient from token :return: Patient """ auth_token = request.get_json().get('token') if auth_token: hid, utype = Auth.decode_auth_token(auth_token) # Get the ids of the HCPs of patient if utype == "HCP": res = hcp_get_patients(hcpdb, pat, hid) return make_response(jsonify(res)), 200 else: response_object = {'Success': False, 'message': nonHCP} return make_response(response_object), 401 else: response_object = {'status': 'fail', 'message': invalid_token} return make_response(jsonify(response_object)), 401
def set_profile_picture(): """ Set Patient Profile Picture Returns: Response: JSON """ # Get Auth Token auth_token = request.get_json().get('token') if auth_token: pid, utype = Auth.decode_auth_token(auth_token) pic = request.get_json().get('profilePicture') res = pat_set_profile_picture(pat, pid, pic) if res: response_object = {"Success": True, "profilePicture": pic} return make_response(jsonify(response_object)), 200 else: response_object = {'status': 'fail', 'message': "invalid_token"} return make_response(jsonify(response_object)), 401
def gethcps(): """Get Patients's HCPs Returns: Response: JSON """ auth_token = request.get_json().get('token') if auth_token: pid, utype = Auth.decode_auth_token(auth_token) # Get the ids of the HCPs of patient results = pat_get_hcps(pat, hcpdb, pid) return make_response(jsonify(results)), 200 else: response_object = { 'status': 'fail', 'message': 'Token Invalid. Provide a valid auth token.' } return make_response(jsonify(response_object)), 401
def edit_profile(): """edit Patient Profile Returns: Response: JSON """ post_data = request.get_json() auth_token = post_data.get('token') if auth_token: pid, utype = Auth.decode_auth_token(auth_token) res = pat_edit_profile(pat, pid, post_data) return make_response(jsonify(res)), 200 else: response_object = { 'status': 'fail', 'message': 'Provide a valid auth token.' } return make_response(jsonify(response_object)), 401
def appointment_get_calendar(post_data): """ Get a list of Appointment IDs specific to the user from within the token. Request: { token: string } Response: 200 OK ( List[AppointmentId] ) """ auth_token = post_data.get('token') if auth_token: pid, utype = Auth.decode_auth_token(auth_token) if utype == "PATIENT": docs = patient_db.document(str(pid)).get().to_dict() output = docs['calendar'] elif utype == "HCP": docs = hcp_db.document(str(pid)).get().to_dict() output = docs['calendar'] else: response_object = { 'Success': False, 'message': 'Failed to verify role' } return response_object, 401 calendar = [] for event in output: appointments_output = appointmentsdb.document( str(event)).get().to_dict() calendar.append(appointments_output) return calendar, 200 response_object = { 'status': 'fail', 'message': 'Error, in token authentication' } return response_object, 401
def set_health_events(): """ Creates a health event given an HCP token, a patient ID and the criteria of a health event :return: HealthEvent """ post_data = request.get_json() auth_token = post_data.get('token') if auth_token: hid, utype = Auth.decode_auth_token(auth_token) if utype == "HCP": try: pid = post_data.get('id') resp = hcp_set_health_events(pat, pid, post_data) except Exception as e: return f"Unable to find {post_data.get('id')} because {e}", 404 return make_response(jsonify(resp.health)), 200 else: response_object = {'Success': False, 'message': nonHCP} return make_response(jsonify(response_object)), 401 else: response_object = {'status': 'fail', 'message': invalid_token} return make_response(jsonify(response_object)), 401
def test_number(): """ Notify patient of appoint Request{ token: string appointment_id: string } :return: Response """ post_data = request.get_json() auth_token = post_data.get('token') if auth_token: hid, utype = Auth.decode_auth_token(auth_token) if utype == "HCP": appointment_id = post_data.get('id') res = hcp_test_number(appointmentsdb, pat, appointment_id) if res: return make_response(jsonify(res)), 200 else: response_object = {'Success': False, 'message': nonHCP} return make_response(jsonify(response_object)), 401 else: response_object = {'status': 'fail', 'message': invalid_token} return make_response(jsonify(response_object)), 401
from flask import Blueprint, request, jsonify, make_response from sys import path from os.path import join, dirname path.append(join(dirname(__file__), '../../..')) from src.util.firebase.db import Database # noqa from src.util.util import Auth # noqa from . import appointment_helper # noqa pdb = Database() hcp_db = pdb.getHCP() patient_db = pdb.getPatients() appointmentsdb = pdb.getAppointments() auth = Auth() path.append(join(dirname(__file__), '../../..')) appointment_endpoints = Blueprint('appointment', __name__) @appointment_endpoints.route('/') def root(): """ Deafault Route Returns: reponse: string """ return "appointment root"
def create_appointment(post_data): """ Create a new appointment given the appointment details, returns an unique appointment id Request: token: string date: int (UNIX Time) duration: int (0-1440 minutes) hcpid: str (if patient initiate an appointment need to specify which hcp) patient: str (if HCP initiate an appointment need to specify which patient) subject: str notes: Optional[str] videoUrl: Optional[str] Response: 200 OK { appointmentId: string } """ auth_token = post_data.get('token') if auth_token: pid, utype = Auth.decode_auth_token(auth_token) doctor_id = pid patient_id = pid # Check whether user is HCP or Patient if utype == "HCP": patient_id = post_data.get('patient') elif utype == "PATIENT": doctor_id = post_data.get('hcpid') else: response_object = { 'Success': False, 'message': 'Failed to verify role' } return response_object, 401 appointment_id = str(patient_id) + "," +\ str(doctor_id) + "," + str(post_data.get('date')) try: # Get the existing appointments from HCP: hcp_ref = hcp_db.document(str(doctor_id)) hcp_ref_details = hcp_ref.get().to_dict() # Get the office hours of HCP appt_date = post_data.get('date') appt_time = int(int(appt_date) / 1000) appt_date = datetime.datetime.fromtimestamp(appt_time) appt_start_time = appt_date.hour * 60 + appt_date.minute # Used if need to check for ending time # appt_end_time = appt_start_time + int(post_data.get('duration')) day_number = appt_date.weekday() + 1 if day_number > 6: day_number = 0 office_hours = hcp_ref_details['hours'] res = office_hours[day_number].strip('][').split(', ') if int(res[0]) == -1 and int(res[1]) == -1: response_object = { 'status': 'fail', 'message': 'Whole day is closed' } return response_object, 401 if (appt_start_time >= int(res[0])) and (appt_start_time <= int( res[1])): new_appointment = Appointment( id=appointment_id, date=post_data.get('date'), duration=post_data.get('duration'), doctor=str(doctor_id), patient=str(patient_id), subject=post_data.get('subject'), notes=post_data.get('notes'), videoUrl=post_data.get('videoUrl')) appointmentsdb.document(new_appointment.id).set({ "id": new_appointment.id, "date": new_appointment.date, "duration": new_appointment.duration, "doctor": str(doctor_id), "patient": str(patient_id), "subject": new_appointment.subject, "notes": new_appointment.notes, "videoUrl": new_appointment.videoUrl }) # Add the appointment id to both respective patient and HCP # database patient_ref = patient_db.document(str(patient_id)) # Get the existing list of appointments and append it patient_calendar = patient_ref.get().to_dict()['calendar'] patient_calendar.append(appointment_id) patient_ref.update({u'calendar': patient_calendar}) patient_doctors = patient_ref.get().to_dict()['doctors'] if str(doctor_id) not in patient_doctors: patient_doctors.append(doctor_id) patient_ref.update({u'doctors': patient_doctors}) hcp_patients = hcp_ref_details['patients'] if str(patient_id) not in hcp_patients: hcp_patients.append(patient_id) hcp_ref.update({u'patients': hcp_patients}) hcp_calendar = hcp_ref_details['calendar'] hcp_calendar.append(appointment_id) hcp_ref.update({u'calendar': hcp_calendar}) response_object = {"appointmentId": new_appointment.id} return response_object, 200 else: response_object = { 'status': 'fail', 'message': 'appointment starting ' 'time out of office hours' } return response_object, 401 except Exception as e: return f"Failure due to {e}", 404 else: response_object = { 'status': 'fail', 'message': 'Error: Error in token authentication' } return response_object, 401
def getbytoken(): """Get HCP by token Returns: Response: JSON """ # Get Auth Token auth_token = request.get_json() auth_token = auth_token.get('token') if auth_token: hid, utype = Auth.decode_auth_token(auth_token) if utype == "HCP": resp = hcp_get_by_token(hcpdb, hid) hours = { "sunday": { "startTime": resp.hours.sunday.startTime, "endTime": resp.hours.sunday.endTime }, "monday": { "startTime": resp.hours.monday.startTime, "endTime": resp.hours.monday.endTime }, "tuesday": { "startTime": resp.hours.tuesday.startTime, "endTime": resp.hours.tuesday.endTime }, "wednesday": { "startTime": resp.hours.wednesday.startTime, "endTime": resp.hours.wednesday.endTime }, "thursday": { "startTime": resp.hours.thursday.startTime, "endTime": resp.hours.thursday.endTime }, "friday": { "startTime": resp.hours.friday.startTime, "endTime": resp.hours.friday.endTime }, "saturday": { "startTime": resp.hours.saturday.startTime, "endTime": resp.hours.saturday.endTime } } response_object = { "id": resp.id, "firstName": resp.firstName, "lastName": resp.lastName, "phone": resp.phone, "email": resp.email, "profilePicture": resp.profilePicture, "calendar": resp.calendar, "specialty": resp.specialty, "hours": hours, "patients": resp.patients, "title": resp.title, } return make_response(jsonify(response_object)), 200 else: response_object = {'Success': False, 'message': nonHCP} return make_response(response_object), 401 else: response_object = {'status': 'fail', 'message': invalid_token} return make_response(jsonify(response_object)), 401
def delete_appointment(post_data): """ Remove appointment with the given appointment id, the request must originate from either the concerned patient or healthcare professional Request: { id: string } Response: 200 OK { success: boolean } """ auth_token = post_data.get('token') if auth_token: try: pid, utype = Auth.decode_auth_token(auth_token) appointment_id = post_data.get('id') elements = appointment_id.split(',') doctor_id = str(elements[1]) patient_id = str(elements[0]) user_id_verified = False if (utype == "HCP") and (str(pid) == doctor_id) or ( utype == "PATIENT") and (str(pid) == patient_id): user_id_verified = True if user_id_verified: # Access both respective patient and HCP document patient_ref = patient_db.document(patient_id) hcp_ref = hcp_db.document(doctor_id) # Remove the appointment and update patient_calendar = patient_ref.get().to_dict()['calendar'] try: patient_calendar.remove(appointment_id) except Exception: pass patient_ref.update({u'calendar': patient_calendar}) hcp_calendar = hcp_ref.get().to_dict()['calendar'] try: hcp_calendar.remove(appointment_id) except Exception: pass hcp_ref.update({u'calendar': hcp_calendar}) appointmentsdb.document(appointment_id).delete() response_object = {'success': 'True'} return response_object, 200 else: response_object = { 'status': 'fail', 'message': 'Delete request not originated from ' 'concerned patient or health care professional.' } return response_object, 401 except Exception as e: return f"An Error Occurred: {e}", 401 else: response_object = { 'status': 'fail', 'message': 'Error in token authentication' } return response_object, 401