Medevio/80 Pacienti: GUI pro správu pacientů mimo Medicus

- pacienti_gui.py: Tkinter aplikace se scrollovatelným seznamem pacientů
  ACTIVE v Medevio, kteří nejsou registrovaní v Medicusu; tlačítka
  VZP dotaz, Bod zlomu (binary search pojištění) a Označ neaktivní
- _test_breakpoint.py: dočasný testovací skript pro binary search
- NOTES.md: technická dokumentace adresáře

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
Vladimir Buzalka
2026-05-20 07:05:13 +02:00
parent fc13fe9d34
commit d30404ffd0
3 changed files with 869 additions and 0 deletions
+92
View File
@@ -0,0 +1,92 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Dočasný test binary search pojištění pro jedno RC."""
import sys, time
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")
from datetime import date, timedelta
from pathlib import Path
sys.path.insert(0, "U:/OrdinaceProjekt")
from Knihovny.vzpb2b_client import VZPB2BClient
CERT_PATH = Path("U:/OrdinaceProjekt/Insurance/Certificates/picka.pfx")
CERT_PASSWORD = "Vlado7309208104+"
ICZ = "09305000"
RC = "485221756"
DELAY = 1.50 # s
client = VZPB2BClient("prod", str(CERT_PATH), CERT_PASSWORD, icz=ICZ)
call_count = 0
def check(d: date) -> tuple[dict, bool]:
global call_count
call_count += 1
print(f" [{call_count:02d}] Testuji {d.isoformat()} ...", end=" ", flush=True)
for attempt in range(3):
try:
xml = client.stav_pojisteni(RC, k_datu=d.isoformat())
status = client.parse_stav_pojisteni(xml)
break
except Exception as e:
print(f"\n CHYBA (pokus {attempt+1}/3): {e} — čekám 3s ...", end=" ", flush=True)
time.sleep(3)
else:
print("SELHALO po 3 pokusech, končím.")
sys.exit(1)
stav = status.get("stav")
poj = status.get("kodPojistovny")
active = (status.get("stavVyrizeni") == 1 and stav == "1")
print(f"stav={stav!r:4s} pojišťovna={poj!r} aktivní={active}")
time.sleep(DELAY)
return status, active
today = date.today()
start_date = today - timedelta(days=730)
print("=" * 60)
print(f"RC: {RC}")
print(f"Okno: {start_date} -> {today}")
print("=" * 60)
print("\n[1] Kontrola krajů:")
status_start, active_start = check(start_date)
status_end, active_end = check(today)
print()
if not active_start:
print("✗ Na začátku (2 roky) již stav != '1' — rozšiřte okno nebo jiná situace.")
sys.exit(0)
if active_end:
print("✗ Dnes stále stav '1' — v tomto okně zlom není.")
sys.exit(0)
print("✓ Levý okraj aktivní, pravý neaktivní → spouštím binary search.\n")
print("[2] Binary search:")
left, right = start_date, today
left_status, right_status = status_start, status_end
while (right - left).days > 1:
mid = left + timedelta(days=(right - left).days // 2)
mid_status, mid_active = check(mid)
if mid_active:
left, left_status = mid, mid_status
direction = "→ posunuji LEFT doprava"
else:
right, right_status = mid, mid_status
direction = "← posunuji RIGHT doleva"
print(f" {direction} (interval: {left}{right}, {(right-left).days} dní)")
print()
print("=" * 60)
print("VÝSLEDEK:")
print(f" Poslední den pojištění (stav=1) : {left}")
print(f" pojišťovna: {left_status.get('nazevPojistovny')} / stav: {left_status.get('stav')}")
print(f" První den se změnou : {right}")
print(f" pojišťovna: {right_status.get('nazevPojistovny')} / stav: {right_status.get('stav')}")
print(f" Celkem API volání: {call_count}")
print("=" * 60)