notebookvb

This commit is contained in:
Vladimir Buzalka
2026-05-16 07:59:59 +02:00
parent 92e2585433
commit 5607649162
12 changed files with 944 additions and 15 deletions
+92
View File
@@ -0,0 +1,92 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Analýza 129 extra pacientů v Medeviu (nejsou v Medicusu):
- Mají účet v Medeviu?
- Jaké jsou jejich statusy?
"""
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 pymysql
from Knihovny.medicus_db import get_medicus_db
DB_CONFIG = {
"host": "192.168.1.76",
"port": 3306,
"user": "root",
"password": "Vlado9674+",
"database": "medevio",
"charset": "utf8mb4",
"cursorclass": pymysql.cursors.DictCursor,
}
def main():
# Načti registrované v 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()
# Najdi všechny ACTIVE v Medeviu, co nejsou v Medicusu
conn = pymysql.connect(**DB_CONFIG)
with conn.cursor() as cur:
cur.execute("""
SELECT patient_id, name, surname, identification_number, user_id, status
FROM medevio_pacient
WHERE status = 'ACTIVE'
AND identification_number IS NOT NULL
ORDER BY surname, name
""")
all_active = cur.fetchall()
conn.close()
# Filtruj ty mimo Medicus
extras = [
r for r in all_active
if r["identification_number"] not in medicus_rc
]
print(f"{'=' * 80}")
print(f"EXTRA PACIENTI V MEDEVIU (mimo Medicus): {len(extras)}")
print(f"{'=' * 80}\n")
# Rozdělení podle user_id
with_account = [r for r in extras if r["user_id"]]
without_account = [r for r in extras if not r["user_id"]]
print(f"S účtem (user_id NOT NULL): {len(with_account)}")
print(f"Bez účtu (user_id IS NULL): {len(without_account)}\n")
if without_account:
print("" * 80)
print("BEZ ÚČTU — KANDIDÁTI NA REMOVE:")
print("" * 80)
for r in without_account[:10]: # První 10
print(f" {r['surname']} {r['name']} RC: {r['identification_number']}")
if len(without_account) > 10:
print(f" ... a dalších {len(without_account) - 10}")
if with_account:
print("\n" + "" * 80)
print("S ÚČTEM — NORMÁLNÍ PACIENTI (nejsou v Medicusu, ale mají Medevio účet):")
print("" * 80)
for r in with_account[:10]: # První 10
print(f" {r['surname']} {r['name']} RC: {r['identification_number']}")
if len(with_account) > 10:
print(f" ... a dalších {len(with_account) - 10}")
print(f"\n{'=' * 80}")
if __name__ == "__main__":
main()
+99
View File
@@ -0,0 +1,99 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
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 pymysql
import fdb
from pathlib import Path
DB_CONFIG = {
"host": "192.168.1.76",
"port": 3306,
"user": "root",
"password": "Vlado9674+",
"database": "medevio",
"charset": "utf8mb4",
"cursorclass": pymysql.cursors.DictCursor,
}
RC = "8206694232"
print("=" * 80)
print(f"KONTROLA PACIENTA: Kurajda Martin (RC: {RC})")
print("=" * 80)
# --- V Medeviu (MySQL) ---
print("\n[Medevio — MySQL]")
conn = pymysql.connect(**DB_CONFIG)
with conn.cursor() as cur:
cur.execute("""
SELECT name, surname, status, user_id, identification_number
FROM medevio_pacient
WHERE identification_number = %s
""", (RC,))
medevio_rows = cur.fetchall()
conn.close()
if medevio_rows:
for r in medevio_rows:
print(f" Jméno: {r['surname']} {r['name']}")
print(f" Status: {r['status']}")
print(f" User ID: {r['user_id']}")
else:
print(" NENALEZEN")
# --- V Medicusu (Firebird) ---
print("\n[Medicus — Firebird]")
dsn = r"localhost:c:\medicus 3\data\medicus.fdb"
conn_fb = fdb.connect(dsn=dsn, user="SYSDBA", password="masterkey", charset="win1250")
cur_fb = conn_fb.cursor()
# Najdi pacienta podle RC
cur_fb.execute("""
SELECT idpac, prijmeni, jmeno, vyrazen
FROM kar
WHERE rodcis = ?
""", (RC,))
kar_rows = cur_fb.fetchall()
if kar_rows:
for kar in kar_rows:
idpac, prijmeni, jmeno, vyrazen = kar
print(f" Jméno: {prijmeni} {jmeno}")
print(f" Vyrazen: {vyrazen}")
# Zjisti registraci
cur_fb.execute("""
SELECT r.idpac, r.datum, r.datum_zruseni, r.priznak
FROM registr r
WHERE r.idpac = ? AND r.idicp = (
SELECT i.idicp FROM icp i
WHERE i.icp = '09305001' AND i.odb = '001'
)
ORDER BY r.datum DESC
""", (idpac,))
reg_rows = cur_fb.fetchall()
if reg_rows:
print(f" Registrace (posledních {len(reg_rows)}):")
for r in reg_rows[:3]: # Poslední 3
idpac2, datum, datum_zruseni, priznak = r
zrusena = "ANO" if datum_zruseni else "NE"
print(f" Datum: {datum}, Zrušena: {zrusena}, Příznak: {priznak}")
else:
print(f" Žádná registrace u našeho doktora")
else:
print(" NENALEZEN")
conn_fb.close()
print("\n" + "=" * 80)
+102
View File
@@ -0,0 +1,102 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Kontrola statusu pacientů po remove skriptu:
- Kolik je označeno jako REMOVED?
- Kolik zbývá ACTIVE bez účtu a bez registrace v Medicusu?
"""
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 pymysql
from Knihovny.medicus_db import get_medicus_db
# ==================== CONFIG ====================
DB_CONFIG = {
"host": "192.168.1.76",
"port": 3306,
"user": "root",
"password": "Vlado9674+",
"database": "medevio",
"charset": "utf8mb4",
"cursorclass": pymysql.cursors.DictCursor,
}
# ==================== MAIN ====================
def main():
print("=" * 70)
print("KONTROLA STATUSU PACIENTŮ V MEDEVIO")
print("=" * 70)
# --- Medevio (MySQL) ---
print("\n[Medevio — MySQL]")
conn = pymysql.connect(**DB_CONFIG)
with conn.cursor() as cur:
cur.execute("SELECT COUNT(*) as cnt FROM medevio_pacient WHERE status = 'ACTIVE'")
active = cur.fetchone()["cnt"]
cur.execute("SELECT COUNT(*) as cnt FROM medevio_pacient WHERE status = 'REMOVED'")
removed = cur.fetchone()["cnt"]
cur.execute("""
SELECT COUNT(*) as cnt FROM medevio_pacient
WHERE status = 'ACTIVE' AND user_id IS NULL
""")
active_no_account = cur.fetchone()["cnt"]
conn.close()
print(f" ACTIVE pacientů: {active}")
print(f" REMOVED pacientů: {removed}")
print(f" ACTIVE bez účtu (user_id NULL): {active_no_account}")
# --- Medicus (Firebird) ---
print("\n[Medicus — Firebird]")
db = get_medicus_db()
rows = db.get_active_registered_patients()
medicus_registered = len(rows)
medicus_rc = {r[0].strip() for r in rows if r[0]}
db.close()
print(f" Registrovaní pacienti: {medicus_registered}")
# --- Kandidáti na REMOVED ---
print("\n[Analýza]")
print(f" ACTIVE bez účtu: {active_no_account}")
# Zjisti, kolik z těch ACTIVE bez účtu nejsou v Medicusu
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
""")
candidates_raw = cur.fetchall()
conn.close()
candidates_not_in_medicus = [
r for r in candidates_raw
if r["identification_number"] not in medicus_rc
]
print(f" Z toho mimo Medicus (kandidáti na REMOVED): {len(candidates_not_in_medicus)}")
print("\n" + "=" * 70)
if __name__ == "__main__":
main()
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Porovnání počtu pacientů:
- ACTIVE v Medevio (MySQL)
- registrovaní v Medicusu (Firebird)
"""
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 pymysql
from Knihovny.medicus_db import get_medicus_db
# ==================== CONFIG ====================
DB_CONFIG = {
"host": "192.168.1.76",
"port": 3306,
"user": "root",
"password": "Vlado9674+",
"database": "medevio",
"charset": "utf8mb4",
"cursorclass": pymysql.cursors.DictCursor,
}
# ==================== MAIN ====================
def main():
print("=" * 70)
print("KONTROLA SYNCHRONIZACE PACIENTŮ")
print("=" * 70)
# --- Medevio (MySQL) ---
print("\n[Medevio — MySQL]")
conn = pymysql.connect(**DB_CONFIG)
with conn.cursor() as cur:
cur.execute("SELECT COUNT(*) as cnt FROM medevio_pacient WHERE status = 'ACTIVE'")
medevio_active = cur.fetchone()["cnt"]
conn.close()
print(f" ACTIVE pacienti: {medevio_active}")
# --- Medicus (Firebird) ---
print("\n[Medicus — Firebird]")
db = get_medicus_db()
rows = db.get_active_registered_patients()
medicus_registered = len(rows)
db.close()
print(f" Registrovaní pacienti: {medicus_registered}")
# --- Porovnání ---
print("\n" + "=" * 70)
diff = medevio_active - medicus_registered
if diff == 0:
print(f"✓ SHODUJE SE! ({medevio_active} = {medicus_registered})")
elif diff > 0:
print(f"⚠ Medevio má {diff} VÍCE pacientů ({medevio_active} vs {medicus_registered})")
print(f" → Jsou to možná pacienti bez účtu v Medicusu, kandidáti na REMOVED")
else:
print(f"⚠ Medicús má {-diff} VÍCE pacientů ({medicus_registered} vs {medevio_active})")
print(f" → V Medicusu jsou pacienti, co nejsou v Medevio")
print("=" * 70)
if __name__ == "__main__":
main()
+99
View File
@@ -0,0 +1,99 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
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 pymysql
import fdb
DB_CONFIG = {
"host": "192.168.1.76",
"port": 3306,
"user": "root",
"password": "Vlado9674+",
"database": "medevio",
"charset": "utf8mb4",
"cursorclass": pymysql.cursors.DictCursor,
}
RC = "9054260083"
print("=" * 80)
print(f"KONTROLA PACIENTA: Vymětalová Kristýna (RC: {RC})")
print("=" * 80)
# --- V Medeviu (MySQL) ---
print("\n[Medevio — MySQL]")
conn = pymysql.connect(**DB_CONFIG)
with conn.cursor() as cur:
cur.execute("""
SELECT name, surname, status, user_id, identification_number
FROM medevio_pacient
WHERE identification_number = %s
""", (RC,))
medevio_rows = cur.fetchall()
conn.close()
if medevio_rows:
for r in medevio_rows:
print(f" Jméno: {r['surname']} {r['name']}")
print(f" Status: {r['status']}")
print(f" User ID: {r['user_id']}")
else:
print(" NENALEZENA")
# --- V Medicusu (Firebird) ---
print("\n[Medicus — Firebird]")
dsn = r"localhost:c:\medicus 3\data\medicus.fdb"
conn_fb = fdb.connect(dsn=dsn, user="SYSDBA", password="masterkey", charset="win1250")
cur_fb = conn_fb.cursor()
# Najdi pacienta podle RC
cur_fb.execute("""
SELECT idpac, prijmeni, jmeno, vyrazen
FROM kar
WHERE rodcis = ?
""", (RC,))
kar_rows = cur_fb.fetchall()
if kar_rows:
print(f" NALEZENA v Medicusu!")
for kar in kar_rows:
idpac, prijmeni, jmeno, vyrazen = kar
print(f" Jméno: {prijmeni} {jmeno}")
print(f" Vyrazen: {vyrazen}")
# Zjisti registraci
cur_fb.execute("""
SELECT r.datum, r.datum_zruseni, r.priznak
FROM registr r
WHERE r.idpac = ? AND r.idicp = (
SELECT i.idicp FROM icp i
WHERE i.icp = '09305001' AND i.odb = '001'
)
ORDER BY r.datum DESC
""", (idpac,))
reg_rows = cur_fb.fetchall()
if reg_rows:
print(f" Registrace (posledních {len(reg_rows)}):")
for r in reg_rows[:3]:
datum, datum_zruseni, priznak = r
zrusena = "ANO" if datum_zruseni else "NE"
print(f" Datum: {datum}, Zrušena: {zrusena}, Příznak: {priznak}")
else:
print(f" ŽÁDNÁ registrace u našeho doktora!")
else:
print(f" NENALEZENA v Medicusu!")
conn_fb.close()
print("\n" + "=" * 80)
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
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 fdb
dsn = r"localhost:c:\medicus 3\data\medicus.fdb"
conn = fdb.connect(dsn=dsn, user="SYSDBA", password="masterkey", charset="win1250")
cur = conn.cursor()
RC = "9054260083"
# Zjisti podrobně
cur.execute("""
SELECT
kar.rodcis,
kar.prijmeni,
kar.jmeno,
kar.vyrazen,
r.idpac,
r.datum,
r.datum_zruseni,
r.priznak,
i.icp,
i.odb
FROM kar
LEFT JOIN registr r ON kar.idpac = r.idpac
LEFT JOIN icp i ON r.idicp = i.idicp
WHERE kar.rodcis = ?
ORDER BY r.datum DESC
""", (RC,))
rows = cur.fetchall()
print(f"Vymětalová Kristýna — podrobnosti:\n")
for r in rows:
print(f"RC: {r[0]}")
print(f"Jméno: {r[2]} {r[1]}")
print(f"Vyrazen: {r[3]}")
print(f"ID pacienta: {r[4]}")
print(f"Registrace datum: {r[5]}")
print(f"Registrace zrušena: {r[6]}")
print(f"Příznak: {r[7]}")
print(f"ICP: {r[8]}")
print(f"Odb: {r[9]}")
print()
conn.close()
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
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 pymysql
from Knihovny.medicus_db import get_medicus_db
DB_CONFIG = {
"host": "192.168.1.76",
"port": 3306,
"user": "root",
"password": "Vlado9674+",
"database": "medevio",
"charset": "utf8mb4",
"cursorclass": pymysql.cursors.DictCursor,
}
# Načti registrované v 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()
# Najdi všechny ACTIVE s účtem mimo Medicus
conn = pymysql.connect(**DB_CONFIG)
with conn.cursor() as cur:
cur.execute("""
SELECT name, surname, identification_number, user_id
FROM medevio_pacient
WHERE status = 'ACTIVE'
AND user_id IS NOT NULL
AND identification_number IS NOT NULL
ORDER BY surname, name
""")
all_with_account = cur.fetchall()
conn.close()
# Filtruj ty mimo Medicus
extras = [
r for r in all_with_account
if r["identification_number"] not in medicus_rc
]
print(f"PACIENTI S MEDEVIO ÚČTEM MIMO MEDICUS ({len(extras)}):\n")
for i, r in enumerate(extras, 1):
print(f"{i:2d}. {r['surname']} {r['name']} (RC: {r['identification_number']})")
+88
View File
@@ -0,0 +1,88 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
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 pymysql
from Knihovny.medicus_db import get_medicus_db
DB_CONFIG = {
"host": "192.168.1.76",
"port": 3306,
"user": "root",
"password": "Vlado9674+",
"database": "medevio",
"charset": "utf8mb4",
"cursorclass": pymysql.cursors.DictCursor,
}
# Načti registrované v 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í v Medicusu: {len(medicus_rc)}\n")
# Načti všechny pacienty z MySQL
conn = pymysql.connect(**DB_CONFIG)
with conn.cursor() as cur:
cur.execute("SELECT status, user_id, identification_number FROM medevio_pacient ORDER BY status, user_id")
all_rows = cur.fetchall()
conn.close()
# Analýza
stats = {}
for r in all_rows:
status = r['status']
has_user_id = "S user_id" if r['user_id'] else "BEZ user_id"
key = f"{status}{has_user_id}"
if key not in stats:
stats[key] = {"total": 0, "in_medicus": 0, "out_medicus": 0}
stats[key]["total"] += 1
if r['identification_number']:
if r['identification_number'] in medicus_rc:
stats[key]["in_medicus"] += 1
else:
stats[key]["out_medicus"] += 1
print("=" * 90)
print("STATISTIKA user_id v Medeviu")
print("=" * 90)
for key in sorted(stats.keys()):
s = stats[key]
print(f"\n{key:40s}")
print(f" Celkem: {s['total']:5d}")
print(f" V Medicusu: {s['in_medicus']:5d}")
print(f" MIMO Medicus: {s['out_medicus']:5d}")
print("\n" + "=" * 90)
print("SHRNUTÍ:")
print("=" * 90)
with_user = sum(s['total'] for k, s in stats.items() if "S user_id" in k)
without_user = sum(s['total'] for k, s in stats.items() if "BEZ user_id" in k)
print(f"\nCelkem S user_id: {with_user}")
print(f"Celkem BEZ user_id: {without_user}")
print(f"CELKEM: {with_user + without_user}")
# Vztah k Medicusu
active_with_user_out = sum(s['out_medicus'] for k, s in stats.items() if "ACTIVE" in k and "S user_id" in k)
active_without_user_out = sum(s['out_medicus'] for k, s in stats.items() if "ACTIVE" in k and "BEZ user_id" in k)
print(f"\nACTIVE S user_id mimo Medicus: {active_with_user_out}")
print(f"ACTIVE BEZ user_id mimo Medicus: {active_without_user_out}")
print("=" * 90)
+57 -15
View File
@@ -21,15 +21,18 @@ import json
import time import time
import pymysql import pymysql
import requests import requests
import threading
from pathlib import Path from pathlib import Path
from datetime import datetime from datetime import datetime
from dateutil import parser as dtparser, tz from dateutil import parser as dtparser, tz
from concurrent.futures import ThreadPoolExecutor, as_completed
# ==================== CONFIG ==================== # ==================== CONFIG ====================
GRAPHQL_URL = "https://api.medevio.cz/graphql" GRAPHQL_URL = "https://api.medevio.cz/graphql"
CLINIC_SLUG = "mudr-buzalkova" CLINIC_SLUG = "mudr-buzalkova"
PAGE_SIZE = 50 PAGE_SIZE = 500
DELAY_BETWEEN_REQUESTS = 0.3 DELAY_BETWEEN_REQUESTS = 0.3
MAX_WORKERS = 5 # Počet paralelních threadů pro stahování detailů
TOKEN_PATH = Path(__file__).resolve().parent.parent / "token.txt" TOKEN_PATH = Path(__file__).resolve().parent.parent / "token.txt"
@@ -245,6 +248,56 @@ def fetch_patient_detail(headers, patient_id):
return None return None
# ==================== RATE LIMITER ====================
class RateLimiter:
"""Globální rate limiter pro API requesty."""
def __init__(self, delay_seconds):
self.delay = delay_seconds
self.last_call = 0
self.lock = threading.Lock()
def wait(self):
with self.lock:
elapsed = time.time() - self.last_call
if elapsed < self.delay:
time.sleep(self.delay - elapsed)
self.last_call = time.time()
rate_limiter = RateLimiter(DELAY_BETWEEN_REQUESTS)
def fetch_patient_detail_safe(headers, patient_id):
"""Stáhne detail s globálním rate limitem."""
rate_limiter.wait()
return fetch_patient_detail(headers, patient_id)
def fetch_all_details_threaded(headers, patients):
"""Stáhne detaily všech pacientů paralelně."""
detailed = []
errors = 0
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
futures = {
executor.submit(fetch_patient_detail_safe, headers, p["id"]): p
for p in patients
}
for i, future in enumerate(as_completed(futures)):
detail = future.result()
if detail:
detailed.append(detail)
else:
errors += 1
if (i + 1) % 50 == 0:
print(f" Detail {i + 1}/{len(patients)}...")
return detailed, errors
def patient_to_row(p): def patient_to_row(p):
"""Převede patient dict na tuple pro UPSERT.""" """Převede patient dict na tuple pro UPSERT."""
insurance = p.get("insuranceCompanyObject") or {} insurance = p.get("insuranceCompanyObject") or {}
@@ -308,20 +361,9 @@ def main():
conn.close() conn.close()
return return
# --- Krok 2: pro každého stáhni detail --- # --- Krok 2: pro každého stáhni detail (paralelně) ---
print(f"\nStahuji detaily pro {len(patients)} pacientu...") print(f"\nStahuji detaily pro {len(patients)} pacientu ({MAX_WORKERS} threadů)...")
detailed = [] detailed, errors = fetch_all_details_threaded(headers, patients)
errors = 0
for i, p in enumerate(patients):
detail = fetch_patient_detail(headers, p["id"])
if detail:
detailed.append(detail)
else:
errors += 1
if (i + 1) % 50 == 0:
print(f" Detail {i + 1}/{len(patients)}...")
time.sleep(DELAY_BETWEEN_REQUESTS)
# --- Krok 3: upsert do MySQL --- # --- Krok 3: upsert do MySQL ---
count = upsert_patients(conn, detailed) count = upsert_patients(conn, detailed)
+154
View File
@@ -0,0 +1,154 @@
#!/usr/bin/env python3
"""
MCP server pro Firebird/Medicus — používá oficiální MCP SDK (FastMCP)
Spustit: python mcp_firebird.py
"""
import sys
import fdb
import traceback
from typing import Optional
from mcp.server.fastmcp import FastMCP
FB_CONFIG = {
'dsn': r'localhost:c:\medicus 3\data\medicus.fdb',
'user': 'SYSDBA',
'password': 'masterkey',
'charset': 'win1250',
'port': 3070,
}
# Všechny logy MUSÍ jít na stderr — stdout je rezervován pro JSON-RPC
def log(msg: str):
print(msg, file=sys.stderr, flush=True)
# Připojení k Firebirdu
try:
conn = fdb.connect(**FB_CONFIG)
log("✓ Připojeno k Firebirdu (Medicus)")
except Exception as e:
log(f"✗ Chyba připojení k Firebirdu: {e}")
sys.exit(1)
def rows_to_json(rows, description):
"""Převede fdb rows na JSON-serializovatelný formát"""
import datetime
import decimal
def convert(val):
if isinstance(val, (datetime.date, datetime.datetime)):
return val.isoformat()
if isinstance(val, decimal.Decimal):
return float(val)
if isinstance(val, bytes):
return val.decode('win1250', errors='replace')
return val
cols = [d[0].strip() for d in description]
return [dict(zip(cols, [convert(v) for v in row])) for row in rows]
# MCP server
mcp = FastMCP("medicus-firebird")
@mcp.tool()
def execute_query(sql: str, params: Optional[list] = None) -> dict:
"""Spusť SQL dotaz na Medicus databázi.
Pro SELECT vrátí columns + rows. Pro INSERT/UPDATE/DELETE vrátí rowcount.
"""
try:
cur = conn.cursor()
if params:
cur.execute(sql, params)
else:
cur.execute(sql)
if sql.strip().upper().startswith('SELECT'):
rows = rows_to_json(cur.fetchall(), cur.description or [])
return {
'rowcount': len(rows),
'rows': rows
}
else:
conn.commit()
return {
'rowcount': cur.rowcount,
'message': f'Dotaz proveden: {cur.rowcount} řádků ovlivněno'
}
except Exception as e:
log(f"execute_query chyba: {traceback.format_exc()}")
raise
@mcp.tool()
def list_tables() -> list[str]:
"""Vrátí seznam všech uživatelských tabulek v Medicus databázi."""
try:
cur = conn.cursor()
cur.execute("""
SELECT TRIM(RDB$RELATION_NAME)
FROM RDB$RELATIONS
WHERE RDB$SYSTEM_FLAG = 0
ORDER BY RDB$RELATION_NAME
""")
return [row[0] for row in cur.fetchall()]
except Exception as e:
log(f"list_tables chyba: {traceback.format_exc()}")
raise
@mcp.tool()
def get_table_columns(table_name: str) -> list[str]:
"""Vrátí seznam sloupců dané tabulky."""
try:
cur = conn.cursor()
cur.execute("""
SELECT TRIM(RDB$FIELD_NAME)
FROM RDB$RELATION_FIELDS
WHERE TRIM(RDB$RELATION_NAME) = ?
ORDER BY RDB$FIELD_POSITION
""", [table_name.upper()])
return [row[0] for row in cur.fetchall()]
except Exception as e:
log(f"get_table_columns chyba: {traceback.format_exc()}")
raise
@mcp.tool()
def get_schema() -> dict:
"""Vrátí kompletní schéma DB — všechny tabulky a jejich sloupce."""
try:
cur = conn.cursor()
cur.execute("""
SELECT r.RDB$RELATION_NAME, f.RDB$FIELD_NAME
FROM RDB$RELATIONS r
LEFT JOIN RDB$RELATION_FIELDS f ON r.RDB$RELATION_NAME = f.RDB$RELATION_NAME
WHERE r.RDB$SYSTEM_FLAG = 0
ORDER BY r.RDB$RELATION_NAME, f.RDB$FIELD_POSITION
""")
schema = {}
for tbl_name, col_name in cur.fetchall():
tbl = tbl_name.strip() if tbl_name else 'unknown'
col = col_name.strip() if col_name else ''
if tbl not in schema:
schema[tbl] = []
if col:
schema[tbl].append(col)
return {
'table_count': len(schema),
'tables': list(schema.keys()),
'schema': schema
}
except Exception as e:
log(f"get_schema chyba: {traceback.format_exc()}")
raise
if __name__ == '__main__':
log("MCP Firebird server spuštěn (FastMCP)")
mcp.run()
+1
View File
@@ -0,0 +1 @@
{"method": "get_schema"}
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Test pripojeni k Firebird databazi na REPORTER"""
import sys
print("=== Test pripojeni k Firebird na REPORTER ===\n")
# 1. Zkontroluj fdb
try:
import fdb
print("+ fdb je nainstalovan")
except ImportError as e:
print(f"- fdb neni nainstalovan: {e}")
print(" Instalace: pip install fdb")
sys.exit(1)
# 2. Zkus pripojeni
print("\nPokus o pripojeni k databazi...")
print(" dsn: reporter:c:\\medicus\\medicus.fdb")
print(" user: SYSDBA")
print(" charset: win1250\n")
try:
conn = fdb.connect(
dsn=r'reporter:c:\medicus\medicus.fdb',
user='SYSDBA',
password='masterkey',
charset='win1250'
)
print("+ Pripojeni se podarilo!")
# Testovaci SELECT
cursor = conn.cursor()
# Jednoducky test - zjisti verzi Firebirdu
cursor.execute("SELECT RDB$GET_CONTEXT('SYSTEM', 'ENGINE_VERSION') FROM RDB$DATABASE")
version = cursor.fetchone()[0]
print(f"+ Firebird verze: {version}")
# Zjisti kolik je tabulek
cursor.execute("SELECT COUNT(*) FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG = 0")
table_count = cursor.fetchone()[0]
print(f"+ Pocet uzivatelskych tabulek: {table_count}")
conn.close()
print("\n" + "="*60)
print("SUCCESS: Databaze na REPORTER je dostupna a funguje!")
print("="*60)
print("\nMuzete pouzit:")
print(" conn = fdb.connect(")
print(" dsn=r'reporter:c:\\medicus\\medicus.fdb',")
print(" user='SYSDBA',")
print(" password='masterkey',")
print(" charset='win1250'")
print(" )")
except Exception as e:
print(f"\n- Chyba: {type(e).__name__}")
print(f" {e}")
import traceback
traceback.print_exc()
sys.exit(1)