From 02cb5bb9f80d6bf8b9c96b0f0f4b91fabc300061 Mon Sep 17 00:00:00 2001 From: "vladimir.buzalka" Date: Fri, 14 Nov 2025 13:24:09 +0100 Subject: [PATCH] Z230 --- .idea/Medevio.iml | 2 +- .idea/misc.xml | 2 +- ...PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py} | 80 +++---- .../PRAVIDELNE_1_ReadLast300DonePozadavku.py | 168 +++++++++++++++ Testy/09 Testy pt details all.py | 183 ++++++++++++++++ .../10 Testy stahni pouze active pozadavky.py | 197 +++++++++++++++++ Testy/11 Testy.py | 87 ++++++++ Testy/12 Testy.py | 168 +++++++++++++++ Testy/patient_detail.graphql | 201 ++++++++++++++++++ 9 files changed, 1049 insertions(+), 39 deletions(-) rename 10ReadPozadavky/{PRAVIDELNE_1_ReadPozadavkySaveMySql.py => PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py} (72%) create mode 100644 10ReadPozadavky/PRAVIDELNE_1_ReadLast300DonePozadavku.py create mode 100644 Testy/09 Testy pt details all.py create mode 100644 Testy/10 Testy stahni pouze active pozadavky.py create mode 100644 Testy/11 Testy.py create mode 100644 Testy/12 Testy.py create mode 100644 Testy/patient_detail.graphql diff --git a/.idea/Medevio.iml b/.idea/Medevio.iml index 3cd7809..78fd998 100644 --- a/.idea/Medevio.iml +++ b/.idea/Medevio.iml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 7a3c570..7b70d2f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/10ReadPozadavky/PRAVIDELNE_1_ReadPozadavkySaveMySql.py b/10ReadPozadavky/PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py similarity index 72% rename from 10ReadPozadavky/PRAVIDELNE_1_ReadPozadavkySaveMySql.py rename to 10ReadPozadavky/PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py index ed314c5..43c709a 100644 --- a/10ReadPozadavky/PRAVIDELNE_1_ReadPozadavkySaveMySql.py +++ b/10ReadPozadavky/PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py @@ -7,20 +7,12 @@ from pathlib import Path from datetime import datetime import time -import time, socket -# for _ in range(30): -# try: -# socket.create_connection(("127.0.0.1", 3307), timeout=3).close() -# break -# except OSError: -# time.sleep(10) # ================================ # 🔧 CONFIGURATION # ================================ TOKEN_PATH = Path("token.txt") CLINIC_SLUG = "mudr-buzalkova" BATCH_SIZE = 100 -DONE_LIMIT = 200 # only last 200 DONE DB_CONFIG = { "host": "192.168.1.76", @@ -69,14 +61,15 @@ query ClinicRequestGrid_ListPatientRequestsForClinic2( # ================================ # 🔑 TOKEN # ================================ -def read_token(p: Path) -> str: - tok = p.read_text(encoding="utf-8").strip() +def read_token(path: Path) -> str: + tok = path.read_text(encoding="utf-8").strip() if tok.startswith("Bearer "): tok = tok.split(" ", 1)[1] return tok + # ================================ -# 🕒 DATETIME CONVERSION +# 🕒 DATETIME FORMAT # ================================ def to_mysql_dt(iso_str): if not iso_str: @@ -84,14 +77,16 @@ def to_mysql_dt(iso_str): try: dt = datetime.fromisoformat(iso_str.replace("Z", "+00:00")) return dt.strftime("%Y-%m-%d %H:%M:%S") - except Exception: + except: return None + # ================================ -# 💾 UPSERT TO MYSQL +# 💾 UPSERT # ================================ def upsert(conn, r): - p = (r.get("extendedPatient") or {}) + p = r.get("extendedPatient") or {} + sql = """ INSERT INTO pozadavky ( id, displayTitle, createdAt, updatedAt, doneAt, removedAt, @@ -106,6 +101,7 @@ def upsert(conn, r): pacient_prijmeni=VALUES(pacient_prijmeni), pacient_rodnecislo=VALUES(pacient_rodnecislo) """ + vals = ( r.get("id"), r.get("displayTitle"), @@ -117,33 +113,38 @@ def upsert(conn, r): p.get("surname"), p.get("identificationNumber"), ) + with conn.cursor() as cur: cur.execute(sql, vals) conn.commit() + # ================================ -# 📡 FETCH FUNCTION +# 📡 FETCH ACTIVE PAGE # ================================ -def fetch_requests(headers, state, limit=None): - """Fetch requests for a given state; optional limit for DONE.""" +def fetch_active(headers, offset): variables = { "clinicSlug": CLINIC_SLUG, "queueId": None, "queueAssignment": "ANY", - "pageInfo": {"first": limit or BATCH_SIZE, "offset": 0}, + "pageInfo": {"first": BATCH_SIZE, "offset": offset}, "locale": "cs", - "state": state, + "state": "ACTIVE", } + payload = { "operationName": "ClinicRequestGrid_ListPatientRequestsForClinic2", "query": GRAPHQL_QUERY, "variables": variables, } + r = requests.post("https://api.medevio.cz/graphql", json=payload, headers=headers) r.raise_for_status() data = r.json().get("data", {}).get("requestsResponse", {}) + return data.get("patientRequests", []), data.get("count", 0) + # ================================ # 🧠 MAIN # ================================ @@ -157,34 +158,39 @@ def main(): conn = pymysql.connect(**DB_CONFIG) - print(f"\n=== Medevio požadavky sync @ {datetime.now():%Y-%m-%d %H:%M:%S} ===") + print(f"\n=== Sync ACTIVE požadavků @ {datetime.now():%Y-%m-%d %H:%M:%S} ===") - # --- ACTIVE (all, paginated) - print("\n📡 Fetching all ACTIVE requests...") + # ------------------------------- + # 🚀 FETCH ALL ACTIVE REQUESTS + # ------------------------------- offset = 0 - total_active = 0 + total_processed = 0 + total_count = None + while True: - requests_batch, count = fetch_requests(headers, "ACTIVE", BATCH_SIZE) - if not requests_batch: + batch, count = fetch_active(headers, offset) + + if total_count is None: + total_count = count + print(f"📡 Celkem ACTIVE v Medevio: {count}") + + if not batch: break - for r in requests_batch: + + for r in batch: upsert(conn, r) - total_active += len(requests_batch) - print(f" • {total_active} ACTIVE processed") - if len(requests_batch) < BATCH_SIZE: + + total_processed += len(batch) + print(f" • {total_processed}/{total_count} ACTIVE processed") + + if offset + BATCH_SIZE >= count: break + offset += BATCH_SIZE time.sleep(0.4) - # --- DONE (only 200 latest) - print("\n📡 Fetching last 200 DONE requests...") - done_requests, done_count = fetch_requests(headers, "DONE", DONE_LIMIT) - for r in done_requests: - upsert(conn, r) - print(f" ✅ DONE processed: {len(done_requests)} (of total {done_count})") - conn.close() - print("\n✅ Sync completed successfully.\n") + print("\n✅ ACTIVE sync hotovo!\n") if __name__ == "__main__": diff --git a/10ReadPozadavky/PRAVIDELNE_1_ReadLast300DonePozadavku.py b/10ReadPozadavky/PRAVIDELNE_1_ReadLast300DonePozadavku.py new file mode 100644 index 0000000..9b94413 --- /dev/null +++ b/10ReadPozadavky/PRAVIDELNE_1_ReadLast300DonePozadavku.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import pymysql +import requests +from pathlib import Path +from datetime import datetime + +# ================================ +# 🔧 CONFIGURATION +# ================================ +TOKEN_PATH = Path("token.txt") +CLINIC_SLUG = "mudr-buzalkova" + +LIMIT = 300 # download the latest 300 requests + +DB_CONFIG = { + "host": "192.168.1.76", + "port": 3307, + "user": "root", + "password": "Vlado9674+", + "database": "medevio", + "charset": "utf8mb4", + "cursorclass": pymysql.cursors.DictCursor, +} + +GRAPHQL_QUERY = r""" +query ClinicRequestGrid_ListPatientRequestsForClinic2( + $clinicSlug: String!, + $queueId: String, + $queueAssignment: QueueAssignmentFilter!, + $pageInfo: PageInfo!, + $locale: Locale!, + $state: PatientRequestState +) { + requestsResponse: listPatientRequestsForClinic2( + clinicSlug: $clinicSlug, + queueId: $queueId, + queueAssignment: $queueAssignment, + pageInfo: $pageInfo, + state: $state + ) { + count + patientRequests { + id + displayTitle(locale: $locale) + createdAt + updatedAt + doneAt + removedAt + extendedPatient { + name + surname + identificationNumber + } + } + } +} +""" + +# ================================ +# TOKEN +# ================================ +def read_token(p: Path) -> str: + tok = p.read_text(encoding="utf-8").strip() + if tok.startswith("Bearer "): + return tok.split(" ", 1)[1] + return tok + +# ================================ +# DATE PARSER +# ================================ +def to_mysql_dt(iso_str): + if not iso_str: + return None + try: + dt = datetime.fromisoformat(iso_str.replace("Z", "+00:00")) + return dt.strftime("%Y-%m-%d %H:%M:%S") + except: + return None + +# ================================ +# UPSERT +# ================================ +def upsert(conn, r): + p = (r.get("extendedPatient") or {}) + sql = """ + INSERT INTO pozadavky ( + id, displayTitle, createdAt, updatedAt, doneAt, removedAt, + pacient_jmeno, pacient_prijmeni, pacient_rodnecislo + ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s) + ON DUPLICATE KEY UPDATE + displayTitle=VALUES(displayTitle), + updatedAt=VALUES(updatedAt), + doneAt=VALUES(doneAt), + removedAt=VALUES(removedAt), + pacient_jmeno=VALUES(pacient_jmeno), + pacient_prijmeni=VALUES(pacient_prijmeni), + pacient_rodnecislo=VALUES(pacient_rodnecislo) + """ + vals = ( + r.get("id"), + r.get("displayTitle"), + to_mysql_dt(r.get("createdAt")), + to_mysql_dt(r.get("updatedAt")), + to_mysql_dt(r.get("doneAt")), + to_mysql_dt(r.get("removedAt")), + p.get("name"), + p.get("surname"), + p.get("identificationNumber"), + ) + with conn.cursor() as cur: + cur.execute(sql, vals) + conn.commit() + +# ================================ +# FETCH LATEST 300 REQUESTS +# ================================ +def fetch_latest_requests(headers): + vars = { + "clinicSlug": CLINIC_SLUG, + "queueId": None, + "queueAssignment": "ANY", + "pageInfo": {"first": LIMIT, "offset": 0}, + "locale": "cs", + "state": "DONE" # ALL STATES (ACTIVE, DONE, REMOVED) + } + + payload = { + "operationName": "ClinicRequestGrid_ListPatientRequestsForClinic2", + "query": GRAPHQL_QUERY, + "variables": vars, + } + + r = requests.post("https://api.medevio.cz/graphql", json=payload, headers=headers) + r.raise_for_status() + + data = r.json()["data"]["requestsResponse"] + return data.get("patientRequests", []) + +# ================================ +# MAIN +# ================================ +def main(): + token = read_token(TOKEN_PATH) + headers = { + "Authorization": f"Bearer {token}", + "Content-Type": "application/json", + "Accept": "application/json", + } + + conn = pymysql.connect(**DB_CONFIG) + + print(f"\n=== Downloading last {LIMIT} requests @ {datetime.now():%Y-%m-%d %H:%M:%S} ===") + + requests_list = fetch_latest_requests(headers) + + print(f"📌 Requests returned: {len(requests_list)}") + + for r in requests_list: + upsert(conn, r) + + conn.close() + print("\n✅ Done. Latest requests synced.\n") + + +if __name__ == "__main__": + main() diff --git a/Testy/09 Testy pt details all.py b/Testy/09 Testy pt details all.py new file mode 100644 index 0000000..7933114 --- /dev/null +++ b/Testy/09 Testy pt details all.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import json +import time +import random +import requests +import pymysql +from pathlib import Path + +from datetime import datetime + +# Patients with details_updated_at older than this date will be refreshed +# UpdateOlderThan = datetime(2025, 2, 20) # example date +UpdateOlderThan = None #když chceš všechny aktualizovat + +TOKEN_PATH = Path("token.txt") +GRAPHQL_URL = "https://api.medevio.cz/graphql" +CLINIC_SLUG = "mudr-buzalkova" + +DB_CONFIG = { + "host": "192.168.1.76", + "port": 3307, + "user": "root", + "password": "Vlado9674+", + "database": "medevio", + "charset": "utf8mb4", + "cursorclass": pymysql.cursors.DictCursor, +} + +def normalize_dt(dt_str): + if not dt_str: + return None + dt_str = dt_str.replace("Z", "").replace("T", " ") + if "." in dt_str: + dt_str = dt_str.split(".")[0] + return dt_str + +def save_patient_detail(cur, p): + user = p.get("user") or {} + ins = p.get("insuranceCompanyObject") or {} + tags = p.get("tags") or [] + clinics = p.get("clinics") or [] + + sql = """ + UPDATE medevio_pacienti SET + email = %s, + telefon = %s, + dob = %s, + street = %s, + house_number = %s, + city = %s, + + user_id = %s, + user_email = %s, + user_name = %s, + user_surname = %s, + user_phone = %s, + user_reg_time = %s, + user_deactivated_time = %s, + + created_at = %s, + note = %s, + has_mobile_app = %s, + user_relationship = %s, + + pojistovna_code = %s, + tags_json = %s, + clinics_json = %s, + last_update = NOW(), + details_updated_at = NOW() + + WHERE id = %s + """ + + cur.execute(sql, ( + p.get("email"), + p.get("phone"), + p.get("dob"), + + p.get("street"), + p.get("houseNumber"), + p.get("city"), + + user.get("id"), + user.get("email"), + user.get("name"), + user.get("surname"), + user.get("phone"), + normalize_dt(user.get("registrationCompletedTime")), + normalize_dt(user.get("deactivatedTime")), + + normalize_dt(p.get("createdAt")), + p.get("note"), + 1 if p.get("hasMobileApp") else 0, + p.get("userRelationship"), + + ins.get("code"), + json.dumps(tags, ensure_ascii=False), + json.dumps(clinics, ensure_ascii=False), + + p.get("id") + )) + +# === PLACEHOLDER: Insert your full GraphQL query here === +QUERY = Path("patient_detail.graphql").read_text(encoding="utf-8") + +def main(): + token = TOKEN_PATH.read_text().strip() + + headers = { + "Authorization": f"Bearer {token}", + "Content-Type": "application/json", + "Accept": "application/json", + } + + conn = pymysql.connect(**DB_CONFIG) + cur = conn.cursor() + + if UpdateOlderThan: + print(f"🔎 Updating patients with details_updated_at NULL or < {UpdateOlderThan}") + cur.execute(""" + SELECT id, prijmeni, jmeno, details_updated_at + FROM medevio_pacienti + WHERE details_updated_at IS NULL OR details_updated_at < %s + ORDER BY prijmeni, jmeno + """, (UpdateOlderThan,)) + else: + print("🔎 Updating only patients with details_updated_at NULL") + cur.execute(""" + SELECT id, prijmeni, jmeno, details_updated_at + FROM medevio_pacienti + WHERE details_updated_at IS NULL + ORDER BY prijmeni, jmeno + """) + patients = cur.fetchall() + + total = len(patients) + print(f"⏳ Starting full patient detail sync for {total} patients...") + + for idx, row in enumerate(patients, start=1): + pid = row["id"] + name = f"{row.get('prijmeni','')}, {row.get('jmeno','')}" + print(f"[{idx}/{total}] Updating: {name} ({pid})") + + variables = { + "clinicSlug": CLINIC_SLUG, + "patientId": pid, + "patientUuid": pid, + "challengesStatus": "SENT", + "locale": "cs", + } + + try: + r = requests.post( + GRAPHQL_URL, + json={"query": QUERY, "variables": variables}, + headers=headers, + timeout=30 + ) + r.raise_for_status() + js = r.json() + + p = js["data"]["patient"] + if p: + save_patient_detail(cur, p) + conn.commit() + print(" ✔ saved") + else: + print(" ⚠ no patient data returned") + + except Exception as e: + print(f" ❌ ERROR: {e}") + time.sleep(2) + continue + + time.sleep(random.uniform(0.5, 1.5)) + + conn.close() + print("✅ DONE – full detail sync completed.") + +if __name__ == "__main__": + main() diff --git a/Testy/10 Testy stahni pouze active pozadavky.py b/Testy/10 Testy stahni pouze active pozadavky.py new file mode 100644 index 0000000..43c709a --- /dev/null +++ b/Testy/10 Testy stahni pouze active pozadavky.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import pymysql +import requests +from pathlib import Path +from datetime import datetime +import time + +# ================================ +# 🔧 CONFIGURATION +# ================================ +TOKEN_PATH = Path("token.txt") +CLINIC_SLUG = "mudr-buzalkova" +BATCH_SIZE = 100 + +DB_CONFIG = { + "host": "192.168.1.76", + "port": 3307, + "user": "root", + "password": "Vlado9674+", + "database": "medevio", + "charset": "utf8mb4", + "cursorclass": pymysql.cursors.DictCursor, +} + +GRAPHQL_QUERY = r""" +query ClinicRequestGrid_ListPatientRequestsForClinic2( + $clinicSlug: String!, + $queueId: String, + $queueAssignment: QueueAssignmentFilter!, + $pageInfo: PageInfo!, + $locale: Locale!, + $state: PatientRequestState +) { + requestsResponse: listPatientRequestsForClinic2( + clinicSlug: $clinicSlug, + queueId: $queueId, + queueAssignment: $queueAssignment, + pageInfo: $pageInfo, + state: $state + ) { + count + patientRequests { + id + displayTitle(locale: $locale) + createdAt + updatedAt + doneAt + removedAt + extendedPatient { + name + surname + identificationNumber + } + } + } +} +""" + +# ================================ +# 🔑 TOKEN +# ================================ +def read_token(path: Path) -> str: + tok = path.read_text(encoding="utf-8").strip() + if tok.startswith("Bearer "): + tok = tok.split(" ", 1)[1] + return tok + + +# ================================ +# 🕒 DATETIME FORMAT +# ================================ +def to_mysql_dt(iso_str): + if not iso_str: + return None + try: + dt = datetime.fromisoformat(iso_str.replace("Z", "+00:00")) + return dt.strftime("%Y-%m-%d %H:%M:%S") + except: + return None + + +# ================================ +# 💾 UPSERT +# ================================ +def upsert(conn, r): + p = r.get("extendedPatient") or {} + + sql = """ + INSERT INTO pozadavky ( + id, displayTitle, createdAt, updatedAt, doneAt, removedAt, + pacient_jmeno, pacient_prijmeni, pacient_rodnecislo + ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s) + ON DUPLICATE KEY UPDATE + displayTitle=VALUES(displayTitle), + updatedAt=VALUES(updatedAt), + doneAt=VALUES(doneAt), + removedAt=VALUES(removedAt), + pacient_jmeno=VALUES(pacient_jmeno), + pacient_prijmeni=VALUES(pacient_prijmeni), + pacient_rodnecislo=VALUES(pacient_rodnecislo) + """ + + vals = ( + r.get("id"), + r.get("displayTitle"), + to_mysql_dt(r.get("createdAt")), + to_mysql_dt(r.get("updatedAt")), + to_mysql_dt(r.get("doneAt")), + to_mysql_dt(r.get("removedAt")), + p.get("name"), + p.get("surname"), + p.get("identificationNumber"), + ) + + with conn.cursor() as cur: + cur.execute(sql, vals) + conn.commit() + + +# ================================ +# 📡 FETCH ACTIVE PAGE +# ================================ +def fetch_active(headers, offset): + variables = { + "clinicSlug": CLINIC_SLUG, + "queueId": None, + "queueAssignment": "ANY", + "pageInfo": {"first": BATCH_SIZE, "offset": offset}, + "locale": "cs", + "state": "ACTIVE", + } + + payload = { + "operationName": "ClinicRequestGrid_ListPatientRequestsForClinic2", + "query": GRAPHQL_QUERY, + "variables": variables, + } + + r = requests.post("https://api.medevio.cz/graphql", json=payload, headers=headers) + r.raise_for_status() + data = r.json().get("data", {}).get("requestsResponse", {}) + + return data.get("patientRequests", []), data.get("count", 0) + + +# ================================ +# 🧠 MAIN +# ================================ +def main(): + token = read_token(TOKEN_PATH) + headers = { + "Authorization": f"Bearer {token}", + "Content-Type": "application/json", + "Accept": "application/json", + } + + conn = pymysql.connect(**DB_CONFIG) + + print(f"\n=== Sync ACTIVE požadavků @ {datetime.now():%Y-%m-%d %H:%M:%S} ===") + + # ------------------------------- + # 🚀 FETCH ALL ACTIVE REQUESTS + # ------------------------------- + offset = 0 + total_processed = 0 + total_count = None + + while True: + batch, count = fetch_active(headers, offset) + + if total_count is None: + total_count = count + print(f"📡 Celkem ACTIVE v Medevio: {count}") + + if not batch: + break + + for r in batch: + upsert(conn, r) + + total_processed += len(batch) + print(f" • {total_processed}/{total_count} ACTIVE processed") + + if offset + BATCH_SIZE >= count: + break + + offset += BATCH_SIZE + time.sleep(0.4) + + conn.close() + print("\n✅ ACTIVE sync hotovo!\n") + + +if __name__ == "__main__": + main() diff --git a/Testy/11 Testy.py b/Testy/11 Testy.py new file mode 100644 index 0000000..b653a38 --- /dev/null +++ b/Testy/11 Testy.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import json +import requests +from pathlib import Path + +TOKEN_PATH = Path("token.txt") +GRAPHQL_URL = "https://api.medevio.cz/graphql" +CLINIC_SLUG = "mudr-buzalkova" + +QUERY = r""" +query ClinicLegacyRequestList_ListPatientRequestsForClinic( + $clinicSlug: String!, + $queueId: String, + $queueAssignment: QueueAssignmentFilter!, + $state: PatientRequestState, + $pageInfo: PageInfo!, + $locale: Locale! +) { + requests: listPatientRequestsForClinic( + clinicSlug: $clinicSlug + queueId: $queueId + queueAssignment: $queueAssignment + state: $state + pageInfo: $pageInfo + ) { + id + displayTitle(locale: $locale) + createdAt + doneAt + removedAt + extendedPatient { + name + surname + } + } +} +""" + +def main(): + token = TOKEN_PATH.read_text().strip() + + headers = { + "Authorization": f"Bearer {token}", + "Content-Type": "application/json", + "Accept": "application/json", + } + + variables = { + "clinicSlug": CLINIC_SLUG, + "queueId": None, + "queueAssignment": "ANY", + "state": "ACTIVE", + "pageInfo": {"first": 200, "offset": 100}, + "locale": "cs", + } + + print("⏳ Testing ACTIVE request fetch (LEGACY API)…") + + r = requests.post( + GRAPHQL_URL, + json={"query": QUERY, "variables": variables}, + headers=headers, + timeout=30 + ) + r.raise_for_status() + + js = r.json() + + # extract list + requests_list = js.get("data", {}).get("requests", []) + + print("\n📌 Number of ACTIVE requests returned:", len(requests_list)) + + print("\n📌 First 5 request IDs:") + for item in requests_list[:5]: + print(" •", item.get("id")) + + # debug dump if needed + # print(json.dumps(js, indent=2, ensure_ascii=False)) + + print("\n✅ Test completed.\n") + + +if __name__ == "__main__": + main() diff --git a/Testy/12 Testy.py b/Testy/12 Testy.py new file mode 100644 index 0000000..9b94413 --- /dev/null +++ b/Testy/12 Testy.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import pymysql +import requests +from pathlib import Path +from datetime import datetime + +# ================================ +# 🔧 CONFIGURATION +# ================================ +TOKEN_PATH = Path("token.txt") +CLINIC_SLUG = "mudr-buzalkova" + +LIMIT = 300 # download the latest 300 requests + +DB_CONFIG = { + "host": "192.168.1.76", + "port": 3307, + "user": "root", + "password": "Vlado9674+", + "database": "medevio", + "charset": "utf8mb4", + "cursorclass": pymysql.cursors.DictCursor, +} + +GRAPHQL_QUERY = r""" +query ClinicRequestGrid_ListPatientRequestsForClinic2( + $clinicSlug: String!, + $queueId: String, + $queueAssignment: QueueAssignmentFilter!, + $pageInfo: PageInfo!, + $locale: Locale!, + $state: PatientRequestState +) { + requestsResponse: listPatientRequestsForClinic2( + clinicSlug: $clinicSlug, + queueId: $queueId, + queueAssignment: $queueAssignment, + pageInfo: $pageInfo, + state: $state + ) { + count + patientRequests { + id + displayTitle(locale: $locale) + createdAt + updatedAt + doneAt + removedAt + extendedPatient { + name + surname + identificationNumber + } + } + } +} +""" + +# ================================ +# TOKEN +# ================================ +def read_token(p: Path) -> str: + tok = p.read_text(encoding="utf-8").strip() + if tok.startswith("Bearer "): + return tok.split(" ", 1)[1] + return tok + +# ================================ +# DATE PARSER +# ================================ +def to_mysql_dt(iso_str): + if not iso_str: + return None + try: + dt = datetime.fromisoformat(iso_str.replace("Z", "+00:00")) + return dt.strftime("%Y-%m-%d %H:%M:%S") + except: + return None + +# ================================ +# UPSERT +# ================================ +def upsert(conn, r): + p = (r.get("extendedPatient") or {}) + sql = """ + INSERT INTO pozadavky ( + id, displayTitle, createdAt, updatedAt, doneAt, removedAt, + pacient_jmeno, pacient_prijmeni, pacient_rodnecislo + ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s) + ON DUPLICATE KEY UPDATE + displayTitle=VALUES(displayTitle), + updatedAt=VALUES(updatedAt), + doneAt=VALUES(doneAt), + removedAt=VALUES(removedAt), + pacient_jmeno=VALUES(pacient_jmeno), + pacient_prijmeni=VALUES(pacient_prijmeni), + pacient_rodnecislo=VALUES(pacient_rodnecislo) + """ + vals = ( + r.get("id"), + r.get("displayTitle"), + to_mysql_dt(r.get("createdAt")), + to_mysql_dt(r.get("updatedAt")), + to_mysql_dt(r.get("doneAt")), + to_mysql_dt(r.get("removedAt")), + p.get("name"), + p.get("surname"), + p.get("identificationNumber"), + ) + with conn.cursor() as cur: + cur.execute(sql, vals) + conn.commit() + +# ================================ +# FETCH LATEST 300 REQUESTS +# ================================ +def fetch_latest_requests(headers): + vars = { + "clinicSlug": CLINIC_SLUG, + "queueId": None, + "queueAssignment": "ANY", + "pageInfo": {"first": LIMIT, "offset": 0}, + "locale": "cs", + "state": "DONE" # ALL STATES (ACTIVE, DONE, REMOVED) + } + + payload = { + "operationName": "ClinicRequestGrid_ListPatientRequestsForClinic2", + "query": GRAPHQL_QUERY, + "variables": vars, + } + + r = requests.post("https://api.medevio.cz/graphql", json=payload, headers=headers) + r.raise_for_status() + + data = r.json()["data"]["requestsResponse"] + return data.get("patientRequests", []) + +# ================================ +# MAIN +# ================================ +def main(): + token = read_token(TOKEN_PATH) + headers = { + "Authorization": f"Bearer {token}", + "Content-Type": "application/json", + "Accept": "application/json", + } + + conn = pymysql.connect(**DB_CONFIG) + + print(f"\n=== Downloading last {LIMIT} requests @ {datetime.now():%Y-%m-%d %H:%M:%S} ===") + + requests_list = fetch_latest_requests(headers) + + print(f"📌 Requests returned: {len(requests_list)}") + + for r in requests_list: + upsert(conn, r) + + conn.close() + print("\n✅ Done. Latest requests synced.\n") + + +if __name__ == "__main__": + main() diff --git a/Testy/patient_detail.graphql b/Testy/patient_detail.graphql new file mode 100644 index 0000000..a602fa9 --- /dev/null +++ b/Testy/patient_detail.graphql @@ -0,0 +1,201 @@ +query ClinicPatientDetailModal_GetData( + $clinicSlug: String!, + $patientId: String!, + $patientUuid: UUID!, + $challengesStatus: ECRFChallengeStatus!, + $locale: Locale! +) { + clinic: getClinic(clinicSlug: $clinicSlug) { + id + features + sslSUKLCertificateId + type + ais + slug + ...ClinicWithTypeAndFeatures_Clinic + ...PatientInfo_Clinic + __typename + } + patient: getPatientForClinic(clinicSlug: $clinicSlug, patientId: $patientId) { + ...ClinicPatientDetailModal_Patient + __typename + } + challenges: listPatientChallenges2( + clinicSlug: $clinicSlug + patientId: $patientId + status: $challengesStatus + ) { + ...ChallengeTableList_EcrfChallenge + __typename + } + patientRequestsResponse: filterPatientRequestsForClinic( + clinicSlug: $clinicSlug + filter: {patientId: $patientUuid} + pageInfo: {first: 1, offset: 0} + ) { + count + items { id __typename } + __typename + } + treatmentPlanPatients: listTreatmentPlanPatients( + clinicSlug: $clinicSlug + patientId: $patientUuid + ) { + ...ClinicPlanPatientList_PlanPatient + __typename + } + premiumPlans: listClinicPremiumPlans(clinicSlug: $clinicSlug) { + id + __typename + } + mergeSuggestions: findMergeSuggestions( + clinicSlug: $clinicSlug + input: {existingPatientId: $patientUuid} + ) { + ...MergeSuggestionAlert_MergeSuggestionResult + __typename + } + insuranceCards: getPatientDocuments( + patientId: $patientUuid + type: InsuranceCard + ) { + ...PatientInfo_InsuranceCard + __typename + } +} + +# — fragmenty (přesně tak, jak jsi měl) — +fragment ClinicWithTypeAndFeatures_Clinic on Clinic { + id + type + features + __typename +} + +fragment PatientInfo_Clinic on Clinic { + country + id + slug + ais + ...ClinicWithTypeAndFeatures_Clinic + __typename +} + +fragment ClinicPatientDetailModal_Patient on ExtendedPatient { + id + isInClinic + kind + name + isUnknownPatient + sex + surname + identificationNumber + editableByDoctor + type + key + user { id name surname __typename } + ...ClinicPatientDetail_Patient + ...PatientInfo_AccountPatient + ...ClinicPatientInfo_Patient + __typename +} + +fragment ClinicPatientDetail_Patient on ExtendedPatient { + name + surname + email + id + identificationNumber + isInClinic + key + phone + sex + type + dob + user { id __typename } + isUnknownPatient + hasMobileApp + __typename +} + +fragment PatientInfo_AccountPatient on ExtendedPatient { + id + createdAt + key + user { + registrationCompletedTime + deactivatedTime + __typename + } + __typename +} + +fragment ClinicPatientInfo_Patient on ExtendedPatient { + anamnesisShared + anamnesisStatusForClinic { updatedAt __typename } + clinics { id name slug __typename } + id + isInClinic + dob + city + familyMembers: family { __typename } + houseNumber + identificationNumber + insuranceCompanyObject { id code name shortName __typename } + kind + name + note + owner { name surname __typename } + key + status + street + surname + user { id email name phone surname __typename } + userRelationship + premiumPlanPatient { id __typename } + sex + tags(onlyImportant: false) { id name color icon __typename } + type + isUnknownPatient + hasMobileApp + __typename +} + +fragment ChallengeTableList_EcrfChallenge on ECRFChallenge { + id + createdAt + sentAt + issuedToPatient { + id + identificationNumber + name + surname + __typename + } + userECRF(locale: $locale) { id name __typename } + patientRequestId + status + __typename +} + +fragment MergeSuggestionAlert_MergeSuggestionResult on MergeSuggestionResult { + extendedPatient { id __typename } + matchResult + __typename +} + +fragment ClinicPlanPatientList_PlanPatient on TreatmentPlanPatient { + id + createdAt + listPatient { id identificationNumber name key status surname __typename } + treatmentPlan { id slug name __typename } + __typename +} + +fragment PatientInfo_InsuranceCard on PatientDocument { + id + contentType + url + downloadUrl + __typename +}