195 lines
7.1 KiB
Python
195 lines
7.1 KiB
Python
"""
|
|
Reimport vsech XML souboru z xml_archive do MySQL — bez volani API.
|
|
|
|
Pouziti:
|
|
python reimport_z_xml.py # vsechna XML z 2026-04-11
|
|
python reimport_z_xml.py xml_archive/2026-04-11 # konkretni adresar
|
|
python reimport_z_xml.py xml_archive # vsechny podadresare rekurzivne
|
|
"""
|
|
|
|
import sys
|
|
import importlib.util
|
|
from pathlib import Path
|
|
from datetime import date
|
|
import fdb
|
|
import pymysql
|
|
import pymysql.cursors
|
|
|
|
# Windows konzole
|
|
if hasattr(sys.stdout, "reconfigure"):
|
|
sys.stdout.reconfigure(errors="replace")
|
|
|
|
# ── Konfigurace ───────────────────────────────────────────────────────────────
|
|
XML_ADRESAR = Path(__file__).parent / "xml_archive" / "2026-04-11"
|
|
|
|
FB = dict(
|
|
dsn = r"localhost:c:\medicus 3\data\medicus.fdb",
|
|
user = "SYSDBA",
|
|
password = "masterkey",
|
|
charset = "win1250",
|
|
)
|
|
|
|
DB = dict(
|
|
host = "192.168.1.76",
|
|
user = "root",
|
|
password = "Vlado9674+",
|
|
database = "medicus",
|
|
charset = "utf8mb4",
|
|
cursorclass = pymysql.cursors.DictCursor,
|
|
)
|
|
|
|
ICP = "09305001"
|
|
ODB = "001"
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
# Nacteni parsovaci logiky z 06UlozitDoMySQL.py
|
|
_spec = importlib.util.spec_from_file_location(
|
|
"m06", Path(__file__).parent / "06UlozitDoMySQL.py"
|
|
)
|
|
_m06 = importlib.util.module_from_spec(_spec)
|
|
_spec.loader.exec_module(_m06)
|
|
|
|
parsuj_xml = _m06.parsuj_xml
|
|
uloz = _m06.uloz
|
|
inicializuj_schema = _m06.inicializuj_schema
|
|
|
|
|
|
def nacti_pacienty_z_fb():
|
|
"""Vrati slovnik {(prijmeni_upper, datnar): idpac} ze vsech pacientu v Medicusu."""
|
|
conn = fdb.connect(**FB)
|
|
try:
|
|
cur = conn.cursor()
|
|
dnes = date.today().isoformat()
|
|
cur.execute("""
|
|
SELECT KAR.IDPAC, KAR.PRIJMENI, KAR.JMENO, KAR.DATNAR
|
|
FROM KAR
|
|
WHERE KAR.vyrazen = 'N'
|
|
AND EXISTS (
|
|
SELECT 1 FROM registr r
|
|
JOIN icp i ON r.idicp = i.idicp
|
|
WHERE r.idpac = kar.idpac
|
|
AND r.datum <= ?
|
|
AND (r.datum_zruseni IS NULL OR r.datum_zruseni >= ?)
|
|
AND r.priznak IN ('V','D','A')
|
|
AND i.icp = ?
|
|
AND i.odb = ?
|
|
)
|
|
""", (dnes, dnes, ICP, ODB))
|
|
result = {}
|
|
for row in cur.fetchall():
|
|
idpac, prijmeni, jmeno, datnar = row
|
|
klic = (prijmeni.strip().upper(), datnar)
|
|
result[klic] = {"idpac": idpac, "prijmeni": prijmeni.strip(), "jmeno": jmeno.strip(), "datnar": datnar}
|
|
print(f"Firebird: nacteno {len(result)} registrovanych pacientu")
|
|
return result
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
def upsert_pacient(cur, pac):
|
|
cur.execute("""
|
|
INSERT INTO pacient (idpac, prijmeni, jmena, datum_narozeni)
|
|
VALUES (%s, %s, %s, %s)
|
|
ON DUPLICATE KEY UPDATE
|
|
prijmeni = VALUES(prijmeni),
|
|
jmena = VALUES(jmena)
|
|
""", (pac["idpac"], pac["prijmeni"], pac["jmeno"], pac["datnar"]))
|
|
cur.execute("SELECT id FROM pacient WHERE idpac = %s", (pac["idpac"],))
|
|
return cur.fetchone()["id"]
|
|
|
|
|
|
def main():
|
|
# Adresar z argumentu nebo default
|
|
adresar = Path(sys.argv[1]) if len(sys.argv) > 1 else XML_ADRESAR
|
|
if not adresar.is_dir():
|
|
sys.exit(f"Adresar neexistuje: {adresar}")
|
|
|
|
# Najdi vsechna XML rekurzivne
|
|
xml_soubory = sorted(adresar.rglob("*.xml"))
|
|
if not xml_soubory:
|
|
sys.exit(f"Zadne XML soubory nalezeny v: {adresar}")
|
|
print(f"Nalezeno {len(xml_soubory)} XML souboru v: {adresar}")
|
|
|
|
# Nacti pacienty z Firebirdu
|
|
fb_pacienti = nacti_pacienty_z_fb()
|
|
|
|
# Pripoj se k MySQL a inicializuj schema
|
|
conn = pymysql.connect(**DB)
|
|
try:
|
|
inicializuj_schema(conn)
|
|
|
|
ok = chyba = preskoceno = 0
|
|
p_celkem = v_celkem = 0
|
|
|
|
for i, xml_path in enumerate(xml_soubory, 1):
|
|
rel = xml_path.relative_to(Path(__file__).parent)
|
|
try:
|
|
zprava, predpisy, vydeji, predepisujici, vydavajici = parsuj_xml(xml_path)
|
|
except Exception as e:
|
|
print(f"[{i:4}/{len(xml_soubory)}] {xml_path.name:<45} CHYBA parsovani: {e}")
|
|
chyba += 1
|
|
continue
|
|
|
|
# Zjisti prijmeni a datum narozeni z XML odpovedi
|
|
pac_prijmeni = (zprava.get("pacient_prijmeni") or "").upper()
|
|
pac_datnar = zprava.get("pacient_datum_narozeni") # string YYYY-MM-DD nebo None
|
|
|
|
# Prevod na date objekt pro porovnani s Firebirdem
|
|
if pac_datnar and isinstance(pac_datnar, str):
|
|
try:
|
|
from datetime import datetime
|
|
pac_datnar_d = datetime.strptime(pac_datnar[:10], "%Y-%m-%d").date()
|
|
except ValueError:
|
|
pac_datnar_d = None
|
|
elif hasattr(pac_datnar, "year"):
|
|
pac_datnar_d = pac_datnar
|
|
else:
|
|
pac_datnar_d = None
|
|
|
|
klic = (pac_prijmeni, pac_datnar_d)
|
|
fb_pac = fb_pacienti.get(klic)
|
|
|
|
if not fb_pac:
|
|
# Pacient neni registrovan — uloz bez idpac (bude ignorovan pri hromadnem behu)
|
|
# Zkus najit v MySQL podle jmena a data
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
"SELECT id FROM pacient WHERE prijmeni = %s AND datum_narozeni = %s",
|
|
(zprava.get("pacient_prijmeni"), pac_datnar)
|
|
)
|
|
row = cur.fetchone()
|
|
if row:
|
|
pacient_id = row["id"]
|
|
else:
|
|
preskoceno += 1
|
|
print(f"[{i:4}/{len(xml_soubory)}] {xml_path.name:<45} PRESKOCENO (neni v registru)")
|
|
continue
|
|
else:
|
|
with conn.cursor() as cur:
|
|
pacient_id = upsert_pacient(cur, fb_pac)
|
|
conn.commit()
|
|
|
|
try:
|
|
stats = uloz(conn, zprava, predpisy, vydeji, predepisujici, vydavajici,
|
|
pacient_id=pacient_id, xml_soubor=str(rel))
|
|
conn.commit()
|
|
p_celkem += stats["predpisy_novych"]
|
|
v_celkem += stats["vydeji_novych"]
|
|
print(f"[{i:4}/{len(xml_soubory)}] {xml_path.name:<45} OK "
|
|
f"{stats['predpisy_novych']:3}p {stats['vydeji_novych']:3}v")
|
|
ok += 1
|
|
except Exception as e:
|
|
conn.rollback()
|
|
print(f"[{i:4}/{len(xml_soubory)}] {xml_path.name:<45} CHYBA ukladani: {e}")
|
|
chyba += 1
|
|
|
|
print()
|
|
print(f"Hotovo: {ok} OK, {chyba} chyb, {preskoceno} preskoceno")
|
|
print(f"Celkem vlozeno: {p_celkem} predpisu, {v_celkem} vydejuu")
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|