# MedicusWithClaude – poznámky pro Clauda

## Stav projektu
- Zahájeno: 2026-03-13
- Cíl: průzkum Firebird DB Medicus → analýzy a reporty
- Zatím: úspěšně čteme i zapisujeme do DB, rozumíme RTF formátu
- **2026-03-17**: Obnovena session – Claude si přečetl poznámky, připraven pokračovat
- **2026-03-18**: Obnovena session – Claude si přečetl poznámky, připraven pokračovat. Průběžně zapisuje do tohoto souboru.
- **2026-03-20**: Obnovena session – merge logika z `test_import_single.py` integrována do `s03soubory.py`. Import pipeline kompletní.
- **2026-04-01**: Opravena chyba `BlobReader invalid BLOB handle` v `dekurz_report.py` – viz níže.

## Bezpečnost
- Pracujeme na **místní kopii** – poškození DB nevadí, obnova = 5 minut
- Lze bez obav experimentovat, zapisovat testovací data atd.
- Testovací záznamy nemusíme mazat

## Připojení k DB
```python
import fdb
conn = fdb.connect(
    dsn=r'localhost:c:\medicus 3\data\medicus.fdb',
    user='SYSDBA',
    password='masterkey',
    charset='win1250'
)
```
- fdb verze 2.0.4, Python na PATH (prostý `python` příkaz)
- Firebird instalace: `C:\Program Files\Firebird\Firebird_2_5_CGM\bin\`
- Jedná se o **HQbird** (IBSurgeon enhanced Firebird) – port **3070** (ne standardní 3050)
- fbtracemgr trace nefungoval spolehlivě – doporučeno použít **FBScanner** (stejný výrobce)

## O Medicusu
- Lékařský software pro praktického lékaře
- Vyvíjen od ~roku 2000, organicky rostl přidáváním funkcí
- Firebird 2.5 – nikdy nepřejdou na nový (desetitisíce instalací, 993 tabulek)
- Žádné zabezpečení DB – vše čitelné přes SYSDBA/masterkey
- Charset: win1250

## DB fakta
- 993 tabulek celkem
- Charset: win1250

## Klíčové tabulky

### KAR – Kartotéka (základní kámen Medicusu)
- 6319 pacientů – všichni kdo kdy prošli ordinací
- Primární klíč: **IDPAC** (interní ID, používá se jako FK v ostatních tabulkách)
- Identifikace pacienta v ČR/pojišťovna: **RODCIS** (rodné číslo, bez lomítka, např. 7309208104)
- **PRIJMENI**, **JMENO**, TITUL, TITULZA, DATNAR, POHLAVI
- **POJ** – pojišťovna (3 znaky, např. 111 = VZP)
- Adresy: TRV* (trvalé), PRE* (přechodné)
- **VYRAZEN** – příznak vyřazeného pacienta
- HLAVDGN – hlavní diagnóza

### DEKURS – záznamy z návštěv
- 172 068 záznamů
- **IDPAC** → vazba na KAR
- **DATUM** (date), **CAS** (time) – kdy
- **DEKURS** – text záznamu (BLOB, RTF nebo holý text)
- **DGN1** – hlavní diagnóza (5 znaků, např. 'Z000 '), VDGN1-4 – vedlejší
- **IDPRAC** – který pracovník
- IDODD, IDUZI – oddělení/uživatel (u Buzalky = 2, 2, 6)
- IDSKUPINA, IDTYP – volitelné (NULL OK)

## Základní schéma
```
KAR (kartotéka) ←IDPAC→ DEKURS (záznamy z návštěv)
```

## Testovací pacient (uživatel)
- **IDPAC = 9742** – Buzalka Vladimír, RC 7309208104, nar. 20.9.1973
- IDODD=2, IDPRAC=2, IDUZI=6 (použít při INSERT do DEKURS)

## RTF formát v DEKURS

### Základní struktura
```
{\rtf1\ansi\ansicpg1250\uc1\deff0\deflang1029
  {\info{\bookmarks "popis","Typ:ID",číslo}}   ← metadata Medicusu
  {\fonttbl{\f0\fnil\fcharset238 Arial;}{\f2...Courier New;}{\f5...Symbol;}}
  {\colortbl ;\red0\green0\blue255;\red255\green255\blue0;\red0\green128\blue0;\red192\green192\blue192;}
  {\stylesheet{styly...}}
\uc1\pard\s10\plain...  ← tělo záznamu
}
```

### Barvy (\cfX)
- `\cf1` = modrá (odkazy)
- `\cf2` = žlutá (highlight)
- `\cf3` = zelená
- `\cf4` = šedá (pozadí buněk tabulky `\clcbpat4`)

### Velikost písma (\fsXX = XX/2 bodů)
- `\fs18` = 9pt (tabulky)
- `\fs20` = 10pt (normální)
- `\fs24` = 12pt atd.

### Řezy a formátování
- `\b` = tučné, `\i` = kurzíva, `\ul` = podtržené
- `\ql` = vlevo, `\qr` = vpravo, `\qc` = střed

### Styly (stylesheet)
- `cs15/cs16` = Normální
- `cs20` = Vkládaný text
- `cs21` = Záhlaví (italic)
- `cs22/cs23` = Odkaz (underline, modrá)
- `s8/s10` = Vlevo (paragraph styl)

### Záložky (bookmarks v {\info})
- Klikatelné odkazy v Medicusu
- Formát: `"popis","Typ:ID",číslo`
- Typy: `Files:ID`, `MEDLAB:ID`, `Lab:ID`, `Ock:ID`, `VykA:ID`

### České znaky
- RTF hex escape v win1250: `\'e1`=á, `\'9e`=ž, `\'fd`=ý atd.

