z230
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
#!/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")
|
||||
Reference in New Issue
Block a user