Example #1
0
def servicelist():
    conn = get_db()
    cur = conn.cursor()
    cur.execute("""
        (SELECT id,
                name,
                type,
                active,
                (SELECT type AS othertype
                 FROM   service
                 WHERE  type != 'NF9132'
                 LIMIT  1) AS othertype
         FROM   service
         WHERE  type = 'NF9132'
         UNION
         SELECT id,
                name,
                type,
                active,
                (SELECT type AS othertype
                 FROM   service
                 WHERE  type != 'NF9133'
                 LIMIT  1) AS othertype
         FROM   service
         WHERE  type = 'NF9133')
        ORDER  BY id ASC;""")
    results = cur.fetchall()
    slist = [{
        "id": x[0],
        "name": x[1],
        "type": x[2],
        "active": x[3],
        "othertype": x[4]
    } for x in results]
    return render_template("servicelist.html", servicelist=slist)
Example #2
0
def service():
    if request.args.get("id") is None or request.args.get("action") is None:
        # dbg("MISSING ARGS")
        return redirect(url_for("servicelist"))
    else:
        service_id = int(request.args.get("id"))
        action = request.args.get("action")
    conn = get_db()
    cur = conn.cursor()
    cur.execute("SELECT id, name FROM service WHERE id=%s ORDER BY id ASC",
                (service_id, ))
    slist = [{"id": x[0], "name": x[1]} for x in cur.fetchall()]
    service = slist[0]
    # dbg(slist)
    msg = f"Setting '{service['name']}' (id #{service['id']}) to"
    if action == "activate":
        cur.execute("UPDATE service set active = true where id = %s",
                    (str(service_id), ))
        conn.commit()
        msg += " ACTIVE"
    elif action == "deactivate":
        cur.execute("UPDATE service set active = false where id = %s",
                    (str(service_id), ))
        conn.commit()
        msg += " INACTIVE"
    elif action == "set_type":
        newtype = request.args.get("newtype")
        cur.execute("UPDATE service set type = %s where id = %s",
                    (newtype, str(service_id)))
        conn.commit()
        msg += f" Night float list '{newtype}'"
    # dbg({"msg": msg, "service": service, "slist": slist})
    cur.close()
    conn.close()
    return render_template("service.html", msg=msg, service=service)
Example #3
0
def get_callback_number(nflist):
    """Get the phone number to text if there are missing signouts for a given list.

    :param str nflist: the night float list to get the callback number for (ex: "NF9132")

    :returns: The twilio_formatted callback to text (ex: '+13128675309')
    :rtype: str
    """

    conn = get_db()
    cur = conn.cursor()
    dayofyear = datetime.datetime.today().timetuple().tm_yday
    cur.execute(
        """ SELECT callback
              FROM assignments
             INNER JOIN nightfloat
                ON assignments.nightfloat = nightfloat.id
             WHERE dayofyear = %s
               AND type = %s""",
        (dayofyear, nflist),
    )
    callback = cur.fetchall()
    if len(callback) > 0:
        callback = callback[0][0]
    else:
        callback = "+17732403395"
    cur.close()
    conn.close()
    if app.config["DEBUG_CALLBACKS"]:
        print(
            "DEBUG_CALLBACKS set -- would have returned '%s' but returning '%s' instead"
            % (callback, app.config["DEBUG_TARGET_NUMBER"]))
        callback = app.config["DEBUG_TARGET_NUMBER"]
    return callback
Example #4
0
def notify_late_signup(signout_id, notify=True):
    """TODO: Send a text message to night float indicating that a 'late' addition
    to the signout list has occured

    :param int signout_id: DB id of the late signup

    :returns: none

    """
    conn = get_db()
    cur = conn.cursor()
    cur.execute(
        """
        SELECT intern_name,
               service.name,
               intern_callback,
               TYPE
          FROM signout
         INNER JOIN service
            ON signout.service = service.id
         WHERE signout.id = %s """,
        (signout_id, ),
    )
    results = cur.fetchall()[0]
    cur.close()
    conn.close()

    if (app.config["twilio_sid"] == "" or app.config["twilio_auth_token"] == ""
            or app.config["twilio_number"] == "+"):
        print(
            "Skipping notifications as twilio configuration not set in dbsettings.json"
        )
        return

    callback_number = get_callback_number(results[3])
    client = Client(app.config["twilio_sid"], app.config["twilio_auth_token"])
    body = (
        f"Notifying that the list {results[1]} was added when all other " +
        f"callbacks were complete.  Please call back {results[0]} at {results[2]}"
    )
    if app.config["DEBUG_PRINT_NOT_MESSAGE"] == 0 and notify:
        client.messages.create(to=callback_number,
                               from_=app.config["twilio_number"],
                               body=body)
    elif not notify:
        print(
            f"DEBUG_PRINT: Since notify=True, printing message rather than sending: {body}"
        )
    else:
        print(
            f"DEBUG_PRINT: Since DEBUG_PRINT_NOT_MESSAGE > 0, printing message rather than sending: {body}"
        )
