PNWithClaude – Dokumentace projektu
Účel: Python skripty spouštěné tlačítkem z Medicusu, které rozšiřují možnosti vestavěných reportů. Vznikly díky SQL loggeru/debuggeru v Medicusu, který odhalil strukturu databáze.
Prostředí
| Položka | Hodnota |
|---|---|
| Python | 3.12.9 (64-bit) |
| Python exe | C:\Users\vlado\PycharmProjects\Medicus\.venv\Scripts\python.exe |
| Pythonw exe | C:\Users\vlado\PycharmProjects\Medicus\.venv\Scripts\pythonw.exe |
| Projekt | C:\Users\vlado\PycharmProjects\Medicus\ |
| Skripty | C:\Users\vlado\PycharmProjects\Medicus\PNWithClaude\ |
| Databáze | Firebird – localhost:c:\medicus 3\data\medicus.fdb |
Klíčové Python balíčky
fdb– Firebird databázový drivertkinter– GUI (součást Pythonu, není třeba instalovat)
Připojení k databázi
import fdb
conn = fdb.connect(
dsn=r'localhost:c:\medicus 3\data\medicus.fdb',
user='SYSDBA',
password='masterkey',
charset='win1250'
)
⚠️ Charset
win1250je kritický – bez něj jsou česká písmena rozbitá.
Konvence pojmenování skriptů
NNN_popisne_jmeno.py
NNN= třímístné číslo (001, 002, 003, ...)- Příklad:
003_aktivni_PN_seznam.py
Jak nastavit tlačítko v Medicusu
Medicus → Konfigurace → Externí programy (nebo Nástroje → Nastavení)
Pole v dialogu „Externí program"
| Pole | Hodnota |
|---|---|
| Příkazový řádek | "C:\Users\vlado\PycharmProjects\Medicus\.venv\Scripts\pythonw.exe" "C:\Users\vlado\PycharmProjects\Medicus\PNWithClaude\NNN_skript.py" |
| Program | C:\Users\vlado\PycharmProjects\Medicus\.venv\Scripts\pythonw.exe |
| Spustit v | (nechat prázdné) |
| Popis | Název tlačítka v Medicusu |
| Pacient | ☐ nezaškrtávat (pokud skript nepotřebuje aktuálního pacienta) |
⚠️
pythonw.exemístopython.exe= žádné černé konzolové okno!⚠️ „Spustit v" nechat prázdné – Medicus hlásí chybu pokud složka „neexistuje" (i když existuje), ale hlavně to nepotřebujeme, protože používáme absolutní cesty všude.
Jak přidat tlačítko na lištu
Po uložení externího programu → pravým tlačítkem na lištu → přizpůsobit → najít nový program → přetáhnout na lištu.
Předávání dat z Medicusu skriptu
Medicus umí předat proměnné přes příkazový řádek, např.:
"pythonw.exe" "skript.py" "%RODCISN%" "%JMENO%" "%PRIJMENI%"
Dostupné proměnné (ukázka ze stávající konfigurace laboratoře):
%JMENO%– jméno pacienta%PRIJMENI%– příjmení%RODCISN%– rodné číslo (bez lomítka)%POJ%– pojišťovna%DGN%– diagnóza
V Pythonu pak čteš: sys.argv[1], sys.argv[2], atd.
Jak zjistit SQL dotazy Medicusu – SQL Logger
- Medicus → Nástroje → SQL Monitor (nebo podobně v menu)
- Zapnout logging
- Provést akci v Medicusu (otevřít záložku, spustit report)
- Zkopírovat SQL z logu
Log se ukládá do: C:\Medicus 3\Debug\Monitor_DDMMYY_HHMMSS.log
💡 Zlatý důl! SQL logger odhalí přesnou strukturu tabulek a podmínky filtrování, které Medicus interně používá.
Struktura databáze – klíčové tabulky
Pacienti
| Tabulka | Popis |
|---|---|
KAR |
Kartotéka pacientů – IDPAC, PRIJMENI, JMENO, RODCIS |
Pracovní neschopnost (PN)
| Tabulka | Popis |
|---|---|
NES |
Hlavní tabulka neschopenek |
HPN |
Elektronická podání na ČSSZ (eNeschopenka) – komunikační vrstva, 5693 záznamů |
HPN_NOTIFIKACE |
Notifikace z ČSSZ |
HPN_NOTIFIKACE_DETAIL |
Detail notifikací, stavy podání (STAV_PODANI) |
HPN_PODANI |
Podání na ČSSZ |
HOSPNES |
Hospitalizační neschopenky |
Klíčové sloupce tabulky NES
| Sloupec | Popis |
|---|---|
IDPAC |
ID pacienta (JOIN s KAR) |
ZACNES |
Začátek PN (DATE) |
KONNES |
Konec PN (DATE) – NULL = stále trvá |
DIAGNO |
Diagnóza (MKN-10 kód) |
CISNES |
Číslo neschopenky (starý formát) |
ECN |
eČíslo neschopenky (nový elektronický formát) |
PRACNE |
Pracovní neschopnost = 'A' |
STORNO |
Storno záznamu = 'T' (True) |
STATDPNKOD |
Stav DPN kód |
VERZE_DPN |
Verze DPN |
SQL – aktivní PN k dnešnímu datu
SELECT
kar.PRIJMENI,
kar.JMENO,
kar.RODCIS,
nes.ZACNES,
nes.KONNES,
nes.DIAGNO,
COALESCE(nes.ECN, nes.CISNES) AS CISNES -- preferuj eČíslo, fallback na staré
FROM NES nes
JOIN KAR kar ON kar.IDPAC = nes.IDPAC
WHERE
nes.ZACNES <= CAST('TODAY' AS DATE)
AND (nes.KONNES >= CAST('TODAY' AS DATE) OR nes.KONNES IS NULL)
AND nes.PRACNE = 'A'
AND nes.STORNO <> 'T'
ORDER BY kar.PRIJMENI, kar.JMENO
💡
COALESCE(nes.ECN, nes.CISNES)– starší neschopenky mají jenCISNES, novější elektronické majíECN. Takhle dostaneme vždy správné číslo.
Šablona nového skriptu
"""
NNN_nazev_skriptu.py
====================
Popis co skript dělá.
"""
import sys, os, traceback
_LOG = r"C:\Users\vlado\PycharmProjects\Medicus\PNWithClaude\NNN_error.log"
def _log_exception(exc_type, exc_value, exc_tb):
with open(_LOG, "w", encoding="utf-8") as f:
traceback.print_exception(exc_type, exc_value, exc_tb, file=f)
sys.excepthook = _log_exception
import fdb
import datetime
import tkinter as tk
from tkinter import ttk
DSN = r'localhost:c:\medicus 3\data\medicus.fdb'
USER = 'SYSDBA'
PASSWORD = 'masterkey'
CHARSET = 'win1250'
SQL = """
SELECT ...
FROM ...
WHERE ...
"""
def nacti_data():
conn = fdb.connect(dsn=DSN, user=USER, password=PASSWORD, charset=CHARSET)
try:
cur = conn.cursor()
cur.execute(SQL)
return cur.fetchall()
finally:
conn.close()
def zobraz_okno(rows):
root = tk.Tk()
root.title("Název okna")
# Centrování na střed monitoru
w, h = 900, 550
root.update_idletasks()
sw, sh = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry(f"{w}x{h}+{(sw-w)//2}+{(sh-h)//2}")
# ... GUI kód ...
root.mainloop()
if __name__ == "__main__":
try:
rows = nacti_data()
zobraz_okno(rows)
except Exception:
with open(_LOG, "w", encoding="utf-8") as f:
traceback.print_exc(file=f)
raise
Řazení v ttk.Treeview – vzorový kód
_sort_state = {} # uchovává směr řazení pro každý sloupec
def sort_by(col):
ascending = not _sort_state.get(col, False)
_sort_state[col] = ascending
data = [(tree.set(k, col), k) for k in tree.get_children("")]
if col == "Dní": # číselné sloupce
data.sort(key=lambda t: int(t[0]) if t[0].isdigit() else 0, reverse=not ascending)
else: # textové sloupce
data.sort(key=lambda t: t[0].lower(), reverse=not ascending)
for idx, (_, k) in enumerate(data):
tree.move(k, "", idx)
# Šipka v záhlaví aktivního sloupce
for c in cols:
arrow = (" ▲" if ascending else " ▼") if c == col else ""
tree.heading(c, text=c + arrow, command=lambda c=c: sort_by(c))
# Připoj řazení na záhlaví
for col in cols:
tree.heading(col, text=col, command=lambda c=col: sort_by(c))
# Výchozí řazení při spuštění
sort_by("Dní")
Ladění problémů
Skript nefunguje z Medicusu, ale z PyCharmu ano
- Přepnout dočasně na
python.exe(nepythonw.exe) – uvidíš konzoli - Zkontrolovat
NNN_error.logv adresáři skriptů - Nejčastější příčiny:
__file__je prázdný → používej absolutní cesty pro log soubory- Chybí
fbclient.dllv PATH → testuj test skriptem - Pole „Spustit v" v Medicusu → nechat prázdné
Test skript pro ověření prostředí
Viz test_spusteni.py – testuje Python, fdb import, tkinter a DB spojení.
Výstup: Python: OK, fdb: OK, tkinter: OK, DB spojeni: OK
Černé konzolové okno
Použít pythonw.exe místo python.exe v konfiguraci Medicusu.
Seznam skriptů
| Číslo | Soubor | Popis |
|---|---|---|
| 001 | 001_pruzkum_PN_tabulek.py |
Průzkum struktury DB – tabulky a sloupce s PN |
| 003 | 003_aktivni_PN_seznam.py |
Aktivní PN k dnešnímu datu – tlačítko na liště |
Číslo 002 přeskočeno (bylo pracovní/testovací stadium).
Projekt vznikl: březen 2026 | Medicus 3 Komfort | Firebird DB | Python 3.12