def load_appointments(self, doctor_timezone): """ Load all of today's appointments for the logged in doctor """ access_token = self.get_token() api = AppointmentEndpoint(access_token) today = datetime.datetime.now() today = today.strftime('%Y-%m-%d') appointments = api.list(date=today) for a in appointments: patient = self.get_patient(a['patient']) patient_name = patient['first_name'] + ' ' + patient['last_name'] check_in_time = None seen_time = None print(a['status']) if a['status'] in ['In Session', 'Complete']: seen_time = datetime.datetime.now() elif a['status'] in ['Arrived', 'Checked In', 'In Room']: check_in_time = datetime.datetime.now() print('CHECKED IN') appointment = Appointment( drchrono_id=a['id'], doctor=a['doctor'], patient_name=patient_name, patient_id=a['patient'], scheduled_time=datetime.datetime.strptime( a['scheduled_time'], '%Y-%m-%dT%H:%M:%S'), duration=a['duration'], status=a['status'], check_in_time=check_in_time, seen_time=seen_time) appointment.save()
def form_valid(self, form): patients_api = PatientEndpoint(self.request.session["access_token"]) try: patients_api.update(self.request.session["patient_id"], form.cleaned_data) except APIException: return render( self.request, "patient_checkin.html", { "error": "There was an error updating your information", "form": form }, ) appointments_api = AppointmentEndpoint( self.request.session["access_token"]) for appointment_id in self.request.session["appointment_ids"]: try: appointments_api.update(appointment_id, {"status": "Arrived"}) except APIException: return render( self.request, "patient_checkin.html", { "error": "There was an error checking in to your appointment", "form": form, }, ) appointment = Appointment.objects.get(api_id=appointment_id) appointment.status = "Arrived" appointment.check_in_time = timezone.now() appointment.save() return super(PatientDemographicsView, self).form_valid(form)
def form_valid(self, form): first_name = form.cleaned_data['first_name'] last_name = form.cleaned_data['last_name'] social_security_number = form.cleaned_data['social_security_number'] patient = Patient.objects.filter( first_name=first_name, last_name=last_name, social_security_number=social_security_number).first() # FIXME: pretty sure there is a better way to do this self.success_url = '../demographics/' + str(patient.id) # get first appointment for today that patient # is not already checked in for # for testing/dubugging: # statuses = ['', None] statuses = [ '', None, 'Checked In', 'In Session', 'Complete', 'Cancelled' ] date = timezone.now().date() appointment = Appointment.objects.filter(patient=patient, scheduled_time__date=date, status__in=statuses).first() access_token = self.request.session['access_token'] endpoint = AppointmentEndpoint(access_token) response = endpoint.update(appointment.id, {'status': 'Checked In'}) appointment.check_in() return super(CheckInView, self).form_valid(form)
def post(self, request, *args, **kwargs): form = self.form_class(request.POST) appointment_id = kwargs['pk'] if form.is_valid(): status = form.cleaned_data['status'] access_token = self.request.session['access_token'] appointment_endpoint = AppointmentEndpoint(access_token) response = appointment_endpoint.update(appointment_id, {'status': status}) # FIXME: find a better way to update/refresh template view doctor_id = self.request.session['doctor_id'] doctor = Doctor.objects.get(pk=doctor_id) utils.populate_appointments(appointment_endpoint, doctor) app = Appointment.objects.get(pk=appointment_id) if status == 'Checked In': app.check_in() elif status == 'In Session': app.start() elif status == 'Cancelled': app.cancel() return HttpResponseRedirect(self.request.path_info)
def finalize_appointment(request): """ This is an ajax call to finalize the appointment in progress :param request: contains appointment_id and appointment notes :return: success msg or exception """ appointment_id = request.POST.get('appointment_id', '') notes = request.POST.get('notes', '').trim() if not (appointment_id and notes): return JsonResponse( {'msg': 'No appointment_id or notes in the the request body'}) access_token = UserSocialAuth.objects.get( provider='drchrono').extra_data['access_token'] appointment_api = AppointmentEndpoint(access_token) try: appointment_api.update(appointment_id, { 'status': 'Complete', 'notes': notes }) except APIException: return JsonResponse( {'msg': 'Could not update the appointment in the api'}) return JsonResponse({'msg': 'Success'})
def get_appointment(request): """ This is an ajax call to get an appointment from drchrono api :param request: containing appointment_id in the request body :return: success msg with appointment data or API error """ appointment_id = request.POST.get('appointment_id', '') if not appointment_id: return JsonResponse( {'msg': 'No appointment_id in the the request body'}) access_token = UserSocialAuth.objects.get( provider='drchrono').extra_data['access_token'] appointment_api = AppointmentEndpoint(access_token) try: appointment = appointment_api.fetch(appointment_id) if appointment: appointment = decorate_appointments([appointment], access_token) except APIException: return JsonResponse({'msg': 'No appointment is returned from api'}) return JsonResponse({'msg': 'Success', 'appointment': appointment})
def post(self, request): access_token = self.request.session.get('access_token') a = AppointmentEndpoint(access_token) if request.method == 'POST': request_data = json.loads(request.body) appointment_id = request_data.get("id") status = request_data.get("status") data = {'status': status} try: resp = a.update(appointment_id, data) appt = Appointment.objects.get(pk=appointment_id) appt.status = status # setup arrival time in database if patient has arrived if status == 'Complete' and appt.appt_end_time is None: appt.appt_end_time = datetime.datetime.now().strftime( '%H:%M:%S') if status == 'Arrived' and appt.check_in_time is None: appt.check_in_time = datetime.datetime.now().strftime( '%H:%M:%S') if status == 'In Session' and appt.appt_start_time is None: appt.appt_start_time = datetime.datetime.now().strftime( '%H:%M:%S') appt.save() except APIException: return JsonResponse({"status": "false"}, status=500) return JsonResponse({"status": "true"})
def get_appointments(self, doctor): """ Return all appointments for today TODO: Performing local db sync on page load slows performance, even if by a non-negligible amount Write cron/celery task to periodically sync so we can remove the API call from here """ access_token = self.get_token() api = AppointmentEndpoint(access_token) apts_api = api.list(params={"verbose": True, "doctor": doctor['id']}, date=self.today_date) for apt in apts_api: try: # TODO: Update status locally if value from API result differs apt_db = Appointment.objects.get(id=apt['id']) # Check if status has changed and update if needed # if apt_db.status != apt['status']: # apt_db.status = apt['status'] # apt_db.save() except Appointment.DoesNotExist: Appointment.create_from_api(apt, access_token) # Sort appointments by status, in order of time_spent_waiting yesterday = datetime.today() - timedelta(days=1) apts_db = Appointment.objects\ .filter(scheduled_time__gt=yesterday)\ .exclude(status=Appointment.IN_SESSION)\ .order_by(Appointment.ORDER_HIERARCHY) return apts_db
def get(self, request): if self.request.is_ajax() and self.request.GET.get( 'listtype') == 'current': current_appointment = Appointment.current.first() response_data = None if current_appointment: response_data = current_appointment else: nextappointment = Appointment.future.first() if nextappointment: nextappointment.queue_status = 'current' nextappointment.save() response_data = nextappointment if response_data == None: return JsonResponse({"data": None}) context = { 'appointment': response_data, } return render(request, 'appointment_current.html', context) else: access_token = self.request.session.get('access_token') apppointment_api = AppointmentEndpoint(access_token) apppointment_api.get_and_store_data() context = { 'future': Appointment.future.all(), 'past': Appointment.past.all(), } return render(request, 'appointment_list.html', context)
def post(self, request): access_token = self.request.session.get('access_token') apppointment_api = AppointmentEndpoint(access_token) if self.request.is_ajax() and self.request.POST.get('status'): appointment = Appointment.current.first() if appointment: appointment_id = appointment.id appointment_status = self.request.POST.get('status') updateddate = datetime.now().strftime('%Y-%m-%dT%H:%M:%S') data = { 'status': appointment_status, 'updated_at': updateddate } response = {} try: response = apppointment_api.update(appointment_id, data) appointment.appointment_status = appointment_status if appointment_status == 'In Session': appointment.session_start_time = datetime.now() elif appointment_status in ('Complete', 'No Show'): appointment.session_complete_time = datetime.now() appointment.queue_status = 'past' appointment.save() except APIException: return JsonResponse({"status": "false"}, status=500) return JsonResponse({"status": "true"})
def update_appointments(self, doctor_id): access_token = self.get_token() api = AppointmentEndpoint(access_token) today = date.today() params = {} params['doctor'] = doctor_id lst = list(api.list(params=params, date=today)) for item in lst: Appointment.objects.update_or_create(defaults={ 'doctor': Doctor.objects.get(id=doctor_id), 'duration': item['duration'], 'exam_room': item['exam_room'], 'office': item['office'], 'patient': Patient.objects.get(id=item['patient']), 'scheduled_time': item['scheduled_time'], 'status': item['status'] }, id=item['id'])
def get_context_data(self, **kwargs): kwargs = super(DoctorWelcome, self).get_context_data(**kwargs) access_token = get_token() dt_api = DoctorEndpoint(access_token) ap_api = AppointmentEndpoint(access_token) pt_api = PatientSummaryEndpoint(access_token) doctor = next(dt_api.list()) appointments = list(ap_api.list(date=dt.date.today())) app_list = [] for a in appointments: patient_info = pt_api.fetch(id=a["patient"]) a["patient_info"] = patient_info a['start_time'] = dt.datetime.strptime(a["scheduled_time"], "%Y-%m-%dT%H:%M:%S") a['end_time'] = a["start_time"]\ + dt.timedelta(minutes=int(a["duration"])) updated_at = dt.datetime.strptime(a['updated_at'], "%Y-%m-%dT%H:%M:%S") wait_time = dt.datetime.now() - updated_at a["wait_time"] = round(wait_time.total_seconds() / 60) app_list.append(a) confirmed = filter(lambda x: x["status"] == "", app_list) current = filter(lambda x: x["status"] == "In Session", app_list) arrived = filter(lambda x: x["status"] == "Arrived", app_list) complete = filter(lambda x: x["status"] == "Complete", app_list) kwargs['doctor'] = doctor kwargs['confirmed'] = confirmed kwargs['current'] = current kwargs['arrived'] = arrived kwargs['complete'] = complete return kwargs
def visit_patient(request): """ This is an ajax call to update appointment status from 'Checked In' to 'In Session' :param request: request from doctor containing appointment_id :return: success msg with some appointment details """ appointment_id = request.POST.get('appointment_id', '') if not appointment_id: return JsonResponse( {'msg': 'No appointment_id in the the request body'}) access_token = UserSocialAuth.objects.get( provider='drchrono').extra_data['access_token'] appointment_api = AppointmentEndpoint(access_token) try: appointment_api.update(appointment_id, {'status': 'In Session'}) appointment = appointment_api.fetch(appointment_id) if appointment: appointment = decorate_appointments([appointment], access_token) except APIException: return JsonResponse( {'msg': 'Could not update the appointment in the api'}) return JsonResponse({'msg': 'Success', 'appointment': appointment})
def appointments_list(self, params=None, date=None, start=None, end=None, **kwargs): """ Obtains Appointments list https://app.drchrono.com/api-docs/#operation/appointments_list Args: params (dict, optional): cursor : string (Cursor): The pagination cursor value. date : string (date) date_range : string (date_range) doctor : integer (doctor) office : integer (office) page_size: integer (Page size): Number of results to return per page. patient : integer (patient) since : string (since) status : string (status) date (string, optional): Date start (string, optional): Start end (string, optional): End Returns: list: appointments list """ api = AppointmentEndpoint(self.access_token) g = api.list(params, date, start, end, **kwargs) return self.__get_list(g)
def make_api_request(self): """ Use the token we have stored in the DB to make an API request and get doctor details. If this succeeds, we've proved that the OAuth setup is working """ # We can create an instance of an endpoint resource class, and use it to fetch details access_token = self.get_token() self.request.session['access_token'] = access_token doctor_api = DoctorEndpoint(access_token) patient_api = PatientEndpoint(access_token) apppointment_api = AppointmentEndpoint(access_token) # Grab the first doctor from the list; normally this would be the whole # practice group, but your hackathon account probably only has one doctor in it. doctor = doctor_api.get_and_store_data() self.request.session['doctor'] = doctor.id # Get patients and appointments for the doctor and store it in the local DB patient_api.get_and_store_data(doctor=doctor) date = datetime.now( tz=pytz.timezone(doctor.timezone)).strftime('%Y-%m-%d') apppointment_api.get_and_store_data(doctor=doctor, date=date) return doctor
def confirm(self, request): # print pk pk = request.POST.get('pk', None) oauth_provider = UserSocialAuth.objects.get(provider='drchrono') access_token = oauth_provider.extra_data['access_token'] endpoint = AppointmentEndpoint(access_token) res = endpoint.update(pk, {'status': 'Arrived'}) api_data = endpoint.fetch(id=pk) try: model = Appointment.objects.get(pk=pk) serializer = AppointmentSerializer(model, data=api_data) if serializer.is_valid(): serializer.save() message = 'Successfully check in.' return HttpResponse(message, status=200) except Appointment.DoesNotExist: pass message = 'Sorry, fail to check in.' return HttpResponse(message, status=403)
def clean(self): try: oauth_provider = UserSocialAuth.objects.get(provider='drchrono') access_token = oauth_provider.extra_data['access_token'] except UserSocialAuth.DoesNotExist: raise forms.ValidationError( "We had a problem authenticating with the drchrono API.") full_name = f"{self.cleaned_data.get('first_name')} {self.cleaned_data.get('last_name')}" appointments_client = AppointmentEndpoint(access_token) patient_client = PatientEndpoint(access_token) self.cleaned_data['appointment_id'] = None self.cleaned_data['patient_id'] = None # get a list of patients, make a list of their full names to search through patients = list(patient_client.list()) patients_full_names = [ f"{patient.get('first_name')} {patient.get('last_name')}" for patient in list(patient_client.list()) ] patient_found = full_name in patients_full_names if not patient_found: raise forms.ValidationError( "Couldn't find a patient matching your name.") patient = patients[patients_full_names.index(full_name)] self.cleaned_data['patient_id'] = patient.get('id') # okay, we found them. do they have an appt. ? today = timezone.now() today_str = today.strftime('%m-%d-%y') appointments = list( appointments_client.list( {'patient': self.cleaned_data.get('patient_id')}, start=today_str, end=today_str)) patient_has_appointment_today = len(appointments) > 0 if not patient_has_appointment_today: raise forms.ValidationError( "Couldn't find an appointment for you today.") # if they have any appointments set their status to Arrived for appointment in appointments: self.cleaned_data['appointment_id'] = appointment.get('id') import random if random.randrange(20) % 4: appointments_client.update(self.cleaned_data['appointment_id'], {'status': 'Arrived'}) # create a Visit object visit, created = Visit.objects.get_or_create( appointment_id=self.cleaned_data['appointment_id'], patient_id=self.cleaned_data['patient_id']) # if there was already a Visit object and it is set to Arrived, they already checked in! if not created and visit.status == 'Arrived': raise forms.ValidationError( "You already checked in for your appointment today.")
def change_appointment(self, id="None", data={}): ''' Submit request to change an appintment with ID All request data is in dict 'data', ''' access_token = self.get_token() api = AppointmentEndpoint(access_token) return api.update(id, data)
def post(self, request, appointment_id, patient_id): form = self.patient_demographics(request.POST) if form.is_valid(): try: PatientEndpoint(access_token=get_token()).update(patient_id, form.cleaned_data) updated_patient_dmg = PatientEndpoint(access_token=get_token()).fetch(patient_id) patient_object, created = Patient.objects.update_or_create( patient_id=updated_patient_dmg['id'], defaults={ 'gender': updated_patient_dmg['gender'], 'doctor_id': updated_patient_dmg['doctor'], 'first_name': updated_patient_dmg['first_name'], 'last_name': updated_patient_dmg['last_name'], 'email': updated_patient_dmg['email'], 'patient_photo': updated_patient_dmg['patient_photo'] } ) appointment_details = AppointmentEndpoint(access_token=get_token()).fetch(appointment_id) updated_appointment = { 'doctor': appointment_details['doctor'], 'duration': appointment_details['duration'], 'exam_room': appointment_details['exam_room'], 'office': appointment_details['office'], 'patient': appointment_details['patient'], 'scheduled_time': appointment_details['scheduled_time'], 'status': 'Arrived' } AppointmentEndpoint(access_token=get_token()).update(appointment_id,updated_appointment) user_timezone = request.COOKIES.get('tzname_from_user') time_now = datetime.now(pytz.timezone('UTC')) arrival_time = time_now.astimezone(pytz.timezone(user_timezone)) appointment_object, created = Appointment.objects.update_or_create( appointment_id=appointment_details['id'], defaults={ 'status': 'Arrived', 'patient': Patient.objects.get(patient_id=appointment_details['patient']), 'check_in_time': arrival_time, 'scheduled_time': appointment_details['scheduled_time'] } ) return render(request, 'finish_check_in.html', {"patient": updated_patient_dmg}) except APIException: form.add_error(None, 'Error in updating form. Please try again.') return render( request, self.template_name, { 'form': form, 'appointment_id': appointment_id, 'patient_id': patient_id, })
def fetch_appointment_list(self): """ Use the token we have stored in the DB to make an API request and get appointment list. """ # We can create an instance of an endpoint resource class, and use it to fetch details access_token = self.get_token() api = AppointmentEndpoint(access_token) # Grab all appointments from one date return api.list(date='2020-02-06')
def change_appointment_status(self, appointment_id, status): """ :param appointment_id: get the appointment_id from the url. status: status to update """ api = AppointmentEndpoint(self.access_token) params = {"status": status} api.update(appointment_id, params, True)
def form_valid(self, form): patient_id = self.kwargs['p_id'] appointment_id = self.kwargs['a_id'] access_token = get_token() api = PatientEndpoint(access_token) ap_api = AppointmentEndpoint(access_token) data = form.cleaned_data api.update(id=patient_id, data=data) ap_api.update(id=appointment_id, data={"status": "Arrived"}) return super(PatientInformationView, self).form_valid(form)
def get(self, request, *args, **kwargs): response = super(FinishConsult, self).get(request, *args, **kwargs) id = self.kwargs['appointment'] status = 'Complete' # Update both API and local cache endpoint = AppointmentEndpoint() endpoint.update(id, {'status': status}) Appointment.objects.get(id=id).finish_consut() return response
def get(self, request, *args, **kwargs): response = super(StartConsult, self).get(request, *args, **kwargs) id = self.kwargs['appointment'] status = 'In Session' # Update both API and local cache endpoint = AppointmentEndpoint() endpoint.update(id, {'status': status}) Appointment.objects.get(id=id).start_consult() return response
def cancel_appointment(request, appointment_id): """ Cancel the Doctor / Patient Appointment. """ api_appt = AppointmentEndpoint(ChronoOauth.get_token()) api_appt.update(appointment_id, {'status' : 'Cancelled' }) return JsonResponse({ 'success' : True })
def appointments_update(self, id, data, partial=True, **kwargs): """ Updates an appointment https://app.drchrono.com/api-docs/#operation/appointments_partial_update Args: id (int): Appointment id. Example: id = 174509207 data (dict): Data to update. Example: data = {"scheduled_time": "2021-05-06T10:39:00"} partial (bool, optional): Defaults to True. """ api = AppointmentEndpoint(self.access_token) api.update(id, data, partial=True, **kwargs)
def make_api_request(self): """ Use the token we have stored in the DB to make an API request and get doctor details. If this succeeds, we've proved that the OAuth setup is working """ # We can create an instance of an endpoint resource class, and use it to fetch details access_token = self.get_token() api = AppointmentEndpoint(access_token) # Grab the first doctor from the list; normally this would be the whole practice group, but your hackathon # account probably only has one doctor in it. return (api.list(date="2019-10-22"))
def patch(self, request, *args, **kwargs): ''' Update appointment status in drchrono ''' request_data = json.loads(request.body)['params'] doctor_welcome = DoctorWelcome() access_token = doctor_welcome.get_token() api = AppointmentEndpoint(access_token) api.update(request_data['appointment'], {'status': request_data['status']}) return HttpResponse(status=200)
def form_valid(self, form): # This method is called when valid form data has been POSTed. # It should return an HttpResponse. first_name = form.cleaned_data.get('first_name') last_name = form.cleaned_data.get('last_name') # dob = form.cleaned_data.get('date_of_birth') # TODO: Use ssn to get the patient ssn = form.cleaned_data.get('social_security_number') patient = get_object_or_none(Patient, first_name=first_name, last_name=last_name, social_security_number=str(ssn)) if patient: access_token = self.request.session['access_token'] apppointment_api = AppointmentEndpoint(access_token) appointments = Appointment.today.filter(patient=patient.id) updateddate = datetime.now().isoformat() for appointment in appointments: updated_fields = { 'appointment_status': 'Checked In', 'checkedin_status': True, 'checkedin_time': updateddate, } data = {'status': 'Checked In', 'updated_at': updateddate} response = {} try: response = apppointment_api.update(appointment.id, data) updated_appointment, created = update_or_create_object( Appointment, updated_fields, pk=appointment.id) self.request.session['checkedin_patient'] = patient.id return super(CheckinView, self).form_valid(form) except APIException: context = { 'form': form, 'message': 'Trouble checking you in, Please consult a staff member', } return render(self.request, "checkin.html", context) context = { 'form': form, 'message': 'Appointment for the Patient not found', } return render(self.request, "checkin.html", context) context = { 'form': form, 'message': 'Patient not found', } return render(self.request, "checkin.html", context)
def begin_appointment(request, id): access_token = get_token() api = AppointmentEndpoint(access_token) appointment = api.fetch(id=id) updated_at = dt.datetime.strptime(appointment['updated_at'], "%Y-%m-%dT%H:%M:%S") wait_time = dt.datetime.now() - updated_at diff = round(wait_time.total_seconds() / 60) wt = WaitTime(appointment_id=id, wait_time=diff) wt.save() api.update(id=id, data={"status": "In Session"}) return redirect('/welcome')