Fix issues #6, #7, #11, #12, #13: med reminders, push notifications, auth persistence, scheduling conflicts
- Fix TIME object vs string comparison in scheduler preventing adaptive med reminders from ever firing (#12, #6) - Add frequency filtering to midnight schedule creation for every_n_days meds - Require start_date and interval_days for every_n_days medications - Add refresh token support (30-day) to API and bot for persistent sessions (#13) - Add "trusted device" checkbox to frontend login for long-lived sessions (#7) - Auto-refresh expired tokens in both bot (apiRequest) and frontend (api.ts) - Restore bot sessions from cache on restart using refresh tokens - Duration-aware routine scheduling conflict detection (#11) - Add conflict check when starting routine sessions against medication times - Add diagnostic logging to notification delivery channels Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -145,6 +145,17 @@ def register(app):
|
||||
meds = postgres.select("medications", where={"user_uuid": user_uuid}, order_by="name")
|
||||
return flask.jsonify(meds), 200
|
||||
|
||||
def _time_str_to_minutes(time_str):
|
||||
"""Convert 'HH:MM' to minutes since midnight."""
|
||||
parts = time_str.split(":")
|
||||
return int(parts[0]) * 60 + int(parts[1])
|
||||
|
||||
def _get_routine_duration_minutes(routine_id):
|
||||
"""Get total duration of a routine from its steps."""
|
||||
steps = postgres.select("routine_steps", where={"routine_id": routine_id})
|
||||
total = sum(s.get("duration_minutes", 0) or 0 for s in steps)
|
||||
return max(total, 1)
|
||||
|
||||
def _check_med_schedule_conflicts(user_uuid, new_times, new_days=None, exclude_med_id=None):
|
||||
"""Check if the proposed medication schedule conflicts with existing routines or medications.
|
||||
Returns (has_conflict, conflict_message) tuple.
|
||||
@@ -152,13 +163,23 @@ def register(app):
|
||||
if not new_times:
|
||||
return False, None
|
||||
|
||||
# Check conflicts with routines
|
||||
# Check conflicts with routines (duration-aware)
|
||||
user_routines = postgres.select("routines", {"user_uuid": user_uuid})
|
||||
for r in user_routines:
|
||||
sched = postgres.select_one("routine_schedules", {"routine_id": r["id"]})
|
||||
if sched and sched.get("time") in new_times:
|
||||
routine_days = json.loads(sched.get("days", "[]"))
|
||||
if not new_days or any(d in routine_days for d in new_days):
|
||||
if not sched or not sched.get("time"):
|
||||
continue
|
||||
routine_days = sched.get("days", [])
|
||||
if isinstance(routine_days, str):
|
||||
routine_days = json.loads(routine_days)
|
||||
if new_days and not any(d in routine_days for d in new_days):
|
||||
continue
|
||||
routine_start = _time_str_to_minutes(sched["time"])
|
||||
routine_dur = _get_routine_duration_minutes(r["id"])
|
||||
for t in new_times:
|
||||
med_start = _time_str_to_minutes(t)
|
||||
# Med falls within routine time range
|
||||
if routine_start <= med_start < routine_start + routine_dur:
|
||||
return True, f"Time conflicts with routine: {r.get('name', 'Unnamed routine')}"
|
||||
|
||||
# Check conflicts with other medications
|
||||
@@ -188,6 +209,11 @@ def register(app):
|
||||
if missing:
|
||||
return flask.jsonify({"error": f"missing required fields: {', '.join(missing)}"}), 400
|
||||
|
||||
# Validate every_n_days required fields
|
||||
if data.get("frequency") == "every_n_days":
|
||||
if not data.get("start_date") or not data.get("interval_days"):
|
||||
return flask.jsonify({"error": "every_n_days frequency requires both start_date and interval_days"}), 400
|
||||
|
||||
# Check for schedule conflicts
|
||||
new_times = data.get("times", [])
|
||||
new_days = data.get("days_of_week", [])
|
||||
|
||||
Reference in New Issue
Block a user