#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys as _sys _sys.stdout.reconfigure(encoding="utf-8", errors="replace") _sys.stderr.reconfigure(encoding="utf-8", errors="replace") """ 06_nasledny_lekar.py ==================== Pro všechny ukončené pacienty (103) se dotáže VZP ke dni ukonceni+1 na jejich nového praktického lékaře (odbornost 001). Výsledek je jeden ze tří stavů: nenalezen → pacient u VZP neexistuje (zemřel / přestal být pojištěný) bez_lekare → pacient existuje, ale nemá GP (dosud se nepřehlásil) prehlasil → přehlásil se k novému lékaři (ukládáme ICP, jméno, datum) Ukládá do tabulky seznam_pojistencu_nasledny_lekar. Přeskočí pacienty, kteří tam už jsou (resumovatelný běh). """ import sys import time import xml.etree.ElementTree as ET from datetime import date, timedelta from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "Knihovny")) from mysql_db import connect_mysql from vzpb2b_client import VZPB2BClient PFX_PATH = str(Path(__file__).resolve().parents[1] / "Certificates" / "picka.pfx") PFX_PASSWORD = "Vlado7309208104+" ICZ = "09305000" API_PAUSE = 2 CREATE_SQL = """ CREATE TABLE IF NOT EXISTS seznam_pojistencu_nasledny_lekar ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, cip VARCHAR(12) NOT NULL, prijmeni VARCHAR(60) NOT NULL, jmeno VARCHAR(40) NOT NULL, datum_ukonceni DATE NOT NULL COMMENT 'Datum ukončení u nás', datum_dotazu DATE NOT NULL COMMENT 'Dotaz k datu ukonceni+1', stav_vzp VARCHAR(20) NOT NULL COMMENT 'nenalezen / bez_lekare / prehlasil', stav_vyrizeni VARCHAR(10) NULL COMMENT 'stavVyrizeniPozadavku z VZP', novy_icp VARCHAR(20) NULL, novy_icz VARCHAR(20) NULL, novy_nazev VARCHAR(200) NULL COMMENT 'nazevSZZ — jméno lékaře', novy_ordinace VARCHAR(200) NULL COMMENT 'nazevICP — název ordinace', datum_prehlaseni DATE NULL COMMENT 'datumRegistrace u nového lékaře', dotazeno_dne DATE NOT NULL, UNIQUE KEY uq_cip (cip) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Stav pojištěnce ke dni ukončení registrace u naší ordinace'; """ NS = "http://xmlns.gemsystem.cz/B2B/RegistracePojistencePZSB2B/1" def parse_nasledny(xml_text: str) -> dict: """ Vrátí dict s klíči: stav_vzp, stav_vyrizeni, novy_icp, novy_icz, novy_nazev, novy_ordinace, datum_prehlaseni. """ try: root = ET.fromstring(xml_text) except ET.ParseError: return {"stav_vzp": "chyba_xml", "stav_vyrizeni": None, "novy_icp": None, "novy_icz": None, "novy_nazev": None, "novy_ordinace": None, "datum_prehlaseni": None} def find(el, tag): e = el.find(f"{{{NS}}}{tag}") return e.text.strip() if e is not None and e.text else None stav_vyrizeni = find(root, "stavVyrizeniPozadavku") # Hledám odbornost 001 s jiným lékařem odbornosti = root.findall(f".//{{{NS}}}odbornost") for odb in odbornosti: # Vnější element — má ICZ icz = find(odb, "ICZ") icp = find(odb, "ICP") if not icp: continue # Ověřím odbornost (vnořený subelement) sub = odb.find(f"{{{NS}}}odbornost") if sub is None: continue kod = find(sub, "kod") if kod != "001": continue # Nalezen nový GP dr = date.fromisoformat(find(odb, "datumRegistrace")) \ if find(odb, "datumRegistrace") else None return { "stav_vzp": "prehlasil", "stav_vyrizeni": stav_vyrizeni, "novy_icp": icp, "novy_icz": icz, "novy_nazev": find(odb, "nazevSZZ"), "novy_ordinace": find(odb, "nazevICP"), "datum_prehlaseni": dr, } # Žádná odbornost 001 nenalezena if stav_vyrizeni == "0": stav = "nenalezen" elif stav_vyrizeni == "1": stav = "bez_lekare" else: # Zkusím ještě — pokud jsou nějaké záznamy ale ne 001, je to bez_lekare stav = "nenalezen" if not odbornosti else "bez_lekare" return {"stav_vzp": stav, "stav_vyrizeni": stav_vyrizeni, "novy_icp": None, "novy_icz": None, "novy_nazev": None, "novy_ordinace": None, "datum_prehlaseni": None} # ── Načtení ukončených pacientů ─────────────────────────────────────────────── conn = connect_mysql() cur = conn.cursor() cur.execute(CREATE_SQL) # Ukončení z vzp_registrace_lekari cur.execute(""" SELECT r.rc, r.prijmeni, r.jmeno, r.datum_ukonceni FROM vzp_registrace_lekari r INNER JOIN ( SELECT rc, MAX(k_datu) mk FROM vzp_registrace_lekari WHERE kod_odbornosti='001' AND ICP='09305001' AND ma_lekare=1 GROUP BY rc ) l ON r.rc=l.rc AND r.k_datu=l.mk WHERE r.kod_odbornosti='001' AND r.ICP='09305001' AND r.datum_ukonceni < '3000-01-01' AND r.datum_ukonceni < CURDATE() """) pacienti = [(r[0], r[1] or "", r[2] or "", r[3]) for r in cur.fetchall()] # Doplním ze zlomů (13 nespárovaných) cur.execute(""" SELECT cip, prijmeni, jmeno, zlom_datum FROM seznam_pojistencu_zlomy WHERE stav='ukončen' AND zlom_datum IS NOT NULL AND zlom_datum < CURDATE() """) for r in cur.fetchall(): if r[0] not in {p[0] for p in pacienti}: pacienti.append((r[0], r[1], r[2], r[3])) # Přeskočím již zpracované cur.execute("SELECT cip FROM seznam_pojistencu_nasledny_lekar") hotovi = {r[0] for r in cur.fetchall()} ke_zpracovani = [(c, p, j, d) for c, p, j, d in pacienti if c not in hotovi] print(f"Ukončených celkem: {len(pacienti)}") print(f"Již zpracováno: {len(hotovi)}") print(f"Ke zpracování: {len(ke_zpracovani)}") if not ke_zpracovani: print("Vše již zpracováno.") cur.close(); conn.close(); sys.exit(0) vzp = VZPB2BClient("prod", PFX_PATH, PFX_PASSWORD, icz=ICZ) # ── Hlavní smyčka ───────────────────────────────────────────────────────────── print() sirka = max(len(f"{p} {j}") for _, p, j, _ in ke_zpracovani) + 2 for i, (cip, pri, jme, du) in enumerate(ke_zpracovani, 1): datum_dotazu = du + timedelta(days=1) jmeno_str = f"{pri} {jme}" print(f"[{i:>3}/{len(ke_zpracovani)}] {jmeno_str:<{sirka}} ({cip}) k {datum_dotazu}", end=" ", flush=True) try: xml = vzp.registrace_lekare(cip, datum_dotazu.isoformat(), odbornosti=["001"]) time.sleep(API_PAUSE) vysl = parse_nasledny(xml) except Exception as e: print(f"CHYBA: {e}") vysl = {"stav_vzp": "chyba", "stav_vyrizeni": str(e), "novy_icp": None, "novy_icz": None, "novy_nazev": None, "novy_ordinace": None, "datum_prehlaseni": None} # Výpis stav = vysl["stav_vzp"] if stav == "prehlasil": print(f"→ přehlásil se: {vysl['novy_nazev']} (ICP {vysl['novy_icp']}, od {vysl['datum_prehlaseni']})") elif stav == "bez_lekare": print("→ bez nového lékaře") elif stav == "nenalezen": print("→ nenalezen (zemřel / nepojištěný)") else: print(f"→ {stav}") cur.execute(""" INSERT INTO seznam_pojistencu_nasledny_lekar (cip, prijmeni, jmeno, datum_ukonceni, datum_dotazu, stav_vzp, stav_vyrizeni, novy_icp, novy_icz, novy_nazev, novy_ordinace, datum_prehlaseni, dotazeno_dne) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) ON DUPLICATE KEY UPDATE datum_ukonceni=VALUES(datum_ukonceni), datum_dotazu=VALUES(datum_dotazu), stav_vzp=VALUES(stav_vzp), stav_vyrizeni=VALUES(stav_vyrizeni), novy_icp=VALUES(novy_icp), novy_icz=VALUES(novy_icz), novy_nazev=VALUES(novy_nazev), novy_ordinace=VALUES(novy_ordinace), datum_prehlaseni=VALUES(datum_prehlaseni), dotazeno_dne=VALUES(dotazeno_dne) """, (cip, pri, jme, du, datum_dotazu, stav, vysl["stav_vyrizeni"], vysl["novy_icp"], vysl["novy_icz"], vysl["novy_nazev"], vysl["novy_ordinace"], vysl["datum_prehlaseni"], date.today())) cur.close() conn.close() # ── Souhrn ──────────────────────────────────────────────────────────────────── print(f"\nHotovo. Zpracováno {len(ke_zpracovani)} pacientů.")