# NacistLekovyZaznam — Funkční SOAP klient pro IS eRecept SÚKL

## Status
**OVĚŘENO FUNKČNÍ** — 5. dubna 2026
Odpověď serveru: `HTTP 200`, velikost: ~227 KB reálných dat
Schéma ověřeno proti: `Cuer2Schema.xsd` verze `202501A` (dokumentace SÚKL 2025-04-24)

---

## Co tato operace dělá

`NacistLekovyZaznam` je SOAP operace IS eRecept (SÚKL), která vrátí kompletní **lékový záznam pacienta** — tedy seznam všech předpisů a výdejů léků napříč všemi lékaři a lékárnami v ČR za zadané období.

Typické použití: lékař si před konzultací zobrazí, co pacient aktuálně bere, co mu bylo předepsáno a vydáno v lékárně.

---

## Klíčové informace (těžce dohledané)

### Endpoint (produkce)
```
https://lekar-soap.erecept.sukl.cz/cuer/Lekar2
```
> **Pozor:** Endpoint má na konci číslici `2` — tj. `/cuer/Lekar2`, nikoli `/cuer/Lekar`.
> Tato operace **není** dostupná na starším endpointu `/cuer/Lekar`.
> Poprvé zdokumentováno v: `eRecept_lekovy_zaznam_1v3.docx` (dokumentace SÚKL ze dne 2024-01-18).

### Endpoint (testovací prostředí)
```
https://lekar-soap.test-erecept.sukl.cz/cuer/Lekar2
```

### SOAPAction
```
"NacistLekovyZaznam"
```

### XML namespace
```
http://www.sukl.cz/erp/201912
```
> Namespace pochází z prosince 2019 a **nemění se** ani v novějších verzích rozhraní.
> Verze rozhraní se předává v elementu `<Verze>` uvnitř zprávy, ne změnou namespace.
> SÚKL zachovává zpětnou kompatibilitu — namespace zůstává `201912` i pro verze `202401A`, `202501A` atd.

---

## Další operace dostupné na stejném endpointu `/cuer/Lekar2`

Dle `CUERLekarService.wsdl` (2025-04-24) jsou na tomto endpointu celkem **4 operace**:

| Operace | SOAPAction | Popis |
|---|---|---|
| `NacistLekovyZaznam` | `NacistLekovyZaznam` | ✅ lékový záznam pacienta |
| `OverDuplicity` | `OverDuplicity` | kontrola duplicitních předpisů |
| `ZjistitPoznamkyHvlp` | `ZjistitPoznamkyHvlp` | poznámky k HVLP přípravkům |
| `GetAppInfo` | `GetAppInfo` | info o verzi API |
| `AppPing` | `AppPing` | test spojení |

---

## Autentizace (dvojitá)

IS eRecept vyžaduje **dvě vrstvy** autentizace současně:

### 1. Klientský certifikát (TLS mutual auth)
- Soubor: `AMBSUKL214235369G_31DEC2024.pfx` (certifikát lékaře vydaný SÚKL)
- Formát: PKCS#12 (`.pfx`)
- Knihovna: `requests-pkcs12` → `Pkcs12Adapter`
- Platnost certifikátu: do 31. 12. 2024 (při expiraci je nutné zažádat SÚKL o nový)

### 2. HTTP Basic Auth
- Uživatel: UUID lékaře (přiděluje SÚKL, jednoznačný v celé ČR)
- Heslo: osobní heslo lékaře do portálu eRecept

---

## Struktura SOAP dotazu

