""" Stazeni detailu receptu (NacistPredpis) pro poslednich N receptu z Medicusu. Spusteni: python 08StahnoutPredpisy.py # 10 receptu od 2025-01-01 python 08StahnoutPredpisy.py --limit 50 # 50 receptu python 08StahnoutPredpisy.py --od 2026-01-01 Pauza mezi volanimi: 5 sekund. XML odpovedi se ukladaji do xml_archive/YYYY-MM-DD/ERP_kod.xml """ import sys import time import uuid from datetime import datetime, timezone, date from pathlib import Path import fdb from requests import Session from requests_pkcs12 import Pkcs12Adapter if hasattr(sys.stdout, "reconfigure"): sys.stdout.reconfigure(errors="replace") # ── Konfigurace eRecept ────────────────────────────────────────────────────── PFX_FILE = r"C:\Users\vlado\PycharmProjects\Recepty\AMBSUKL214235369G_31DEC2024.pfx" PFX_PASS = "Vlado7309208104++" API_USER = "e08c89c6-2b1a-4eba-8ed9-4e3e63618379" API_PASS = "Buzalka@Vladimir2025" UZIVATEL = "E08C89C6-2B1A-4EBA-8ED9-4E3E63618379" PRACOVISTE = "00214235367" ENDPOINT = "https://lekar-soap.erecept.sukl.cz/cuer/Lekar" NAMESPACE = "http://www.sukl.cz/erp/201704" PAUZA = 5 # sekund # ── Konfigurace Firebird ───────────────────────────────────────────────────── FB_DSN = r'localhost:c:\medicus 3\data\medicus.fdb' FB_USER = 'SYSDBA' FB_PASS = 'masterkey' FB_CHARSET = 'win1250' # ── Adresare ───────────────────────────────────────────────────────────────── XML_DIR = Path(__file__).parent / "xml_archive" def nacti_erp_kody(fb_conn, datum_od, limit, prijmeni=None): """Nacte unikatni ID_Dokladu (erp kody) z Firebirdu — recept_epodani.erp.""" sql = """ SELECT FIRST ? r.datum, r.lek, r.dop, r.idpac, TRIM(kar.prijmeni) AS prijmeni, TRIM(kar.jmeno) AS jmeno, ep.erp FROM recept r JOIN recept_epodani ep ON r.id_epodani = ep.id JOIN kar ON r.idpac = kar.idpac WHERE r.datum >= ? AND ep.erp IS NOT NULL """ params = [limit, datum_od] if prijmeni: placeholders = ",".join(["?"] * len(prijmeni)) sql += f" AND UPPER(TRIM(kar.prijmeni)) IN ({placeholders})" params.extend(p.upper() for p in prijmeni) sql += " ORDER BY r.datum DESC" cur = fb_conn.cursor() cur.execute(sql, params) rows = cur.fetchall() cur.close() # deduplikace dle erp kodu — zachovat prvni vyskyt (nejnovejsi datum) seen = set() unique = [] for row in rows: erp = row[6] if erp not in seen: seen.add(erp) unique.append(row) return unique def volej_nacist_predpis(sess, erp_kod): """Zavola NacistPredpis a vrati (status_code, response_text).""" id_zpravy = str(uuid.uuid4()) odeslano = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S+00:00") soap_body = ( '' '' '' f'' f'' f'' f'{UZIVATEL}' f'{PRACOVISTE}' f'' f'' f'{erp_kod}' f'' f'' f'' f'{id_zpravy}' f'202501A' f'{odeslano}' f'MEDICUS_____' f'' f'' '' '' ) headers = { "Content-Type": 'text/xml; charset="UTF-8"', "SOAPAction": '"NacistPredpis"', "User-Agent": "Medicus", } resp = sess.post(ENDPOINT, data=soap_body.encode("utf-8"), headers=headers, timeout=15) return resp.status_code, resp.text ## ── Parametry (uprav zde) ──────────────────────────────────────────────────── LIMIT = 100 # max pocet receptu ke stazeni DATUM_OD = "2025-01-01" # recepty od tohoto data PRIJMENI = ["Buzalka"] # filtr prijmeni (list), nebo None = vsichni ## ───────────────────────────────────────────────────────────────────────────── def main(): datum_od = DATUM_OD dnes = date.today().isoformat() out_dir = XML_DIR / dnes out_dir.mkdir(parents=True, exist_ok=True) # Firebird print(f"Pripojuji Firebird...") fb = fdb.connect(dsn=FB_DSN, user=FB_USER, password=FB_PASS, charset=FB_CHARSET) rows = nacti_erp_kody(fb, datum_od, LIMIT, PRIJMENI) fb.close() print(f"Nacteno {len(rows)} receptu z Medicusu (od {datum_od})\n") if not rows: print("Zadne recepty k stazeni.") return # SOAP session sess = Session() sess.mount("https://", Pkcs12Adapter(pkcs12_filename=PFX_FILE, pkcs12_password=PFX_PASS)) sess.auth = (API_USER, API_PASS) ok = 0 chyby = 0 for i, row in enumerate(rows, 1): datum_rec, lek, dop, idpac, prijmeni, jmeno, erp_kod = row lek_str = f"{lek} {dop}".strip() if dop else str(lek).strip() label = f"{prijmeni} {jmeno}".strip() print(f"[{i:4d}/{len(rows)}] {label:30s} {erp_kod} ", end="", flush=True) try: status, text = volej_nacist_predpis(sess, erp_kod) if status == 200 and "" not in text: xml_file = out_dir / f"{erp_kod}.xml" xml_file.write_text(text, encoding="utf-8") size_kb = len(text.encode("utf-8")) / 1024 print(f"OK {size_kb:6.1f} KB {lek_str[:40]}") ok += 1 else: # SOAP Fault nebo HTTP chyba chyba_short = text[:120].replace("\n", " ") print(f"CHYBA HTTP {status} {chyba_short}") # ulozit i chybovou odpoved xml_file = out_dir / f"{erp_kod}_CHYBA.xml" xml_file.write_text(text, encoding="utf-8") chyby += 1 except Exception as e: print(f"EXCEPTION {e}") chyby += 1 if i < len(rows): time.sleep(PAUZA) print(f"\nHotovo: {ok} OK, {chyby} chyb") print(f"XML: {out_dir}") if __name__ == "__main__": main()