Example #5
0
def addservice():
    if request.method == "GET":
        return render_template("addservice.html")
    conn = get_db()
    cur = conn.cursor()
    cur.execute(
        "INSERT INTO SERVICE (name, type) VALUES (%s, %s) RETURNING id",
        (request.form["name"], request.form["nflist"]),
    )
    cur.fetchone()[0]
    conn.commit()
    conn.close()
    return redirect(url_for("servicelist"))
Example #6
0
def start_signout():
    signout_id = 0
    if request.args.get("id") is None:
        return "ERROR: Tried to start signout without an id query parameter for which signout db entry"
    try:
        signout_id = request.args.get("id")
        conn = get_db()
        cur = conn.cursor()
        cur.execute(
            "UPDATE signout set starttime=current_timestamp where id=%s" %
            str(signout_id))
        conn.commit()
        cur.close()
        conn.close()
        return json.dumps({"id": signout_id, "status": "OK"})
    except Exception:
        return json.dumps({"id": signout_id, "status": "ERROR"})
Example #7
0
def get_missing_signouts(nflist):
    """Get the active signouts that have not yet happened for the current day.

    :param str nflist: the night float list to get the missing signouts for (ex: "NF9132")

    :returns: a list of strings representing the names of the lists that haven't
        been signed out yet (ex: ["Breast, APP", "STR, Intern #1"]) or None if
        all lists are signed out
    :rtype: [str]

    """
    conn = get_db()
    cur = conn.cursor()
    cur.execute(
        """
        SELECT id, name
          FROM service
         WHERE active IS true
           AND type = %s
           AND id NOT IN (
                SELECT service
                  FROM signout
                 INNER JOIN service
                    ON signout.service = service.id
                 WHERE date_part('day', addtime) = date_part('day', current_timestamp)
                   AND date_part('month', addtime) = date_part('month', current_timestamp)
                   AND date_part('year', addtime) = date_part('year', current_timestamp)
                   AND type = %s
               );""",
        (nflist, nflist),
    )
    results = cur.fetchall()
    cur.close()
    conn.close()
    if len(results) == 0:
        return None
    return [x[1] for x in results]