```xml
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <NacistLekovyZaznamLekarDotaz xmlns="http://www.sukl.cz/erp/201912">

      <Doklad>
        <Pristupujici>
          <Uzivatel>E08C89C6-2B1A-4EBA-8ED9-4E3E63618379</Uzivatel>  <!-- UUID lékaře, povinný -->
          <Pracoviste>00214235367</Pracoviste>                         <!-- IČP pracoviště, povinný -->
        </Pristupujici>
        <PocetZnakuATC>7</PocetZnakuATC>    <!-- POUZE hodnoty 5 nebo 7 (enum!), povinný -->
        <PocetMesicu>60</PocetMesicu>        <!-- max 99, VOLITELNÝ -->
        <Pacient>
          <Totoznost>
            <Jmeno>
              <Prijmeni>Buzalka</Prijmeni>
              <Jmena>Vladimír</Jmena>
            </Jmeno>
            <DatumNarozeni>1973-09-20</DatumNarozeni>
          </Totoznost>
        </Pacient>
        <!-- Zastupce — volitelný, pouze pokud dotazuje zastupující lékař -->
        <!-- <Zastupce>
          <DruhDokladu>OP</DruhDokladu>     1–2 znaky, volitelný -->
        <!--   <CisloDokladu>123456789</CisloDokladu>  1–9 znaků, volitelný -->
        <!-- </Zastupce> -->
      </Doklad>

      <Zprava>
        <ID_Zpravy>dabda2ad-df61-41db-bd46-a969eced026b</ID_Zpravy>  <!-- UUID, generovat pro každý dotaz -->
        <Verze>202501A</Verze>                                         <!-- aktuální verze protokolu -->
        <Odeslano>2026-04-05T10:00:00+00:00</Odeslano>                <!-- UTC timestamp -->
        <SW_Klienta>MEDICUS_____</SW_Klienta>                         <!-- identifikátor SW, přesně 12 znaků -->
      </Zprava>

    </NacistLekovyZaznamLekarDotaz>
  </soapenv:Body>
</soapenv:Envelope>
```

### Parametry dotazu (ověřeno proti Cuer2Schema.xsd verze 202501A)

| Element | Povinný | Omezení | Poznámka |
|---|---|---|---|
| `Uzivatel` | ✅ ano | UUID formát | UUID lékaře přidělené SÚKL |
| `Pracoviste` | ✅ ano | — | IČP pracoviště lékaře |
| `PocetZnakuATC` | ✅ ano | **pouze 5 nebo 7** | enum — jiné hodnoty server odmítne |
| `PocetMesicu` | ❌ volitelný | max 99 | počet měsíců do minulosti |
| `Prijmeni` | ✅ ano | — | příjmení pacienta |
| `Jmena` | ✅ ano | — | jméno/jména pacienta |
| `DatumNarozeni` | ✅ ano | `YYYY-MM-DD` | datum narození pacienta |
| `Zastupce` | ❌ volitelný | — | pouze pro zastupujícího lékaře |
| `ID_Zpravy` | ✅ ano | UUID formát | nové UUID pro každý dotaz |
| `Verze` | ✅ ano | — | aktuálně `202501A` |
| `Odeslano` | ✅ ano | ISO 8601 | čas odeslání s časovou zónou |
| `SW_Klienta` | ✅ ano | přesně 12 znaků | doplnit mezerami zleva nebo zprava |

---

## Struktura odpovědi (ověřeno proti Cuer2Schema.xsd verze 202501A)