### Tabulky
- Plně funkční RTF tabulky (`\trowd`, `\cell`, `\cellx...`)
- Používají se např. pro laboratorní výsledky (viz ID=243082, 50KB)

### Holý text (starší záznamy)
- Některé starší záznamy jsou prostý text bez RTF obálky
- Nutno detekovat: začíná na `{\\rtf` = RTF, jinak plain text

### Příklad minimálního RTF záznamu
```
{\rtf1\ansi\ansicpg1250\uc1\deff0\deflang1029
{\fonttbl{\f0\fnil\fcharset238 Arial;}}
{\colortbl ;\red0\green0\blue255;\red0\green128\blue0;\red0\green0\blue0;}
\pard\plain\f0\fs20 Text záznamu zde\par
}
```

## INSERT do DEKURS – ověřený postup
```python
import fdb, datetime

conn = fdb.connect(...)
cur = conn.cursor()

cur.execute('SELECT MAX(ID) FROM DEKURS')
next_id = cur.fetchone()[0] + 1

text = r'{\rtf1\ansi\ansicpg1250...\par' + '\n}'  # raw string pro RTF!

cur.execute("""
    INSERT INTO DEKURS (ID, IDPAC, IDODD, IDPRAC, IDUZI, DATUM, CAS, DEKURS, DGN1)
    VALUES (?, ?, 2, 2, 6, ?, ?, ?, ?)
""", (next_id, idpac, datum, cas, text, dgn1))

conn.commit()
```
- RTF string musí být **raw string** (r'...') kvůli zpětným lomítkům
- DGN1 = 5 znaků s mezerou: `'Z000 '`
- DATUM = datetime.date(...), CAS = datetime.time(...)

## Soubory v projektu
- `explore_db.py` – výpis všech tabulek a jejich sloupců
- `inspect_table.py` – detailní info o konkrétní tabulce (arg: název tabulky)
- `sample_dekurs.py` – ukázky nejstarších a nejnovějších záznamů
- `sample_dekurs2.py` – celý text jednoho záznamu
- `sample_rtf.py` – nejdelší záznamy pacienta (dle délky RTF)
- `analyze_rtf.py` – analýza RTF tagů v záznamu
- `insert_test.py` – testovací INSERT do DEKURS
- `CLAUDE_NOTES.md` – tento soubor

## Export FILES do externích DB (zjištěno 2026-03-17 přes FBScanner)

### Mechanismus přesunu
Medicus vytváří **měsíční** externí Firebird databáze ve formátu `MEDICUS_FILES_YYYYMM.fdb`.

**Postup exportu:**
1. SELECT dat z FILES po 10 záznamech: `select first 10 ID, BODY, DATUM from FILES where ID > X ORDER BY ID ASC`
2. Binární data (skeny) se zapíší do externího `.fdb` souboru
3. V hlavní DB se BODY přepíše referenčním číslem (ID v externím souboru): `update FILES set BODY = 379 where ID = 10009`
4. Do EXTERNI_DB se zapíše lokace: `insert into EXTERNI_DB (DBNAME, SERVER, PATH, HESLO) values ('DB202501', 'localhost/3053', 'u:\MEDICUS_FILES_202501.fdb', '<encrypted>')`

