Kazeia-central/kazeia_central/features/medical/patients/service.py

63 lines
3.0 KiB
Python

"""Service Patients (médical) : dossier clinique chiffré côté central + profils
on-device pilotés par RPC (profile_dump/upsert base64-JSON, vc19).
Séparation stricte : la **fiche clinique** (identité/contact/clinique) est PII santé
→ elle reste chiffrée sur le PC, jamais poussée sur la tablette. Seul l'**opérationnel**
(langue, voix, prompt) vit sur le profil on-device et se pousse via `profile_upsert`.
"""
from __future__ import annotations
from typing import Any
from kazeia_central.core.adb import Adb
from kazeia_central.core.provider import ProviderClient
from kazeia_central.core.store import Store
def list_patients(adb: Adb, store: Store, serial: str) -> list[dict[str, Any]]:
"""Profils on-device de la tablette croisés avec le dossier clinique central."""
profs = ProviderClient(adb, serial).profiles()
fiches = store.fiches(serial) if store.is_unlocked else {}
out = []
for p in profs:
f = fiches.get(p.id, {})
civil = (f.get("fiche") or {}).get("civil") or {}
out.append({
"profile_id": p.id, "display_name": p.display_name, "voice_id": p.voice_id,
"has_pin": p.has_pin, "is_default": p.is_default, "turn_count": p.turn_count,
"has_fiche": bool(f.get("fiche")), "language": f.get("language"),
"full_name": civil.get("full_name"),
})
return out
def get_patient(adb: Adb, store: Store, serial: str, profile_id: str) -> dict[str, Any]:
"""Détail : profil on-device riche (prompt/langue via profile_dump) + fiche clinique."""
prof = ProviderClient(adb, serial).profile_dump(profile_id)
rec = store.fiche(serial, profile_id) or {}
return {"profile": prof, "fiche": rec.get("fiche") or {},
"language": rec.get("language") or prof.get("language")}
def save_fiche(store: Store, serial: str, profile_id: str, fiche: dict, language: str | None,
*, now: int, actor: str | None = None) -> dict[str, Any]:
"""Enregistre la fiche clinique chiffrée côté central (ne touche PAS la tablette)."""
store.save_fiche(serial, profile_id, fiche, language, now=now)
store.audit("patient_fiche_saved", actor=actor, target=f"{serial}/{profile_id}", now=now)
return {"ok": True, "profile_id": profile_id}
def set_language(adb: Adb, store: Store, serial: str, profile_id: str, language: str,
*, now: int, actor: str | None = None) -> dict[str, Any]:
"""Pousse la langue sur le profil on-device (profile_dump → +language →
profile_upsert ; PIN absent = inchangé) et la reflète dans le dossier central."""
c = ProviderClient(adb, serial)
prof = c.profile_dump(profile_id)
prof["language"] = language
c.profile_upsert(prof)
store.set_fiche_language(serial, profile_id, language, now=now)
store.audit("patient_language_set", actor=actor, target=f"{serial}/{profile_id}",
detail={"language": language}, now=now)
return {"profile_id": profile_id, "language": language, "pushed": True}