From 65ef01589cf4e008a195f780c3c751678734b9fd Mon Sep 17 00:00:00 2001 From: Vladimir Buzalka Date: Sat, 27 Sep 2025 15:03:31 +0200 Subject: [PATCH 01/23] notebookVB --- .idea/Insurance.iml | 10 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .idea/workspace.xml | 123 +++++++++++ 01 testik.py | 131 +++++++++++ 02 testík.py | 203 ++++++++++++++++++ File3.py | 5 + functions.py | 138 ++++++++++++ 9 files changed, 630 insertions(+) create mode 100644 .idea/Insurance.iml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 01 testik.py create mode 100644 02 testík.py create mode 100644 File3.py create mode 100644 functions.py diff --git a/.idea/Insurance.iml b/.idea/Insurance.iml new file mode 100644 index 0000000..235ece6 --- /dev/null +++ b/.idea/Insurance.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..6239183 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..6213dc3 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1758916129960 + + + + \ No newline at end of file diff --git a/01 testik.py b/01 testik.py new file mode 100644 index 0000000..d94b674 --- /dev/null +++ b/01 testik.py @@ -0,0 +1,131 @@ +# 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 + +# ========== CONFIG ========== +PFX_PATH = r"mbcert.pfx" +PFX_PASS = "Vlado7309208104++" +VERIFY = True + +EP_STAV = "https://prod.b2b.vzp.cz/B2BProxy/HttpProxy/stavPojisteniB2B" +SOAP_NS = "http://schemas.xmlsoap.org/soap/envelope/" +NS_STAV = "http://xmlns.gemsystem.cz/stavPojisteniB2B" + +# RC provided by you (can contain slash; we normalize before sending/saving) +RC = "280616/091" +K_DATU = date.today().isoformat() + +# MySQL (table already created as per previous DDL) +MYSQL_CFG = dict( + host="192.168.1.76", + port=3307, + user="root", + password="Vlado9674+", + database="medevio", + cursorclass=DictCursor, + autocommit=False, +) + +# ========== HELPERS ========== +def to_int_or_none(val): + if val is None: + return None + s = str(val).strip() + return int(s) if s.isdigit() else None + +def normalize_rc(rc: str) -> str: + return rc.replace("/", "").strip() + +def post_soap(endpoint: str, body_xml: str) -> str: + env = f''' + + {body_xml} +''' + s = requests.Session() + s.mount("https://", Pkcs12Adapter(pkcs12_filename=PFX_PATH, pkcs12_password=PFX_PASS)) + r = s.post( + endpoint, + data=env.encode("utf-8"), + headers={"Content-Type": "text/xml; charset=utf-8", "SOAPAction": "process"}, + timeout=30, + verify=VERIFY, + ) + print("HTTP:", r.status_code) + return r.text + +def parse_stav(xml_text: str): + NS = {"soap": SOAP_NS, "s": NS_STAV} + root = ET.fromstring(xml_text) + out = { + "stav": None, + "kodPojistovny": None, + "nazevPojistovny": None, + "pojisteniKod": None, + "stavVyrizeniPozadavku": None, + } + node = root.find(".//s:stavPojisteni", NS) + if node is not None: + for tag in ("stav", "kodPojistovny", "nazevPojistovny", "pojisteniKod"): + el = node.find(f"s:{tag}", NS) + out[tag] = el.text.strip() if el is not None and el.text else None + st = root.find(".//s:stavVyrizeniPozadavku", NS) + out["stavVyrizeniPozadavku"] = st.text.strip() if st is not None and st.text else None + return out + +def save_stav_pojisteni(rc: str, k_datu: str, parsed: dict, response_xml: str) -> int: + """ + Insert one log row into medevio.vzp_stav_pojisteni and print what is being saved. + Assumes the table already exists (no DDL/verification here). + """ + payload = { + "rc": normalize_rc(rc), + "k_datu": k_datu, + "stav": to_int_or_none(parsed.get("stav")), # handles 'X' -> None + "kod_pojistovny": parsed.get("kodPojistovny"), + "nazev_pojistovny": parsed.get("nazevPojistovny"), + "pojisteni_kod": parsed.get("pojisteniKod"), + "stav_vyrizeni": to_int_or_none(parsed.get("stavVyrizeniPozadavku")), + "response_xml": response_xml, + } + + print("\n=== vzp_stav_pojisteni: will insert ===") + pprint(payload) + + sql = """ + INSERT INTO vzp_stav_pojisteni + (rc, k_datu, stav, kod_pojistovny, nazev_pojistovny, pojisteni_kod, stav_vyrizeni, response_xml) + VALUES + (%(rc)s, %(k_datu)s, %(stav)s, %(kod_pojistovny)s, %(nazev_pojistovny)s, %(pojisteni_kod)s, %(stav_vyrizeni)s, %(response_xml)s) + """ + + conn = pymysql.connect(**MYSQL_CFG) + try: + with conn.cursor() as cur: + cur.execute(sql, payload) + conn.commit() + finally: + conn.close() + + print("Inserted 1 row into vzp_stav_pojisteni.") + return 1 + +# ========== MAIN ========== +if __name__ == "__main__": + rc_norm = normalize_rc(RC) + body = f""" + + {rc_norm} + {K_DATU} +""".strip() + + xml = post_soap(EP_STAV, body) + parsed = parse_stav(xml) + print(parsed) # keep your quick print + + # Save to MySQL and print exactly what is saved + save_stav_pojisteni(RC, K_DATU, parsed, xml) diff --git a/02 testík.py b/02 testík.py new file mode 100644 index 0000000..d3e4d74 --- /dev/null +++ b/02 testík.py @@ -0,0 +1,203 @@ +#!/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 + +# ------------------- 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 +MYSQL_CFG = dict( + host="192.168.1.76", + port=3307, + user="root", + password="Vlado9674+", + database="medevio", + cursorclass=DictCursor, + autocommit=False, +) + +# 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) -> int: + """ + Insert or update rows into medevio.vzp_registrace and print each payload. + Assumes the table already exists (as per your DDL). + """ + if not rows: + print("No rows found; nothing to save.") + return 0 + + 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 = [] + for r in rows: + payload = { + "rc": rc_norm, + "query_date": qd, + **r, + "stav_vyrizeni": stav_vyrizeni, + "response_xml": xml_text, + } + payloads.append(payload) + + # 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) + + conn = pymysql.connect(**MYSQL_CFG) + try: + with conn.cursor() as cur: + cur.executemany(sql, payloads) + conn.commit() + finally: + conn.close() + + print(f"\nUpserted rows: {len(payloads)}") + return len(payloads) + + +# ------------------- MAIN FLOW ------------------- +def main(): + # 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 + } + + # 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) + upsert_rows(RC, K_DATU, rows, stav, resp.text) + + +if __name__ == "__main__": + main() diff --git a/File3.py b/File3.py new file mode 100644 index 0000000..5a73eb7 --- /dev/null +++ b/File3.py @@ -0,0 +1,5 @@ +from functions import check_insurance +import time +import fdb + + diff --git a/functions.py b/functions.py new file mode 100644 index 0000000..5d129aa --- /dev/null +++ b/functions.py @@ -0,0 +1,138 @@ +# functions.py +# pip install requests_pkcs12 pymysql +from __future__ import annotations + +import os +from datetime import date +from pprint import pprint +import xml.etree.ElementTree as ET + +import requests +from requests_pkcs12 import Pkcs12Adapter +import pymysql +from pymysql.cursors import DictCursor + +# ======== CONFIG (env overrides allowed) ======== +PFX_PATH = os.getenv("VZP_PFX_PATH", r"mbcert.pfx") +PFX_PASS = os.getenv("VZP_PFX_PASS", "Vlado7309208104++") +VERIFY = os.getenv("VZP_CA_VERIFY", "true").lower() != "false" # set to path or "false" to disable + +EP_STAV = "https://prod.b2b.vzp.cz/B2BProxy/HttpProxy/stavPojisteniB2B" +SOAP_NS = "http://schemas.xmlsoap.org/soap/envelope/" +NS_STAV = "http://xmlns.gemsystem.cz/stavPojisteniB2B" + +MYSQL_CFG = { + "host": os.getenv("MYSQL_HOST", "192.168.1.76"), + "port": int(os.getenv("MYSQL_PORT", "3307")), + "user": os.getenv("MYSQL_USER", "root"), + "password": os.getenv("MYSQL_PASSWORD", "Vlado9674+"), + "database": os.getenv("MYSQL_DB", "medevio"), + "cursorclass": DictCursor, + "autocommit": False, +} + +# ======== HELPERS ======== +def normalize_rc(rc: str) -> str: + """Return rodné číslo without slash/spaces.""" + return rc.replace("/", "").replace(" ", "").strip() + +def to_int_or_none(val): + if val is None: + return None + s = str(val).strip() + return int(s) if s.isdigit() else None + +def _session(): + s = requests.Session() + s.mount("https://", Pkcs12Adapter(pkcs12_filename=PFX_PATH, pkcs12_password=PFX_PASS)) + return s + +def post_soap(endpoint: str, inner_xml: str) -> str: + """Wrap body in SOAP 1.1 envelope and POST with mTLS.""" + envelope = f''' + + {inner_xml} +''' + r = _session().post( + endpoint, + data=envelope.encode("utf-8"), + headers={"Content-Type": "text/xml; charset=utf-8", "SOAPAction": "process"}, + timeout=30, + verify=VERIFY, + ) + # You may log r.status_code if needed. + return r.text + +def parse_stav(xml_text: str) -> dict: + """Parse StavPojisteniB2B response → dict with keys: + 'stav','kodPojistovny','nazevPojistovny','pojisteniKod','stavVyrizeniPozadavku'.""" + NS = {"soap": SOAP_NS, "s": NS_STAV} + root = ET.fromstring(xml_text) + out = {"stav": None, "kodPojistovny": None, "nazevPojistovny": None, + "pojisteniKod": None, "stavVyrizeniPozadavku": None} + node = root.find(".//s:stavPojisteni", NS) + if node is not None: + for tag in ("stav", "kodPojistovny", "nazevPojistovny", "pojisteniKod"): + el = node.find(f"s:{tag}", NS) + out[tag] = el.text.strip() if (el is not None and el.text) else None + st = root.find(".//s:stavVyrizeniPozadavku", NS) + out["stavVyrizeniPozadavku"] = st.text.strip() if (st is not None and st.text) else None + return out + +def save_stav_pojisteni(rc: str, k_datu: str, parsed: dict, response_xml: str) -> None: + """Insert one log row into medevio.vzp_stav_pojisteni and print what is being saved.""" + payload = { + "rc": normalize_rc(rc), + "k_datu": k_datu, + "stav": to_int_or_none(parsed.get("stav")), # 'X' -> None + "kod_pojistovny": parsed.get("kodPojistovny"), + "nazev_pojistovny": parsed.get("nazevPojistovny"), + "pojisteni_kod": parsed.get("pojisteniKod"), + "stav_vyrizeni": to_int_or_none(parsed.get("stavVyrizeniPozadavku")), + "response_xml": response_xml, + } + + print("\n=== vzp_stav_pojisteni: will insert ===") + pprint(payload) + + sql = """ + INSERT INTO vzp_stav_pojisteni + (rc, k_datu, stav, kod_pojistovny, nazev_pojistovny, pojisteni_kod, stav_vyrizeni, response_xml) + VALUES + (%(rc)s, %(k_datu)s, %(stav)s, %(kod_pojistovny)s, %(nazev_pojistovny)s, %(pojisteni_kod)s, %(stav_vyrizeni)s, %(response_xml)s) + """ + conn = pymysql.connect(**MYSQL_CFG) + try: + with conn.cursor() as cur: + cur.execute(sql, payload) + conn.commit() + finally: + conn.close() + print("Inserted 1 row into vzp_stav_pojisteni.") + +# ======== PUBLIC API ======== +def check_insurance(rc: str, mode: str | None = None, k_datu: str | None = None): + """ + Call VZP 'StavPojisteniB2B' for given RC and date. + Returns (is_active, info_dict). + - is_active: True iff info_dict['stav'] == '1' + - info_dict: {'stav','kodPojistovny','nazevPojistovny','pojisteniKod','stavVyrizeniPozadavku'} + If mode == 'nodb' (case-insensitive), DOES NOT write to DB. Otherwise logs into medevio.vzp_stav_pojisteni. + """ + rc_norm = normalize_rc(rc) + kd = k_datu or date.today().isoformat() + + body = f""" + + {rc_norm} + {kd} +""".strip() + + xml = post_soap(EP_STAV, body) + info = parse_stav(xml) + is_active = (info.get("stav") == "1") + + if not (mode and mode.lower() == "nodb"): + save_stav_pojisteni(rc_norm, kd, info, xml) + + return is_active, info From 1b4ea727048e24be987f3ca365d10411a73723ad Mon Sep 17 00:00:00 2001 From: Vladimir Buzalka Date: Sat, 27 Sep 2025 15:03:47 +0200 Subject: [PATCH 02/23] notebookVB --- MBcert.pfx | Bin 0 -> 7026 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 MBcert.pfx diff --git a/MBcert.pfx b/MBcert.pfx new file mode 100644 index 0000000000000000000000000000000000000000..6fbd2741c20d386c7fd14a989157822f1b4d63bb GIT binary patch literal 7026 zcmZX2Wl$VIv+d#*+=IKjy9W;z+}+(B7Wc5h-QC^Y3GNbtOK@1&Ac4zw>%DvH)%($> zyH8J_sjiypAHxnLa)O3}VFwa1!Xq(8%0)s@p%9=7fJ8*FKqCAP8k-#m5BvX=;2vOs zaJTG0xXTYagGc#4U7wJlpbLPoZ|p$WXLe$E5h@-(GUfl+(FELyCK|>?V!vbN~ z!QByEdw(eY?VpQ{2+wK7QIVF$uP=uUM(4~L90Fd$xnE*4I0N!mGi=P#0!|n*jqM#r z>eHv%-@SV?-Rf&9{#lm1OG&fl@>ftnB5e@UEdPf2m(3_vLsEEX-wV|c=(iP$Z=X$1 zV!fFp`hz;mST!~V`HlMc#YyQuoBqL%#DEZkX$u5XZ;P?73BR+BzVBL?xvB8VOW|oP zA5Iyab1Bh=+hN32+tDOwjN3elJLEB?0M9R!zUY-dGVlJdT&zWD9Z22dH@{Wq+e?+Qu$e*DiHU9{Zkfko|ZCQ_^x4D`#*|%_Ivt`s-V5 zNT{j0Uzks8z?a5Xq~>3M);r16inBFdbYFGKoVNSa(W#eh!|M4>fn!W3;Zr+uof0q{ z?J*p1cPfH8-FIg_snOmeBaaX18-W_nJSRASxthy3mPxa!$_PBdy(U_8tT0ISb+tl$u|!zmPv%)!J{gAGNWWMlf`I6}dvIjxJO zj26y)p&Zb=ki9iR>py#w&B%FkZ#sWLKC3cPzn7 znN}8R{Nl2wVJ!h-(Nh>{BiC4F$qN>i&V6x24*3F!OC(ouxxP>Z`0Z-}Kc1}H2DE~O z5{~V969RTmk&*Rq$8Xy%Hr(M#LfSC(ZT46)s2cu1P=GhF23Dome&pziR)zId0veZE z(W$fYP^vrFKlHnA5Wex9z~Nk;b?MwhV}VyLq@GgcT76?$jq9LF-p(|;q8)nHJj8+B z9wbckQ;o91{(e;S$H%zcYSFBbF*m6d4r=;fOcZrDsWs_ zNe&hS|7UAPT=Zy!?>TM4<5pOUeA_Y9SKtr>57QZ&_h6JM#PnQhNkzih4tHTR@cvh6 zB#92bm#0l~J3m$zfC2r=&tg_XW%dl{@XweHRrZb$Gt5fWY59~6&%acgkKIYoI@Dtc zz)Wp(j@swJS#bmLE|y2sEf_n`Vad%o$T1qJ4q#bxjHBsLFg&R=^J&_b@G~!V4 zIU4w@%G{lPdAQ(r@Fycj+wM)_i6Xrz!fU_9E`{`Wxb3l!n|~_WDR&kn5@rZ5tU=yt z)6twGVU(MPLd5*Kf6>e!d{K17-p3i>`e@Cm!NyP|Jz-pT6}Jud#pZCa2@PWu;=+*# zGN9pESSUAHq%do3AeJ)ViDKVlNNz0ECphcG7>BH%ZVs^k8&b@3(LvoE#c*D%?=I|~ zq+(&M`zSkRhC0+gcb7`jglzH{U~?za;D6kql97oa4szRGI#M*eUCZBbgs!n;|IfNa z!sUR6g@pnD0PHgVOX6_wlkx(-0lWdW04IPuKm#BRAO~;)*a2)G#_@swi8%p0A1ucQ z3Vxu#2l4=T*nQ!VnBbvcp@4jtP#g}Vb^zrM5p#eW!1+VS8DItQ_-K;(khKArexNzP z5@7McsDE4{@!|i&{U?|BIHU35r9L`+0WKe1&H(F=*z_Z|`ENyXfa-s%dVORTA1ZF_ zKwO0XnE?U50EqLK9f$*lh5~%J%m1xF{r}5fUbZt4Gj8$dKg&M^h%*37!~*q;7u*w2 zp2;-mBh0F2gEagIFFjkh=&QXS7jD8yF~BUnA4NNy!;ogxiTsC*_le9h#IW%Agx|cT z&qXrsJN%{=9eBc{+PB!8V_o#SCpmoxJDe6~XbUF&lp0!re2IP3rMWH7jbyq}d&zIP zQE5*jypADoMZ=cr5Fg;+L{(3<$b0Ge50Cl4Aa(0Mwz2I~%7~p3@Ddzs|T6=7%88ks)J&=KY?DEqQnC0;Gj70JCC6f^Uf2p!rHp9rKA# z$c*n}`Wx-@gHd7EF1PD*KA=9! zAHOMb4;ANS68Iu2OIqNF-;KeZIz?Tf7=yFx=yDb@-!N^}T)m>F24*d+3D3pBWPb)5Nnv-$W6FNbf3(a$XDFjn$;nEe8`UI zUf>_IEs;jE9%{18`ETxk`lTXkZ644KTEXqmdf{E_1JbUSp3o*bGZxtsW?5xfofr?i z13{4$fkDZsvk*^oUSO5FBl;9SU(qx>rk)pJl~}s@Y~O zAp`IwBqZTGVkZq*y7DG%?|t&u zKfGMx3Af}Dnazp~# zA4#Q1Mk-5E8A#O5>ngY+!1&K}=}#xC?Ia;LQ_l9}R(G!93_NCXW@Su-84H>lHA^#( zjAd`@RE%SD7hm8tx_r5Qq^`y`{&b^Zi`!z^r!jCvsTsJrLiWl_@#!;K>KqOE+@*g1 zE+QsH5lD+JHLT9@XbcH0$Z@HD{pY^XpCudYS}xEOE68>T8C<}aYSW^CquPzlrqE&( z)niRgsFz`wKlT@|k=&R>p}@<|a>CtlCWbsxWeb^0iWNR44GcjIJLdCU)+njAqSll zt28chY9Dc+jMFl(!4Oi>-%^LvWav`d6ZP=J^kLiROV16wJ7|!*FD@Y+{es(&gwZT@8kcWW`0<57!e$l;ezW zJZ9BDbD-RNtgNiBW0z=C4ooMklpp8lL*hBqfssPM9tqRKl^IA{@jO>6!?uhnShO4z z)X#h7TZi3f5MK$p|00KLOx#$Dp}?}Z0)GLA+91mo;-n@Vdl790BZ5xkF%>~`7~aP5 zcY+0+0%Ed-Pdw)okBfj#0DdU+D=*jBi{u_aH{`ZY- zGZAhXG&RNh!(;yB*gS1%$4Dx&bK^nith$txE^v%B_g2tUD_bSPXr`Tv1sWA;y*doia!v3-cYR?m9xysEF)$qCjDM{x*_6Ne z+wvQm|6Z!pr_?Pf*^d`uBKj|(Rs6EN+Kj1fY$av*;>rVHS&g-qdsv3J5#gGpZ%nVG zlA5vr5@JLCHIDqnufnu%y?jtd7axa~xRi@-4SBLI8mp1dt!(#k#fXKUt`(fLe1|l5*OC!s^v!N% zqlTw<9IQt>eq@xmF*bA}J6^V1DFA*UA|K1^s^ap!hZv@`qtf8wrTjTunR4PA(KcCC zjgib-oW~ajbmGcq_#T&n%UJ#z*aq0TO0@+ybskTI(8=o(AfvXEIn!5O1T*ESRzlah z?&LV3Zk(DfQJ+m>5tNr9kLKgG+cKq&8EYF!aWA8jhUPl( zCTzL;K}+am`C!-@k?IN+*|VKI$Ht=+>$7}Odbx*oyiCx!XOj?%m(*;iIkn@hbJ`+F zoZJjF!k>^v=KK}^%Hy75HDZ~lRCZdz@#P8E#~=OKy0T_M@YL{?ZgIVJ)->0KW4}hx zc2?KcM=IO^E^TPp%eFoWU%Vn+zCN#vbFOD*AM=$()UK$GU}IZ*?|`I1kz-d-@sf0* ze(ZfMV?w$EY6nO?dx^&0{0`!oCj}v-ER{4gX>w9{>$Bt+l01`_pa7R=D>L!C( zI4Oj_r?%u)WrhhIoi8wUF%{YQvzAk0aZufew=`eJ8!d>`Ug`YP{QGQh{(Lc(zdPfa z|FZD~AKlxth~gkc0=VvtDR?tCvhZ2mj{4tDAFHq6ZZH602WvacL@Y=D>Rxe~X zdui@S$#8k)w_0RT20!IE2ZNzG)iYRC~rf74SjY3LRG3^QSeL50umSZsc9_>J6Gb(kmigLC;7(k^bW1eCC<zSB)tf zdmZfo5&rG4ym;@h)7mwzv0cO>*QL?~9dCCA!=vM;lVI#qxt(GA+sNwb@j57CH&Yjz z_vJGJB0D+lZ=yQ7yut%-a*cwOFH_AY%Fqc_h-I>*d1tW-<418f7BQJtL=`6H^14a+ zcJVHiy*crLb+hSXamv)EUf&Zt7Z%fhT^uMf*}Wsnf?Q-jC98a;aW2J$Rl14D*fz_N zj*8u(vzt|p`8fqupT8Ks;j;z816`=QsNfK5YtTFXzI>am4j?L04O^1*+5e+lI__Ue z%o6O1MQPenSqOHeeh%+9h}X{rtxuPrA~FH3IzxdbuYT%bWD=&0hXs7S zaw?vVpS~O+%ch+`So5n`Cz0FF_-d&6E9*#%Sbx{5OwxgjH4II(wTzm;YhFSN4dYHx z`Iz{#lZPbVJWGuQ_!oP@$p<2}`qgTfJx|qTu|2)BP_jO{wp>u$QLE??>q8^(G;n4M zl`gc0-@7JedPq%rrjYrWbby&jCKG&bRw)_r# zO~SikPd~HSve!GNAUSo(JRkBRNHFYfe)uGQ6T`nv_IkW%{7so4yfGiZB~2MgSTrK$ zO;zG9qcP_Uc`?O9XO#D;txx}?oiyi$dY-eP7cXmz*6}bm%AGnB)}Gc{ek_in;3R+( zP;SEV35h;ODCI;ybIJOUWMfB^EkRn+HeQoco0{>Y;lhz}q5_Yuq?P$pp$;^Ay2>Ys zy{QfMqo^rkFqn!!@JcgI)ZXfPuwnrwiM-*=Q77aT+MIid(NTWoTu5!P3#zdJG4?W? z9V?+W>@&~|sSc!1POUy`EsVE;1HADz;wG$QT51G{*x%|akt!ISeLsM96)7U#5qK_L5Y@nya}5M0V<9MEEs-5`USbH)3+bR>Uug ziIE42fP02XwcFQYq-Z)>`}Au#LJwgTTcw_abVMxs&qvb9X+u zh2o*fZY9bqn$@WSZh6z>Bp)fADZtySS+qU5@J2pSSH`(9?Prxfv1@UDy~|W563;s&tP-d6g0N<;ecZ!AtHVgXa5pI zwt*IR6aII!P4#Rkeh)RH<;x=C(gAD?r;;w?D3pyFYK3TI9N9(Ls>|>q+HGg@vct|T zFSM=_ML%Oiz4|=%J32`Y<#{p$S`=`9^nul)g1?X@1)Y?j?gh%Ypj@1$&KQ!Oi&@1w zENDK4NQhWVsnkEw372=JH;6$RbX4c(PO9A)*yn^9#)y?OB`9~tINo85U#_R~td58) z&GDPUd+4B!zN%7|6F>^;C^sN_M5Du%q5TcLh~{3JB7gn;-h$HsW-@u}lZXk1f0zvZ zqeK2M#)uO-UaneJr2npe(i2j5$%uKHNmu3fn)PqXduHT5yPNLrabs=4iEk2kA=m$^ zGi%-a2g{n-r$}dmOv_vsY0m=x#h1m9cRJ0Hht)0`B;!#JH-j zdma1F+8a=@#w!P}J}7v2>PDk*=P<}ErLOLP9n$b!0mC}4YfJ?4_7!@*R9wW$oF|HD zNHDzg-#l&-q>5019}H45noc^qlx#v5F{Vm-tA=>G_SoQKx$7zRcFGO?@w2KKj;R=C zQOgSI8}zje*K$YYN|8%kelvzc7G1Y{`~@TYmg`R--y1zy>&Kbq(C&@= zMWS%3#~nM^_*IhnNaB~dTn^p?F^Qon+nH&jSx|c%+EHUuZz--ZttJT3V zUwicsv%~b7s6K+aFsdomMW5BO$Wq%B@@wl8G0EY$|6!*W$aUxoPx7t$S#OtFd;{8Sh`P9nCMh(3k`vc0Y{oZoNTgZoZr4xL&shPeta_<4U8Ae4@mM;_$#)l`i;Pxflr%#2 zg21WChtS-{?c_uq!()TPq`2~QaXp=H7XZ6`8D9+iCQVz|mEN~&@f-6B6_hfI!{ne> z?X13s5gUJmLVE>5cpR{zfdZC*-u&edJpWpV_3eDzk9|r}#S5LA*CRR;Yyyeu<^;QV z-pG?z-h*~$sVnUk08`R{E$_hC)c&;qFHJg+A zSsICW_V|cyzC0PZt)AZ)eWLd>5Mdma;<2OZUn~cf9T65wS|ypY*OS5Ct|#6$_k7=p z*%@~M|N8l!%(IY5Ye4`(deIf9VB=J*NVs0H(cxhHZhC(aB;IFzVp9R{f~Pwk2>L~G zXhUzN`o^M7Sf}@E$d9F6O9gLPvUn3JxjSp4P%>MrcR|?MpR55j7~&re%S-M2HA?sj zljrI85JO%q9k}yrTDIHAGy~<*u(UUTNV#oYX!MWB;XtM2IranqFj;ze5S4@l6 zXWs#MWPzRic(j<-HGh4;!Sh^c*x$_MsvuwNiB78=TzI*?{oWb_wDjb(pVV>DpqC<( z%M1^)(AHr3Z8U1?OIS@pTmT-KsHqW6^xTF_)E^3Krx{?Xy8^30_6wjN|AM}V(Kq+8 z{mn8f`gXEs?In%@^ZMWk(|~XBwc(rn@D7epI)yQ5P_<98v`aD7p)^@;Z%=oBN!U{r z;=jRRiKkYU;cKJX_93*WhRT)daHt&=%cqMf-h);QFXf>}2c+@Ni6MFwmc2ap;bUk);%7QguV*9z-s^rAZYkQDJccgCs3LMh8wS1Ep&& PjOjJ)3vB%V`2hVd5Y;@9 literal 0 HcmV?d00001 From ca18fd8a5ceaf18904f6b23cd988d4cf0aa5abc7 Mon Sep 17 00:00:00 2001 From: Vladimir Buzalka Date: Sat, 27 Sep 2025 20:25:35 +0200 Subject: [PATCH 03/23] notebookVB --- File3.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/File3.py b/File3.py index 5a73eb7..5b772f2 100644 --- a/File3.py +++ b/File3.py @@ -3,3 +3,22 @@ import time import fdb +# MEDICUS local CFG (table already created as per previous DDL) +MEDICUS_CFG = dict( + dsn=r"192.168.1.4:z:\medicus 3\data\medicus.fdb", + user="SYSDBA", + password="masterkey", + charset="win1250" +) +conn=fdb.connect(**MEDICUS_CFG) + +cur=conn.cursor() +cur.execute("select rodcis, prijmeni, jmeno from kar where rodcis starting with '8'") + +rows=cur.fetchall() +print(len(rows)) + +for row in rows: + print(row[0], row[1],row[2]) + print(check_insurance(row[0])) + time.sleep(.25) \ No newline at end of file From 7eec4caf827b00700745a3c2d6bd3d4ad8f563b5 Mon Sep 17 00:00:00 2001 From: Vladimir Buzalka Date: Sun, 28 Sep 2025 14:25:20 +0200 Subject: [PATCH 04/23] notebookVB --- 01 testik.py | 3 ++- 03 Vyber.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 04 testik.py | 7 +++++++ functions.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 03 Vyber.py create mode 100644 04 testik.py diff --git a/01 testik.py b/01 testik.py index d94b674..8c333e1 100644 --- a/01 testik.py +++ b/01 testik.py @@ -17,7 +17,8 @@ SOAP_NS = "http://schemas.xmlsoap.org/soap/envelope/" NS_STAV = "http://xmlns.gemsystem.cz/stavPojisteniB2B" # RC provided by you (can contain slash; we normalize before sending/saving) -RC = "280616/091" +RC = "7309208104" +# RC = "280616/091" K_DATU = date.today().isoformat() # MySQL (table already created as per previous DDL) diff --git a/03 Vyber.py b/03 Vyber.py new file mode 100644 index 0000000..87c758c --- /dev/null +++ b/03 Vyber.py @@ -0,0 +1,46 @@ +from functions import get_medicus_connection +from functions import get_mysql_connection +from functions import check_insurance +import time + +def prepare_processed_rcs(): + consql=get_mysql_connection() + cursql=consql.cursor() + + sql=""" + WITH ranked AS ( + SELECT + vr.*, + ROW_NUMBER() OVER ( + PARTITION BY rc + ORDER BY k_datu DESC, queried_at DESC + ) AS rn + FROM vzp_stav_pojisteni AS vr + ) + 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) + +con=get_medicus_connection() +cur=con.cursor() +cur.execute("select rodcis, prijmeni, jmeno from kar where rodcis starting with '7'") + +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]) + print(check_insurance(row[0])) + time.sleep(5) diff --git a/04 testik.py b/04 testik.py new file mode 100644 index 0000000..b2d20d6 --- /dev/null +++ b/04 testik.py @@ -0,0 +1,7 @@ +from functions import check_insurance + +if __name__ == "__main__": + rc = "7309208104" + res = check_insurance(rc) + print("=== RESULT ===") + print(res) \ No newline at end of file diff --git a/functions.py b/functions.py index 5d129aa..614717c 100644 --- a/functions.py +++ b/functions.py @@ -11,6 +11,48 @@ import requests from requests_pkcs12 import Pkcs12Adapter import pymysql from pymysql.cursors import DictCursor +import fdb + +MEDICUS_CFG = dict( + dsn=r"192.168.1.4:z:\medicus 3\data\medicus.fdb", + user="SYSDBA", + password="masterkey", + charset="win1250", +) + +def get_medicus_connection(): + """ + Attempt to create a Firebird connection to the Medicus database. + Returns: + fdb.Connection object on success + None on failure + """ + try: + return fdb.connect(**MEDICUS_CFG) + except fdb.fbcore.DatabaseError as e: + print(f"Medicus DB connection failed: {e}") + return None + +# -------- MySQL (Medevio, etc.) ------- +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 +) + +def get_mysql_connection(): + """ + Return a PyMySQL connection or None if the connection fails. + """ + try: + return pymysql.connect(**MYSQL_CFG) + except pymysql.MySQLError as e: + print(f"MySQL connection failed: {e}") + return None # ======== CONFIG (env overrides allowed) ======== PFX_PATH = os.getenv("VZP_PFX_PATH", r"mbcert.pfx") From b8b466b8894c38a8bc90446c6bc3b71c379da21f Mon Sep 17 00:00:00 2001 From: Vladimir Buzalka Date: Sun, 28 Sep 2025 14:42:35 +0200 Subject: [PATCH 05/23] notebookVB --- 05 testik.py | 4 ++++ functions.py | 16 ++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 05 testik.py diff --git a/05 testik.py b/05 testik.py new file mode 100644 index 0000000..48cda59 --- /dev/null +++ b/05 testik.py @@ -0,0 +1,4 @@ +import socket + +computer_name = socket.gethostname() +print(computer_name) \ No newline at end of file diff --git a/functions.py b/functions.py index 614717c..aa56af9 100644 --- a/functions.py +++ b/functions.py @@ -13,13 +13,8 @@ import pymysql from pymysql.cursors import DictCursor import fdb -MEDICUS_CFG = dict( - dsn=r"192.168.1.4:z:\medicus 3\data\medicus.fdb", - user="SYSDBA", - password="masterkey", - charset="win1250", -) +import socket def get_medicus_connection(): """ Attempt to create a Firebird connection to the Medicus database. @@ -27,6 +22,15 @@ def get_medicus_connection(): fdb.Connection object on success None on failure """ + if socket.gethostname().strip()=="NTBVBHP470G10": + MEDICUS_CFG = dict( + dsn=r"192.168.1.4:z:\medicus 3\data\medicus.fdb", + user="SYSDBA", + password="masterkey", + charset="win1250", + ) + elif: + try: return fdb.connect(**MEDICUS_CFG) except fdb.fbcore.DatabaseError as e: From b88d16eb102df6a0d2a6ca5fdfc38ead7db8fe09 Mon Sep 17 00:00:00 2001 From: Vladimir Buzalka Date: Sun, 28 Sep 2025 14:54:51 +0200 Subject: [PATCH 06/23] notebookVB --- requirements.txt | Bin 0 -> 392 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..282c77288494b459a146c68654a478900c904fd6 GIT binary patch literal 392 zcmZ9IOAdlS5JYQj;!z|r;Ai6vG|_kfqxg-e2)NM0t8ZFBV@MI`s(#bcuV8$BtHBkm9fmctJH@&X9&6LCh%{9~5+z_&t xGjh( Date: Sun, 28 Sep 2025 14:55:01 +0200 Subject: [PATCH 07/23] notebookVB --- functions.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/functions.py b/functions.py index aa56af9..d250519 100644 --- a/functions.py +++ b/functions.py @@ -29,7 +29,13 @@ def get_medicus_connection(): password="masterkey", charset="win1250", ) - elif: + elif socket.gethostname().strip()=="SESTRA": + MEDICUS_CFG = dict( + dsn=r"192.168.1.10:m:\medicus\data\medicus.fdb", + user="SYSDBA", + password="masterkey", + charset="win1250", + ) try: return fdb.connect(**MEDICUS_CFG) From adfa781cd054b23cd0ea4089942f98dff1330e00 Mon Sep 17 00:00:00 2001 From: "michaela.buzalkova" Date: Sun, 28 Sep 2025 15:33:05 +0200 Subject: [PATCH 08/23] sestra --- .idea/Insurance.iml | 2 +- .idea/misc.xml | 10 +++++ .idea/workspace.xml | 94 ++++++++++++++++++++++++++++++++++++++------- 03 Vyber.py | 4 +- functions.py | 44 +++++++++++---------- 5 files changed, 118 insertions(+), 36 deletions(-) create mode 100644 .idea/misc.xml diff --git a/.idea/Insurance.iml b/.idea/Insurance.iml index 235ece6..099709f 100644 --- a/.idea/Insurance.iml +++ b/.idea/Insurance.iml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..28a0efa --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 6213dc3..da793cc 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,14 +5,10 @@ - - - - - - - - + + + +