### Výsledek
- Hlavní DB: FILES.BODY obsahuje jen malé číslo (referenci) místo MB blobu
- Skenované soubory jsou fyzicky v `u:\MEDICUS_FILES_YYYYMM.fdb`
- Medicus načítá soubory přes EXTERNI_DB tabulku (SERVER + PATH + HESLO)
- Hesla v EXTERNI_DB jsou šifrovaná (base64 AES)

### FBScanner
- Nainstalován, funguje jako proxy: Medicus → [3050] FBScanner → [3053] Firebird
- Community Edition 2.5 – stačí pro monitoring
- Export proveden na záloze (ne produkční DB)

## Přímý zápis do externí DB – dokončeno (2026-03-17)

### Nový soubor: `funkce_ext.py`
Náhrada za `funkce.zapis_file()`. Ukládá PDF přímo do měsíční externí FDB
místo do hlavní medicus.fdb.

**Funkce:** `zapis_file_ext(vstupconnection, idpac, cesta, souborname, prvnizavorka, soubordate, souborfiledate, poznamka, ext_base_path=r'u:\\')`
- Parametry shodné s `funkce.zapis_file()` → jen prohodit import
- Vrací `fileid` stejně jako původní funkce

**Co dělá:**
1. Z `soubordate` odvodí `YYYYMM` → `DBNAME = 'DB202603'`
2. Načte PDF jako bytes
3. Vyhledá EXTERNI_DB pro daný měsíc:
   - Nalezeno → připojí se k existující FDB (masterkey)
   - Nenalezeno → vytvoří novou `MEDICUS_FILES_YYYYMM.fdb`, zaregistruje do EXTERNI_DB
4. Vygeneruje `UID = uuid.uuid4().hex` (32 znaků)
5. Zapíše do DATA tabulky: `UID, DATA (blob), DATASIZE, CHUNK=0`
6. Sestaví 48bajtovou BODY referenci
7. Získá `fileid` z Gen_Files
8. Vloží do FILES s BODY = reference (ne blob)

### Úprava `s03soubory.py`
- Přidán import `funkce_ext`
- Volání `funkce.zapis_file(...)` nahrazeno `funkce_ext.zapis_file_ext(...)`

### BODY reference – binární formát (48 B)
```
magic      4 B  = b'\xee\xbb\xaa\x0b'
uid       32 B  = UUID4 hex (ASCII, 32 znaků)
dblen      4 B  = len(DBNAME) jako little-endian uint32
dbname     N B  = DBNAME ASCII (typicky 'DB202603', 8 B)
```
Celkem typicky: 4 + 32 + 4 + 8 = **48 bajtů**

### Struktura DATA tabulky (externe DB)
```
UID      VARCHAR(32) NOT NULL
DATA     BLOB SUB_TYPE 0
DATASIZE INTEGER
CHUNK    INTEGER
```
Generator: `GEN_UID` (Medicus ho asi nepoužívá přímo, UID je UUID string)

### EXTERNI_DB tabulka (hlavní DB)
```
DBNAME   např. 'DB202603'
SERVER   např. 'localhost/3053'  (FBScanner proxy)
PATH     např. 'u:\MEDICUS_FILES_202603.fdb'
HESLO    šifrované heslo (Medicus AES) – zkopírujeme z existující položky
```
Při vytváření nové DB: HESLO zkopírujeme z libovolné existující EXTERNI_DB položky
(všechny používají masterkey, jen jinak zašifrované – ale stejný klíč).

### Poznámka k HESLO šifrování
Hesla v EXTERNI_DB jsou šifrovaná Medicusem. Při vytváření nové DB proto
zkopírujeme HESLO z existující položky (stejné heslo = stejný šifrovaný text).
Medicus pak dokáže novou DB otevřít standardně. Pokud by to nefungovalo,
lze heslo zadat manuálně přes správce Medicusu.

## Stav 2026-03-18 – nastudováno po obnově session

### Co bylo dokončeno (včera večer)
- `funkce_ext.zapis_file_ext()` je **otestována a funkční**
- `s03soubory.py` volá `zapis_file_ext` místo původní `funkce.zapis_file`
- Celý import pipeline funguje end-to-end