Example #8
0
def submission_weekday():
    conn = get_db()
    if request.method == "GET":
        cur = conn.cursor()
        cur.execute("""
            SELECT id,
                   name
              FROM service
             WHERE TYPE='NF9132'
               AND active='t'
             ORDER BY name ASC
            """)
        solid_services = [{"id": x[0], "name": x[1]} for x in cur.fetchall()]
        cur.execute("""
            SELECT id,
                   name
              FROM service
             WHERE TYPE='NF9133'
               AND active='t'
             ORDER BY name ASC""")
        liquid_services = [{"id": x[0], "name": x[1]} for x in cur.fetchall()]
        cur.execute("""
            SELECT intern_name,
                   name,
                   addtime::TIMESTAMP::TIME,
                   signout.active,
                   completetime - starttime AS elapsedtime
              FROM signout
              LEFT JOIN service
                ON signout.service = service.id
             WHERE date_part('day', addtime) = date_part('day', CURRENT_TIMESTAMP)
               AND date_part('month', addtime) = date_part('month', CURRENT_TIMESTAMP)
               AND date_part('year', addtime) = date_part('year', CURRENT_TIMESTAMP)
               AND oncall IS FALSE
               AND TYPE = 'NF9132'
             ORDER BY addtime ASC""")
        noncall_solid_interns = [{
            "intern_name":
            x[0],
            "name":
            x[1],
            "addtime":
            fix_earlytimes(CLEANUP_TIMESTAMP.sub(".\\1", str(x[2]))),
            "active":
            x[3],
            "fgcolor":
            get_foreground_color(x[3]),
            "elapsedtime":
            format_timestamp(str(x[4])),
        } for x in cur.fetchall()]
        cur.execute("""
            SELECT intern_name,
                   name,
                   addtime::TIMESTAMP::TIME,
                   signout.active,
                   completetime - starttime AS elapsedtime
              FROM signout
              LEFT JOIN service
                ON signout.service = service.id
             WHERE date_part('day', addtime) = date_part('day', CURRENT_TIMESTAMP)
               AND date_part('month', addtime) = date_part('month', CURRENT_TIMESTAMP)
               AND date_part('year', addtime) = date_part('year', CURRENT_TIMESTAMP)
               AND oncall IS TRUE
               AND TYPE = 'NF9132'
             ORDER BY addtime ASC""")
        call_solid_interns = [{
            "intern_name":
            x[0],
            "name":
            x[1],
            "addtime":
            fix_earlytimes(CLEANUP_TIMESTAMP.sub(".\\1", str(x[2]))),
            "active":
            x[3],
            "fgcolor":
            get_foreground_color(x[3]),
            "elapsedtime":
            format_timestamp(str(x[4])),
        } for x in cur.fetchall()]
        cur.execute("""
            SELECT intern_name,
                   name,
                   addtime::TIMESTAMP::TIME,
                   signout.active,
                   completetime - starttime AS elapsedtime
              FROM signout
              LEFT JOIN service
                ON signout.service = service.id
             WHERE date_part('day', addtime) = date_part('day', CURRENT_TIMESTAMP)
               AND date_part('month', addtime) = date_part('month', CURRENT_TIMESTAMP)
               AND date_part('year', addtime) = date_part('year', CURRENT_TIMESTAMP)
               AND oncall IS FALSE
               AND TYPE = 'NF9133'
             ORDER BY addtime ASC""")
        noncall_liquid_interns = gen_med_sorter([{
            "intern_name":
            x[0],
            "name":
            x[1],
            "addtime":
            fix_earlytimes(CLEANUP_TIMESTAMP.sub(".\\1", str(x[2]))),
            "active":
            x[3],
            "fgcolor":
            get_foreground_color(x[3]),
            "elapsedtime":
            format_timestamp(str(x[4])),
        } for x in cur.fetchall()])
        cur.execute("""
            SELECT intern_name,
                   name,
                   addtime::TIMESTAMP::TIME,
                   signout.active,
                   completetime - starttime AS elapsedtime
              FROM signout
              LEFT JOIN service
                ON signout.service = service.id
             WHERE date_part('day', addtime) = date_part('day', CURRENT_TIMESTAMP)
               AND date_part('month', addtime) = date_part('month', CURRENT_TIMESTAMP)
               AND date_part('year', addtime) = date_part('year', CURRENT_TIMESTAMP)
               AND oncall IS TRUE
               AND TYPE = 'NF9133'
             ORDER BY addtime ASC""")
        call_liquid_interns = [{
            "intern_name":
            x[0],
            "name":
            x[1],
            "addtime":
            fix_earlytimes(CLEANUP_TIMESTAMP.sub(".\\1", str(x[2]))),
            "active":
            x[3],
            "fgcolor":
            get_foreground_color(x[3]),
            "elapsedtime":
            format_timestamp(str(x[4])),
        } for x in cur.fetchall()]
        cur.close()
        conn.close()
        return render_template(
            "submission.html",
            solid_services=solid_services,
            liquid_services=liquid_services,
            noncall_solid_interns=noncall_solid_interns,
            call_solid_interns=call_solid_interns,
            noncall_liquid_interns=noncall_liquid_interns,
            call_liquid_interns=call_liquid_interns,
        )
    else:
        cur = conn.cursor()
        if request.form.getlist("service") is None:
            # This should never happen
            return render_template("received.html")
        # dbg(request.form)
        # dbg(request.form.getlist("service"))
        for serviceid in request.form.getlist("service"):
            cur.execute(
                """
                INSERT INTO signout (intern_name, intern_callback, service, oncall, ipaddress, hosttimestamp)
                VALUES (%s, %s, %s, %s, %s, %s) RETURNING id;""",
                (
                    request.form["intern_name"],
                    request.form["intern_callback"],
                    serviceid,
                    request.form["oncall"],
                    request.remote_addr,
                    request.form["hosttimestamp"],
                ),
            )
            callback_id = cur.fetchone()[0]
            conn.commit()
        cur.execute("SELECT type FROM service WHERE id = %s", (serviceid, ))
        nflist = cur.fetchall()[0][0]
        cur.execute(
            """
            SELECT count(distinct(hosttimestamp, intern_name))
              FROM signout
             INNER JOIN service
                ON signout.service = service.id
             WHERE date_part('day', addtime) = date_part('day', CURRENT_TIMESTAMP)
               AND date_part('month', addtime) = date_part('month', CURRENT_TIMESTAMP)
               AND date_part('year', addtime) = date_part('year', CURRENT_TIMESTAMP)
               AND signout.active = 't'
               AND service.type = %s;""",
            (nflist, ),
        )
        count = cur.fetchall()[0][0]
        cur.close()
        conn.close()
        timenow = datetime.datetime.now()
        if count < 2:
            if ((timenow.hour == 19 and timenow.minute > 30)
                    or (timenow.hour > 19) or (timenow.hour < 12)):
                notify_late_signup(callback_id)
        return render_template("received.html")
