Files
insurance/knihovny/medicus_db.py
2026-01-27 05:28:26 +01:00

233 lines
5.5 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
VZP insurance history checker (single RC)
-----------------------------------------
- asks for RC
- determines current insurance
- searches backwards to find last change date
- strict rate limit: 1 request / second
- no MedicusDB dependency
"""
import sys
import time
import logging
from pathlib import Path
from datetime import date, timedelta
import pymysql
# ==========================================
# PROJECT ROOT (import fix)
# ==========================================
PROJECT_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(PROJECT_ROOT))
from knihovny.vzpb2b_client import VZPB2BClient
# ==========================================
# LOGGING
# ==========================================
logging.basicConfig(
filename="insurance_history.log",
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
encoding="utf-8"
)
console = logging.getLogger("console")
console.setLevel(logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter("%(message)s"))
console.addHandler(handler)
def log(msg):
logging.info(msg)
console.info(msg)
def log_err(msg):
logging.error(msg)
console.error(msg)
# ==========================================
# MYSQL CONNECTION
# ==========================================
mysql = pymysql.connect(
host="192.168.1.76",
port=3307,
user="root",
password="Vlado9674+",
database="medevio",
charset="utf8mb4",
autocommit=True
)
def save_result(rc, prijmeni, jmeno, k_datu, result, xml):
sql = """
INSERT INTO vzp_stav_pojisteni
(rc, prijmeni, jmeno, k_datu,
stav, kod_pojistovny, nazev_pojistovny,
pojisteni_kod, stav_vyrizeni, response_xml)
VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
"""
with mysql.cursor() as cur:
cur.execute(sql, (
rc,
prijmeni,
jmeno,
k_datu,
result["stav"],
result["kodPojistovny"],
result["nazevPojistovny"],
result["pojisteniKod"],
result["stavVyrizeni"],
xml
))
# ==========================================
# VZP RATE LIMITER (1 REQUEST / SECOND)
# ==========================================
_LAST_VZP_CALL = 0.0
def vzp_call(func, *args, **kwargs):
global _LAST_VZP_CALL
now = time.time()
elapsed = now - _LAST_VZP_CALL
if elapsed < 1.0:
time.sleep(1.0 - elapsed)
result = func(*args, **kwargs)
_LAST_VZP_CALL = time.time()
return result
# ==========================================
# CONFIGURATION
# ==========================================
PFX_PATH = PROJECT_ROOT / "certificates" / "picka.pfx"
PFX_PASSWORD = "Vlado7309208104+"
ENV = "prod"
ICZ = "00000000"
DIC = "00000000"
if not PFX_PATH.exists():
raise FileNotFoundError(f"PFX certificate not found: {PFX_PATH}")
# ==========================================
# INIT VZP CLIENT
# ==========================================
vzp = VZPB2BClient(
ENV,
str(PFX_PATH),
PFX_PASSWORD,
icz=ICZ,
dic=DIC
)
# ==========================================
# INPUT
# ==========================================
rc = input("Zadej rodné číslo (bez /): ").strip()
# try to load name from DB (optional)
with mysql.cursor(pymysql.cursors.DictCursor) as cur:
cur.execute(
"""
SELECT prijmeni, jmeno
FROM vzp_stav_pojisteni
WHERE rc = %s
ORDER BY k_datu DESC
LIMIT 1
""",
(rc,)
)
row = cur.fetchone()
if row:
prijmeni = row["prijmeni"]
jmeno = row["jmeno"]
else:
prijmeni = "?"
jmeno = "?"
today = date.today()
log(f"▶ Kontrola pojištění: {prijmeni} {jmeno} ({rc})")
# ==========================================
# CURRENT STATUS
# ==========================================
xml = vzp_call(
vzp.stav_pojisteni,
rc=rc,
k_datu=today.isoformat()
)
current = vzp.parse_stav_pojisteni(xml)
save_result(rc, prijmeni, jmeno, today, current, xml)
current_code = current["kodPojistovny"]
log(f"✔ Aktuální pojišťovna: {current['nazevPojistovny']} ({current_code})")
# ==========================================
# BACKWARD SEARCH
# ==========================================
def check_at(d):
xml = vzp_call(
vzp.stav_pojisteni,
rc=rc,
k_datu=d.isoformat()
)
res = vzp.parse_stav_pojisteni(xml)
kod = res["kodPojistovny"]
# 👇 THIS IS THE VISIBILITY YOU WANT
log(f" test {d.isoformat()} → kód {kod}")
save_result(rc, prijmeni, jmeno, d, res, xml)
return kod
log("\n⏪ Hledám poslední změnu pojišťovny...")
# 1⃣ yearly steps
probe = today
last_same = today
while True:
probe -= timedelta(days=365)
if probe.year < today.year - 20:
break
if check_at(probe) != current_code:
break
last_same = probe
# 2⃣ monthly steps
probe = last_same
while True:
probe -= timedelta(days=30)
if check_at(probe) != current_code:
break
last_same = probe
# 3⃣ daily steps
probe = last_same
while True:
probe -= timedelta(days=1)
if check_at(probe) != current_code:
change_date = probe + timedelta(days=1)
break
# ==========================================
# RESULT
# ==========================================
log("\n✅ VÝSLEDEK")
log(f"Pojišťovna {current_code} platí od: {change_date.isoformat()}")
# ==========================================
# CLEANUP
# ==========================================
mysql.close()
log("\nDONE.")