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 pymysql
import requests
import threading
from pathlib import Path
from datetime import datetime
from dateutil import parser as dtparser, tz
from concurrent.futures import ThreadPoolExecutor, as_completed
# ==================== CONFIG ====================
GRAPHQL_URL = "https://api.medevio.cz/graphql"
CLINIC_SLUG = "mudr-buzalkova"
PAGE_SIZE = 50
PAGE_SIZE = 500
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"
@@ -245,6 +248,56 @@ def fetch_patient_detail(headers, patient_id):
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):
"""Převede patient dict na tuple pro UPSERT."""
insurance = p.get("insuranceCompanyObject") or {}
@@ -308,20 +361,9 @@ def main():
conn.close()
return
# --- Krok 2: pro každého stáhni detail ---
print(f"\nStahuji detaily pro {len(patients)} pacientu...")
detailed = []
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 2: pro každého stáhni detail (paralelně) ---
print(f"\nStahuji detaily pro {len(patients)} pacientu ({MAX_WORKERS} threadů)...")
detailed, errors = fetch_all_details_threaded(headers, patients)
# --- Krok 3: upsert do MySQL ---
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)