### Celý import pipeline (s03soubory.py)
1. Scanuje složku `u:\NextcloudOrdinace\Dokumentace_ke_zpracování`
2. Ověří formát názvu souboru: `RC YYYY-MM-DD Jmeno, Jmeno. [prvnizavorka] [druhazavorka].pdf`
3. Ověří rodné číslo v KAR tabulce
4. Seskupí soubory podle RC (jeden pacient = jeden dekurs)
5. Pro každý PDF zavolá `funkce_ext.zapis_file_ext()` → zapíše do externí DB
6. Přesune soubor do `u:\NextcloudOrdinace\Dokumentace_zpracovaná`
7. Sestaví RTF se záložkami (klikatelné odkazy na soubory v Medicusu)
8. Zapíše dekurs do DEKURS tabulky

### Klíčové soubory
- `funkce_ext.py` – zápis PDF do měsíční externí FDB (náhrada za funkce.zapis_file)
- `funkce.py` – původní funkce (zapis_file, zapis_dekurs, get_files_id, get_idpac, convert_to1250)
- `s03soubory.py` – hlavní import script (spouštět na Windows)
- `s04_presun_externi_db.py` – utility: přesun ext DB souborů do u:\externi\ a update PATH v EXTERNI_DB
- `test_ext_db4.py` – ověření BODY bajty z FILES tabulky (hex dump)

### Formát názvu souboru pro import
```
RC YYYY-MM-DD Prijmeni, Jmeno. [prvnizavorka] [druhazavorka].pdf
např: 7309208104 2026-03-17 Buzalka, Vladimír. [EKG] [normální nález].pdf
```

## Oprava RTF klikacích odkazů (2026-03-18)

### Problém
`s03soubory.py` generoval RTF s `\cs22` pro styl odkazu, ale Medicus vyžaduje `\cs32`.
Druhý+ bookmark neměl link styling vůbec. `poradi` se nikdy neinkrementoval.

### Zjištěno analýzou Medicusem vytvořeného DEKURS (ID=263480, AhojClaude.pdf)
Správný RTF formát klikacího odkazu:
```
{\*\cs32\f0\ul\fs20\cf1 Odkaz;}   ← stylesheet: cs32, NE cs22
\uc1\pard\s10\plain\cs20\f0\i\fs20 Přílohy: {\*\bkmkstart 0}\plain\cs32\f0\ul\fs20\cf1 TEXT{\*\bkmkend 0}\par
```
- "Přílohy:" je inline s prvním odkazem na stejném `\pard` řádku
- Každý další odkaz: `\pard\s10{\*\bkmkstart N}\plain\cs32\f0\ul\fs20\cf1 TEXT{\*\bkmkend N}\par`

### Opraveno v s03soubory.py + test_import_3files.py
1. `\cs22` → `\cs32` v stylesheet i těle RTF
2. Header `Vložené přílohy:` je na **samostatném** `\pard` řádku (RTF: `Vlo\'9een\'e9 p\'f8\'edlohy:`)
3. Všechny bookmarky mají stejný formát: `\pard\s10{\*\bkmkstart N}\plain\cs32\f0\ul\fs20\cf1 TEXT{\*\bkmkend N}\par`
4. Přidáno `poradi += 1` (bug: poradi se nikdy neinkrementoval)
5. Odstraněna proměnná `prvnibookmark` – již nepotřebná

### RTF kódování českých znaků (win1250)
- ž = `\'9e`, é = `\'e9`, ř = `\'f8`, í = `\'ed`, á = `\'e1`
- "Vložené přílohy:" → `Vlo\'9een\'e9 p\'f8\'edlohy:`

## Merge do existujícího dekurzu (2026-03-18)

### Rozhodovací logika (3 případy)
1. Poslední dekurs pacienta je z dnešního dne A má `Vložené přílohy:`
   → **přidat soubor DO existující sekce** (`pridat_do_sekce_prilohy`)
2. Poslední dekurs je z dnešního dne, ale sekci nemá
   → **prepend nové sekce na začátek** (`merge_rtf_prepend`)
3. Poslední dekurs je z jiného dne / neexistuje
   → **nový dekurs pro dnešek**
- Funkce: `najdi_posledni_dekurs_dnes(conn, idpac, datum_vlozeni)`

### pridat_do_sekce_prilohy (přidání do existující sekce)
1. Spočítat `"Files:"` v `{\info{\bookmarks}}` = N → nový bkmkstart = N
2. Posunout všechny bkmkstart/bkmkend ≥ N o +1 (uvolnit index N)
3. Vložit nový `\pard` před `\pard\s10\plain\cs15\f0\fs20 \par` (konec sekce)
4. Vložit bookmark na pozici N do `{\info{\bookmarks}}`

