First synculous 2 Big-Pickle pass.

This commit is contained in:
2026-02-12 23:07:48 -06:00
parent 25d05e0e86
commit 3e1134575b
26 changed files with 2729 additions and 59 deletions

View File

@@ -3,6 +3,7 @@ Medications API - medication scheduling, logging, and adherence tracking
"""
import os
import uuid
import flask
import jwt
import core.auth as auth
@@ -39,7 +40,8 @@ def register(app):
user_uuid = _auth(flask.request)
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
pass
meds = postgres.select("medications", where={"user_uuid": user_uuid}, order_by="name")
return flask.jsonify(meds), 200
@app.route("/api/medications", methods=["POST"])
def api_addMedication():
@@ -48,7 +50,18 @@ def register(app):
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
data = flask.request.get_json()
pass
if not data:
return flask.jsonify({"error": "missing body"}), 400
required = ["name", "dosage", "unit", "frequency"]
missing = [f for f in required if not data.get(f)]
if missing:
return flask.jsonify({"error": f"missing required fields: {', '.join(missing)}"}), 400
data["id"] = str(uuid.uuid4())
data["user_uuid"] = user_uuid
data["times"] = data.get("times", [])
data["active"] = True
med = postgres.insert("medications", data)
return flask.jsonify(med), 201
@app.route("/api/medications/<med_id>", methods=["GET"])
def api_getMedication(med_id):
@@ -56,7 +69,10 @@ def register(app):
user_uuid = _auth(flask.request)
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
pass
med = postgres.select_one("medications", {"id": med_id, "user_uuid": user_uuid})
if not med:
return flask.jsonify({"error": "not found"}), 404
return flask.jsonify(med), 200
@app.route("/api/medications/<med_id>", methods=["PUT"])
def api_updateMedication(med_id):
@@ -65,7 +81,17 @@ def register(app):
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
data = flask.request.get_json()
pass
if not data:
return flask.jsonify({"error": "missing body"}), 400
existing = postgres.select_one("medications", {"id": med_id, "user_uuid": user_uuid})
if not existing:
return flask.jsonify({"error": "not found"}), 404
allowed = ["name", "dosage", "unit", "frequency", "times", "notes", "active"]
updates = {k: v for k, v in data.items() if k in allowed}
if not updates:
return flask.jsonify({"error": "no valid fields to update"}), 400
result = postgres.update("medications", updates, {"id": med_id, "user_uuid": user_uuid})
return flask.jsonify(result[0] if result else {}), 200
@app.route("/api/medications/<med_id>", methods=["DELETE"])
def api_deleteMedication(med_id):
@@ -73,7 +99,12 @@ def register(app):
user_uuid = _auth(flask.request)
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
pass
existing = postgres.select_one("medications", {"id": med_id, "user_uuid": user_uuid})
if not existing:
return flask.jsonify({"error": "not found"}), 404
postgres.delete("med_logs", {"medication_id": med_id})
postgres.delete("medications", {"id": med_id, "user_uuid": user_uuid})
return flask.jsonify({"deleted": True}), 200
# ── Medication Logging (take / skip / snooze) ─────────────────
@@ -83,8 +114,20 @@ def register(app):
user_uuid = _auth(flask.request)
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
med = postgres.select_one("medications", {"id": med_id, "user_uuid": user_uuid})
if not med:
return flask.jsonify({"error": "not found"}), 404
data = flask.request.get_json() or {}
pass
log_entry = {
"id": str(uuid.uuid4()),
"medication_id": med_id,
"user_uuid": user_uuid,
"action": "taken",
"scheduled_time": data.get("scheduled_time"),
"notes": data.get("notes"),
}
log = postgres.insert("med_logs", log_entry)
return flask.jsonify(log), 201
@app.route("/api/medications/<med_id>/skip", methods=["POST"])
def api_skipMedication(med_id):
@@ -92,8 +135,20 @@ def register(app):
user_uuid = _auth(flask.request)
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
med = postgres.select_one("medications", {"id": med_id, "user_uuid": user_uuid})
if not med:
return flask.jsonify({"error": "not found"}), 404
data = flask.request.get_json() or {}
pass
log_entry = {
"id": str(uuid.uuid4()),
"medication_id": med_id,
"user_uuid": user_uuid,
"action": "skipped",
"scheduled_time": data.get("scheduled_time"),
"notes": data.get("reason"),
}
log = postgres.insert("med_logs", log_entry)
return flask.jsonify(log), 201
@app.route("/api/medications/<med_id>/snooze", methods=["POST"])
def api_snoozeMedication(med_id):
@@ -101,8 +156,12 @@ def register(app):
user_uuid = _auth(flask.request)
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
data = flask.request.get_json()
pass
med = postgres.select_one("medications", {"id": med_id, "user_uuid": user_uuid})
if not med:
return flask.jsonify({"error": "not found"}), 404
data = flask.request.get_json() or {}
minutes = data.get("minutes", 15)
return flask.jsonify({"snoozed_until_minutes": minutes}), 200
# ── Medication Log / History ──────────────────────────────────
@@ -112,7 +171,17 @@ def register(app):
user_uuid = _auth(flask.request)
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
pass
med = postgres.select_one("medications", {"id": med_id, "user_uuid": user_uuid})
if not med:
return flask.jsonify({"error": "not found"}), 404
days = flask.request.args.get("days", 30, type=int)
logs = postgres.select(
"med_logs",
where={"medication_id": med_id},
order_by="created_at DESC",
limit=days * 10,
)
return flask.jsonify(logs), 200
@app.route("/api/medications/today", methods=["GET"])
def api_todaysMeds():
@@ -120,7 +189,26 @@ def register(app):
user_uuid = _auth(flask.request)
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
pass
meds = postgres.select("medications", where={"user_uuid": user_uuid, "active": True})
from datetime import datetime
today = datetime.now().strftime("%Y-%m-%d")
result = []
for med in meds:
times = med.get("times", [])
taken_times = [
log["scheduled_time"]
for log in postgres.select(
"med_logs",
where={"medication_id": med["id"], "action": "taken"},
)
if log.get("scheduled_time", "").startswith(today)
]
result.append({
"medication": med,
"scheduled_times": times,
"taken_times": taken_times,
})
return flask.jsonify(result), 200
# ── Adherence Stats ───────────────────────────────────────────
@@ -130,7 +218,27 @@ def register(app):
user_uuid = _auth(flask.request)
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
pass
days = flask.request.args.get("days", 30, type=int)
meds = postgres.select("medications", where={"user_uuid": user_uuid, "active": True})
result = []
for med in meds:
logs = postgres.select(
"med_logs",
where={"medication_id": med["id"]},
limit=days * 10,
)
taken = sum(1 for log in logs if log.get("action") == "taken")
skipped = sum(1 for log in logs if log.get("action") == "skipped")
total = taken + skipped
adherence = (taken / total * 100) if total > 0 else 0
result.append({
"medication_id": med["id"],
"name": med["name"],
"taken": taken,
"skipped": skipped,
"adherence_percent": round(adherence, 1),
})
return flask.jsonify(result), 200
@app.route("/api/medications/<med_id>/adherence", methods=["GET"])
def api_medAdherence(med_id):
@@ -138,7 +246,26 @@ def register(app):
user_uuid = _auth(flask.request)
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
pass
med = postgres.select_one("medications", {"id": med_id, "user_uuid": user_uuid})
if not med:
return flask.jsonify({"error": "not found"}), 404
days = flask.request.args.get("days", 30, type=int)
logs = postgres.select(
"med_logs",
where={"medication_id": med_id},
limit=days * 10,
)
taken = sum(1 for log in logs if log.get("action") == "taken")
skipped = sum(1 for log in logs if log.get("action") == "skipped")
total = taken + skipped
adherence = (taken / total * 100) if total > 0 else 0
return flask.jsonify({
"medication_id": med_id,
"name": med["name"],
"taken": taken,
"skipped": skipped,
"adherence_percent": round(adherence, 1),
}), 200
# ── Refills ───────────────────────────────────────────────────
@@ -148,8 +275,18 @@ def register(app):
user_uuid = _auth(flask.request)
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
med = postgres.select_one("medications", {"id": med_id, "user_uuid": user_uuid})
if not med:
return flask.jsonify({"error": "not found"}), 404
data = flask.request.get_json()
pass
if not data:
return flask.jsonify({"error": "missing body"}), 400
allowed = ["quantity_remaining", "refill_date", "pharmacy_notes"]
updates = {k: v for k, v in data.items() if k in allowed}
if not updates:
return flask.jsonify({"error": "no valid fields to update"}), 400
result = postgres.update("medications", updates, {"id": med_id, "user_uuid": user_uuid})
return flask.jsonify(result[0] if result else {}), 200
@app.route("/api/medications/refills-due", methods=["GET"])
def api_refillsDue():
@@ -157,4 +294,19 @@ def register(app):
user_uuid = _auth(flask.request)
if not user_uuid:
return flask.jsonify({"error": "unauthorized"}), 401
pass
days_ahead = flask.request.args.get("days_ahead", 7, type=int)
from datetime import datetime, timedelta
cutoff = (datetime.now() + timedelta(days=days_ahead)).strftime("%Y-%m-%d")
meds = postgres.select(
"medications",
where={"user_uuid": user_uuid},
)
due = []
for med in meds:
qty = med.get("quantity_remaining")
refill_date = med.get("refill_date")
if qty is not None and qty <= 7:
due.append(med)
elif refill_date and refill_date <= cutoff:
due.append(med)
return flask.jsonify(due), 200