From 484cd4f10a7b136a250cd98dd8f0255d49e55d7d Mon Sep 17 00:00:00 2001 From: Vladimir Buzalka Date: Thu, 14 May 2026 07:34:03 +0200 Subject: [PATCH] notebookvb --- Knihovny/medicus_db.py | 7 +- Medevio/80 Pacienti/bulk_set_removed.py | 179 ++++++++++++++++++++++++ Medevio/medevio_api_notes.md | 34 +++++ 3 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 Medevio/80 Pacienti/bulk_set_removed.py diff --git a/Knihovny/medicus_db.py b/Knihovny/medicus_db.py index 6c58171..f8c182d 100644 --- a/Knihovny/medicus_db.py +++ b/Knihovny/medicus_db.py @@ -9,9 +9,10 @@ def get_medicus_connection(): """ computer_name = socket.gethostname().upper() dsn_map = { - "LEKAR": r"localhost:M:\medicus\data\medicus.fdb", - "SESTRA": r"192.168.1.10:m:\medicus\data\medicus.fdb", - "LENOVO": r"192.168.1.10:m:\medicus\data\medicus.fdb", + "LEKAR": r"localhost:M:\medicus\data\medicus.fdb", + "SESTRA": r"192.168.1.10:m:\medicus\data\medicus.fdb", + "LENOVO": r"192.168.1.10:m:\medicus\data\medicus.fdb", + "NTBVBHP470G10": r"localhost:c:\medicus 3\data\medicus.fdb", } dsn = dsn_map.get(computer_name, r"localhost:c:\medicus 3\data\medicus.fdb") print(f"[medicus_db] Připojuji se jako {computer_name} → {dsn}") diff --git a/Medevio/80 Pacienti/bulk_set_removed.py b/Medevio/80 Pacienti/bulk_set_removed.py new file mode 100644 index 0000000..57b90f3 --- /dev/null +++ b/Medevio/80 Pacienti/bulk_set_removed.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Hromadně změní status na REMOVED pro pacienty, kteří: + - jsou ACTIVE v Medevio (medevio_pacient.status = 'ACTIVE') + - nemají Medevio účet (user_id IS NULL) + - nejsou registrovaní u lékaře v Medicusu (Firebird DB) + +Spustit po sync_patients_to_mysql.py (data musí být čerstvá). +Token: Medevio/token.txt +""" + +import sys +try: + sys.stdout.reconfigure(encoding="utf-8") + sys.stderr.reconfigure(encoding="utf-8") +except AttributeError: + import io + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8") + sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8") + +sys.path.insert(0, 'U:/OrdinaceProjekt') + +import time +import pymysql +import requests +from pathlib import Path +from Knihovny.medicus_db import get_medicus_db + +# ==================== CONFIG ==================== +GRAPHQL_URL = "https://api.medevio.cz/graphql" +CLINIC_SLUG = "mudr-buzalkova" +DELAY = 0.5 # sekundy mezi voláními API +DRY_RUN = True # True = jen výpis, False = skutečná změna + +TOKEN_PATH = Path(__file__).resolve().parent.parent / "token.txt" + +DB_CONFIG = { + "host": "192.168.1.76", + "port": 3306, + "user": "root", + "password": "Vlado9674+", + "database": "medevio", + "charset": "utf8mb4", + "cursorclass": pymysql.cursors.DictCursor, +} + +MUTATION = """ +mutation ClinicPatientEditStatusModal_UpdateClinicPatientStatus( + $clinicSlug: String!, $patientId: String!, $status: ClinicPatientStatus! +) { + updated: updateClinicPatientStatus( + clinicSlug: $clinicSlug + patientId: $patientId + status: $status + ) +} +""" + +# ==================== HELPERS ==================== + +def make_headers(token): + return { + "content-type": "application/json", + "authorization": f"Bearer {token}", + "origin": "https://my.medevio.cz", + "referer": "https://my.medevio.cz/", + } + + +def set_patient_removed(headers, patient_id): + payload = { + "operationName": "ClinicPatientEditStatusModal_UpdateClinicPatientStatus", + "query": MUTATION, + "variables": { + "clinicSlug": CLINIC_SLUG, + "patientId": patient_id, + "status": "REMOVED", + }, + } + resp = requests.post(GRAPHQL_URL, headers=headers, json=payload, timeout=20) + resp.raise_for_status() + data = resp.json() + if "errors" in data: + return False, str(data["errors"]) + return data.get("data", {}).get("updated", False), None + + +# ==================== MAIN ==================== + +def main(): + # --- Token --- + token = TOKEN_PATH.read_text(encoding="utf-8").strip() + if token.startswith("Bearer "): + token = token.split(" ", 1)[1] + headers = make_headers(token) + + # --- Načti registrované v Medicusu (rodná čísla) --- + print("Načítám registrované pacienty z Medicusu...") + db = get_medicus_db() + rows = db.get_active_registered_patients() + medicus_rc = {r[0].strip() for r in rows if r[0]} + db.close() + print(f" Registrovaných v Medicusu: {len(medicus_rc)}") + + # --- Načti kandidáty z MySQL --- + conn = pymysql.connect(**DB_CONFIG) + with conn.cursor() as cur: + cur.execute(""" + SELECT patient_id, name, surname, identification_number + FROM medevio_pacient + WHERE status = 'ACTIVE' + AND user_id IS NULL + AND identification_number IS NOT NULL + AND surname NOT LIKE '%%\\%%%' + ORDER BY surname, name + """) + kandidati_raw = cur.fetchall() + conn.close() + + # Filtruj ty, co nejsou v Medicusu + kandidati = [ + r for r in kandidati_raw + if r["identification_number"] not in medicus_rc + ] + print(f" Kandidátů (ACTIVE, bez účtu, mimo Medicus): {len(kandidati)}") + + if not kandidati: + print("Nic ke změně.") + return + + if DRY_RUN: + print("\n=== DRY RUN — žádné změny se neodesílají ===") + for r in kandidati: + print(f" {r['surname']} {r['name']} RC: {r['identification_number']} ID: {r['patient_id']}") + print(f"\nCelkem: {len(kandidati)} pacientů by bylo nastaveno na REMOVED.") + print("Nastav DRY_RUN = False pro skutečné provedení.") + return + + # --- Hromadná změna --- + print(f"\nMěním status {len(kandidati)} pacientů na REMOVED...") + ok = 0 + fail = 0 + for i, r in enumerate(kandidati): + pid = r["patient_id"] + name = f"{r['surname']} {r['name']}" + success, err = set_patient_removed(headers, pid) + if success: + ok += 1 + print(f" [{i+1}/{len(kandidati)}] OK {name}") + else: + fail += 1 + print(f" [{i+1}/{len(kandidati)}] CHYBA {name}: {err}") + time.sleep(DELAY) + + # Aktualizuj MySQL + if ok > 0: + ids_ok = [] + for i, r in enumerate(kandidati): + pid = r["patient_id"] + ids_ok.append(pid) + + conn2 = pymysql.connect(**DB_CONFIG) + with conn2.cursor() as cur: + fmt = ",".join(["%s"] * len(ids_ok)) + cur.execute( + f"UPDATE medevio_pacient SET status='REMOVED' WHERE patient_id IN ({fmt})", + ids_ok, + ) + conn2.commit() + conn2.close() + print(f"\nMySQL aktualizováno: {ok} záznamů → REMOVED") + + print(f"\nHotovo — úspěch: {ok}, chyba: {fail}") + + +if __name__ == "__main__": + main() diff --git a/Medevio/medevio_api_notes.md b/Medevio/medevio_api_notes.md index 776aa3e..ac61ca7 100644 --- a/Medevio/medevio_api_notes.md +++ b/Medevio/medevio_api_notes.md @@ -189,6 +189,9 @@ Dvoustupňový proces: Skript: `Medevio/80 Pacienti/sync_patients_to_mysql.py` Výsledek: 1963 pacientů synchronizováno (květen 2026). +**Má pacient Medevio účet?** → `user_id IS NOT NULL` (žádný redundantní boolean sloupec) +- 1 230 pacientů má účet (63 %), 733 nemá (37 %) — stav květen 2026 + #### Známé problémy - **`hasMobileApp` je nefunkční na úrovni pacienta** — ověřeno na více endpointech: @@ -279,6 +282,37 @@ reservation { } ``` +### Patient Status Change (Zmena stavu) + +| Operation | Variables | Response | +|-----------|-----------|----------| +| `ClinicPatientEditStatusModal_UpdateClinicPatientStatus` | `clinicSlug`, `patientId` (UUID), `status` | `updated` (boolean) | + +#### Dostupné stavy (`ClinicPatientStatus`) +| UI název | API hodnota | +|----------|-------------| +| Aktivní | `ACTIVE` | +| Odmítnutý | `DECLINED` | +| Vyřazený | `REMOVED` | +| Čekající | `PENDING` | + +#### Mutation +```graphql +mutation ClinicPatientEditStatusModal_UpdateClinicPatientStatus($clinicSlug: String!, $patientId: String!, $status: ClinicPatientStatus!) { + updated: updateClinicPatientStatus( + clinicSlug: $clinicSlug + patientId: $patientId + status: $status + ) +} +``` + +Odpověď: `{ "data": { "updated": true } }` + +Skript pro hromadnou změnu: `Medevio/80 Pacienti/bulk_set_removed.py` + +--- + ### References (Referovani) | Operation | Variables | Response |