### merge_rtf_prepend (prepend nové sekce)
1. Posunout existující `\bkmkstart N` / `\bkmkend N` o počet nových souborů
2. Přidat naše bookmarky NA ZAČÁTEK `{\info{\bookmarks ...}}`
3. Vložit naše `\pard` tělo PŘED první `\uc1\pard` existujícího těla

### Detekce sekce
- Přítomnost: `PRILOHY_HEADER = r"Vlo\'9een\'e9 p\'f8\'edlohy:"` – hledáme v RTF
- Konec sekce: `PRILOHY_CLOSING = r'\pard\s10\plain\cs15\f0\fs20 \par'`

### Skripty
- `test_import_merge.py` – 3 soubory → merge do dnešního dekurzu (bez sekce přílohy)
- `test_import_single.py` – 1 soubor → merge DO existující sekce přílohy
- `test_import_3files.py` – 3 soubory → vždy nový dekurs (bez merge logiky, starší)

### Stav testování (2026-03-18)
- `test_import_3files.py` ✅ ověřeno – klikací odkazy fungují, "Vložené přílohy:" správně
- `test_import_merge.py` ✅ připraveno – merge 3 souborů do dnešního dekurzu (bez sekce)
- `test_import_single.py` ✅ připraveno – přidání 1 souboru DO existující sekce přílohy

### Stav s03soubory.py (2026-03-20) – KOMPLETNÍ ✅
- Merge logika plně integrována z `test_import_single.py`
- Přidány konstanty `PRILOHY_HEADER`, `PRILOHY_CLOSING`
- Přidány funkce: `najdi_posledni_dekurs_dnes()`, `ma_sekci_prilohy()`, `pridat_do_sekce_prilohy()`, `merge_rtf_prepend()`
- RTF šablona přesunuta do konstanty `RTF_TEMPLATE`
- Odstraněn dead code: `prvnibookmark`, staré šablony, nepoužívané `convert_to1250`
- `pridat_do_sekce_prilohy()` podporuje **více souborů najednou** (oproti test_import_single.py, kde byl jen 1)
- `idpac` se bere z prvního záznamu skupiny (čistěji než z `row` po skončení loopu)

### Rozhodovací logika s03soubory.py – 3 případy
1. Dnešní dekurs **má** sekci `Vložené přílohy` → soubory přidány **dovnitř** sekce (`pridat_do_sekce_prilohy`)
2. Dnešní dekurs **nemá** sekci příloh → nová sekce vložena **na začátek** (`merge_rtf_prepend`)
3. Žádný dnešní dekurs → **nový** záznam (INSERT)

### Stav testovacích skriptů
- `test_import_3files.py` ✅ ověřeno – klikací odkazy fungují
- `test_import_merge.py` ✅ otestováno – merge 3 souborů (jen 2 případy, bez detekce sekce)
- `test_import_single.py` ✅ otestováno – všechny 3 případy, základ pro s03soubory.py

## Oprava BlobReader v dekurz_report.py (2026-04-01)

### Chyba
```
Exception ignored while calling deallocator <function BlobReader.__del__>:
fdb.fbcore.DatabaseError: BlobReader.close/isc_close_blob: invalid BLOB handle (-901)
```
Skript fungoval správně (exit code 0, Excel uložen), ale garbage collector házel warningy.

### Příčina
`fdb` vrací BLOB sloupce jako `BlobReader` objekty. Po `conn.close()` se při GC pokoušely
zavřít handle, který již neexistoval.

### Oprava
Explicitně zavřít `BlobReader` hned po `.read()`, ještě za živa spojení:

```python
# PŘED (špatně):
rtf = dekurs_blob.read() if hasattr(dekurs_blob, 'read') else (dekurs_blob or '')

# PO (správně):
if hasattr(dekurs_blob, 'read'):
    rtf = dekurs_blob.read()
    dekurs_blob.close()
else:
    rtf = dekurs_blob or ''
```

### Obecné pravidlo
Kdykoli čteme BLOB z fdb, vždy `.close()` po `.read()` – jinak GC po `conn.close()` hlásí chybu.

---

## Další postup (nápady)
- Otestovat `s03soubory.py` na Windows se skutečnými soubory (všechny 3 případy)
- Napsat `rtf_to_text()` pro extrakci čistého textu z dekurzů
- Prozkoumat tabulky: LECH/LECD (léky?), POU (poukazy?), AMBULEKY (výkony?)
- První report – domluvit s uživatelem co chce vidět

