# Dotazy — přehled lékového záznamu pacienta Skripty pro zobrazení a export lékového záznamu konkrétního pacienta z MySQL databáze `medicus`. Pacient se identifikuje **rodným číslem** — to se vyhledá v lokální Firebird databázi Medicusu, odkud se získá příjmení a datum narození, a teprve těmito dvěma hodnotami se najde pacient v MySQL. --- ## Soubory | Soubor | Co dělá | |--------|---------| | `prehled_pacienta.py` | Konzolový výpis — lékaři + předpisy pacienta | | `prehled_pacienta_excel.py` | Export do formátovaného souboru Excel (.xlsx) | --- ## Nastavení (obě skripty) Na začátku každého souboru jsou tři proměnné: ```python RODNE_CISLO = "440802/018" # rodné číslo — funguje s lomítkem i bez: "4408020183" DATUM_OD = "01.01.2025" # předpisy od tohoto data; None = všechny předpisy VYSTUP_DIR = None # pouze excel: složka výstupu; None = stejná jako skript ``` --- ## Spuštění ```bash # Konzolový výpis .venv\Scripts\python.exe Dotazy\prehled_pacienta.py # Export do Excelu .venv\Scripts\python.exe Dotazy\prehled_pacienta_excel.py ``` --- ## Zdroje dat ### 1. Firebird — Medicus (`medicus.fdb`) Slouží výhradně k identifikaci pacienta podle rodného čísla. ``` DSN: localhost:c:\medicus 3\data\medicus.fdb User: SYSDBA / masterkey Charset: win1250 Tabulka: KAR ``` Dotaz: ```sql SELECT KAR.PRIJMENI, KAR.JMENO, KAR.DATNAR FROM KAR WHERE KAR.RODCIS = ? ``` Rodné číslo se normalizuje před dotazem — odstraní se lomítko a mezery: ```python rc = rc.replace("/", "").replace(" ", "").strip() ``` ### 2. MySQL — databáze `medicus` Obsahuje lékové záznamy stažené z eReceptu SÚKL. ``` Host: 192.168.1.76 User: root DB: medicus ``` Pacient se vyhledá podle příjmení a data narození (získaných z Firebirdu): ```sql SELECT id, prijmeni, jmena, datum_narozeni FROM pacient WHERE prijmeni = %s AND datum_narozeni = %s ``` --- ## Co se zobrazuje ### Část 1 — Předepisující lékaři Všichni lékaři, kteří pacientovi za celou dobu předepsali alespoň jeden lék, seřazeni sestupně podle počtu předpisů. Sloupce: `#` | `Lékař` | `Odbornost` | `Pracoviště a adresa` | `Předpisů` ```sql 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 ``` ### Část 2 — Všechny předpisy Předpisy od `DATUM_OD`, seřazené sestupně dle data vystavení. Zobrazuje se **vydaný lék** (z tabulky `vydej`), nikoli předepsaný název. Pokud lék nebyl vyzvednut, zobrazí se předepsaný název s příznakem `*NV`. Sloupce: `#` | `Datum` | `Vydaný lék` | `ATC` | `Návod` | `Lékař` | `Odbornost` | `Adresa` ```sql 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 AND p.datum_vystaveni >= %s -- pouze pokud DATUM_OD není None ORDER BY p.datum_vystaveni DESC ``` Klíčový princip `COALESCE(v.nazev, p.nazev)`: - `v.nazev` — název léku, který lékárna **skutečně vydala** (může být jiná značka než předepsaná) - `p.nazev` — název léku, který lékař **předepsal** (zobrazí se jen pokud výdej neexistuje → `*NV`) --- ## Odbornost lékaře Odbornost se odvozuje z posledních 3 číslic pole `predepisujici.icp` (IČP pracoviště). ``` ICP: 09305001 → kód odbornosti: 001 → všeobecné praktické lékařství ICP: 08006272 → kód odbornosti: 272 → alergologie ICP: 08075603 → kód odbornosti: 603 → onkologie ``` Funkce: ```python def odbornost_z_icp(icp): if not icp or len(icp) < 3: return "" return ODBORNOST.get(icp[-3:], f"odb. {icp[-3:]}") ``` Pro neznámé kódy se zobrazí `odb. XXX` (XXX = třímístný kód). ### Zdroj dat — tabulky `vzp_pracoviste` + `odbornost` (MySQL) Slovník `ODBORNOST` se **načítá dynamicky při startu skriptu** z MySQL: ```python def _nacti_odbornosti(): conn = pymysql.connect(**DB) try: with conn.cursor(pymysql.cursors.Cursor) as cur: cur.execute(""" SELECT vp.icp, o.nazev FROM vzp_pracoviste vp JOIN odbornost o ON o.kod = vp.odbornost WHERE CURDATE() BETWEEN vp.platnost_od AND vp.platnost_do ORDER BY vp.platnost_od DESC """) result = {} for icp, nazev in cur.fetchall(): result.setdefault(icp, nazev) return result finally: conn.close() ODBORNOST = _nacti_odbornosti() ``` - `vzp_pracoviste` — oficiální číselník VZP (stahován týdně z VZP Point přes `import_vzp_pracoviste.py`), obsahuje ~52 000 záznamů s přímou vazbou ICP → kód odbornosti - `odbornost` — číselník názvů odborností importovaný z Firebird tabulky `odborn` (360 aktuálně platných kódů) - Vyhledávání probíhá podle **plného 8-znakového ICP** — spolehlivé i pro pracoviště, která změnila odbornost - Slovník obsahuje ~43 000 aktuálně platných ICP kódů --- ## Excel export (`prehled_pacienta_excel.py`) Soubor se ukládá do stejné složky jako skript (nebo do `VYSTUP_DIR`). ### Pojmenování souborů ``` LZ_{Prijmeni}_{Jmeno}_{datum_narozeni}.xlsx ← základní LZ_{Prijmeni}_{Jmeno}_{datum_narozeni}_v2.xlsx ← pokud základní existuje LZ_{Prijmeni}_{Jmeno}_{datum_narozeni}_v3.xlsx ← atd. ``` Versioning zabrání přepsání dříve exportovaných souborů. ### Vzhled a formátování | Prvek | Barva | Popis | |-------|-------|-------| | Záhlaví (jméno pacienta) | `#1F4E79` tmavě modrá | tučné, 14pt | | Záhlaví tabulky | `#1F4E79` tmavě modrá | bílý text, 10pt | | Nadpis sekce | `#2E75B6` střední modrá | bílý text, 11pt | | Info o pacientovi | `#DEEAF1` světle modrá | datum narozeni, datum tisku, předpisy od | | Sudé řádky | `#EBF3FB` velmi světle modrá | střídání řádků | | Liché řádky | `#FFFFFF` bílá | | | Nevyzvednuto | `#FCE4D6` lososová | zvýraznění celého řádku | | Ohraničení | `#B8CCE4` světle modrá | tenká linka | - Font: **Arial** ve všech buňkách - Automatická šířka sloupců a výška řádků (`autofit`) - Zmrazení prvního řádku (`freeze_panes = "A2"`) - 8 sloupců: `#` | `Lékař/Datum` | `Odbornost/Vydaný lék` | `Pracoviště/ATC` | … | `Předpisů/Pracoviště a adresa` ### Tabulka lékařů (8 sloupců) `#` | `Lékař` | `Odbornost` | `Pracoviště` | `Ulice` | `PSČ` | `Město` | `Předpisů` ### Tabulka předpisů (8 sloupců) `#` | `Datum` | `Vydaný lék` | `ATC` | `Návod` | `Lékař` | `Odbornost` | `Pracoviště a adresa` --- ## Závislosti ``` pymysql ← MySQL klient fdb ← Firebird klient openpyxl ← Excel export (pouze prehled_pacienta_excel.py) ``` Všechny jsou součástí `requirements.txt` a nainstalují se přes `setup.ps1`. --- ## Typické chybové situace | Chyba | Příčina | Řešení | |-------|---------|--------| | `Rodne cislo nenalezeno v Medicusu` | RC není v tabulce KAR | Zkontrolovat číslo, ověřit v Medicusu | | `Pacient nema zaznam v MySQL` | Lékový záznam nebyl stažen | Spustit `07StahnoutVsechny.py` nebo `reimport_z_xml.py` | | `PermissionError` při ukládání xlsx | Soubor je otevřen v Excelu | Zavřít Excel a spustit znovu — verzování uloží jako `_v2` | | Odbornost zobrazena jako `odb. XXX` | Kód není ve slovníku | Informativní stav — kód je platný, jen není pojmenován |