AidAILine / med_tracker.py
J-Barrert's picture
Upload 14 files
585cfd5 verified
Raw
History Blame Contribute Delete
4.24 kB
"""
med_tracker.py — Medication CRUD with persistent JSON storage.
Each record is scoped to a care profile via profile_id.
"""
from __future__ import annotations
import json
import os
import uuid
from datetime import datetime
from typing import List, Dict, Any, Optional
from config import MEDICATIONS_JSON
def _load() -> List[Dict[str, Any]]:
if MEDICATIONS_JSON.exists():
try:
with open(MEDICATIONS_JSON, "r", encoding="utf-8") as f:
return json.load(f)
except Exception:
return []
return []
def _save(meds: List[Dict[str, Any]]):
MEDICATIONS_JSON.parent.mkdir(parents=True, exist_ok=True)
with open(MEDICATIONS_JSON, "w", encoding="utf-8") as f:
json.dump(meds, f, indent=2, ensure_ascii=False)
f.flush()
os.fsync(f.fileno())
def _new_id() -> str:
return str(uuid.uuid4())
def _now() -> str:
return datetime.now().isoformat(timespec="seconds")
def _for_profile(meds: List[Dict[str, Any]], profile_id: Optional[str]) -> List[Dict[str, Any]]:
if not profile_id:
return []
return [m for m in meds if m.get("profile_id") == profile_id]
def add_medication(
name: str,
dosage: str = "",
frequency: str = "",
status: str = "current",
side_effects: str = "",
personal_notes: str = "",
category: str = "",
profile_id: str = "",
) -> Dict[str, Any]:
"""Add a new medication for profile_id. status: current | past."""
if not profile_id:
raise ValueError("No active care profile.")
if not name.strip():
raise ValueError("Medication name is required.")
status = status if status in ("current", "past") else "current"
med = {
"id": _new_id(),
"profile_id": profile_id,
"name": name.strip(),
"dosage": dosage.strip(),
"frequency": frequency.strip(),
"status": status,
"side_effects": side_effects.strip(),
"personal_notes": personal_notes.strip(),
"category": category.strip(),
"created_at": _now(),
"updated_at": _now(),
}
meds = _load()
meds.append(med)
_save(meds)
return med
def edit_medication(
med_id: str,
name: Optional[str] = None,
dosage: Optional[str] = None,
frequency: Optional[str] = None,
status: Optional[str] = None,
side_effects: Optional[str] = None,
personal_notes: Optional[str] = None,
category: Optional[str] = None,
) -> Optional[Dict[str, Any]]:
meds = _load()
for med in meds:
if med["id"] == med_id:
if name is not None:
med["name"] = name.strip()
if dosage is not None:
med["dosage"] = dosage.strip()
if frequency is not None:
med["frequency"] = frequency.strip()
if status is not None and status in ("current", "past"):
med["status"] = status
if side_effects is not None:
med["side_effects"] = side_effects.strip()
if personal_notes is not None:
med["personal_notes"] = personal_notes.strip()
if category is not None:
med["category"] = category.strip()
med["updated_at"] = _now()
_save(meds)
return med
return None
def delete_medication(med_id: str) -> bool:
meds = _load()
new_meds = [m for m in meds if m["id"] != med_id]
if len(new_meds) == len(meds):
return False
_save(new_meds)
return True
def get_medications(filter: str = "all", profile_id: Optional[str] = None) -> List[Dict[str, Any]]:
meds = _for_profile(_load(), profile_id)
if filter in ("current", "past"):
meds = [m for m in meds if m.get("status") == filter]
return sorted(meds, key=lambda m: m.get("name", "").lower())
def get_medication_by_id(med_id: str) -> Optional[Dict[str, Any]]:
for m in _load():
if m["id"] == med_id:
return m
return None
def delete_for_profile(profile_id: str) -> int:
meds = _load()
kept = [m for m in meds if m.get("profile_id") != profile_id]
deleted = len(meds) - len(kept)
if deleted:
_save(kept)
return deleted