#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ batch_stav0_20250101.py ======================== Zpracuje 50 pacientů, kteří k 1. 1. 2025 vrátili stavVyrizeniPozadavku=0 na dotaz registrace lékaře (= VZP pojištěnce nenašla). Pro každého: 1. Dotáže VZP stavPojisteni k 2025-01-01 → uloží do vzp_stav_pojisteni. 2. Pokud stav != '1' a != '4', binárně hledá zlom pojištění a uloží do vzp_sledovani_pojisteni. Resumovatelný — pacienty, kteří už mají záznam v vzp_stav_pojisteni k 2025-01-01, přeskočí. """ import sys import time from pathlib import Path from datetime import date, timedelta PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent sys.path.insert(0, str(PROJECT_ROOT)) from Knihovny.mysql_db import connect_mysql from Knihovny.vzpb2b_client import VZPB2BClient # ── KONFIGURACE ─────────────────────────────────────────────────────────────── K_DATU = date(2025, 1, 1) API_DELAY = 1.5 PFX_PATH = Path(__file__).resolve().parent.parent / "Certificates" / "picka.pfx" PFX_PASSWORD = "Vlado7309208104+" ICZ = "00000000" DIC = "00000000" ENV = "prod" # ── PACIENTI ───────────────────────────────────────────────────────────────── PACIENTI = [ ("415513130", "Rohlíková", "Marie"), ("420622031", "Hamerník", "Josef"), ("430127082", "Anderle", "Václav"), ("435625017", "Kafková", "Marie"), ("436005111", "Plzáková", "Ivana"), ("445624103", "Kloučková", "Vlasta"), ("446116017", "Strnadová", "Dagmar"), ("456016085", "Kubcová", "Anna"), ("485627038", "Poustková", "Jiřina"), ("506109148", "Holubcová", "Svatava"), ("6008040247", "Šulc", "Jiří"), ("6054574130", "Přibová", "Darina"), ("6102694070", "Elouchefoun", "Aziz"), ("6654251978", "Svozilová", "Ivana"), ("6808292018", "Moudrý", "Jiří"), ("6853222079", "Milatová", "Martina"), ("6909154934", "Novák", "Petr"), ("7056764319", "Michlíková", "Anna"), ("7157734210", "Moudry Molloy", "Joanne"), ("7309300449", "Vojáček", "Aleš"), ("7410540709", "Torres blanco", "Jose maria"), ("7459303599", "Noháčová", "Kateřina"), ("7651090106", "Matějková", "Jana"), ("7803744597", "Barrell", "Peter"), ("7855080420", "Vondřičková", "Zuzana"), ("7908030427", "Smetana", "Libor"), ("7957312099", "Nimeřická", "Michaela"), ("7961794126", "Tomyshynets", "Halyna"), ("8005291404", "Hanzl", "František"), ("8156013041", "Maršíková", "Simona"), ("8157544241", "Jarošová", "Zuzana"), ("8203120299", "Otčenášek", "Vojtěch"), ("8253215223", "Slavíková", "Kateřina"), ("8301070558", "Kříž", "Michal"), ("8352210438", "Bartáková", "Jana"), ("8412175123", "Mičulka", "Jan"), ("8454664262", "Feoktistová", "Irina"), ("8462150147", "Říhová", "Markéta"), ("8503120417", "Šindelář", "Tomáš"), ("8552170517", "Slabá", "Gabriela"), ("8558150227", "Horáková", "Lucie"), ("8652034380", "Kopová", "Jana"), ("8754280403", "Jindrová", "Helena"), ("8755075153", "Babjáková", "Jana"), ("8910584023", "Pham Van", "Duy"), ("8953010330", "Špatná", "Markéta"), ("8956039037", "Slavíková", "Zuzana"), ("9002025956", "Banáš", "Martin"), ("9010262448", "Bečica", "Marek"), ("9811040305", "Sidej", "Natan"), ] # ── INIT ────────────────────────────────────────────────────────────────────── vzp = VZPB2BClient(ENV, str(PFX_PATH), PFX_PASSWORD, icz=ICZ, dic=DIC) mysql = connect_mysql() call_count = 0 today = date.today() # ── HELPERS ─────────────────────────────────────────────────────────────────── def check_stav(rc: str, check_date: date) -> str: global call_count if call_count > 0: time.sleep(API_DELAY) call_count += 1 print(f" [{call_count}] {check_date.isoformat()} ...", end=" ", flush=True) xml = vzp.stav_pojisteni(rc=rc, k_datu=check_date.isoformat()) stav = vzp.parse_stav_pojisteni(xml)["stav"] print(f"stav = {stav!r}") return stav def uloz_stav(rc, prijmeni, jmeno, k_datu, stav): xml = vzp.stav_pojisteni(rc=rc, k_datu=k_datu.isoformat()) with mysql.cursor() as cur: cur.execute(""" INSERT INTO vzp_stav_pojisteni (rc, prijmeni, jmeno, k_datu, stav, response_xml) VALUES (%s, %s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE stav=VALUES(stav), response_xml=VALUES(response_xml) """, (rc, prijmeni, jmeno, k_datu, stav, xml)) def najdi_zlom(rc: str, last_ok_mysql) -> tuple: if last_ok_mysql: low = last_ok_mysql high = today print(f" MySQL last stav='1': {low} → [{low} … {high}]") else: print(" MySQL: žádný stav='1' — hledám zpětně po rocích ...") prev_probe = today low = high = None for n in range(1, 21): y = today.year - n try: probe = date(y, today.month, today.day) except ValueError: probe = date(y, today.month, today.day - 1) stav = check_stav(rc, probe) if stav == "1": low = probe high = prev_probe print(f" Nalezeno stav='1' k {low} → [{low} … {high}]") break prev_probe = probe if low is None: print(" NELZE: stav='1' nenalezen ani 20 let zpět.") return None, None stav_low = check_stav(rc, low) stav_high = check_stav(rc, high) if stav_low != "1": print(f" NELZE: dolní mez {low} má stav='{stav_low}'.") return None, None if stav_high == "1": print(f" INFO: horní mez {high} má stav='1' — aktuálně pojištěn.") return None, None print(f" Binární hledání ({(high - low).days} dní) ...") while (high - low).days > 1: mid = low + timedelta(days=(high - low).days // 2) stav = check_stav(rc, mid) if stav == "1": low = mid else: high = mid return low, high # insured_to, uninsured_from # ── RESUME: načti již hotové ────────────────────────────────────────────────── with mysql.cursor() as cur: cur.execute("SELECT rc FROM vzp_stav_pojisteni WHERE k_datu = %s", (K_DATU,)) hotove = {row[0] for row in cur.fetchall()} zbyvaji = [(rc, p, j) for rc, p, j in PACIENTI if rc not in hotove] print(f"Celkem pacientů: {len(PACIENTI)}, již hotovo: {len(hotove)}, zbývá: {len(zbyvaji)}") print(f"API prodleva: {API_DELAY}s | K_DATU: {K_DATU}\n") print("=" * 60) # ── HLAVNÍ SMYČKA ───────────────────────────────────────────────────────────── vysledky = [] for i, (rc, prijmeni, jmeno) in enumerate(zbyvaji, 1): print(f"\n[{i}/{len(zbyvaji)}] {prijmeni} {jmeno} (RC: {rc})") # Krok 1: stav k K_DATU if call_count > 0: time.sleep(API_DELAY) call_count += 1 print(f" [{call_count}] {K_DATU.isoformat()} ...", end=" ", flush=True) xml_hist = vzp.stav_pojisteni(rc=rc, k_datu=K_DATU.isoformat()) stav_hist = vzp.parse_stav_pojisteni(xml_hist)["stav"] print(f"stav = {stav_hist!r}") with mysql.cursor() as cur: cur.execute(""" INSERT INTO vzp_stav_pojisteni (rc, prijmeni, jmeno, k_datu, stav, response_xml) VALUES (%s, %s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE stav=VALUES(stav), response_xml=VALUES(response_xml) """, (rc, prijmeni, jmeno, K_DATU, stav_hist, xml_hist)) # Krok 2: zlom (jen pokud stav != '1' a != '4') insured_to = uninsured_from = None if stav_hist in ("1", "4"): print(f" → pojištěn (stav={stav_hist!r}), zlom se nehledá") else: # Zkontroluj watchlist with mysql.cursor() as cur: cur.execute("SELECT insured_to, uninsured_from FROM vzp_sledovani_pojisteni WHERE rc = %s", (rc,)) existuje = cur.fetchone() if existuje: insured_to, uninsured_from = existuje print(f" → již ve watchlistu: insured_to={insured_to}, uninsured_from={uninsured_from}") else: with mysql.cursor() as cur: cur.execute( "SELECT MAX(k_datu) FROM vzp_stav_pojisteni WHERE rc = %s AND stav = '1'", (rc,) ) r = cur.fetchone() last_ok = r[0] if r and r[0] else None insured_to, uninsured_from = najdi_zlom(rc, last_ok) with mysql.cursor() as cur: cur.execute(""" INSERT INTO vzp_sledovani_pojisteni (rc, prijmeni, jmeno, insured_to, uninsured_from, aktualni_stav, prvni_detekce, posledni_kontrola) VALUES (%s, %s, %s, %s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE insured_to=VALUES(insured_to), uninsured_from=VALUES(uninsured_from), aktualni_stav=VALUES(aktualni_stav), posledni_kontrola=VALUES(posledni_kontrola) """, (rc, prijmeni, jmeno, insured_to, uninsured_from, stav_hist, today, today)) vysledky.append({ "rc": rc, "prijmeni": prijmeni, "jmeno": jmeno, "stav_20250101": stav_hist, "insured_to": insured_to, "uninsured_from": uninsured_from, }) # ── SOUHRN ──────────────────────────────────────────────────────────────────── mysql.close() print(f"\n{'=' * 60}") print(f" SOUHRN — {len(vysledky)} zpracovaných pacientů") print(f"{'=' * 60}") print(f" {'Příjmení':<20} {'Jméno':<14} {'Stav':>5} {'Pojištěn do':<13} {'Nepoj. od'}") print(f" {'-'*58}") for v in vysledky: ins = str(v["insured_to"]) if v["insured_to"] else "-" uni = str(v["uninsured_from"]) if v["uninsured_from"] else "-" print(f" {v['prijmeni']:<20} {v['jmeno']:<14} {v['stav_20250101']:>5} {ins:<13} {uni}") print(f"\nCelkem VZP dotazů: {call_count}")