diff --git a/Dokumentace/VZP/Ověření čísla pojištěnce/CommonB2B.xsd b/Dokumentace/VZP/Ověření čísla pojištěnce/CommonB2B.xsd new file mode 100644 index 0000000..ea639bd --- /dev/null +++ b/Dokumentace/VZP/Ověření čísla pojištěnce/CommonB2B.xsd @@ -0,0 +1,105 @@ + + + + $Revision: 30974 $ + $Date: 2010-12-23 09:43:29 +0100 (čt, 23 XII 2010) $ + $Author: jserak $ + + + + + Datový typ pro identifikátory zpráv protokolu AS2. + Povolenými hodnotami jsou řetězce délky max. 12 obsahující výhradně + alfanumerické znaky. + + + + + + + + + + Datový typ pro identifikátory subjektů. Nejdelším identifikátorem + subjektu je číslo pojištěnce (včetně příznaku), tj. 12 znaků. + + + + + + + + + + + Datový typ pro typ subjektu. Je definován jako enumerace povolených + hodnot. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  • 0: Data nenalezena
  • +
  • 1: Nalezen jeden záznam nebo obecná návratová hodnota OK
  • +
  • 2: Požadavek byl úspěšně přijat, zpracování bude pokračovat, očekávejte další odpověď
  • +
  • 9: Nalezeno více záznamů
  • +
  • -1: Technická chyba
  • +
  • -2: Chyba vstupních dat
  • +
  • -3: Role nemá oprávnění odesílat data
  • +
  • -9: Služba přijala požadavek, který bude zpracován později
  • +
  • -10: Zpráva je určena pro jiné prostředí
  • +
    +
    + + + + + + + + + + + +
    +
    diff --git a/Dokumentace/VZP/Ověření čísla pojištěnce/OverPrukazPojistenceB2B.wsdl b/Dokumentace/VZP/Ověření čísla pojištěnce/OverPrukazPojistenceB2B.wsdl new file mode 100644 index 0000000..7775f28 --- /dev/null +++ b/Dokumentace/VZP/Ověření čísla pojištěnce/OverPrukazPojistenceB2B.wsdl @@ -0,0 +1,53 @@ + + + $Revision: 28785 $ + $Date: 2010-11-08 14:10:25 +0100 (po, 08 XI 2010) $ + $Author: jserak $ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Dokumentace/VZP/Ověření čísla pojištěnce/OverPrukazPojistenceB2B.xsd b/Dokumentace/VZP/Ověření čísla pojištěnce/OverPrukazPojistenceB2B.xsd new file mode 100644 index 0000000..6114d3a --- /dev/null +++ b/Dokumentace/VZP/Ověření čísla pojištěnce/OverPrukazPojistenceB2B.xsd @@ -0,0 +1,49 @@ + + + + $Revision: 31458 $ + $Date: 2011-01-06 14:54:58 +0100 (čt, 06 I 2011) $ + $Author: msklenar $ + + + + + + + + + + + + + + + + + příznak rodného čísla - v případě duplicity udává pořadí + duplicitního rodného čísla (standardně je 1) + + + + + + + + „A“ – platný průkaz i vyhovující průběh pojištění + „N“ – existující ale neplatný průkaz + „P“ – existující a platný průkaz ale nevyhovující průběh pojištění + „Y“ – více záznamů o průkazu nebo o průběhu pojištění + „X“ – neexistující průkaz v evidenci + + + + + + + + diff --git a/Dokumentace/VZP/ais_point_pzs-2.zip b/Dokumentace/VZP/ais_point_pzs-2.zip new file mode 100644 index 0000000..1aea408 Binary files /dev/null and b/Dokumentace/VZP/ais_point_pzs-2.zip differ diff --git a/Dokumentace/VZP/b2b-rozhrani-stav-pojisteni.zip b/Dokumentace/VZP/b2b-rozhrani-stav-pojisteni.zip new file mode 100644 index 0000000..2445aa7 Binary files /dev/null and b/Dokumentace/VZP/b2b-rozhrani-stav-pojisteni.zip differ diff --git a/Dokumentace/VZP/b2b_rozhrani_ciselniky_pro_pzs.zip b/Dokumentace/VZP/b2b_rozhrani_ciselniky_pro_pzs.zip new file mode 100644 index 0000000..8e19fdd Binary files /dev/null and b/Dokumentace/VZP/b2b_rozhrani_ciselniky_pro_pzs.zip differ diff --git a/Dokumentace/VZP/b2b_rozhrani_overeni_platnosti_prukazu_pojistence_ehic.zip b/Dokumentace/VZP/b2b_rozhrani_overeni_platnosti_prukazu_pojistence_ehic.zip new file mode 100644 index 0000000..dbd3f72 Binary files /dev/null and b/Dokumentace/VZP/b2b_rozhrani_overeni_platnosti_prukazu_pojistence_ehic.zip differ diff --git a/Insurance/README.md b/Insurance/README.md new file mode 100644 index 0000000..f0f456c --- /dev/null +++ b/Insurance/README.md @@ -0,0 +1,221 @@ +# Ověření pojistného statusu pacientů (VZP B2B) + +Systém pro automatické ověřování, zda jsou registrovaní pacienti platně pojištěni u zdravotní pojišťovny. Dotazuje VZP B2B API, ukládá historii do MySQL a generuje PDF reporty o neshodách. + +--- + +## Architektura + +``` +Medicus Firebird DB (192.168.1.4) + └─ get_active_registered_patients() + │ + ▼ + VZPB2BClient.stav_pojisteni() ←─ mTLS (PFX certifikát) + prod.b2b.vzp.cz/stavPojisteniB2B + │ + ▼ + MySQL medevio.vzp_stav_pojisteni + │ + ▼ + Reportovací skript + └─ binární hledání data zlomu pojištění + └─ Jinja2 + WeasyPrint → PDF +``` + +--- + +## Soubory + +``` +20 Ověření proti Medicus/ +├── 10 FinalSaveInsuranceStatusScript(R).py ← sběr dat (spouštět denně) +├── 10 Ověření proti medicus.py ← generování PDF reportu +├── insurance_check.log ← log sběru dat +└── Output/ + └── kontrola_pojisteni_YYYY-MM-DD_HH-MM-SS.pdf +``` + +### Sdílené knihovny (`knihovny/`) + +| Soubor | Třída | Popis | +|---|---|---| +| `medicus_db.py` | `MedicusDB` | Wrapper pro Firebird připojení k Medicus | +| `vzpb2b_client.py` | `VZPB2BClient` | VZP B2B SOAP API klient s mTLS | + +--- + +## Skript 1: FinalSaveInsuranceStatusScript + +**Soubor:** `10 FinalSaveInsuranceStatusScript(R).py` + +Inkrementální sběr pojistných stavů. Lze spouštět opakovaně — při druhém spuštění ve stejný den přeskočí již zkontrolované pacienty. + +### Postup + +1. Načte všechny aktivně registrované pacienty z Medicus (`registr.priznak IN ('A','D','V')`, `kar.vyrazen <> 'A'`) +2. Pro každého pacienta zkontroluje `MAX(k_datu)` v MySQL — pokud je dnešní, přeskočí ho +3. Zavolá VZP B2B `stavPojisteniB2B` SOAP endpoint +4. Uloží XML odpověď + parsovaná data do tabulky `vzp_stav_pojisteni` +5. Mezi dotazy čeká 1,4 s (ochrana proti přetížení VZP API) + +### Konfigurace + +| Proměnná | Hodnota | Popis | +|---|---|---| +| `HOST` | `192.168.1.4` | Medicus Firebird server | +| `DB_PATH` | `c:\Medicus 3\data\MEDICUS.FDB` | Cesta k Firebird databázi | +| `PFX_PATH` | `certificates/picka.pfx` | Klientský certifikát pro mTLS | +| `PFX_PASSWORD` | — | Heslo k PFX souboru | +| `ENV` | `prod` | Prostředí VZP (`prod` / `simu`) | +| MySQL host | `192.168.1.76:3306` | MySQL server, databáze `medevio` | + +### Logování + +Výstup jde současně do `insurance_check.log` i na konzoli. Formát: +``` +2026-01-26 08:15:23 [INFO] Loaded 1620 registered patients +2026-01-26 08:15:23 [INFO] Incremental run: 1620 patients to check today +2026-01-26 08:15:25 [INFO] [1/1620] Checking Novák Jan (1234567890) +2026-01-26 08:15:26 [INFO] ✔ OK (VZP) +``` + +--- + +## Skript 2: Ověření proti medicus (report) + +**Soubor:** `10 Ověření proti medicus.py` + +Porovná registrované pacienty v Medicus s posledním zaznamenaným pojistným stavem v MySQL. Pacienty s neaktivním pojištěním (`stav != "1"`) vypíše do PDF reportu včetně přesného data zlomu pojištění. + +### Postup + +1. Načte registrované pacienty z Medicus +2. Z MySQL vezme **poslední** stav pojištění pro každé RC (pomocí `ROW_NUMBER() OVER PARTITION BY rc ORDER BY k_datu DESC`) +3. Vybere "podezřelé" — registrovaní v Medicus, ale stav `!= "1"` +4. Pro každého podezřelého provede **binární hledání** data zlomu: + - hledá mezi `MAX(k_datu WHERE stav='1')` a dneškem + - výsledek: `insured_to` (poslední den pojištění) a `uninsured_from` (první den bez pojištění) +5. Vygeneruje HTML přes Jinja2 šablonu a převede na PDF přes WeasyPrint +6. PDF otevře automaticky v systémovém prohlížeči + +### Šablona a výstup + +- Šablona: `Templates/vzp_console_report.html` +- Fonty: `Templates/fonts/DejaVuSans*.ttf` +- Výstup: `Output/kontrola_pojisteni_YYYY-MM-DD_HH-MM-SS.pdf` + +--- + +## Databáze + +### Tabulka `vzp_stav_pojisteni` (MySQL, `medevio`) + +| Sloupec | Typ | Popis | +|---|---|---| +| `id` | INT AUTO_INCREMENT | Primární klíč | +| `rc` | VARCHAR(20) | Rodné číslo pacienta | +| `prijmeni` | VARCHAR(100) | Příjmení | +| `jmeno` | VARCHAR(100) | Jméno | +| `k_datu` | DATE | Datum, ke kterému byl stav zjišťován | +| `stav` | VARCHAR(10) | `"1"` = pojištěn, ostatní = problém | +| `kod_pojistovny` | VARCHAR(10) | Kód pojišťovny dle VZP odpovědi | +| `nazev_pojistovny` | VARCHAR(100) | Název pojišťovny | +| `pojisteni_kod` | VARCHAR(20) | Kód druhu pojištění | +| `stav_vyrizeni` | INT | `stavVyrizeniPozadavku` ze SOAP odpovědi | +| `response_xml` | MEDIUMTEXT | Celá SOAP XML odpověď od VZP | +| `created_at` | TIMESTAMP | Čas vložení záznamu | + +**Indexy:** `idx_rc (rc)`, `idx_rc_k_datu (rc, k_datu)`, `idx_rc_stav (rc, stav)` + +### Klíčové SQL dotazy skriptů + +```sql +-- Inkrementální filtr (skript 1) +SELECT MAX(k_datu) AS last_check FROM vzp_stav_pojisteni WHERE rc = ? + +-- Poslední stav každého pacienta (skript 2) +SELECT rc, stav FROM ( + SELECT rc, stav, + ROW_NUMBER() OVER (PARTITION BY rc ORDER BY k_datu DESC) AS rn + FROM vzp_stav_pojisteni +) t WHERE rn = 1 + +-- Poslední den aktivního pojištění (pro binární hledání) +SELECT MAX(k_datu) AS last_insured +FROM vzp_stav_pojisteni WHERE rc = ? AND stav = '1' +``` + +--- + +## VZP B2B API + +### Třída `VZPB2BClient` + +**Autentizace:** mTLS — klientský PFX certifikát přes `requests_pkcs12.Pkcs12Adapter` + +**Metody:** + +| Metoda | SOAP služba | Popis | +|---|---|---| +| `stav_pojisteni(rc, k_datu)` | `stavPojisteniB2B` | Ověří pojistný stav pacienta k datu | +| `parse_stav_pojisteni(xml)` | — | Parsuje XML odpověď na dict | +| `over_prukaz_pojistence(cislo, k_datu)` | `OverPrukazPojistenceB2B` | Ověří průkaz pojištěnce (EHIC) | + +**Prostředí:** + +| ENV | URL | +|---|---| +| `prod` | `https://prod.b2b.vzp.cz/B2BProxy/HttpProxy/stavPojisteniB2B` | +| `simu` | `https://simu.b2b.vzp.cz/B2BProxy/HttpProxy/SIMUstavPojisteniB2B` | + +**Návratová struktura `parse_stav_pojisteni()`:** + +```python +{ + "stavVyrizeni": int, # stavVyrizeniPozadavku ze SOAP + "stav": str, # "1" = pojištěn + "kodPojistovny": str, # např. "111" + "nazevPojistovny": str, # např. "VZP" + "pojisteniKod": str +} +``` + +--- + +## Medicus DB + +### Třída `MedicusDB` + +Připojení: Firebird (`fdb`), `192.168.1.4`, charset `WIN1250`, user `SYSDBA`. + +**Metoda `get_active_registered_patients()`** — vrací pacienty splňující: +- `registr.datum_zruseni IS NULL` — registrace není zrušená +- `registr.priznak IN ('A','D','V')` — aktivní typy registrace +- `kar.rodcis IS NOT NULL AND kar.rodcis <> ''` — má rodné číslo +- `kar.vyrazen <> 'A'` — pacient není vyřazen + +--- + +## Kapacitní odhad + +| Parametr | Hodnota | +|---|---| +| Počet pacientů | ~1 600 | +| Velikost XML odpovědi | ~500–1 500 B | +| Přírůstek dat | ~1,6 MB/den | +| Přírůstek řádků | ~1 600/den | +| Roční objem | ~580 MB / ~580 000 řádků | +| Limit MEDIUMTEXT | 16 MB/řádek — bez problémů | + +--- + +## Spuštění + +```bash +# 1. Denní sběr dat (ideálně naplánovat přes Task Scheduler) +python "10 FinalSaveInsuranceStatusScript(R).py" + +# 2. Vygenerování PDF reportu (na vyžádání) +python "10 Ověření proti medicus.py" +```