diff --git a/Insurance/KdoJeLékař/NOTES.md b/Insurance/KdoJeLékař/NOTES.md
new file mode 100644
index 0000000..8bef44c
--- /dev/null
+++ b/Insurance/KdoJeLékař/NOTES.md
@@ -0,0 +1,102 @@
+# KdoJeLékař — poznámky k vývoji
+
+## Cíl
+
+Zjistit pro pacienty z Medicus DB, kdo je jejich registrující **praktický lékař (001)**, **gynekolog (002)** a **stomatolog (014)** — dotazem na VZP B2B portál.
+
+---
+
+## VZP B2B služba: `RegistracePojistencePZSB2B`
+
+### Endpoint (produkce)
+```
+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
+
+ 7309208104
+ 2026-04-28
+
+ 001
+ 002
+ 014
+
+
+```
+
+XML namespace odpovědi: `http://xmlns.gemsystem.cz/B2B/RegistracePojistencePZSB2B/1`
+
+### Struktura odpovědi
+Pro každou odbornost vrátí jeden `` element:
+
+| 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 |
+
+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).
+
+---
+
+## Zdrojový kód pro inspiraci
+
+Vše je hotové v `u:\insurance\`, stačí přenést a adaptovat:
+
+| 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 |
+
+---
+
+## Certifikáty — stav k 28. 4. 2026
+
+| 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 |
+
+### 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`, `""`
+
+→ **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.
+
+---
+
+## 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`)
diff --git a/Insurance/KdoJeLékař/_test_temp.py b/Insurance/KdoJeLékař/_test_temp.py
new file mode 100644
index 0000000..159fa10
--- /dev/null
+++ b/Insurance/KdoJeLékař/_test_temp.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+import sys
+sys.path.insert(0, r"u:\insurance")
+
+from requests_pkcs12 import Pkcs12Adapter
+import requests
+import xml.etree.ElementTree as ET
+from datetime import date
+
+ENDPOINT = "https://prod.b2b.vzp.cz/B2BProxy/HttpProxy/RegistracePojistencePZSB2B"
+PFX_PATH = r"u:\ordinaceprojekt\Insurance\Certificates\MBQualifiedCert.pfx"
+PFX_PASS = "Vlado7309208104++"
+
+RC = "7309208104"
+K_DATU = date.today().isoformat()
+ODBORNOSTI = ["001", "002", "014"] # VPL, gynekologie, stomatologie
+
+NS = {
+ "soap": "http://schemas.xmlsoap.org/soap/envelope/",
+ "rp": "http://xmlns.gemsystem.cz/B2B/RegistracePojistencePZSB2B/1",
+}
+
+odb_xml = "".join(f"{k}" for k in ODBORNOSTI)
+envelope = f"""
+
+
+
+ {RC}
+ {K_DATU}
+ {odb_xml}
+
+
+"""
+
+session = requests.Session()
+session.mount("https://", Pkcs12Adapter(pkcs12_filename=PFX_PATH, pkcs12_password=PFX_PASS))
+
+resp = session.post(ENDPOINT, data=envelope.encode("utf-8"),
+ headers={"Content-Type": "text/xml; charset=utf-8", "SOAPAction": "process"},
+ timeout=30, verify=True)
+
+print(f"HTTP: {resp.status_code}\n")
+print("=== RAW XML ===")
+print(resp.text)
+print("\n=== PARSED ===")
+
+root = ET.fromstring(resp.text)
+items = root.findall(".//rp:seznamOdbornosti/rp:odbornost", NS)
+if not items:
+ st = root.find(".//rp:stavVyrizeniPozadavku", NS)
+ print(f"Žádné záznamy. stavVyrizeniPozadavku={st.text if st is not None else '?'}")
+else:
+ for it in items:
+ def g(tag):
+ el = it.find(f"rp:{tag}", NS)
+ return el.text.strip() if el is not None and el.text else None
+
+ odb = it.find("rp:odbornost", NS)
+ odb_kod = odb.find("rp:kod", NS).text.strip() if odb is not None and odb.find("rp:kod", NS) is not None else None
+ odb_naz = odb.find("rp:nazev", NS).text.strip() if odb is not None and odb.find("rp:nazev", NS) is not None else None
+
+ print(f" odbornost: {odb_kod} – {odb_naz}")
+ print(f" ICZ: {g('ICZ')}")
+ print(f" ICP: {g('ICP')}")
+ print(f" nazevICP: {g('nazevICP')}")
+ print(f" nazevSZZ: {g('nazevSZZ')}")
+ print(f" datumRegistrace: {g('datumRegistrace')}")
+ print(f" datumZahajeni: {g('datumZahajeni')}")
+ print(f" datumUkonceni: {g('datumUkonceni')}")
+ print()
+
+st = root.find(".//rp:stavVyrizeniPozadavku", NS)
+print(f"stavVyrizeniPozadavku: {st.text.strip() if st is not None and st.text else '?'}")