```
NacistLekovyZaznamOdpoved
├── Doklad
│   ├── Pacient                       potvrzení identity pacienta
│   │   ├── Jmeno (Prijmeni, Jmena)   volitelný
│   │   └── DatumNarozeni             volitelný
│   │
│   ├── PredepisujiciSeznam           volitelný — lékaři kteří předepisovali
│   │   └── Predepisujici[]
│   │       ├── Lekar                 Kod (UUID) + Jmeno — volitelný
│   │       ├── ICZ                   8 číslic — volitelný
│   │       ├── ICP                   8 číslic — povinný
│   │       ├── PZS                   volitelný
│   │       │   ├── Nazev             max 200 znaků
│   │       │   ├── Telefon           max 20 znaků — volitelný
│   │       │   └── Adresa
│   │       └── Telefon               max 20 znaků — volitelný
│   │
│   ├── VydavajiciSeznam              volitelný — lékárníci kteří vydávali
│   │   └── Vydavajici[]
│   │       ├── Lekarnik              Kod (UUID) + Jmeno
│   │       └── PZS                   Nazev + Adresa
│   │
│   ├── PredpisSeznam                 volitelný — všechny předpisy
│   │   └── Predpis[]
│   │       ├── ID_LP_Predpis         UUID předpisu — povinný
│   │       ├── KodPredepisujiciho    odkaz do PredepisujiciSeznam — povinný
│   │       ├── DatumVystaveni        datum vystavení
│   │       ├── Mnozstvi              int, 1–9999
│   │       ├── Navod                 max 80 znaků (dávkování)
│   │       ├── Opakovani             int — volitelný
│   │       ├── HVLPReg               volitelný (registrovaný HVLP)
│   │       ├── HVLPNereg             volitelný (neregistrovaný HVLP)
│   │       ├── IPLP                  volitelný (individuálně připravovaný LP)
│   │       ├── INN                   volitelný (generický název)
│   │       └── ModryPruh             boolean — volitelný
│   │
│   ├── VydejSeznam                   volitelný — výdeje z lékáren
│   │   └── Vydej[]
│   │       ├── ID_LP_Vydej           UUID výdeje
│   │       ├── ID_LP_Predpis         UUID předpisu — volitelný (odkaz na předpis)
│   │       ├── KodVydavajiciho       odkaz do VydavajiciSeznam — povinný
│   │       ├── DatumVydeje           datum výdeje
│   │       ├── Mnozstvi              decimal, 0.01–9999.99
│   │       ├── Navod                 max 80 znaků
│   │       ├── Exspirace             datum — volitelný
│   │       ├── Sarze                 max 50 znaků
│   │       ├── SerioveCislo          max 20 znaků — volitelný
│   │       ├── Pozn                  max 1000 znaků — volitelný
│   │       ├── HVLPReg               volitelný
│   │       ├── HVLPNereg             volitelný
│   │       └── IPLP                  volitelný
│   │
│   └── DuplicitaSeznam               volitelný — detekované duplicity výdejů
│       └── Duplicita[]
│           └── ID_LP[]
│               ├── ID_LP_Vydej       UUID — volitelný
│               └── ID_LP_Predpis     UUID — volitelný
│
└── Zprava
    ├── ID_Zpravy                     echo zpět
    ├── Verze
    ├── Odeslano
    └── ...
```

> **Poznámka k odkazům:** `KodPredepisujiciho` v předpisu odpovídá `Lekar.Kod` v `PredepisujiciSeznam`.
> Stejně tak `KodVydavajiciho` odpovídá `Lekarnik.Kod` v `VydavajiciSeznam`.
> Struktura je záměrně normalizovaná — lékaři a lékárny jsou uloženi jednou, předpisy a výdeje se na ně odkazují.

Reálná velikost odpovědi: **~227 KB** (pacient s 60měsíční historií).

---

## HTTP hlavičky

```python
headers = {
    "Content-Type": 'text/xml; charset="UTF-8"',
    "SOAPAction": '"NacistLekovyZaznam"',   # uvozovky jsou součástí hodnoty!
    "User-Agent": "Medicus"
}
```

---

## Závislosti (Python)

```
requests
requests-pkcs12
```

Instalace:
```bash
pip install requests requests-pkcs12
```

---

## Jak dohledat správný endpoint (postup pro budoucí operace)

Endpoint `/cuer/Lekar2` byl dohledán tímto postupem:

1. Prohledání veškeré dokumentace SÚKL (2017–2025) fulltext hledáním výrazu `soap:address`
2. Klíčový dokument: `eRecept_lekovy_zaznam_1v3.docx` (2024-01-18):
   > *"Pro webové služby, které používá lékař a klinický farmaceut je nová verze rozhraní 202401A (původní 201912A): `https://lekar-soap.erecept.sukl.cz/cuer/Lekar2`"*
3. Ověřeno živým voláním — HTTP 200, reálná data

### Mapa endpointů IS eRecept (produkce)

| Endpoint | Určen pro | Operace |
|---|---|---|
| `https://lekar-soap.erecept.sukl.cz/cuer/Lekar` | lékař | CUER operace (předpis, zrušení…) |
| `https://lekar-soap.erecept.sukl.cz/cuer/Lekar2` | lékař | **NacistLekovyZaznam**, OverDuplicity, ZjistitPoznamkyHvlp |
| `https://lekar-soap.erecept.sukl.cz/rlpo/Lekar` | lékař | RLPO operace |
| `https://lekarnik-soap.erecept.sukl.cz/cuer/Lekarnik` | lékárník | CUER operace (výdej…) |
| `https://lekarnik-soap.erecept.sukl.cz/cuer/Lekarnik2` | lékárník | nové CUER operace lékárníka |
| `https://cuer-soap.erecept.sukl.cz/` | lékárna, ZP | doplatky, limity pojištěnce |

