Exemplo n.º 1
0
def patient_profile(slug):
    """
    Renders a detailed view of a selected patient's profile.
    Corresponding html file is in `recover/templates/patients/profile.html`
    :param slug: A unique id associated with a given patient.
    """

    patient = Patient.objects.get_or_404(slug=slug)
    today = datetime.datetime.today()
    end = today
    start = end - datetime.timedelta(days=1)
    try:
        last_pull = patient.date_last_data_fetch
        if last_pull != today.isoformat()[0:10]:
            today = today
            last = datetime.datetime.strptime(last_pull, '%Y-%m-%d')
            days = (today - last).days
            patient_data = PatientData(patient)
            PatientData.get_heart_rate_data_for_x_days(patient_data, days)
            PatientData.get_activity_data_for_x_days(patient_data, days)
        resting_hr = 0
        HRdata = {}
        HRaverage = {}
        StepsData = {}
        ave_count = 0
        for i in range(0, len(patient[DAILY_DATA])):
            HRdata.update(patient[DAILY_DATA][i][HR])
            StepsData.update(patient[DAILY_DATA][i][STEPS])
            try:
                resting_hr += patient[DAILY_DATA][i][RESTING_HR]
                ave_count += 1
            except TypeError:
                pass
            HRaverage[patient[DAILY_DATA][i]['date']] = patient[DAILY_DATA][i][RESTING_HR]
        try:
            resting_hr /= ave_count
        except ZeroDivisionError:
            pass

    except (KeyError, IndexError):
        p = PatientData(patient)
        if p.get_heart_rate_data_for_day():
            resting_hr = patient[DAILY_DATA][-1][HR]
            HRdata = patient[DAILY_DATA][-1][HR]
        else:
            resting_hr = "No Data."
            HRdata = "No Data."

    try:
        last_worn = datetime.datetime.strptime(patient.date_last_worn(), "%Y-%m-%d")
        last_worn = last_worn.strftime('%b %-d, %Y')
    except Exception as e:
        last_worn = e.message
    return render_template('patients/profile.html', patient=patient, resting=resting_hr, HRaverage=HRaverage,
                           HRdata=HRdata, StepsData=StepsData, start=start, end=end,
                           alerts=unread_alerts(patient.id), config=config_for_patient(patient.id),
                           last_worn=last_worn, all_alerts=all_alerts(patient.id))
Exemplo n.º 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("/")