Example #9
0
def query():
    conn = get_db()
    if request.method == "GET":
        cur = conn.cursor()
        rangestring = "Showing signouts for %s" % (
            datetime.date.today() -
            datetime.timedelta(days=1)).strftime("%m-%d-%Y")
        cur.execute("""
            SELECT intern_name,
                   name,
                   TYPE,
                   addtime::TIMESTAMP::TIME,
                   starttime::TIMESTAMP,
                   completetime::TIMESTAMP,
                   addtime::TIMESTAMP::DATE AS adddate
              FROM signout
              LEFT JOIN service
                ON signout.service = service.id
             WHERE date_part('day', addtime) = date_part('day', CURRENT_TIMESTAMP - interval '1 day')
               AND date_part('month', addtime) = date_part('month', CURRENT_TIMESTAMP)
               AND date_part('year', addtime) = date_part('year', CURRENT_TIMESTAMP)
             ORDER BY completetime ASC""")
        signoutlog = [{
            "intern_name":
            x[0],
            "name":
            x[1],
            "type":
            x[2],
            "addtime":
            fix_earlytimes(CLEANUP_TIMESTAMP.sub(".\\1", str(x[3]))),
            "starttime":
            x[4],
            "completetime":
            x[5],
            "adddate":
            x[6].strftime("%m-%d-%Y"),
            "elapsedtime":
            "",
        } for x in cur.fetchall()]
        for idx in range(len(signoutlog)):
            sout = signoutlog[idx]
            try:
                timediff = sout["completetime"] - sout["starttime"]
                elapsed_minutes = int(timediff.seconds / 60)
                elapsed_seconds = timediff.seconds % 60
                sout["elapsedtime"] = "%i:%02d" % (elapsed_minutes,
                                                   elapsed_seconds)
            except Exception:
                sout["elapsedtime"] = "Unable to be computed"
            if sout["starttime"] != None:
                sout["starttime"] = CLEANUP_TIMESTAMP.sub(
                    "", str(sout["starttime"].time()))
            else:
                sout["starttime"] = ""
            if sout["completetime"] != None:
                sout["completetime"] = CLEANUP_TIMESTAMP.sub(
                    "", str(sout["completetime"].time()))
            else:
                sout["completetime"] = ""
        cur.close()
        conn.close()
        return render_template("query.html",
                               signoutlog=signoutlog,
                               rangestring=rangestring)
    else:
        cur = conn.cursor()
        if "NF9133" in request.form.keys():
            if "NF9132" in request.form.keys():
                typestring = ""
            else:
                typestring = " AND type = 'NF9133' "
        else:
            if "NF9132" in request.form.keys():
                typestring = " AND type = 'NF9132' "
            else:
                typestring = " AND type = 'notarealtype' "
        if request.form["addtime_date2"] == "":
            rangestring = "Showing signouts for %s" % request.form[
                "addtime_date"]
            splitdate = cleanup_date_input(
                request.form["addtime_date"]).split("-")
            cur.execute("""
                SELECT intern_name,
                       name,
                       TYPE,
                       addtime::TIMESTAMP::TIME,
                       starttime::TIMESTAMP,
                       completetime::TIMESTAMP,
                       addtime::TIMESTAMP::DATE AS adddate
                  FROM signout
                  LEFT JOIN service
                    ON signout.service = service.id
                 WHERE date_part('day', addtime) = %s
                   AND date_part('month', addtime) = %s
                   AND date_part('year', addtime) = %s %s
                 ORDER BY completetime ASC
                """ % (splitdate[2], splitdate[1], splitdate[0], typestring))
            # dbg(cur.query)
        else:
            rangestring = "Showing signouts from %s to %s inclusive" % (
                request.form["addtime_date"],
                request.form["addtime_date2"],
            )
            splitdate = cleanup_date_input(
                request.form["addtime_date"]).split("-")
            splitenddate = cleanup_date_input(
                request.form["addtime_date2"]).split("-")
            cur.execute("""
                SELECT intern_name,
                       name,
                       TYPE,
                       addtime::TIMESTAMP::TIME,
                       starttime::TIMESTAMP,
                       completetime::TIMESTAMP,
                       addtime::TIMESTAMP::DATE AS adddate
                  FROM signout
                  LEFT JOIN service
                    ON signout.service = service.id
                 WHERE addtime BETWEEN '""" + "-".join(splitdate) +
                        """' and '""" + "-".join(splitenddate) + """'
                ORDER BY completetime ASC""")
            # dbg(cur.query)
        signoutlog = [{
            "intern_name":
            x[0],
            "name":
            x[1],
            "type":
            x[2],
            "addtime":
            fix_earlytimes(CLEANUP_TIMESTAMP.sub("", str(x[3]))),
            "starttime":
            x[4],
            "completetime":
            x[5],
            "adddate":
            x[6].strftime("%m-%d-%Y"),
            "elapsedtime":
            "",
        } for x in cur.fetchall()]
        for idx in range(len(signoutlog)):
            sout = signoutlog[idx]
            try:
                timediff = sout["completetime"] - sout["starttime"]
                elapsed_minutes = int(timediff.seconds / 60)
                elapsed_seconds = timediff.seconds % 60
                sout["elapsedtime"] = "%i:%02d" % (elapsed_minutes,
                                                   elapsed_seconds)
            except Exception:
                sout["elapsedtime"] = "Unable to be computed"
            if sout["starttime"] != None:
                sout["starttime"] = CLEANUP_TIMESTAMP.sub(
                    "", str(sout["starttime"].time()))
            else:
                sout["starttime"] = ""
            if sout["completetime"] != None:
                sout["completetime"] = CLEANUP_TIMESTAMP.sub(
                    "", str(sout["completetime"].time()))
            else:
                sout["completetime"] = ""
            signoutlog[idx] = sout
        cur.close()
        conn.close()
        return render_template("query.html",
                               signoutlog=signoutlog,
                               rangestring=rangestring)
