Files
recept/Dotazy/prehled_pacienta.py
T
2026-04-13 16:45:07 +02:00

393 lines
12 KiB
Python

"""
Prehled lekoveho zaznamu pacienta z MySQL.
Zobrazuje:
1. Lekare, kteri pacientovi predepsali leky (sestupne podle poctu predpisu)
2. Vsechny predpisy od zadaneho data — s nazvem VYDANEHO leku (ne predepsaneho)
Nastaveni:
RODNE_CISLO ... rodne cislo pacienta (cifry, bez lomitka)
DATUM_OD ... predpisy od tohoto data ve formatu DD.MM.RRRR (None = vsechny)
"""
from datetime import date, datetime
import sys
import fdb
import pymysql
import pymysql.cursors
# Kody odbornosti dle SUKL / VZP (posledni 3 cislice ICP)
ODBORNOST = {
# Základní ambulantní odbornosti
"001": "Praktický lékař",
"002": "Pediatr (prakt.)",
"003": "Chirurgie",
"004": "Ortopedie",
"005": "ORL",
"006": "Gynekologie",
"007": "Urologie",
"008": "Neurologie",
"009": "Psychiatrie",
"010": "Oftalmologie",
"011": "Zubní lékařství",
"012": "Dermatovenerologie",
"013": "Infekční lékařství",
"014": "Radiodiagnostika",
"015": "Stomatochirurgie",
"016": "Čelistní ortopedie",
"017": "Dětská psychiatrie",
"018": "Pneumologie",
"019": "Anesteziologie",
"020": "Rehabilitace",
"021": "Radiodiagnostika",
"022": "Radioterapie",
"023": "Nukleární medicína",
"024": "Klin. biochemie",
"025": "Alergologie/imunologie",
"026": "Hematologie",
"027": "Soudní lékařství",
"028": "Soudní psychiatrie",
"029": "Lékařská genetika",
"031": "Gastroenterologie",
"032": "Nefrologie",
"033": "Kardiologie",
"034": "Endokrinologie/diab.",
"035": "Revmatologie",
"040": "Vnitřní lékařství",
"041": "Geriatrie",
"042": "Klin. farmakologie",
"043": "Diabetologie",
"044": "Endokrinologie",
"045": "Hepatologie",
"052": "Dětská neurologie",
"060": "Dětská chirurgie",
"065": "Plastická chirurgie",
"066": "Cévní chirurgie",
"067": "Kardiochirurgie",
"072": "Foniatrie",
"074": "Neurochirurgie",
"077": "Maxilofaciální chir.",
"079": "Hrudní chirurgie",
"082": "Urologie",
"083": "Andrologie",
"085": "Proktologie",
"091": "Gynekolog. onkologie",
"092": "Reprodukční medicína",
"096": "Léčebná rehabilitace",
"097": "Fyzioterapie",
# Interní a specializované odbornosti
"101": "Vnitřní lékařství",
"102": "Kardiologie",
"104": "Kardiologie",
"105": "Gastroenterologie",
"106": "Hepatologie",
"107": "Nefrologie",
"108": "Nefrologie",
"110": "Diabetologie",
"111": "Endokrinologie",
"114": "Pneumologie",
"115": "Ftizeologie",
"121": "Endokrinologie",
"122": "Diabetologie",
"129": "Andrologie",
"143": "Psychiatrie",
"144": "Psychoterapie",
"145": "Adiktologie",
"148": "Dětská psychiatrie",
"155": "Oční onkologie",
"156": "Hematologie",
"157": "Hemostáza",
"160": "Neurologie",
"162": "Epileptologie",
"163": "Dětská neurologie",
"164": "Neurorehabilit.",
"168": "Klin. neurofyziologie",
"169": "Revmatologie",
"174": "Ortoped. protetika",
"181": "Infektologie",
"183": "Tropická medicína",
"185": "Mikrobiologie",
"188": "Virologie",
# Chirurgické a dětské odbornosti
"200": "Stomatologie",
"201": "Stomatochirurgie",
"202": "Maxilofaciální chir.",
"203": "Parodontologie",
"204": "Ortodoncie",
"205": "Zubní protetika",
"206": "Dětská stomatologie",
"220": "Pediatrie",
"221": "Neonatologie",
"222": "Dětská endokrinol.",
"223": "Dětská gastroenterol.",
"234": "Dětská hematologie",
"239": "Dětská nefrologie",
"243": "Dětská pneumologie",
"245": "Dětská psychiatrie",
"246": "Dětská revmatologie",
"247": "Dětská kardiologie",
"250": "Dětská neurologie",
"251": "Dětská neurologie",
"258": "Dětská onkologie",
"261": "Dětská chirurgie",
"262": "Dětská ortopedie",
"263": "Urologie",
"264": "Dětská stomatologie",
"271": "Dětská klin. biochem.",
"272": "Alergologie",
"273": "Dětská alergologie",
"281": "Dětská dermatologie",
"282": "Dětská radiologie",
"283": "Dětská neurochir.",
"289": "Dětská kardiochir.",
"291": "Dětská onkol. chir.",
"294": "Dětská oftalmologie",
"295": "Dětská gynekologie",
# Onkologie a zobrazovací metody
"300": "Onkologie",
"301": "Klin. onkologie",
"302": "Radiodiagnostika",
"303": "Radioterapie",
"304": "Nukleární medicína",
"305": "Nukleární kardiologie",
"316": "Klin. genetika",
"319": "Soudní lékařství",
"321": "Cytologie",
"324": "Klin. onkologie",
"333": "Onkologie",
# Stomatologie (500-599)
"501": "Zubní lékařství",
"502": "Čelistní ortopedie",
"503": "Stomatochirurgie",
"508": "Parodontologie",
"509": "Ortodoncie",
"510": "Dětská stomatologie",
"513": "Zubní protetika",
"535": "Orální medicína",
"555": "Stomatologie",
"558": "Zubní lékařství",
"559": "Stomatologie",
"560": "Stomatologie",
"562": "Stomatologie",
"571": "Stomatologie",
"574": "Stomatologie",
"580": "Stomatologie",
"581": "Stomatologie",
"582": "Stomatologie",
"584": "Stomatologie",
"590": "Lékárenství",
# Onkologie (600-699)
"600": "Onkologie",
"601": "Klin. onkologie",
"603": "Onkologie",
"606": "Radioterapie",
"607": "Nukleární medicína",
"615": "Onkologie",
# Kardiochirurgie, ostatní (700+)
"700": "Chirurgie",
"701": "Cévní chirurgie",
"702": "Hrudní chirurgie",
"704": "Kardiochirurgie",
"705": "Chirurgie",
"706": "Plastická chirurgie",
"719": "Dětská chirurgie",
"721": "Ortopedie",
"722": "Ortopedie",
"723": "Ortopedie",
# Fyzioterapie, rehabilitace (800+)
"801": "Fyzioterapie",
"802": "Ergoterapie",
"852": "Fyzioterapie",
"853": "Fyzioterapie",
"858": "Fyzioterapie",
"860": "Fyzioterapie",
"862": "Fyzioterapie",
"873": "Fyzioterapie",
"880": "Rehabilitace",
"881": "Endokrinologie",
"885": "Rehabilitace",
"889": "Rehabilitace",
"890": "Rehabilitace",
}
def odbornost_z_icp(icp):
"""Vrati nazev odbornosti z ICP kodu (posledni 3 cislice)."""
if not icp or len(icp) < 3:
return ""
kod = icp[-3:]
return ODBORNOST.get(kod, f"odb. {kod}")
# ── NASTAVENÍ ─────────────────────────────────────────────────────────────────
RODNE_CISLO = "440802/018" # funguje s lomitkem i bez: 7309208104 nebo 730920/8104
DATUM_OD = "01.01.2025" # None = vsechny predpisy
# ─────────────────────────────────────────────────────────────────────────────
FB = dict(
dsn = r"localhost:c:\medicus 3\data\medicus.fdb",
user = "SYSDBA",
password= "masterkey",
charset = "win1250",
)
DB = dict(
host = "192.168.1.76",
user = "root",
password = "Vlado9674+",
database = "medicus",
charset = "utf8mb4",
cursorclass = pymysql.cursors.DictCursor,
)
SEP = "-" * 110
SEP2 = "-" * 165
def parse_datum(s, nazev):
try:
return datetime.strptime(s, "%d.%m.%Y").date()
except (ValueError, TypeError):
sys.exit(f"Nespravny format data '{nazev}': '{s}'. Pouzijte DD.MM.RRRR.")
def normalizuj_rc(rc):
"""Odstrani lomitko a mezery z rodneho cisla."""
return rc.replace("/", "").replace(" ", "").strip()
def najdi_v_firebirdu(rodne_cislo):
"""Vrati prijmeni, jmeno a datum narozeni z Medicusu podle rodneho cisla."""
rc = normalizuj_rc(rodne_cislo)
conn = fdb.connect(**FB)
try:
cur = conn.cursor()
cur.execute(
"SELECT KAR.PRIJMENI, KAR.JMENO, KAR.DATNAR "
"FROM KAR WHERE KAR.RODCIS = ?",
(rc,)
)
row = cur.fetchone()
if not row:
sys.exit(f"Rodne cislo '{rodne_cislo}' nenalezeno v Medicusu.")
return {"prijmeni": row[0].strip(), "jmeno": row[1].strip(), "datnar": row[2]}
finally:
conn.close()
def najdi_pacienty(cur, prijmeni, datum_narozeni):
cur.execute(
"SELECT id, prijmeni, jmena, datum_narozeni "
"FROM pacient WHERE prijmeni = %s AND datum_narozeni = %s",
(prijmeni, datum_narozeni),
)
return cur.fetchall()
def tiskni_lekare(cur, pacient_id, prijmeni, jmena, datum_narozeni):
cur.execute(
"""
SELECT pr.prijmeni, pr.jmena,
pr.icp,
CONCAT(pr.pzs_nazev, ', ', pr.ulice, ', ', pr.psc, ' ', pr.mesto) AS adresa,
COUNT(*) AS pocet_predpisu
FROM zprava z
JOIN predpis p ON p.zprava_id = z.id
JOIN predepisujici pr ON pr.lekar_kod = p.kod_predepisujiciho
WHERE z.pacient_id = %s
GROUP BY pr.lekar_kod, pr.prijmeni, pr.jmena, pr.icp, pr.pzs_nazev, pr.ulice, pr.psc, pr.mesto
ORDER BY pocet_predpisu DESC
""",
(pacient_id,),
)
rows = cur.fetchall()
print(f"\n{SEP}")
print(f" PACIENT: {prijmeni} {jmena} | nar. {datum_narozeni.strftime('%d.%m.%Y')}")
print(SEP)
print(f"\nPREDEPISUJICI LEKARI:")
print(f"{'#':<4} {'Lekar':<30} {'Odbornost':<25} {'Pracoviste a adresa':<50} {'Predpisu':>8}")
print(SEP)
for i, r in enumerate(rows, 1):
lekar = f"{r['prijmeni']} {r['jmena']}"
odb = odbornost_z_icp(r['icp'])
print(f"{i:<4} {lekar:<30} {odb:<25} {r['adresa']:<50} {r['pocet_predpisu']:>8}")
if not rows:
print(" Zadne predpisy nenalezeny.")
def tiskni_predpisy(cur, pacient_id, datum_od):
podminka = "AND p.datum_vystaveni >= %s" if datum_od else ""
params = (pacient_id, datum_od) if datum_od else (pacient_id,)
cur.execute(
f"""
SELECT p.datum_vystaveni,
COALESCE(v.nazev, p.nazev) AS vydany_lek,
v.nazev IS NULL AS nevyzvednuto,
p.atc,
p.navod,
pr.prijmeni,
pr.jmena,
pr.icp,
CONCAT(pr.pzs_nazev, ', ', pr.ulice, ', ', pr.psc, ' ', pr.mesto) AS adresa
FROM zprava z
JOIN predpis p ON p.zprava_id = z.id
JOIN predepisujici pr ON pr.lekar_kod = p.kod_predepisujiciho
LEFT JOIN vydej v ON v.id_lp_predpis = p.id_lp_predpis
WHERE z.pacient_id = %s
{podminka}
ORDER BY p.datum_vystaveni DESC
""",
params,
)
rows = cur.fetchall()
od_text = f"od {datum_od.strftime('%d.%m.%Y')}" if datum_od else "vse"
print(f"\nVSECHNY PREDPISY ({od_text}) — celkem {len(rows)}:")
print(f"{'#':<4} {'Datum':<12} {'Vydany lek':<30} {'ATC':<8} {'Navod':<20} {'Lekar':<25} {'Odbornost':<22} Adresa")
print(SEP2)
for i, r in enumerate(rows, 1):
datum = r["datum_vystaveni"].strftime("%d.%m.%Y")
lekar = f"{r['prijmeni']} {r['jmena']}"
lek = (r["vydany_lek"] or "")[:28]
if r["nevyzvednuto"]:
lek = f"{lek} *NV"
navod = (r["navod"] or "")[:19]
atc = (r["atc"] or "")
odb = odbornost_z_icp(r["icp"])[:21]
print(f"{i:<4} {datum:<12} {lek:<30} {atc:<8} {navod:<20} {lekar:<25} {odb:<22} {r['adresa']}")
if not rows:
print(" Zadne predpisy nenalezeny.")
print()
def main():
datum_od = parse_datum(DATUM_OD, "DATUM_OD") if DATUM_OD else None
# 1. Najdi pacienta v Medicusu (Firebird) podle rodneho cisla
fb_pac = najdi_v_firebirdu(RODNE_CISLO)
prijmeni = fb_pac["prijmeni"]
datum_narozeni = fb_pac["datnar"]
print(f"\nFirebird: nalezen {prijmeni} {fb_pac['jmeno']} nar. {datum_narozeni}")
# 2. Dotaz do MySQL
conn = pymysql.connect(**DB)
try:
with conn.cursor() as cur:
pacienti = najdi_pacienty(cur, prijmeni, datum_narozeni)
if not pacienti:
print(f"Pacient '{prijmeni}' nar. {datum_narozeni} nema zaznam v MySQL (lekovy zaznam nebyl stazeny).")
return
for pac in pacienti:
tiskni_lekare(cur, pac["id"], pac["prijmeni"], pac["jmena"], pac["datum_narozeni"])
tiskni_predpisy(cur, pac["id"], datum_od)
finally:
conn.close()
if __name__ == "__main__":
main()