#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Najde přesný den zlomu pojištění pro konkrétního pacienta. Algoritmus: 1. Z MySQL vezme MAX(k_datu) WHERE stav='1' pro daného pacienta. Pokud neexistuje, prochází zpět po 1 roce a hledá první stav='1'. 2. Binárním hledáním najde přesný den: low = poslední den kdy byl stav='1' high = první den kdy byl stav!='1' """ 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 ─────────────────────────────────────────────────────────────── RC = "500208129" PRIJMENI = "Zuzák" JMENO = "Viktor" PFX_PATH = Path(__file__).resolve().parent.parent / "Certificates" / "picka.pfx" PFX_PASSWORD = "Vlado7309208104+" ICZ = "00000000" DIC = "00000000" ENV = "prod" API_DELAY = 2 # sekundy mezi dotazy na VZP # ── INIT VZP ────────────────────────────────────────────────────────────────── if not PFX_PATH.exists(): print(f"CHYBA: PFX certifikat nenalezen: {PFX_PATH}") sys.exit(1) vzp = VZPB2BClient(ENV, str(PFX_PATH), PFX_PASSWORD, icz=ICZ, dic=DIC) call_count = 0 def check_stav(rc: str, check_date: date) -> str | None: global call_count if call_count > 0: time.sleep(API_DELAY) call_count += 1 print(f" [{call_count}] VZP dotaz k {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 # ── KROK 1: DOLNÍ MEZ ───────────────────────────────────────────────────────── print(f"\nHledám zlom pojištění pro {PRIJMENI} {JMENO} (RC: {RC})\n") print("── Krok 1: dolní mez ──────────────────────────────────────────────────") mysql = connect_mysql() with mysql.cursor() as cur: cur.execute( "SELECT MAX(k_datu) FROM vzp_stav_pojisteni WHERE rc = %s AND stav = '1'", (RC,) ) row = cur.fetchone() mysql.close() today = date.today() last_ok = row[0] if row and row[0] else None if last_ok: low = last_ok high = today print(f" MySQL: poslední stav='1' k datu {low}") print(f" → binary search [{low} … {high}]") else: print(" MySQL: žádný záznam se stavem='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"\n Nalezeno stav='1' k {low}") print(f" → binary search [{low} … {high}]") break prev_probe = probe if low is None: print("CHYBA: Stav='1' nenalezen ani 20 let zpatky. Nelze urcit zlom.") sys.exit(1) # ── KROK 2: OVĚŘENÍ HRANIC ──────────────────────────────────────────────────── print("\n── Krok 2: ověření hranic ─────────────────────────────────────────────") stav_low = check_stav(RC, low) stav_high = check_stav(RC, high) if stav_low != "1": print(f"CHYBA: Dolni mez {low} ma stav='{stav_low}' (ocekavam '1'). Nelze pokracovat.") sys.exit(1) if stav_high == "1": print(f"INFO: Horni mez {high} ma stav='1' — pacient je aktualne pojisten, zadny zlom nenalezen.") sys.exit(0) print(f" OK {low} -> '{stav_low}' | {high} -> '{stav_high}' — rozsah v poradku") # ── KROK 3: BINÁRNÍ HLEDÁNÍ ─────────────────────────────────────────────────── print(f"\n── Krok 3: binární hledání ({(high - low).days} dní v rozsahu) ─────────") 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 # ── VÝSLEDEK ────────────────────────────────────────────────────────────────── print(f"\n{'=' * 55}") print(f" VYSLEDEK - {PRIJMENI} {JMENO} (RC: {RC})") print(f"{'=' * 55}") print(f" Posledni den POJISTEN : {low}") print(f" Prvni den BEZ pojisteni: {high}") print(f" Celkem VZP dotazu : {call_count}") print(f"{'=' * 55}\n")