#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 01_zakoupeno.py — workflow status 0: Zakoupeno (datum 31.12.2024) ================================================================= První stav reconciliačního workflow. Všem pacientům ze zakoupeného souboru (CSV příloha smlouvy, 1712 RČ) nastaví status 0 "Zakoupeno" k 31.12.2024. - Pacienti ze smlouvy, kteří už jsou v Mongo (registrovaní k 1.1.2025) → status 0. - Pacienti ze smlouvy, kteří v Mongo nejsou (odhlášeni u Buzalkové před předáním) → doplněni z Medicus kar s markerem `mimo_vzp_populaci` + status 0. - Pacienti v Mongo mimo smlouvu → označeni `ve_smlouve=False` (status 0 nedostanou). Workflow stav drží: status, status_popis, status_datum (aktuální stav) status_historie[] (postup stavů — pro další kroky) Idempotentní — opakované spuštění status 0 nezduplikuje. """ import csv import re import sys from pathlib import Path from datetime import datetime, timezone PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent sys.path.insert(0, str(PROJECT_ROOT)) import pymongo from Knihovny.medicus_db import get_medicus_connection # ── Konfigurace ──────────────────────────────────────────────────────────────── MONGO_URI = "mongodb://192.168.1.76:27017" MONGO_DB = "ordinace" MONGO_COLL = "registrovani_tracking" CSV_PATH = Path(__file__).resolve().parent / "Inputs" / "2025-01-01 seznam_pacientu_jmeno_rc.csv" STATUS = 0 STATUS_POPIS = "Zakoupeno" STATUS_DATUM = "2024-12-31" POJ_ZKR = {"111": "VZP", "201": "VoZP", "205": "ČPZP", "207": "OZP", "209": "ZPŠ", "211": "ZPMV ČR", "213": "RBP"} norm = lambda s: re.sub(r"\D", "", s or "") def status_entry(now): return {"status": STATUS, "status_popis": STATUS_POPIS, "status_datum": STATUS_DATUM, "zapsano": now} def main(): # ── CSV (zakoupený soubor) ────────────────────────────────────────────────── csv_rc = {} with CSV_PATH.open(encoding="utf-8-sig") as f: for row in csv.DictReader(f, delimiter=";"): csv_rc[norm(row["Rodné číslo"])] = row["Příjmení a jméno"] contract = set(csv_rc) print(f"Zakoupený soubor (CSV): {len(contract)} RČ") cli = pymongo.MongoClient(MONGO_URI, serverSelectionTimeoutMS=3000) coll = cli[MONGO_DB][MONGO_COLL] coll.create_index("status") coll.create_index("ve_smlouve") pop = {norm(d["_id"]): d["_id"] for d in coll.find({}, {"_id": 1})} popset = set(pop) present = contract & popset absent = contract - popset extra = popset - contract now = datetime.now(timezone.utc) # ── 1) Pacienti ze smlouvy už v Mongo → status 0 (idempotentně) ───────────── n_pres = 0 for rc in present: _id = pop[rc] d = coll.find_one({"_id": _id}, {"status_historie": 1}) sh = d.get("status_historie", []) if not any(e.get("status") == STATUS for e in sh): sh = sh + [status_entry(now)] coll.update_one({"_id": _id}, {"$set": { "status": STATUS, "status_popis": STATUS_POPIS, "status_datum": STATUS_DATUM, "ve_smlouve": True, "status_historie": sh, "updated_at": now}}) n_pres += 1 # ── 2) Pacienti v Mongo mimo smlouvu → ve_smlouve = False ─────────────────── coll.update_many({"_id": {"$in": [pop[rc] for rc in extra]}}, {"$set": {"ve_smlouve": False, "updated_at": now}}) # ── 3) Pacienti ze smlouvy chybějící v Mongo → doplnit z kar + status 0 ───── conn = get_medicus_connection() cur = conn.cursor() kar = {} abslist = list(absent) for i in range(0, len(abslist), 500): b = abslist[i:i + 500] ph = ",".join("?" for _ in b) cur.execute(f""" SELECT TRIM(k.rodcis), TRIM(k.prijmeni), TRIM(k.jmeno), TRIM(k.poj), (SELECT MAX(r.datum_zruseni) FROM registr r JOIN icp i ON r.idicp=i.idicp WHERE r.idpac=k.idpac AND i.icp='09305001' AND i.odb='001') FROM kar k WHERE k.rodcis IN ({ph})""", b) for rc, p, j, poj, zrus in cur.fetchall(): kar[(rc or "").strip()] = {"prijmeni": p, "jmeno": j, "poj": (poj or "").strip(), "zruseni": zrus} conn.close() n_ins = 0 for rc in absent: if coll.find_one({"_id": rc}): continue k = kar.get(rc, {}) poj = k.get("poj", "") zrus = k.get("zruseni") zrus_s = zrus.strftime("%Y-%m-%d") if zrus else None snap = { "k_datu": "2025-01-01", "kategorie": "ODHLASEN_PRED_PREDANIM", "kategorie_popis": "Registrace u Buzalkové zrušena před předáním (1.1.2025)", "v_zakoupenem_souboru": False, "flag": "NEBYL V ZAKOUPENÉM SOUBORU PACIENTŮ", "flag_duvod": f"registrace u Buzalkové zrušena {zrus_s} (před předáním)", "praktik_nazev": None, "praktik_icz": None, "praktik_icp": None, "praktik_od": None, "datum_zahajeni": None, "datum_ukonceni": None, "medicus_zruseni": zrus_s, } coll.insert_one({ "_id": rc, "rc": rc, "prijmeni": k.get("prijmeni"), "jmeno": k.get("jmeno"), "pojistovna": {"kod": poj, "zkratka": POJ_ZKR.get(poj, poj)}, "medicus_poj": poj, "status": STATUS, "status_popis": STATUS_POPIS, "status_datum": STATUS_DATUM, "ve_smlouve": True, "mimo_vzp_populaci": True, "vychozi_datum": "2025-01-01", "aktualni": snap, "historie": [{**snap, "zmena": "doplněn ze smlouvy (mimo VZP populaci)"}], "status_historie": [status_entry(now)], "created_at": now, "updated_at": now, }) n_ins += 1 # ── Souhrn ────────────────────────────────────────────────────────────────── print(f"present (status 0 nastaveno) : {n_pres}") print(f"absent doplněno ze smlouvy (insert) : {n_ins}") print(f"extra mimo smlouvu (ve_smlouve=False): {len(extra)}") print() print(f"status 0 (Zakoupeno) celkem : {coll.count_documents({'status': 0})}") print(f"ve_smlouve = True : {coll.count_documents({'ve_smlouve': True})}") print(f"kolekce celkem : {coll.count_documents({})}") cli.close() if __name__ == "__main__": main()