Files
insurance/05 Kontrola pojištěnců/30 Porovnani kapitace.py
2026-01-26 19:46:49 +01:00

235 lines
5.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import re
from pathlib import Path
from typing import List, Dict, Set
import pymysql
from knihovny.medicus_db import MedicusDB
# ============================================================
# KONFIGURACE
# ============================================================
# --- Firebird / Medicus ---
FIREBIRD_HOST = "192.168.1.4"
FIREBIRD_DB = r"Z:\medicus 3\data\medicus.fdb"
FIREBIRD_USER = "SYSDBA"
FIREBIRD_PASS = "masterkey"
FIREBIRD_CHARSET = "WIN1250"
# --- MySQL / Kapitace ---
MYSQL_CFG = {
"host": "192.168.1.76",
"port": 3307,
"user": "root",
"password": "Vlado9674+",
"database": "ordinace",
"charset": "utf8mb4",
"autocommit": True,
}
MYSQL_TABLE_HEADER = "zp_kapitace_header"
MYSQL_TABLE_PAC = "zp_kapitace_pojistenec"
# ============================================================
# HELPERY
# ============================================================
_rc_re = re.compile(r"\D+")
def normalize_rc(value: str) -> str:
"""Rodné číslo / číslo pojištěnce → jen číslice."""
if not value:
return ""
return _rc_re.sub("", str(value))
def parse_kapdetail_idpacs(kapdetail: str) -> List[int]:
"""
KAPDETAIL:
<něco>=SOUHRN;idpac;vek|castka;idpac;vek|castka;...
Vrací seznam idpac.
"""
if not kapdetail:
return []
s = kapdetail.strip()
if "=" in s:
s = s.split("=", 1)[1]
parts = [p.strip() for p in s.split(";") if p.strip()]
if not parts:
return []
# první položka je souhrn (není idpac)
if not parts[0].isdigit():
parts = parts[1:]
idpacs: List[int] = []
# idpac je vždy na sudém indexu (0,2,4,...)
for i in range(0, len(parts), 2):
if parts[i].isdigit():
idpacs.append(int(parts[i]))
return idpacs
def chunk_list(lst: List[int], size: int = 500) -> List[List[int]]:
return [lst[i:i + size] for i in range(0, len(lst), size)]
# ============================================================
# FIREBIRD DATA Z MEDICUSU
# ============================================================
def get_latest_fak_for_poj(db: MedicusDB, poj: str) -> Dict:
sql = """
SELECT
fak.id,
fak.cisfak,
fak.poj,
fak.kapdetail
FROM fak
WHERE fak.poj = ?
AND fak.kapdetail IS NOT NULL
AND fak.kapdetail <> ''
ORDER BY fak.cisfak DESC
ROWS 1
"""
rows = db.query_dict(sql, (poj,))
return rows[0] if rows else {}
def get_rodcis_for_idpacs(db: MedicusDB, idpacs: List[int]) -> Dict[int, str]:
"""
Vrátí mapu: idpac → rodcis
"""
result: Dict[int, str] = {}
if not idpacs:
return result
for batch in chunk_list(idpacs):
placeholders = ",".join("?" for _ in batch)
sql = f"""
SELECT
kar.idpac,
kar.rodcis
FROM kar
WHERE kar.idpac IN ({placeholders})
AND kar.rodcis IS NOT NULL
AND kar.rodcis <> ''
AND (kar.vyrazen IS NULL OR kar.vyrazen <> 'A')
"""
rows = db.query(sql, tuple(batch))
for idpac, rodcis in rows:
result[int(idpac)] = str(rodcis)
return result
# ============================================================
# MYSQL KAPITACE ZP
# ============================================================
def get_mysql_kapitace_rc(zp_kod: str) -> Set[str]:
sql = f"""
SELECT p.cislo_pojistence
FROM {MYSQL_TABLE_PAC} p
JOIN {MYSQL_TABLE_HEADER} h ON h.id = p.header_id
WHERE h.zp_kod = %s
AND h.snapshot_date = (
SELECT MAX(h2.snapshot_date)
FROM {MYSQL_TABLE_HEADER} h2
WHERE h2.zp_kod = %s
)
"""
with pymysql.connect(**MYSQL_CFG) as conn:
with conn.cursor() as cur:
cur.execute(sql, (zp_kod, zp_kod))
rows = cur.fetchall()
return {
normalize_rc(r[0])
for r in rows
if normalize_rc(r[0])
}
# ============================================================
# MAIN
# ============================================================
def main():
poj = input("Zadej kód pojišťovny (např. 207): ").strip()
# --- Medicus ---
mdb = MedicusDB(
host=FIREBIRD_HOST,
db_path=FIREBIRD_DB,
user=FIREBIRD_USER,
password=FIREBIRD_PASS,
charset=FIREBIRD_CHARSET,
)
fak = get_latest_fak_for_poj(mdb, poj)
if not fak:
print(f"❌ Nenalezena žádná kapitační faktura pro pojišťovnu {poj}")
mdb.close()
return
print("\nNalezena faktura:")
print(f" ID : {fak['id']}")
print(f" CISFAK : {fak['cisfak']}")
print(f" POJ : {fak['poj']}")
idpacs = parse_kapdetail_idpacs(fak["kapdetail"])
print(f"\nKAPDETAIL → idpac celkem: {len(idpacs)}")
idpac_to_rc = get_rodcis_for_idpacs(mdb, idpacs)
mdb.close()
medicus_rc = {
normalize_rc(rc)
for rc in idpac_to_rc.values()
if normalize_rc(rc)
}
print(f"Medicus (KAR.RODCIS): {len(medicus_rc)}")
# --- MySQL ---
mysql_rc = get_mysql_kapitace_rc(poj)
print(f"MySQL kapitace ZP: {len(mysql_rc)}")
# --- Porovnání ---
both = medicus_rc & mysql_rc
only_medicus = medicus_rc - mysql_rc
only_mysql = mysql_rc - medicus_rc
print("\n" + "=" * 80)
print(f"✅ V obou (OK): {len(both)}")
print(f"❌ Jen v Medicusu: {len(only_medicus)}")
print(f"❌ Jen v MySQL (kapitace): {len(only_mysql)}")
print("=" * 80)
if only_medicus:
print("\n❌ Jen v Medicusu (fakturováno, ale není v kapitaci ZP):")
for rc in sorted(only_medicus):
print(" ", rc)
if only_mysql:
print("\n❌ Jen v MySQL (v kapitaci ZP, ale není ve faktuře Medicusu):")
for rc in sorted(only_mysql):
print(" ", rc)
if __name__ == "__main__":
main()