---

## Ztotožnění pacienta a chybové kódy

Zdroj: živé volání `NacistCiselnikChyb` na `https://lekar-soap.erecept.sukl.cz/cuer/Lekar` — ověřeno 5. 4. 2026.

### Jak funguje ztotožnění pacienta (Registr obyvatel)

Server každý dotaz porovná s **Registrem obyvatel (ROB)**. Lze použít dvě sady údajů:

| Sada | Prvky | Poznámka |
|---|---|---|
| **A — jméno** | Prijmeni + Jmena + DatumNarozeni | základní, stačí pokud je pacient jednoznačný |
| **B — doklad** | DruhDokladu + CisloDokladu | jednoznačné vždy, řeší jmenovce |

Obě sady lze kombinovat. Pokud jsou uvedeny obě, musí být konzistentní (jinak C017).

### Jak přesně probíhá ztotožnění pacienta v ROB

> Zdroj: oficiální dokumentace SÚKL k IS eRecept

IS eRecept nejprve prohledá svůj interní **kmen pacientů** (vlastní databáze dříve ztotožněných osob). Teprve při neúspěchu volá **Registr obyvatel (ROB)** — což může trvat až několik sekund. U každého pacienta s korektními údaji by se to mělo stát pouze jednou. IS eRecept průběžně přebírá změny z ROB (např. přejmenování po svatbě se projeví automaticky).

Způsoby ztotožnění probíhají v tomto pořadí:

#### 1. ECD — elektronicky čitelný doklad
Hledání dle `DruhDokladu` + `CisloDokladu`. Pokud zadáno, má přednost.

#### 2. JPDN — jméno, příjmení, datum narození
Pokud nalezena právě jedna osoba → hotovo (`ROB=JPDN`).
Pokud nalezeno více jmenovců → přechod na JPDNA.
Pokud nenalezena žádná → upozornění (měkká chyba).

#### 3. JPDNA — jméno, příjmení, datum narození + adresa trvalého pobytu
ROB umí automaticky opravit záměnu čísla popisného a orientačního.
Pokud nalezena právě jedna osoba → hotovo (`ROB=JPDNA`).
Pokud nenalezena žádná → upozornění, předpis se uloží s kódem **C023**.

> **Důležité:** Adresu není nutné uvádět, pokud proběhne úspěšné vyhledání bez ní. V takovém případě se na předpisu použije adresa dohledaná v ROB.

> **Cizinci:** Lze uvést zahraniční adresu, nebo adresu hotelu/lázní v ČR.

> **⚠️ Testování:** Ztotožňování reálných osob smí probíhat **pouze na produkci**. O každém ztotožnění je záznam v základních registrech — pacient může obdržet výpis do datové schránky. Na testovacím prostředí jsou dostupné testovací identity na: https://www.szrcr.cz/cs/sluzby/spravci-a-vyvojari/vyvojari-agendovych-informacnich-systemu#testdata (mění se denně mezi 6:00–6:30).

---

### Hodnoty DruhDokladu

⚠️ **Oprava předchozí dokumentace** — povolených hodnot je více než jen `ID` a `P`:

| Hodnota | Doklad |
|---|---|
| `ID` | občanský průkaz (nový formát) |
| `OP` | občanský průkaz (starší označení) |
| `P` | cestovní pas |
| `IR` | povolení k pobytu |
| `VS` | vízový štítek |
| `PS` | pobytový štítek |

`CisloDokladu` — pouze číslice, max 9 znaků.

---

### Chybové kódy — ztotožnění pacienta (skupina C)

