Přidán list ED_PODANI + ED_PODANI_DATA do faktury_report.py; doplněny poznámky o eDávkách

- faktury_report.py: nový list ED_PODANI (ED_BOOKOFSUBMISSIONS) s přehledem podání pojišťovnám
- faktury_report.py: nový list ED_PODANI_DATA s dekódovaným obsahem dávek (KDAVKA, REQUEST XML, odpovědi pojišťoven)
- Opraveno kódování: KDAVKA=cp1250, REQUEST detekce BOM (utf-16/utf-8), SERVERRESPONSE/PROTOCOL=iso-8859-2
- Hyperlinky ED_PODANI ↔ ED_PODANI_DATA a Faktura → FAK
- FakturaceADavky.md: dokumentace ED_* tabulek, portálů pojišťoven, formátů REQUEST XML
- Průzkumné skripty: find_edavky_table, explore_hpn, explore_ed_bookofsubmissions, parse_trace_edavky aj.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-30 07:42:46 +02:00
parent 8497223ebb
commit 4f586f4b57
9 changed files with 1175 additions and 1 deletions
+240
View File
@@ -235,6 +235,246 @@ P ... preventivní prohlídka
- Kapitace se v FAK.KAPITACE neukazuje (je 0), ale v FAKDET.CENAKAP ano nutno ověřit
- PORTAL = registrační dávky, nesouvisí s fakturací, IDFAK bývá NULL
---
## eDávky elektronické odesílání dávek pojišťovnám (zjištěno 2026-03-29)
### Přehled tabulek
Modul eDávky v Medicusu používá tabulky s prefixem `ED_`:
| Tabulka | Záznamy | Popis |
|---|---|---|
| `ED_BOOKOFSUBMISSIONS` | 998 | Hlavní tabulka Kniha podání (od 2016) |
| `ED_BOOKOFSUBMISSIONATTACH` | 0 | Přílohy k podáním (zatím nevyužito) |
| `ED_MAILBOXMESSAGE` | 0 | Schránka zpráv od pojišťoven (zatím prázdná) |
| `ED_STORAGE` | 5 | Konfigurace certifikáty a přihlašovací údaje |
### Jak jsme tabulku našli
Přes Firebird trace log při otevření okna eDávky v Medicusu se nejčastěji dotazuje
na `ED_BOOKOFSUBMISSIONS` (45x) a `ED_MAILBOXMESSAGE` (4990x).
### PORTAL vs ED_BOOKOFSUBMISSIONS
- **PORTAL** (180 záznamů, max 2026-01-27) = starý systém podávání dávek
- **ED_BOOKOFSUBMISSIONS** (998 záznamů, od 2016) = nový systém (přechod ~únor 2026)
- Nepřekrývají se žádný záznam není v obou (různá ID_PODANI/SUBMISSIONID)
- PORTAL má data od 2014, ED_BOOKOFSUBMISSIONS od 2016 (oba systémy běžely paralelně)
---
### ED_BOOKOFSUBMISSIONS hlavní tabulka Knihy podání
**Sloupce:**
| Sloupec | Popis |
|---|---|
| `ID` | primární klíč |
| `CREATED` | datum vytvoření |
| `SENTDATE` | datum odeslání pojišťovně |
| `CREATOR` | jméno autora (např. "Buzalková Michaela MUDr.") |
| `HCPCODE` | IČZ ordinace (09305000) |
| `HCPPERSONNAME` | jméno lékaře |
| `HICCODE` | kód pojišťovny (111, 201, 205, 207, 209, 211...) |
| `INVOICENUMBER` | číslo faktury (např. 0000260020) NULL pro reg. dávky |
| `PERIODFROM` / `PERIODTO` | období dávky |
| `REQUESTTYPE` | typ: **0** = registrační (Reg. listy), **1** = výkonová s fakturou |
| `STATE` | stav podání (0 = odesláno OK) |
| `SUBMISSIONID` | podací číslo přidělené pojišťovnou (např. 59135047) |
| `TOTALSUM` | celková částka (0 pro reg. dávky) |
| `UNIQUEID` | UUID záznamu |
| `USERDESCRIPTION` | popis (zobrazuje se ve sloupci "Zprávy") |
| `REQUEST` | XML žádosti odeslané pojišťovně (BLOB) |
| `SERVERRESPONSE` | odpověď pojišťovny (BLOB, bytes, kódování iso-8859-2) |
| `FDAVKACONTENT` | obsah FDAVKA (BLOB) |
| `KDAVKACONTENT` | obsah KDAVKA (BLOB) |
| `PROTOCOL` | protokol (BLOB) |
**Pojišťovny v datech:** 111 (VZP), 201 (VoZP), 205 (ČPZP), 207 (OZP), 209 (ZPŠ), 211 (ZPMV)
### Kódování pojišťoven (správné!)
- **111** = VZP (Všeobecná zdravotní pojišťovna)
- **201** = VoZP (Vojenská zdravotní pojišťovna)
- **205** = ČPZP (Česká průmyslová zdravotní pojišťovna)
- **207** = OZP (Oborová zdravotní pojišťovna)
- **209** = ZPŠ (Zdravotní pojišťovna Škoda)
- **211** = ZPMV (Zdravotní pojišťovna ministerstva vnitra)
---
### ED_STORAGE konfigurace certifikátů a přihlašovacích údajů
Sloupce: `ID`, `NAME`, `VALUEB` (BLOB XML), `IDUZI`
**Záznamy:**
- `ServerSettingsXml` (per uživatel, IDUZI=None/2/4/6) XML s certifikáty pro každou pojišťovnu
- `LastMessagesDownloadTime` (IDUZI=None) datum posledního stažení zpráv
**Struktura ServerSettingsXml:**
```xml
<Settings>
<PortalZP>
<Portal Code="201">
<SigningCertificate Issuer="..." SerialNumber="..." />
</Portal>
<!-- Code: 201, 205, 207, 209, 212, 213, 217, 228, 333 -->
</PortalZP>
<PortalZPMV>
<!-- Pro ZPMV (211): PIN, Password, Email uloženy v plaintextu! -->
<Portal Code="211" PIN="..." Password="..." Email="ordinace@buzalkova.cz" />
</PortalZPMV>
<PortalVZP>
<!-- Pro VZP (111): SigningCertificate + AuthenticationCertificate -->
<Portal Code="111" UseAlternativePortal="true">
<SigningCertificate Issuer="..." SerialNumber="..." />
<AuthenticationCertificate Issuer="..." SerialNumber="..." />
</Portal>
</PortalVZP>
</Settings>
```
**Certifikát Buzalky Vladimíra (IDUZI=6):**
- Vydavatel: I.CA EU Qualified CA2/RSA 06/2022 (První certifikační autorita, a.s.)
- SerialNumber: `0247068517B0049E2E`
- Platí pro pojišťovny: 201, 205, 207, 209, 213, 217, 228
---
### Formát REQUEST XML registrační dávka (REQUESTTYPE=0)
```xml
<?xml version="1.0" encoding="utf-16"?>
<SubmissionRequest>
<SubmissionType>RegistrationCards</SubmissionType>
<InvoiceType>None</InvoiceType>
<PeriodFrom>2026-03-01T00:00:00.000</PeriodFrom>
<PeriodTo>2026-03-31T00:00:00.000</PeriodTo>
<TotalSum>0</TotalSum>
<HcpCode>09305000</HcpCode> <!-- IČZ ordinace -->
<FICZ>09305000</FICZ>
<HcpOrgNum>68366370</HcpOrgNum> <!-- IČO -->
<HcpPersonName>MUDr. Buzalka Vladimír</HcpPersonName>
<HicCode>111</HicCode> <!-- kód pojišťovny -->
<HicName>Všeobecná zdravotní pojišťovna ČR</HicName>
<HicCity>0900</HicCity>
<FPOB>0900</FPOB>
<VDPOJ>1</VDPOJ>
<InvoiceItems>
<InvoiceItem>
<BatchNumber>8</BatchNumber>
<Type>DP80</Type> <!-- DP80 = registrační dávka -->
<Price>0.00</Price>
<Year>2026</Year>
<Month>3</Month>
<DBODY>0</DBODY>
<DUHR>2</DUHR>
</InvoiceItem>
</InvoiceItems>
</SubmissionRequest>
```
### Formát REQUEST XML výkonová dávka s fakturou (REQUESTTYPE=1)
```xml
<?xml version="1.0" encoding="utf-16"?>
<SubmissionRequest>
<SubmissionType>HealthCareBilling</SubmissionType>
<InvoiceNumber>0000260026</InvoiceNumber>
<InvoiceType>HealthCareInvoice</InvoiceType>
<DateOfIssue>2026-03-01T00:00:00.000</DateOfIssue>
<DateOfDispatch>2026-03-01T00:00:00.000</DateOfDispatch>
<DateOfMaturity>2026-03-31T00:00:00.000</DateOfMaturity>
<PeriodFrom>2025-12-01T00:00:00.000</PeriodFrom>
<PeriodTo>2025-12-31T00:00:00.000</PeriodTo>
<TotalSum>85</TotalSum>
<HcpCode>09305000</HcpCode>
<HcpOrgNum>68366370</HcpOrgNum>
<HcpAccountNumber>2800046620</HcpAccountNumber>
<HcpAccountPrefix>000000</HcpAccountPrefix>
<HcpAccountBankCode>2010</HcpAccountBankCode>
<HcpName>Praktický lékař pro dospělé</HcpName>
<HcpStreet>Lovosická 440/40</HcpStreet>
<HcpCity>Praha 9-Prosek</HcpCity>
<HcpZipCode>19000</HcpZipCode>
<HcpPersonName>MUDr. Buzalková Michaela</HcpPersonName>
<HicCode>207</HicCode>
<HicStreet>Ročkotova 1225/1</HicStreet>
<HicCity>Praha 4</HicCity>
<HicZipCode>140 21</HicZipCode>
<FPOB>0900</FPOB>
<VDPECE>51</VDPECE>
<InvoiceItems>
<InvoiceItem>
<BatchNumber>34</BatchNumber>
<Type>DP05</Type> <!-- DP05 = výkonová dávka -->
<Year>2025</Year>
<Month>12</Month>
<DBODY>85</DBODY>
<DUHR>1</DUHR>
</InvoiceItem>
</InvoiceItems>
</SubmissionRequest>
```
**Poznámka k diakritice v REQUEST:** Medicus ukládá XML v UTF-16, ale česká diakritika v polích jako HcpPersonName, HicName apod. bývá uložena bez háčků/čárek (bug Medicusu při tvorbě XML). Toto není chyba dekódování.
### Formát SERVERRESPONSE (odpověď pojišťovny)
- Kódování: **iso-8859-2** (bytes)
- Struktura: XML `<Komunikace><Data ...><Soubor ...>text</Soubor></Data><Podpis>PKCS7</Podpis></Komunikace>`
- `PZP_IdPodani` = přidělené podací číslo
- `PZP_Chyba="0"` = bez chyby
- Odpověď je podepsána pojišťovnou (PKCS7)
---
### Plán: skript pro automatické odeslání žádosti o seznam registrovaných
### Portály pojišťoven 3 skupiny
#### Skupina 1 Společný portál (201, 205, 207, 209, 213, 217, 228)
- Jeden společný portál pro všechny tyto pojišťovny
- Autentizace a podepisování: **kvalifikovaný certifikát I.CA EU Qualified CA2/RSA 06/2022**
- SerialNumber (Buzalka): `0247068517B0049E2E`
- Vydavatel: První certifikační autorita, a.s.
#### Skupina 2 VZP (111) vlastní portál
- VZP má **samostatný portál** (`UseAlternativePortal="true"` v konfiguraci)
- Podepisování: **komerční certifikát I.CA Public CA/RSA 06/2022** (nižší stupeň než kvalifikovaný)
- SerialNumber: `01DE0F46B713505F1F`
- Autentizace vůči portálu: **certifikát Komerční banky (DCS CA KB)**
- SerialNumber: `46E67A`
#### Skupina 3 ZPMV (211) samostatní exoti
- Žádný certifikát, přihlašování **heslem**
- Konfigurace: PIN, Password, Email (uloženo v plaintextu v ED_STORAGE)
- Email: `ordinace@buzalkova.cz`
### Formáty odpovědí v PORTAL.DATA (historické)
Různé pojišťovny vracely různé formáty:
- **ČPZP/ZPMV** (D01 portál): XML `<ekomunikace><statuscode>100</statuscode><idpodani>D01F...</idpodani>`
- **OZP a ostatní** (starý portál): XML `<Komunikace><Data ...><Soubor Format="BASE64">HTML protokol</Soubor></Data></Komunikace>`
- HTML protokol je v iso-8859-2, obsahuje tabulku s detaily dávky
### Kódování BLOBů v ED_BOOKOFSUBMISSIONS
| Sloupec | Kódování | Poznámka |
|---|---|---|
| `KDAVKACONTENT` | CP1250 | fdb vrací str přes win1250 spojení použít přímo |
| `REQUEST` | ASCII/UTF-8 nebo UTF-16 | Detekovat podle BOM: `FF FE`/`FE FF` → utf-16, začíná `<` → utf-8 |
| `SERVERRESPONSE` | iso-8859-2 | latin-1 re-encoding → decode iso-8859-2 |
| `PROTOCOL` | iso-8859-2 | latin-1 re-encoding → decode iso-8859-2 |
**Důležité:** Pro re-encoding str→bytes vždy používat `latin-1` (ne `cp1250`), protože latin-1 zachová všechny bajty 0255 beze změny včetně null bajtů. Pro utf-16 nikdy nezkoušet decode bez ověření BOM bez BOM Python tiše vrátí čínské znaky místo chyby.
**Co potřebujeme ještě zjistit:**
- URL endpointů jednotlivých portálů (zachytit přes síťový trace)
- Jak přesně se REQUEST podepisuje certifikátem (PKCS12 / Windows certificate store)
**Co už máme:**
- Formát REQUEST XML (viz výše)
- Certifikáty a přihlašovací údaje z ED_STORAGE
- Strukturu odpovědi pojišťovny
- Rozdělení pojišťoven do 3 skupin podle způsobu přístupu
## Kódování KDAVKA/FDAVKA důležité!
Dávkové soubory (KDAVKA, FDAVKA) jsou uloženy v **CP852** (DOS Latin-2, prahistorické kódování).