63 lines
3.0 KiB
Python
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}
|