#!/usr/bin/env python3 """Seed la DB Room d'un émulateur avec un backup JSON exporté par l'app. OUTIL DE TEST MANUEL (post-v1.3.4) — cf recette complète dans docs/DEVELOPPEMENT.md §16.ter « Test manuel sur émulateur ». Constitue l'étape « données réelles dans l'émulateur » : lance l'APK debug une fois (crée la DB via Room), récupère la DB via run-as, injecte les lignes du backup passé en argument (SANS toucher au schéma ni à room_master_table — Room valide le schéma, pas les lignes), puis la repousse. Usage (le téléphone = émulateur démarré, avec com.hormonetrack - APK DEBUG - installé et lancé au moins une fois) : adb shell am force-stop com.hormonetrack adb shell run-as com.hormonetrack cat databases/hormonetrack.db > /tmp/hrt.db python3 scripts/seed-emulator.py /tmp/hrt.db # modifie la BD locale adb push /tmp/hrt.db /data/local/tmp/hrt.db adb shell run-as com.hormonetrack cp /data/local/tmp/hrt.db databases/hormonetrack.db adb shell run-as com.hormonetrack rm -f databases/hormonetrack.db-wal databases/hormonetrack.db-shm ⚠️ PRIVATITÉ : le fichier backup contient des données de santé personnelles et vit sous `local-test-data/` (gitignoré, cf §8.bis). Ce script ne contains AUCUNE donnée : tout passe par arguments/lignes insérées à l'exécution. Ne JAMAIS copier un backup dans le dépôt ni en nommer dans les commentaires. """ import json import sqlite3 import sys def main(): if len(sys.argv) != 3: sys.exit("usage: seed-emulator.py ") db_path, backup_path = sys.argv[1], sys.argv[2] data = json.load(open(backup_path, encoding="utf-8")) con = sqlite3.connect(db_path) cur = con.cursor() # ⚠️ Les colonnes portent les noms des propriétés Kotlin SANS renommage # (Room ne convertit pas en snake_case) ; les enums sont stockés en String. for tr in data["treatments"]: cur.execute( "INSERT OR REPLACE INTO treatments (id, name, type, route, doseAmount," " doseUnit, isActive, notes, esterType, pkModel, absorptionHours," " eliminationHalfLifeHours, bioavailabilityFraction, scaleFactor," " forecastIntervalDays, reminderHour, reminderMinute, reminderEnabled," " calendarEventId, createdAt)" " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", ( tr["id"], tr["name"], tr["type"], tr["route"], tr["doseAmount"], tr["doseUnit"], tr["isActive"], tr.get("notes"), tr.get("esterType", "NONE"), tr.get("pkModel", "ESE"), tr.get("absorptionHours", 4.0), tr.get("eliminationHalfLifeHours", 24.0), tr.get("bioavailabilityFraction", 1.0), tr.get("scaleFactor", 1.0), tr.get("forecastIntervalDays"), tr.get("reminderHour"), tr.get("reminderMinute"), tr.get("reminderEnabled", False), tr.get("calendarEventId"), tr["createdAt"], ), ) for d in data["doseLogs"]: cur.execute( "INSERT OR REPLACE INTO dose_logs (id, treatmentId, timestamp," " doseAmount, notes, esterType) VALUES (?,?,?,?,?,?)", (d["id"], d["treatmentId"], d["timestamp"], d["doseAmount"], d.get("notes"), d.get("esterType")), ) for l in data["labResults"]: cur.execute( "INSERT OR REPLACE INTO lab_results (id, marker, value, unit," " timestamp, notes) VALUES (?,?,?,?,?,?)", (l["id"], l["marker"], l["value"], l["unit"], l["timestamp"], l.get("notes")), ) con.commit() cur.execute( "SELECT (SELECT COUNT(*) FROM treatments), (SELECT COUNT(*) FROM dose_logs)," " (SELECT COUNT(*) FROM lab_results)") t, d, l = cur.fetchone() print(f"seed OK : {t} traitements, {d} doses, {l} labs") con.close() if __name__ == "__main__": main()