diff --git a/02 testík.py b/02 testík.py index 23fe36e..67c1303 100644 --- a/02 testík.py +++ b/02 testík.py @@ -32,7 +32,7 @@ K_DATU = date.today().isoformat() # YYYY-MM-DD ODBORNOSTI = ["001"] # VPL (adult GP) # MySQL -if socket.gethostname().strip() == "NTBVBHP470G10": +if socket.gethostname().strip() in ("NTBVBHP470G10","Z230"): MYSQL_CFG = dict( host="192.168.1.76", port=3307, @@ -175,13 +175,13 @@ ON DUPLICATE KEY UPDATE for p in payloads: pprint(p) - conn = pymysql.connect(**MYSQL_CFG) + connsql = get_mysql_connection() try: - with conn.cursor() as cur: + with connsql.cursor() as cur: cur.executemany(sql, payloads) - conn.commit() + connsql.commit() finally: - conn.close() + connsql.close() print(f"\nUpserted rows: {len(payloads)}") return len(payloads) @@ -216,7 +216,7 @@ def main(): con = get_medicus_connection() cur = con.cursor() - cur.execute("select rodcis, prijmeni, jmeno from kar where rodcis starting with '9'") + cur.execute("select rodcis, prijmeni, jmeno from kar where rodcis starting with '8'") # cur.execute("select first 2 rodcis, prijmeni, jmeno from kar where rodcis starting with '0'") # Vytvor seznam rodnych cisel, která už máme diff --git a/02.2 Testík.py b/02.2 Testík.py new file mode 100644 index 0000000..9f711c4 --- /dev/null +++ b/02.2 Testík.py @@ -0,0 +1,308 @@ +#kód bude vkládat i řádky pro pacienty bez registrovaného lékař v oboru 001#!/usr/bin/env python3 -*- coding: utf-8 -*- """ Call VZP RegistracePojistencePZSB2B for one patient (001 = VPL), parse the response, upsert rows into medevio.vzp_registrace, and print what is being saved. """ # pip install requests_pkcs12 pymysql from requests_pkcs12 import Pkcs12Adapter import requests import xml.etree.ElementTree as ET from datetime import date import pymysql from pymysql.cursors import DictCursor from pprint import pprint from functions import get_medicus_connection from functions import get_mysql_connection import time, random,socket # ------------------- CONFIG ------------------- ENDPOINT = "https://prod.b2b.vzp.cz/B2BProxy/HttpProxy/RegistracePojistencePZSB2B" # case-sensitive PFX_PATH = r"mbcert.pfx" # <-- your .pfx path PFX_PASS = "Vlado7309208104++" # <-- your export password VERIFY = True # or path to CA PEM, e.g. r"C:\certs\vzp_ca.pem" Patient + query RC = "7309208104" # rodné číslo without slash RC = "280616/091" # rodné +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Call VZP RegistracePojistencePZSB2B for one patient (001 = VPL), +parse the response, upsert rows into medevio.vzp_registrace, +and print what is being saved. +""" + +# pip install requests_pkcs12 pymysql + +from requests_pkcs12 import Pkcs12Adapter +import requests +import xml.etree.ElementTree as ET +from datetime import date +import pymysql +from pymysql.cursors import DictCursor +from pprint import pprint +from functions import get_medicus_connection +from functions import get_mysql_connection +import time, random,socket + +# ------------------- CONFIG ------------------- +ENDPOINT = "https://prod.b2b.vzp.cz/B2BProxy/HttpProxy/RegistracePojistencePZSB2B" # case-sensitive +PFX_PATH = r"mbcert.pfx" # <-- your .pfx path +PFX_PASS = "Vlado7309208104++" # <-- your export password +VERIFY = True # or path to CA PEM, e.g. r"C:\certs\vzp_ca.pem" + +# Patient + query +RC = "7309208104" # rodné číslo without slash +# RC = "280616/091" # rodné číslo without slash +K_DATU = date.today().isoformat() # YYYY-MM-DD +ODBORNOSTI = ["001"] # VPL (adult GP) + +# MySQL +if socket.gethostname().strip() in ("NTBVBHP470G10","Z230"): + MYSQL_CFG = dict( + host="192.168.1.76", + port=3307, + user="root", + password="Vlado9674+", + database="medevio", + cursorclass=DictCursor, + autocommit=True, # or False if you prefer manual commit + ) +elif socket.gethostname().strip() == "SESTRA": + MYSQL_CFG = dict( + host="127.0.0.1", + port=3307, + user="root", + password="Vlado9674+", + database="medevio", + cursorclass=DictCursor, + autocommit=True, # or False if you prefer manual commit + ) + + +# Namespaces (from your response/WSDL) +NS = { + "soap": "http://schemas.xmlsoap.org/soap/envelope/", + "rp": "http://xmlns.gemsystem.cz/B2B/RegistracePojistencePZSB2B/1", +} + + +# ------------------- HELPERS ------------------- +def normalize_rc(rc: str) -> str: + return rc.replace("/", "").strip() + +def build_envelope(rc: str, k_datu: str, odb_list: list[str]) -> str: + odb_xml = "".join([f"{kod}" for kod in odb_list]) + inner = f""" + + {rc} + {k_datu} + + {odb_xml} + +""".strip() + + return f""" + + + {inner} + +""" + +def parse_registrace(xml_text: str): + """ + Return (rows, stav_vyrizeni) where rows is a list of dicts + for each item in the response. + """ + root = ET.fromstring(xml_text) + items = root.findall(".//rp:seznamOdbornosti/rp:odbornost", NS) + out = [] + for it in items: + def g(tag, ctx=it): + el = ctx.find(f"rp:{tag}", NS) + return el.text.strip() if el is not None and el.text else None + + poj = it.find("rp:zdravotniPojistovna", NS) + poj_kod = poj.find("rp:kod", NS).text.strip() if (poj is not None and poj.find("rp:kod", NS) is not None) else None + poj_zkr = poj.find("rp:zkratka", NS).text.strip() if (poj is not None and poj.find("rp:zkratka", NS) is not None) else None + + spec = it.find("rp:odbornost", NS) + odb_kod = spec.find("rp:kod", NS).text.strip() if (spec is not None and spec.find("rp:kod", NS) is not None) else None + odb_naz = spec.find("rp:nazev", NS).text.strip() if (spec is not None and spec.find("rp:nazev", NS) is not None) else None + + out.append(dict( + icz=g("ICZ"), + icp=g("ICP"), + nazev_icp=g("nazevICP"), + nazev_szz=g("nazevSZZ"), + poj_kod=poj_kod, + poj_zkratka=poj_zkr, + odbornost_kod=odb_kod, + odbornost_nazev=odb_naz, + datum_registrace=g("datumRegistrace"), + datum_zahajeni=g("datumZahajeni"), + datum_ukonceni=g("datumUkonceni"), + )) + + st = root.find(".//rp:stavVyrizeniPozadavku", NS) + stav_vyrizeni = st.text.strip() if (st is not None and st.text) else None + return out, stav_vyrizeni + +def upsert_rows( + rc: str, + query_date: str, + rows: list[dict], + stav_vyrizeni: str, + xml_text: str, + requested_odb_list: list[str] | None = None, +) -> int: + """ + Insert/update medevio.vzp_registrace. + If no items are returned, insert placeholder row(s) + for each requested specialty (e.g., "001") so the negative result is visible. + """ + sql = """ +INSERT INTO vzp_registrace + (rc, query_date, odbornost_kod, odbornost_nazev, + icz, icp, nazev_icp, nazev_szz, + poj_kod, poj_zkratka, + datum_registrace, datum_zahajeni, datum_ukonceni, + stav_vyrizeni, response_xml) +VALUES + (%(rc)s, %(query_date)s, %(odbornost_kod)s, %(odbornost_nazev)s, + %(icz)s, %(icp)s, %(nazev_icp)s, %(nazev_szz)s, + %(poj_kod)s, %(poj_zkratka)s, + %(datum_registrace)s, %(datum_zahajeni)s, %(datum_ukonceni)s, + %(stav_vyrizeni)s, %(response_xml)s) +ON DUPLICATE KEY UPDATE + odbornost_nazev = VALUES(odbornost_nazev), + nazev_icp = VALUES(nazev_icp), + nazev_szz = VALUES(nazev_szz), + poj_kod = VALUES(poj_kod), + poj_zkratka = VALUES(poj_zkratka), + datum_registrace= VALUES(datum_registrace), + datum_zahajeni = VALUES(datum_zahajeni), + datum_ukonceni = VALUES(datum_ukonceni), + stav_vyrizeni = VALUES(stav_vyrizeni), + response_xml = VALUES(response_xml), + updated_at = CURRENT_TIMESTAMP +""" + rc_norm = normalize_rc(rc) + qd = query_date or date.today().isoformat() + + payloads: list[dict] = [] + + if rows: + # Positive path: save what came from the API + for r in rows: + payloads.append({ + "rc": rc_norm, + "query_date": qd, + **r, + "stav_vyrizeni": stav_vyrizeni, + "response_xml": xml_text, + }) + else: + # Negative path: no registration items -> create placeholders + if not requested_odb_list: + requested_odb_list = ["001"] + for kod in requested_odb_list: + payloads.append({ + "rc": rc_norm, + "query_date": qd, + "odbornost_kod": kod, + "odbornost_nazev": None, + "icz": None, + "icp": None, + "nazev_icp": None, + "nazev_szz": None, + "poj_kod": None, + "poj_zkratka": None, + "datum_registrace": None, + "datum_zahajeni": None, + "datum_ukonceni": None, + # Keep what VZP said (e.g., 'X'), and raw XML for audit + "stav_vyrizeni": stav_vyrizeni, + "response_xml": xml_text, + }) + + # Print what we're going to save + print("\n=== Will save the following payload(s) to medevio.vzp_registrace ===") + for p in payloads: + pprint(p) + + if not payloads: + print("No payloads prepared (this should not happen).") + return 0 + + connsql = get_mysql_connection() + try: + with connsql.cursor() as cur: + cur.executemany(sql, payloads) + connsql.commit() + finally: + connsql.close() + + print(f"\nUpserted rows: {len(payloads)}") + return len(payloads) + + +def prepare_processed_rcs(): + consql=get_mysql_connection() + cursql=consql.cursor() + + sql=""" + WITH ranked AS ( + SELECT + vreg.*, + ROW_NUMBER() OVER ( + PARTITION BY rc + ORDER BY query_date DESC + ) AS rn + FROM vzp_registrace AS vreg + ) + SELECT rc + FROM ranked + WHERE rn = 1 + """ + + cursql.execute(sql) + rows=cursql.fetchall() + print(f"Pocet jiz zpracovanych rodnych cisel v MYSQL MEDEVIO je {len(rows)}") + rc_set_vzp = {row["rc"] for row in rows} + return (rc_set_vzp) + +# ------------------- MAIN FLOW ------------------- +def main(): + + con = get_medicus_connection() + cur = con.cursor() + cur.execute("select rodcis, prijmeni, jmeno from kar where rodcis starting with '7'") + # cur.execute("select first 2 rodcis, prijmeni, jmeno from kar where rodcis starting with '0'") + + # Vytvor seznam rodnych cisel, která už máme + rc_set_vzp = prepare_processed_rcs() + + rows = cur.fetchall() + print(f"Pocet vybranych radku z tabulky KAR je: {len(rows)}") + + for row in rows: + if row[0] in rc_set_vzp: + continue + else: + print(row[0], row[1], row[2]) + K_DATU = date.today().isoformat() # YYYY-MM-DD + ODBORNOSTI = ["001"] + RC=row[0] + + # Build SOAP envelope + envelope = build_envelope(RC, K_DATU, ODBORNOSTI) + + # mTLS session + session = requests.Session() + session.mount("https://", Pkcs12Adapter(pkcs12_filename=PFX_PATH, pkcs12_password=PFX_PASS)) + + headers = { + "Content-Type": "text/xml; charset=utf-8", + "SOAPAction": "process", # Oracle composite usually expects this + } + print(envelope) + # Call service + resp = session.post(ENDPOINT, data=envelope.encode("utf-8"), + headers=headers, timeout=30, verify=VERIFY) + print("HTTP:", resp.status_code) + + # (Optional) Uncomment to see raw XML + print(resp.text) + + # Parse and save + rows, stav = parse_registrace(resp.text) + print(rows,stav) + upsert_rows(RC, K_DATU, rows, stav, resp.text, requested_odb_list=ODBORNOSTI) + + time.sleep(random.uniform(1, 5)) + + + + + + + + +if __name__ == "__main__": + main() diff --git a/functions.py b/functions.py index 27eb0ad..6d72756 100644 --- a/functions.py +++ b/functions.py @@ -22,7 +22,7 @@ def get_medicus_connection(): fdb.Connection object on success None on failure """ - if socket.gethostname().strip()=="NTBVBHP470G10": + if socket.gethostname().strip() in ("NTBVBHP470G10","Z230"): MEDICUS_CFG = dict( dsn=r"192.168.1.4:z:\medicus 3\data\medicus.fdb", user="SYSDBA", @@ -50,7 +50,7 @@ def get_mysql_connection(): """ Return a PyMySQL connection or None if the connection fails. """ - if socket.gethostname().strip() == "NTBVBHP470G10": + if socket.gethostname().strip() in ("NTBVBHP470G10","Z230"): MYSQL_CFG = dict( host="192.168.1.76", port=3307,