Exemple #1
0
def add_patient():
    """
    Allows a physician to enter in patient information and for an
    invitational email to be sent to the patient. The PatientInvite
    is then stored so as to not spam the patient and for logging purposes.
    """
    form = AddPatientForm(request.form)
    if request.method == "POST":
        try:
            # First, ensure this physician is not already monitoring this patient
            if current_user.patients.objects(email=form.email.data).count() > 0:
                flash("Error: You are already monitoring this patient. Please specify a new patient.", "warning")
                return render_template("add-patient.html", form=form)
        except AttributeError:
            pass  # Patients table is empty, so no need to check

        if form.validate():

            # Don't allow physician to send duplicate invite requests to a new patient
            if PatientInvite.objects(email=form.email.data, inviting_physician=current_user.to_dbref()).count() > 0:
                flash("Warning: You have already invited this patient to join.", "warning")
                return redirect("/dashboard")

            full_name = "{} {}".format(form.first_name.data, form.last_name.data)

            # Generate a PatientInvite object and send an invite email to given patient
            invite = PatientInvite(
                inviting_physician=current_user.to_dbref(),
                accepted=False,
                email=form.email.data,
                first_name=form.first_name.data,
                last_name=form.last_name.data,
            )
            invite.save()

            email_sent = email_patient_invite(
                email=form.email.data, name=full_name, invite_id=str(invite.id), physician_name=current_user.full_name
            )

            if email_sent:
                success_msg = (
                    "{name} has been emailed an invitation, and will appear"
                    " on your Dashboard after granting access.".format(name=full_name)
                )

                flash(success_msg, "success")
            else:
                flash(
                    "We were unable to send the patient invitation. Please ensure the address provided is correct.",
                    "warning",
                )

            return redirect("/dashboard")
        else:
            flash("Invalid input: please see the suggestions below.", "warning")

    return render_template("add-patient.html", form=form)
Exemple #2
0
def authorize_new_patient():
    """
    This is called once a patient clicks the confirmation link in their email.
    Redirect a new patient to Fitbit to authorize our app via OAuth 2 Authorization Grant Flow, and
    then receives access token (for making API calls on the user's behalf) as well as a
    refresh token (for obtaining a new access token when the access token expires).
    """
    access_code = request.args.get("code")
    invite_id = request.args.get("state")
    api = Fitbit()

    # Require users to be invited by a physician. Only occurs when they receive an email w/ invite_id (aka "state").
    if invite_id is None:
        flash(
            "Error: an authorization token is required. Please use the confirmation link that was emailed to you.",
            "warning",
        )
        return redirect("/")

    if access_code is None:
        auth_url = api.get_authorization_uri(invite_id)
        return redirect(auth_url)

    try:
        token = api.get_access_token(access_code)
    except Exception as e:
        flash(e.message, "warning")
        return redirect("/")

    try:
        response, token = api.api_call(token, "/1/user/-/profile.json")
    except Exception as e:
        flash(e.message, "warning")
        return redirect("/")

    # fullname = response['user']['fullName']  # Using name entered by Physician on invite instead.
    fitbit_id = response["user"]["encodedId"]

    try:
        invite = PatientInvite.objects.get(id=invite_id)
        if not invite.accepted:
            invite.accepted = True
            PatientInvite.delete(invite)

            try:
                existing_patient = Patient.objects.get(slug=fitbit_id)
                existing_patient.token = token["access_token"]
                existing_patient.refresh = token["refresh_token"]
                existing_patient.save()
                new_patient = existing_patient

            except DoesNotExist:
                new_patient = Patient(
                    slug=fitbit_id,
                    first_name=invite.first_name,
                    last_name=invite.last_name,
                    email=invite.email,
                    token=token["access_token"],
                    refresh=token["refresh_token"],
                    date_joined=datetime.now(),
                    health_data_per_day=[],
                    date_last_data_fetch="",
                )
                new_patient.save()

                # By default, get 5 days worth of data for the brand new patient
                new_patient_data = PatientData(new_patient)
                PatientData.get_heart_rate_data_for_x_days(new_patient_data, 5)
                PatientData.get_activity_data_for_x_days(new_patient_data, 5)

            # Now save this patient to the inviting physician's list of patients.
            inviting_physician = invite.inviting_physician
            inviting_physician.patients.append(new_patient)
            inviting_physician.save()

            # Now attach a generic config to Patient for the Physician to edit later
            min_hr_default = {"value": 50, "window": 15}  # BPS / minute
            max_hr_default = {"value": 110, "window": 15}  # BPS / minute
            min_steps_default = {"value": 500, "window": 60 * 12}  # steps / 12 hr
            max_steps_default = {"value": 5000, "window": 60}  # steps / 1 hr
            config = PatientConfig(
                minHR=min_hr_default,
                maxHR=max_hr_default,
                minSteps=min_steps_default,
                maxSteps=max_steps_default,
                patient=new_patient,
            )
            inviting_physician.patient_config.append(config)
            inviting_physician.save()

            return redirect("/patient-registered?name=" + invite.first_name)
        else:
            flash("It appears you've already confirmed this account.", "warning")
            return redirect("/")

    except DoesNotExist as e:
        flash(e.__str__(), "warning")
        return redirect("/")
Exemple #3
0
def drop():
    from recover.models import Patient, User, PatientInvite
    PatientInvite.drop_collection()
    Patient.drop_collection()
    User.drop_collection()