import sys from pathlib import Path from datetime import datetime, date, timedelta import os import pymysql from knihovny.medicus_db import MedicusDB from knihovny.vzpb2b_client import VZPB2BClient from jinja2 import Environment, FileSystemLoader from weasyprint import HTML # ========================================== # PROJECT ROOT (import + paths) # ========================================== script_location = Path(__file__).resolve().parent project_root = script_location.parent sys.path.insert(0, str(project_root)) # ========================================== # CONFIGURATION # ========================================== MEDICUS_HOST = "192.168.1.4" MEDICUS_DB_PATH = r"z:\Medicus 3\data\MEDICUS.FDB" MYSQL_CONFIG = { "host": "192.168.1.76", "port": 3307, "user": "root", "password": "Vlado9674+", "database": "medevio", "charset": "utf8mb4", "autocommit": True } PFX_PATH = project_root / "certificates" / "MBcert.pfx" PFX_PASSWORD = "Vlado7309208104++" ENV = "prod" ICZ = "00000000" DIC = "00000000" if not PFX_PATH.exists(): raise FileNotFoundError(f"PFX certificate not found: {PFX_PATH}") # ========================================== # PATHS (templates, output) # ========================================== template_dir = project_root / "Templates" output_dir = script_location / "Output" output_dir.mkdir(exist_ok=True) font_regular = (template_dir / "fonts" / "DejaVuSans.ttf").as_uri() font_bold = (template_dir / "fonts" / "DejaVuSans-Bold.ttf").as_uri() font_italic = (template_dir / "fonts" / "DejaVuSans-Oblique.ttf").as_uri() # ========================================== # INIT CONNECTIONS # ========================================== print("Connecting to Medicus...") medicus = MedicusDB(MEDICUS_HOST, MEDICUS_DB_PATH) print("Connecting to MySQL...") mysql = pymysql.connect( cursorclass=pymysql.cursors.DictCursor, **MYSQL_CONFIG ) print("Initializing VZP B2B client...") vzp = VZPB2BClient( ENV, str(PFX_PATH), PFX_PASSWORD, icz=ICZ, dic=DIC ) # ========================================== # BINÁRNÍ HLEDÁNÍ DATA ZLOMU # ========================================== def find_insurance_break_date(vzp_client, rc, start_date, end_date): try: low = start_date high = end_date stav_low = vzp_client.parse_stav_pojisteni( vzp_client.stav_pojisteni(rc=rc, k_datu=low.isoformat()) )["stav"] stav_high = vzp_client.parse_stav_pojisteni( vzp_client.stav_pojisteni(rc=rc, k_datu=high.isoformat()) )["stav"] if stav_low != "1" or stav_high == "1": return None, None while (high - low).days > 1: mid = low + timedelta(days=(high - low).days // 2) xml = vzp_client.stav_pojisteni(rc=rc, k_datu=mid.isoformat()) stav_mid = vzp_client.parse_stav_pojisteni(xml)["stav"] if stav_mid == "1": low = mid else: high = mid return low, high except Exception: return None, None # ========================================== # FETCH REGISTERED PATIENTS # ========================================== print("Fetching registered patients from Medicus...") patients = medicus.get_active_registered_patients(as_dict=True) patients_by_rc = {p["rodcis"]: p for p in patients} print(f"Loaded {len(patients_by_rc)} registered patients") # ========================================== # FETCH LAST INSURANCE STATES # ========================================== sql_last_states = """ SELECT rc, stav FROM ( SELECT rc, stav, ROW_NUMBER() OVER (PARTITION BY rc ORDER BY k_datu DESC) AS rn FROM vzp_stav_pojisteni ) t WHERE rn = 1 """ with mysql.cursor() as cur: cur.execute(sql_last_states) last_states = cur.fetchall() # ========================================== # COMPARE + BREAK DATE # ========================================== suspected = [] today = date.today() for row in last_states: rc = row["rc"] stav = row["stav"] if rc in patients_by_rc and stav != "1": p = patients_by_rc[rc] with mysql.cursor() as c2: c2.execute(""" SELECT MAX(k_datu) AS last_insured FROM vzp_stav_pojisteni WHERE rc = %s AND stav = '1' """, (rc,)) r2 = c2.fetchone() last_known_insured = r2["last_insured"] insured_to = uninsured_from = None if last_known_insured: insured_to, uninsured_from = find_insurance_break_date( vzp, rc, last_known_insured, today ) suspected.append({ "rc": rc, "prijmeni": p["prijmeni"], "jmeno": p["jmeno"], "poj": p["poj"], "stav": stav, "insured_to": insured_to, "uninsured_from": uninsured_from }) print(f"Nalezeno {len(suspected)} problémových záznamů") # ========================================== # CLEANUP DB # ========================================== medicus.close() mysql.close() # ========================================== # PDF GENERATION # ========================================== env = Environment(loader=FileSystemLoader(str(template_dir)), autoescape=True) template = env.get_template("vzp_console_report.html") html_content = template.render( patients=suspected, generated_at=datetime.now().strftime("%d. %m. %Y %H:%M"), font_regular=font_regular, font_bold=font_bold, font_italic=font_italic ) timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") pdf_file = output_dir / f"kontrola_pojisteni_{timestamp}.pdf" print("Generuji PDF přes WeasyPrint...") HTML(string=html_content, base_url=str(template_dir)).write_pdf(pdf_file) print("\n✅ PDF REPORT VYTVOŘEN:") print(pdf_file.resolve()) try: os.startfile(pdf_file) except Exception: pass