---

## KAR.POZNAMKA – automatické tagy (2026-04-09)

Pole `POZNAMKA` v tabulce KAR je **BLOB SUB_TYPE 1** (text blob, win1250) –
Medicus ho renderuje jako RTF stejně jako DEKURS. Lze psát i prostý text.

### Konvence automatických tagů
Automaticky zapisované informace se ukládají na **začátek** POZNAMKA ve formátu:
```
[[klic:hodnota1, hodnota2]] #zapsáno DD-MM-YYYY HH:MM#
```
- Oddělovače `[[` a `]]` se v lékařských poznámkách přirozeně nevyskytují
- Tag lze programově najít a nahradit regexem
- Ruční text lékaře/sestry pod tagem zůstává nedotčen

### Implementovaný tag: prev_prohlidka
```
[[prev_prohlidka:15-05-2024 01022, 15-04-2026]] #zapsáno 09-04-2026 14:30#
```
- `15-05-2024` = datum poslední PP
- `01022` = kód výkonu (01022 = dospělí, 01021 = starší varianta)
- `15-04-2026` = nejdřívější možný termín příští PP (23 měsíců od poslední)
- Skript: `MedicusWithClaudeTest/prev_prohlidka.py`

---

## Tabulka VZPARC – výkonové dávky pojišťovnám (zjištěno 2026-04-09)

Zachyceno přes Firebird trace log při exportu dávek z Medicusu.

### Struktura
- **1954 záznamů**, data od 2007 (s DAVKA blobem od 2013)
- Klíčové sloupce: `ID`, `ROK`, `DRUH`, `DATUMOD`, `DATUMDO`, `DAVKA` (blob), `ICP`, `ODB`, `IDICZ`
- Vazba na ICZ přes `IDICZ`

### Typy dávek (DRUH)
| DRUH | Popis |
|---|---|
| `98` | Výkonová dávka – obsahuje výkony vykázané pojišťovně (DP98 formát) |
| `05` | Doplňková dávka (DP05) |
| `80` | Registrační dávka – přihlášení/odhlášení pacientů (DP80) |
| `36` | Jiný typ |

### DAVKA blob – formát (CP852)
Stejný formát jako KDAVKA v PORTAL, dekódování identické:
```python
text = raw.encode('cp1250', errors='replace').decode('cp852', errors='replace')
```

Struktura DP98 dávky:
```
DP98...  – hlavička (IČP, rok, měsíc, disk, počet případů, částka)
A ...    – ambulantní případ: RC pacienta na pozici 34, délka 10
V ...    – výkon: V + DDMM + YYYY + KOD(5) + ...
Z ...    – ZULP
L ...    – lék
```

### Parsování RC z A řádku
```python
aktualni_rc = line[34:44].strip()   # pevná pozice, délka 10
```

### Parsování výkonu z V řádku
```python
dd   = int(line[1:3])
mm   = int(line[3:5])
yyyy = int(line[5:9])
kod  = line[9:14].strip()   # 5znakový kód výkonu
```

### Poznámka: PORTAL vs VZPARC
- **PORTAL** – starší tabulka, KDAVKA blob, data jen do 2015
- **VZPARC** – správná tabulka pro výkonové dávky, data od 2013 do dnes
- Pro hledání výkonů per pacient vždy používat **VZPARC**

---

## Skript prev_prohlidka.py (MedicusWithClaudeTest/)

Účel: najde datum poslední preventivní prohlídky (PP) pro každého registrovaného
pacienta a zapíše/aktualizuje tag v KAR.POZNAMKA.

### Co dělá
1. Načte registrované pacienty (přesný dotaz přes REGISTR + ICP, IČP=09305001)
2. Projde všechny VZPARC DRUH=98 dávky, hledá výkony `01022` nebo `01021`
3. Pro každého pacienta zachová jen **nejnovější** datum PP
4. Zapíše/přepíše tag `[[prev_prohlidka:...]]` na začátek KAR.POZNAMKA

### Výsledek posledního spuštění (2026-04-09)
- Registrovaných pacientů: 1621
- Dávek VZPARC DRUH=98: 778
- Pacientů s nalezenou PP: 1289
- Zapsáno do KAR: 1120
- Nenalezeno (odregistrovaní nebo bez PP): 169

### Závislosti
```
pip install python-dateutil
```
(fdb již musí být nainstalováno)
