Files
ordinaceprojekt/Insurance/FinalReconcilliation/01_zakoupeno.py
T
Vladimir Buzalka 9b6f89f437 notebookvb
2026-06-16 10:21:19 +02:00

155 lines
6.7 KiB
Python

#!/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)}")
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()