notebookvb

This commit is contained in:
Vladimir Buzalka
2026-04-29 06:24:11 +02:00
parent 4aee1a05bd
commit 3c3a12d5a6
6 changed files with 374 additions and 77 deletions
+72 -66
View File
@@ -6,6 +6,30 @@ Zjistit pro pacienty z Medicus DB, kdo je jejich registrující **praktický lé
---
## Stav k 29. 4. 2026 — hotovo
- Certifikát ✅, tabulky ✅, produkční skript ✅
- Připraveno ke spuštění — přepnout `TEST_MODE = False`
---
## Soubory v tomto adresáři
| Soubor | Popis |
|--------|-------|
| `kdojelekar_tydenni.py` | Produkční skript — batch všech pacientů, ukládá do MySQL |
| `_test_temp.py` | Testovací skript — dotaz na jedno RC, výpis XML + parsovaný výsledek |
| `_test_no_odb.py` | Test bez filtru odborností — sloužil k ověření struktury odpovědi |
---
## Certifikát
**`u:\ordinaceprojekt\Insurance\Certificates\picka.pfx`** / heslo **`Vlado7309208104+`**
Ověřeno 29. 4. 2026 (HTTP 200). Stejný certifikát používá i `StavPojisteni\zkontroluj_a_odesli_zlomy.py`.
---
## VZP B2B služba: `RegistracePojistencePZSB2B`
### Endpoint (produkce)
@@ -14,89 +38,71 @@ https://prod.b2b.vzp.cz/B2BProxy/HttpProxy/RegistracePojistencePZSB2B
```
### Autentizace
mTLS — klientský certifikát `.pfx` od **I.CA** (První certifikační autorita).
Stejný mechanismus jako u `stavPojisteniB2B`.
### SOAP požadavek
```xml
<registracePojistencePZSB2B xmlns="http://xmlns.gemsystem.cz/B2B/RegistracePojistencePZSB2B/1">
<cisloPojistence>7309208104</cisloPojistence>
<kDatu>2026-04-28</kDatu>
<seznamOdbornosti>
<kodOdbornosti>001</kodOdbornosti> <!-- VPL = praktický lékař pro dospělé -->
<kodOdbornosti>002</kodOdbornosti> <!-- gynekologie a porodnictví -->
<kodOdbornosti>014</kodOdbornosti> <!-- stomatologie -->
</seznamOdbornosti>
</registracePojistencePZSB2B>
```
XML namespace odpovědi: `http://xmlns.gemsystem.cz/B2B/RegistracePojistencePZSB2B/1`
mTLS — klientský certifikát `.pfx`, stejný mechanismus jako u `stavPojisteniB2B`.
### Struktura odpovědi
Pro každou odbornost vrátí jeden `<odbornost>` element:
Pro každou odbornost kde má pacient lékaře vrátí jeden `<odbornost>` element.
Pokud lékař není, VZP element vynechá — skript ukládá placeholder řádek s `ma_lekare=0`.
| XML tag | Popis |
|---------|-------|
| `ICZ` | IČZ zdravotnického zařízení |
| `ICP` | IČP lékaře |
| `nazevICP` | Jméno lékaře |
| `nazevSZZ` | Název zdravotnického zařízení |
| `zdravotniPojistovna/kod` | Kód pojišťovny pacienta |
| `zdravotniPojistovna/zkratka` | Zkratka pojišťovny |
| `odbornost/kod` | Kód odbornosti (001/002/014) |
| `odbornost/nazev` | Název odbornosti |
| `datumRegistrace` | Datum registrace u tohoto lékaře |
| `datumZahajeni` | Začátek registrace |
| `datumUkonceni` | Konec registrace (null = stále aktivní) |
| `stavVyrizeniPozadavku` | Stavový kód odpovědi VZP |
| XML tag | Uloženo jako | Popis |
|---------|-------------|-------|
| `ICZ` | `ICZ` | IČZ zdravotnického zařízení |
| `ICP` | `ICP` | IČP lékaře |
| `nazevICP` | `nazev_lekare` | Název pracoviště |
| `nazevSZZ` | `nazev_zzz` | Jméno lékaře |
| `zdravotniPojistovna/kod` | `poj_kod` | Kód pojišťovny pacienta |
| `zdravotniPojistovna/zkratka` | `poj_zkratka` | Zkratka pojišťovny |
| `odbornost/kod` | `kod_odbornosti` | Kód odbornosti (001/002/014) |
| `datumRegistrace` | `datum_registrace` | Kdy pacient podepsal registraci |
| `datumZahajeni` | `datum_zahajeni` | Od kdy registrace platí u VZP |
| `datumUkonceni` | `datum_ukonceni` | Do kdy (3000-01-01 = bez konce) |
| `stavVyrizeniPozadavku` | `stav_vyrizeni` | Stavový kód odpovědi VZP |
Pokud pacient nemá v dané odbornosti registrovaného lékaře, VZP vrátí prázdný seznam — je třeba uložit placeholder řádek (viz vzor v `u:\insurance\02.2 Testík.py`, funkce `upsert_rows`, negativní cesta).
**Poznámka k parsování:** VZP vrací pro každý nalezený záznam dva `<odbornost>` elementy —
vnější (s ICZ/ICP/jménem) a vnořený subelement (jen kód+název). Parser používá
`findall(".//seznamOdbornosti/odbornost")` který zachytí jen vnější.
---
## Zdrojový kód pro inspiraci
## MySQL tabulky
Vše je hotové v `u:\insurance\`, stačí přenést a adaptovat:
### `vzp_registrace_lekari`
Jeden řádek na `(rc, k_datu, kod_odbornosti)`. UNIQUE klíč = `(rc, k_datu, kod_odbornosti)`.
Historie se hromadí — každý týdenní běh přidá nové řádky.
| Soubor | Co obsahuje |
|--------|-------------|
| `u:\insurance\02 testík.py` | Hlavní logika: `build_envelope`, `parse_registrace`, `upsert_rows`, batch smyčka přes Medicus KAR |
| `u:\insurance\02.2 Testík.py` | Vylepšená verze — ukládá i negativní výsledky (pacient bez lékaře) |
| `u:\insurance\functions.py` | `get_medicus_connection()`, `get_mysql_connection()` — připojení k Firebird a MySQL |
| `u:\insurance\knihovny\vzpb2b_client.py` | Třída `VZPB2BClient` — obecný mTLS klient pro VZP B2B |
### `vzp_registrace_raw`
Jeden řádek na `(rc, k_datu)` — celé raw XML odpovědi.
Slouží k případnému přepočtu bez opakování API dotazů. UNIQUE klíč = `(rc, k_datu)`.
---
## Certifikáty — stav k 28. 4. 2026
## Produkční skript `kdojelekar_tydenni.py`
| Soubor | Platnost | Stav |
|--------|----------|------|
| `u:\insurance\Certificates\MBcert.pfx` | do 22. 1. 2026 | **EXPIROVAL** |
| `u:\insurance\10 Tests\MBcert.pfx` | do 22. 1. 2026 | **EXPIROVAL** |
| `u:\insurance\Certificates\ICAPublicMBdo16JAN2027.pfx` | do cca. 16. 1. 2027 | Platný, ale **neznáme heslo** — zjistit! |
| `u:\ordinaceprojekt\Insurance\Certificates\MBQualifiedCert.pfx` | do 16. 1. 2027 | Platný, ale **VZP odmítá** (kvalifikovaný certifikát, ne komerční) |
| `u:\ordinaceprojekt\Insurance\Certificates\picka.pfx` | neznámá | Neznáme heslo |
| `u:\insurance\Certificates\picka.pfx` | neznámá | Neznáme heslo |
### Konfigurace (začátek souboru)
| Proměnná | Výchozí | Popis |
|----------|---------|-------|
| `API_PAUSE` | `2` | Sekundy mezi VZP dotazy |
| `TEST_MODE` | `True` | False = produkční běh |
| `ODBORNOSTI` | `["001","002","014"]` | Dotazované odbornosti |
### Klíčový problém k vyřešení jako první
**`ICAPublicMBdo16JAN2027.pfx` je pravděpodobně správný certifikát** (název naznačuje I.CA, správná CA pro VZP B2B, platný do 2027). Vyzkoušená hesla nepasují:
- `Vlado7309208104++`, `vlado7309208104++`, `7309208104`, `Vlado9674+`, `masterkey`, `""`
### Logika
1. Načte aktivně registrované pacienty z Medicus (přesný select dle SELECTS.md, IČP 09305001)
2. V produkčním běhu přeskočí pacienty, kteří už mají záznam v `vzp_registrace_raw` pro dnešní datum — **resumovatelný běh**
3. Pro každého pacienta zavolá VZP B2B, uloží raw XML + parsované záznamy
4. Placeholdery pro odbornosti bez lékaře ukládá s `ma_lekare=0`
**Zjistit heslo** pod kterým byl exportován (nebo exportovat znovu z Windows certstore).
---
## Testovací skript
`u:\ordinaceprojekt\Insurance\KdoJeLékař\_test_temp.py`
Dotáže se na RC `7309208104`, odbornosti 001+002+014, vypíše raw XML i parsovaný výsledek bez zápisu do DB.
Aktuálně nastavený na `MBQualifiedCert.pfx` — po zjištění hesla přepnout na správný certifikát.
### Knihovny
- `Knihovny/vzpb2b_client.py` → metody `registrace_lekare()` a `parse_registrace_lekare()`
- `Knihovny/medicus_db.py``get_active_registered_patients()` (opraveno 29. 4. 2026)
- `Knihovny/mysql_db.py``connect_mysql()`
---
## Plán dalšího postupu
1. **Zjistit heslo k `ICAPublicMBdo16JAN2027.pfx`** (nebo exportovat nový .pfx z Windows certstore)
2. Ověřit funkčnost — spustit `_test_temp.py` s funkčním certifikátem
3. Vytvořit produkční skript v tomto adresáři — batch zpracování všech pacientů z Medicus KAR
4. Navrhnout cílovou MySQL tabulku `vzp_registrace_lekari` (nebo přidat sloupce do existující `vzp_registrace`)
1. ~~Certifikát~~ — vyřešeno, `picka.pfx` / `Vlado7309208104+`
2. ~~Ověřit funkčnost~~ — hotovo, HTTP 200 s daty
3. ~~Produkční skript~~ — hotovo, `kdojelekar_tydenni.py`
4. ~~MySQL tabulky~~ — hotovo, `vzp_registrace_lekari` + `vzp_registrace_raw`
5. Naplánovat týdenní spouštění (Windows Task Scheduler nebo Claude schedule)
6. Zvážit detekci změn lékaře (analogie zlomů u StavPojisteni) — zatím není v plánu