| Kód | Typ | Popis | Co udělat |
|---|---|---|---|
| **C010** | tvrdá | Jméno + příjmení + datum narození nenalezeno v ROB | Zkontrolovat překlep, záměnu jména a příjmení |
| **C011** | tvrdá | Druh a číslo dokladu nenalezeno v ROB | Zkontrolovat číslo a platnost dokladu |
| **C012** | tvrdá | Adresa neodpovídá — více jmenovců | Doplnit `DruhDokladu` + `CisloDokladu` |
| **C014** | tvrdá | Není uvedeno ani jméno/datum, ani číslo dokladu | Doplnit alespoň jednu sadu |
| **C015** | tvrdá | Více jmenovců v ROB, nelze dohledat adresu | Doplnit adresu **nebo** číslo dokladu |
| **C016** | měkká | Pacient mladší 33 dní | Předpis uložen, ale nebude v lékovém záznamu |
| **C017** | tvrdá | Jméno/datum neodpovídá osobě nalezené dle čísla dokladu | Opravit jméno nebo ho neuvádět |
| **C018** | tvrdá | Nelze dohledat, chybí adresa | Doplnit adresu nebo číslo dokladu |
| **C019** | tvrdá | Datum narození v budoucnosti | Opravit datum |
| **C020** | tvrdá | Chybí jméno, příjmení nebo datum narození | Doplnit kompletní sadu |
| **C022** | tvrdá | Pacient dle ROB již zemřel | — |
| **C023** | měkká | Předpis uložen, ale kvůli chybě ztotožnění **nebude v lékovém záznamu** | Opravit identifikaci a provést změnu předpisu |
| **C024** | měkká | Registr LP prohledán, pacient nenalezen v ROB (možný cizinec) | — |
| **C025** | měkká | Výdej uložen, ale kvůli chybě ztotožnění nebude v lékovém záznamu | — |

> **Měkká chyba** = operace proběhla, ale s upozorněním. **Tvrdá chyba** = operace odmítnuta.

### Chybové kódy — doklad totožnosti

| Kód | Popis |
|---|---|
| **L076** | Neznámý druh dokladu — viz tabulka povolených hodnot výše |

### Chybové kódy — systémové

| Kód | Popis |
|---|---|
| **I005** | Registr obyvatel nedostupný (mimo kontrolu SÚKL) — zkusit znovu |
| **I007** | Chyba dotazu na ROB — vstupní data nemají správný formát |

---

### Proč Medicus žádá o občanský průkaz

Typický scénář: lékař pošle dotaz pouze se jménem + datem narození. Pokud existuje více jmenovců v ROB (méně než 1 % obyvatel), server vrátí **C015**. Medicus tento kód rozpozná a zobrazí dialog *"zadejte číslo občanského průkazu"*. Lékař zadá číslo, Medicus pošle dotaz znovu s `DruhDokladu=ID` + `CisloDokladu=...` → server jednoznačně identifikuje pacienta metodou **ECD**.

### Identifikace pro úhradové mechanismy (ZP)

Oddělená od ztotožnění v ROB — probíhá přes **kód ZP + číslo pojištěnce**. IS eRecept číslo pojištěnce **neověřuje** — není garantováno, že je správné. Pokud lékárna zjistí chybu kódu pojišťovny, může ji opravit operací `ZmenitPojistovnuPredpisu`.

### Skript s občankou

`NacistLekovyZaznam_FUNKCNI_OBCANKA.py` — varianta s `DruhDokladu` + `CisloDokladu` v dotazu.

---

## Soubory skriptů

| Skript | Popis |
|---|---|
| `NacistLekovyZaznam_FUNKCNI.py` | základní dotaz — jméno + datum narození |
| `NacistLekovyZaznam_FUNKCNI_OBCANKA.py` | dotaz s číslem občanského průkazu |
| `NacistCiselnikChyb.py` | stáhne kompletní číselník chybových kódů ze serveru |

---

## Zdroje dokumentace SÚKL

| Soubor | Datum | Obsah |
|---|---|---|
| `eRecept_lekovy_zaznam_1v1.docx` | 2020-05-28 | původní popis lékového záznamu |
| `eRecept_lekovy_zaznam_1v3.docx` | 2024-01-18 | endpointy Lekar2/Lekarnik2, verze 202401A |
| `CUERLekarService.wsdl` | 2025-04-24 | nejnovější definice rozhraní, seznam operací |
| `Cuer2Schema.xsd` | 2025-04-24 | kompletní XSD schéma dotazu i odpovědi, verze 202501A |
| `CuerSchema.xsd` | 2025-04-24 | sdílené typy (Zprava, Pristupujici, adresy…) |
