# Lékový záznam eRecept → MySQL Popis pipeline pro stažení lékového záznamu pacienta z eRecept SÚKL API a jeho uložení do relační databáze MySQL. --- ## Soubory | Soubor | Co dělá | |--------|---------| | `05UlozitOdpoved.py` | Zavolá SOAP API, stáhne XML odpověď, uloží ji do `odpoved_lekovy_zaznam.xml` | | `06UlozitDoMySQL.py` | Naparsuje uložené XML, vytvoří/přepíše tabulky v MySQL, vloží data | ### Typické spuštění ```bash # 1. stáhnout čerstvá data z eReceptu python 05UlozitOdpoved.py # 2. uložit do databáze python 06UlozitDoMySQL.py # nebo předat jiný XML soubor python 06UlozitDoMySQL.py C:\cesta\k\jine_odpovedi.xml ``` --- ## Autentizace (eRecept SÚKL, ostrý provoz) | Parametr | Hodnota | |----------|---------| | Endpoint | `https://lekar-soap.erecept.sukl.cz/cuer/Lekar2` | | mTLS certifikát | `AMBSUKL214235369G_31DEC2024.pfx` (platnost do 31. 12. 2026) | | HTTP Basic user | UUID lékaře `e08c89c6-2b1a-4eba-8ed9-4e3e63618379` | | SOAP operace | `NacistLekovyZaznam` | | XML namespace | `http://www.sukl.cz/erp/201912` | | Verze zprávy | `202501A` | Certifikát = identifikace **ordinace**, UUID+heslo = identifikace **lékaře jako osoby**. --- ## Dotaz — parametry `NacistLekovyZaznamLekarDotaz` ```xml UUID lékaře IČP ordinace 7 60 ...... YYYY-MM-DD ``` --- ## Struktura XML odpovědi Dle XSD `Cuer2Schema.xsd` + `CuerSchema.xsd`, verze `202501A`: ``` NacistLekovyZaznamOdpoved ├── Doklad │ ├── Pacient – jméno + datum narození │ ├── PredepisujiciSeznam – lékaři, kteří předepisovali │ ├── VydavajiciSeznam – lékárny, kde byl výdej │ ├── PredpisSeznam │ │ └── Predpis × N – co bylo předepsáno │ ├── VydejSeznam │ │ └── Vydej × N – co bylo vydáno v lékárně │ └── DuplicitaSeznam – duplicitní výdeje └── Zprava – metadata odpovědi (ID, čas, verze SW) ``` ### Typy léků v Predpis i Vydej Každý předpis / výdej obsahuje právě **jeden** z těchto elementů: | Typ | Popis | Klíčová pole | |-----|-------|-------------| | `HVLPReg` | Registrovaný hromadně vyráběný LP | Kod (SÚKL), ATC, Nazev, Forma, Sila, Baleni | | `HVLPNereg` | Neregistrovaný HVLP | stejná struktura jako HVLPReg | | `IPLP` | Individuálně připravovaný LP (magistraliter) | Nazev, PostupPripravy (receptura), Slozka[] | | `INN` | Předpis účinnou látkou (genericky) | Nazev, Forma, Sila, Baleni | #### IPLP — dvojí uložení receptury - **Předpis** (`PredpisSeznam/Predpis/IPLP`): lékař zadal recepturu jako **volný text** v `PostupPripravy`. Prvky `Slozka` zde lékař typicky nevyplňuje. - **Výdej** (`VydejSeznam/Vydej/IPLP`): lékárna při přípravě zaznamenala **strukturované složky** (`Slozka` s množstvím, jednotkou a názvem suroviny). Kvalita dat závisí na lékárně — některé rozkládají do detailu (suroviny, obal, taxa laborum), jiné evidují jen 1 ks jako celek. --- ## Databázové schéma — `medicus` (MySQL 9.6) Všechny délky a datové typy jsou přesně dle XSD, **ne odhady**. Varianta B — lék je denormalizován přímo do řádku předpisu/výdeje. ### Relační diagram ``` zprava (1) ├── predpis (N) │ └── predpis_slozka (N) -- složky IPLP z předpisu └── vydej (N) └── vydej_slozka (N) -- složky IPLP z výdeje vydej.id_lp_predpis → predpis.id_lp_predpis (párování výdeje s předpisem) ``` ### Tabulka `zprava` Jeden řádek = jedna odpověď API (jedno volání `NacistLekovyZaznam`). | Sloupec | Typ | Zdroj v XSD | |---------|-----|-------------| | `id_zpravy` | CHAR(36) UNIQUE | `zprava_type.ID_Zpravy` | | `verze` | VARCHAR(20) | `zprava_type.Verze` | | `odeslano` | DATETIME | `zprava_type.Odeslano` | | `aplikace` | VARCHAR(512) | `zprava_odpoved_type.Aplikace` | | `id_podani` | CHAR(36) | `zprava_odpoved_type.ID_Podani` | | `prijato` | DATETIME | `zprava_odpoved_type.Prijato` | | `pacient_prijmeni` | VARCHAR(35) | `jmeno_osoby_type.Prijmeni` | | `pacient_jmena` | VARCHAR(24) | `jmeno_osoby_type.Jmena` | | `pacient_datum_narozeni` | DATE | `lz_totoznost_type.DatumNarozeni` | | `stazeno` | DATETIME | automaticky při INSERT | ### Tabulka `predpis` Dle `lz_nacteni_predepsany_lp_erp_type`. | Sloupec | Typ | NOT NULL | Poznámka | |---------|-----|----------|----------| | `id_lp_predpis` | CHAR(36) | ✓ | UUID z eReceptu, globálně unikátní | | `kod_predepisujiciho` | VARCHAR(36) | ✓ | UUID lékaře | | `datum_vystaveni` | DATE | ✓ | | | `mnozstvi` | SMALLINT | ✓ | 1–9999 | | `navod` | VARCHAR(80) | ✓ | max 80 znaků dle XSD | | `opakovani` | INT | | opakování předpisu | | `modry_pruh` | TINYINT(1) | | modrý pruh (návykové látky) | | `typ_leku` | ENUM | | HVLPReg / HVLPNereg / IPLP / INN | | `lek_kod` | CHAR(7) | | kód SÚKL (jen HVLP) | | `atc` | VARCHAR(7) | | ATC kód (jen HVLP) | | `nazev` | VARCHAR(200) | | max 200 — INN má nejdelší název | | `forma` | VARCHAR(27) | | léková forma | | `sila` | VARCHAR(24) | | síla přípravku | | `cesta_podani` | VARCHAR(15) | | POR, INH, … | | `baleni` | VARCHAR(22) | | **string**, ne číslo (může být "100 ks") | | `postup_pripravy` | VARCHAR(4000) | | receptura IPLP jako volný text | ### Tabulka `predpis_slozka` Dle `slozka_iplp_predpis_type`. Řádky vznikají jen pro IPLP předpisy se strukturovanými složkami. | Sloupec | Typ | NOT NULL | Poznámka | |---------|-----|----------|----------| | `predpis_id` | INT | ✓ | FK → predpis.id | | `mnozstvi` | DECIMAL(15,6) | ✓ | přesné množství suroviny | | `jednotka` | ENUM('g','ks') | ✓ | | | `nazev` | VARCHAR(200) | ✓ | název suroviny / přípravku | | `surovina` | CHAR(7) | | kód suroviny v registru SÚKL | | `hvlp_reg` | CHAR(7) | | pokud je složka registrovaný HVLP | ### Tabulka `vydej` Dle `lz_nacteni_vydany_lp_erp_type`. | Sloupec | Typ | NOT NULL | Poznámka | |---------|-----|----------|----------| | `id_lp_vydej` | CHAR(36) | ✓ | UUID výdeje | | `id_lp_predpis` | CHAR(36) | | FK → predpis.id_lp_predpis, NULL = výdej bez e-předpisu | | `kod_vydavajiciho` | VARCHAR(36) | ✓ | UUID lékárníka | | `datum_vydeje` | DATE | ✓ | | | `mnozstvi` | DECIMAL(6,2) | ✓ | **desetinné** — např. 0.5 balení | | `navod` | VARCHAR(80) | ✓ | | | `exspirace` | DATE | | exspirace šarže | | `sarze` | VARCHAR(50) | ✓ | číslo šarže | | `seriove_cislo` | VARCHAR(20) | | sériové číslo (léky s el. sledováním) | | `pozn` | VARCHAR(1000) | | poznámka lékárníka | | `typ_leku` | ENUM | | HVLPReg / HVLPNereg / IPLP | | `lek_kod` | CHAR(7) | | kód SÚKL (HVLP) nebo KodVZP (IPLP) | | `atc` | VARCHAR(7) | | jen HVLP | | `nazev` | VARCHAR(146) | | | | `forma` | VARCHAR(27) | | | | `sila` | VARCHAR(24) | | | | `cesta_podani` | VARCHAR(15) | | | | `postup_pripravy` | VARCHAR(4000) | | receptura IPLP | ### Tabulka `vydej_slozka` Dle `slozka_iplp_type`. Jako `predpis_slozka`, ale navíc obsahuje `hrazeno_zp`. | Sloupec | Typ | NOT NULL | Poznámka | |---------|-----|----------|----------| | `vydej_id` | INT | ✓ | FK → vydej.id | | `mnozstvi` | DECIMAL(15,6) | ✓ | | | `jednotka` | ENUM('g','ks') | ✓ | | | `nazev` | VARCHAR(200) | ✓ | název suroviny | | `hrazeno_zp` | DECIMAL(9,2) | | částka hrazená zdravotní pojišťovnou | | `surovina` | CHAR(7) | | | | `hvlp_reg` | CHAR(7) | | | --- ## Klíčové vlastnosti importu (`06UlozitDoMySQL.py`) - **Idempotentní**: `INSERT IGNORE` na `id_lp_predpis` / `id_lp_vydej` — opakované spuštění se stejným XML nepřidá duplikáty. - **Víc pacientů**: `zprava.id_zpravy` je UNIQUE — každé volání API (jiný pacient, jiný čas) vytvoří nový řádek v `zprava`. Předpisy a výdeje napříč pacienty se agregují v `predpis` / `vydej`. - **Schema se přepisuje**: `vytvor_schema()` vždy DROPne a znovu vytvoří všech 5 tabulek. Při produkčním použití (více pacientů) tuto část odstraňte a spouštějte DDL jen jednou při inicializaci. --- ## Užitečné analytické dotazy ```sql -- nejčastěji předepisované ATC skupiny za posledních 12 měsíců SELECT atc, nazev, COUNT(*) AS pocet, MAX(datum_vystaveni) AS naposledy FROM predpis WHERE datum_vystaveni >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH) GROUP BY atc, nazev ORDER BY pocet DESC; -- co bylo předepsáno ale nevyzvednuto SELECT p.datum_vystaveni, p.nazev, p.atc, p.navod FROM predpis p LEFT JOIN vydej v ON v.id_lp_predpis = p.id_lp_predpis WHERE v.id_lp_vydej IS NULL; -- IPLP magistraliter — kompletní receptury s frekvencí SELECT p.nazev, p.postup_pripravy, COUNT(*) AS pocet_predpisu FROM predpis p WHERE p.typ_leku = 'IPLP' GROUP BY p.nazev, p.postup_pripravy ORDER BY pocet_predpisu DESC; -- IPLP výdeje — strukturované složky (kde je lékárna zadala) SELECT v.datum_vydeje, v.nazev AS pripravek, GROUP_CONCAT(s.mnozstvi, ' ', s.jednotka, ' ', s.nazev ORDER BY s.id SEPARATOR ' + ') AS slozeni FROM vydej v JOIN vydej_slozka s ON s.vydej_id = v.id WHERE v.typ_leku = 'IPLP' GROUP BY v.id ORDER BY v.datum_vydeje DESC; -- nejčastěji používané suroviny v magistrech (ze strany výdeje) SELECT nazev, jednotka, COUNT(*) AS pocet FROM vydej_slozka GROUP BY nazev, jednotka ORDER BY pocet DESC; -- párování: co předepsal lékař vs. co lékárna vydala (generická záměna) SELECT p.datum_vystaveni, p.nazev AS predepsano, p.atc, v.nazev AS vydano, v.datum_vydeje FROM predpis p JOIN vydej v ON v.id_lp_predpis = p.id_lp_predpis WHERE p.nazev <> v.nazev; ``` --- ## Závislosti (Python) ``` requests requests-pkcs12 pymysql ``` ```bash pip install requests requests-pkcs12 pymysql ``` --- ## XSD zdroje Schéma verze `202501A`, soubory v `Dokumentace/2025-04-24/WSDL_XSD/NEPRIORITNI_WEBOVE_SLUZBY/`: | Soubor | Obsah | |--------|-------| | `Cuer2Schema.xsd` | Typy specifické pro lékový záznam: `NacistLekovyZaznamOdpoved`, `lz_nacteni_predepsany_lp_erp_type`, `lz_nacteni_vydany_lp_erp_type`, `slozka_iplp_*` | | `CuerSchema.xsd` | Společné typy: `hvlp_type`, `zprava_odpoved_type`, `zprava_type`, `jmeno_osoby_type`, `jednotka` |