Example #10
0
def nightfloat():
    if request.args.get("list") is None:
        listtype = "NF9132"
    else:
        listtype = request.args.get("list")
        # TODO: This is sort of dangerous.  Should do differently
    conn = get_db()
    if request.method == "GET":
        cur = conn.cursor()
        cur.execute("""
                      SELECT signout.id,
                             intern_name,
                             name,
                             intern_callback
                        FROM signout
                        LEFT JOIN service
                          ON signout.service = service.id
                       WHERE signout.active IS TRUE
                         AND TYPE = '%s'
                         AND date_part('day', addtime) = date_part('day', CURRENT_TIMESTAMP)
                         AND date_part('month', addtime) = date_part('month', CURRENT_TIMESTAMP)
                         AND date_part('year', addtime) = date_part('year', CURRENT_TIMESTAMP)
                       ORDER BY addtime ASC""" % listtype.upper())
        waiting_interns = gen_med_sorter([{
            "id": x[0],
            "intern_name": x[1],
            "name": x[2],
            "intern_callback": x[3]
        } for x in cur.fetchall()])
        cur.execute("""
                    SELECT intern_name,
                           name,
                           intern_callback
                      FROM signout
                      LEFT JOIN service
                        ON signout.service = service.id
                     WHERE signout.active IS FALSE
                       AND TYPE = '%s'
                       AND date_part('day', addtime) = date_part('day', CURRENT_TIMESTAMP)
                       AND date_part('month', addtime) = date_part('month', CURRENT_TIMESTAMP)
                       AND date_part('year', addtime) = date_part('year', CURRENT_TIMESTAMP)
                     ORDER BY completetime ASC
                    """ % listtype.upper())
        completed_interns = [{
            "intern_name": x[0],
            "name": x[1],
            "intern_callback": x[2]
        } for x in cur.fetchall()]
        cur.close()
        conn.close()
        return render_template(
            "nightfloat.html",
            waiting_interns=waiting_interns,
            completed_interns=completed_interns,
            type=listtype,
            querystring="?list=" + listtype,
        )
    cur = conn.cursor()
    cur.execute("""
        UPDATE signout
           SET active = FALSE,
               completetime = CURRENT_TIMESTAMP
         WHERE id = %s""" % request.form["signout.id"])
    conn.commit()
    cur.close()
    conn.close()
    return render_template("removed.html", type=listtype)