Files
janssen/Feasibility/TRASH/sipiq_reminder_v1.0.py
2026-06-18 11:10:00 +02:00

155 lines
6.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
sipiq_reminder_v1.0.py
======================
Verze: 1.0
Datum: 2026-06-18
Autor: Claude Code (pro MUDr. Vladimíra Buzalku)
Popis
-----
Vygeneruje .eml draft PŘIPOMÍNKY vyplnění SIPIQ (studie 77242113UCO3002 / DAWN) pro centra
na KROK 6 (SIPIQ odeslán), která dlouho nereagovala. Vřelá prosba o vyplnění co nejdříve
+ odkaz na dotazník specifický pro centrum (sipiq.link z investigators) + bezpečnostní věta
„pokud jste již vyplnil(a), ignorujte".
To = email + email2 z investigators (+ EXTRA_TO ručně, dd-proxy vynechány), Cc = koordinátorky,
from = vbuzalka@its.jnj.com, tělo BASE64 (Outlook čistě). Draft ≠ odesláno — STATUS „připomínka
SIPIQ odeslána" psát až po ověření odeslání.
Použití:
python sipiq_reminder_v1.0.py --names "Matous,Kojecky,Jungwirthova,Krížová,Mudr" # dry-run
python sipiq_reminder_v1.0.py --names "Matous,Kojecky,Jungwirthova,Krížová,Mudr" --apply
Mongo 192.168.1.76:27017, bez auth, pymongo.
"""
import argparse
import os
import re
import unicodedata
from datetime import date
from email.message import EmailMessage
from pymongo import MongoClient
OUT_DIR = r"u:\Dropbox\!!!Days\Downloads Z230\UploadToJNJ"
CC = "AKocourk@ITS.JNJ.com, EBartoso@its.jnj.com"
FROM = "vbuzalka@its.jnj.com"
SIG = ("MUDr. Vladimír BUZALKA<br>"
"ICON plc / Performing Local Trial Management Services for Janssen Cilag s.r.o. "
"/ Global Clinical Operations<br>"
"Mobile: +420 775 735 276 / Fax: +420 227 012 284<br>"
"E-mail: vbuzalka@its.jnj.com, vladimir.buzalka@iconplc.com")
# Ručně doplněné adresy (z reply-checku / STATUS) — komu navíc poslat
EXTRA_TO = {
"Jungwirthova": ["a.jungwirthova@liberascientia.cz"],
"Krížová": ["Viera.Krizova@fnmh.cz"],
"Mudr": ["petr.pekny@nmskb.cz"], # dr. Pěkný komunikuje za dr. Mudra (dle STATUS)
}
CZ_MON = {1: "ledna", 2: "února", 3: "března", 4: "dubna", 5: "května", 6: "června",
7: "července", 8: "srpna", 9: "září", 10: "října", 11: "listopadu", 12: "prosince"}
MON = {m: i + 1 for i, m in enumerate(
["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"])}
def ascii_slug(s):
return "".join(c for c in unicodedata.normalize("NFKD", str(s or ""))
if not unicodedata.combining(c)).lower().replace(" ", "")
def sent_date_cz(status):
dates = []
for ln in (status or "").splitlines():
if "SIPIQ odesl" in ln:
m = re.match(r"(\d{2})([A-Za-z]{3})(\d{4})", ln.strip())
if m and m.group(2).upper() in MON:
dates.append(date(int(m.group(3)), MON[m.group(2).upper()], int(m.group(1))))
if not dates:
return None
d = max(dates)
return f"{d.day}. {CZ_MON[d.month]} {d.year}"
def is_female(prijmeni):
p = (prijmeni or "").lower()
return p.endswith("ová") or p.endswith("ova") or p.endswith("á")
def build_body(jmeno, prijmeni, sent_cz, link):
f = is_female(prijmeni)
greet = "Vážená paní doktorko," if f else "Vážený pane doktore,"
vyplnil = "vyplnila" if f else "vyplnil"
sent_part = f" dne <b>{sent_cz}</b>" if sent_cz else ""
return (
f'<p>{greet}</p>'
f'<p>dovoluji si zdvořile připomenout feasibility dotazník <b>SIPIQ</b> ke studii '
f'<b>77242113UCO3002 (DAWN)</b> (přípravek icotrokinra, ulcerózní kolitida), '
f'který jsme Vám zaslali{sent_part}.</p>'
f'<p><b>Velmi bychom ocenili jeho vyplnění co nejdříve</b> — je pro nás klíčový pro '
f'posouzení Vašeho centra a další postup. Níže najdete odkaz na dotazník specifický '
f'pro Vaše centrum:</p>'
f'<p><a href="{link}">{link}</a></p>'
f'<p>Pokud jste dotazník již {vyplnil}, přijměte prosím poděkování a tento e-mail '
f'ignorujte.</p>'
f'<p>V případě jakýchkoli dotazů (např. potíže s odkazem) jsem Vám plně k dispozici. '
f'Předem děkuji za Váš čas a vstřícnost.</p>'
f'<p>S pozdravem,<br>{SIG}</p>'
)
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--names", required=True, help="příjmení čárkou (pi v investigators)")
ap.add_argument("--apply", action="store_true")
args = ap.parse_args()
db = MongoClient("mongodb://192.168.1.76:27017", serverSelectionTimeoutMS=8000).feasibility
names = [n.strip() for n in args.names.split(",") if n.strip()]
docs = list(db.investigators.find({"prijmeni": {"$in": names}}))
found = {d["prijmeni"] for d in docs}
for n in names:
if n not in found:
print(f" ! nenalezeno: {n}")
subject = "[Připomínka] 77242113UCO3002 (DAWN) — feasibility dotazník SIPIQ (prosba o vyplnění)"
done = []
for d in docs:
link = (d.get("sipiq") or {}).get("link")
if not link:
print(f" ! {d['prijmeni']}: chybí sipiq.link — přeskakuji"); continue
tos = [e for e in [d.get("email"), d.get("email2")] if e]
tos += EXTRA_TO.get(d["prijmeni"], [])
tos = [e for e in dict.fromkeys(tos) if "dd-proxy" not in e.lower()] # dedup + bez proxy
to = ", ".join(tos)
sent_cz = sent_date_cz(d.get("STATUS"))
body = build_body(d.get("jmeno"), d["prijmeni"], sent_cz, link)
print(f" {d.get('jmeno')} {d['prijmeni']:14} | To: {to}")
if not args.apply:
continue
msg = EmailMessage()
msg["From"] = FROM
msg["To"] = to
msg["Cc"] = CC
msg["Subject"] = subject
msg["X-Unsent"] = "1"
html = (f'<html><body style="font-family:Calibri,Arial,sans-serif;font-size:11pt">'
f'{body}</body></html>')
msg.set_content(html, subtype="html", charset="utf-8", cte="base64")
os.makedirs(OUT_DIR, exist_ok=True)
fn = f"pripominka_sipiq_{ascii_slug(d['prijmeni'])}_18JUN2026.eml"
with open(os.path.join(OUT_DIR, fn), "wb") as fh:
fh.write(bytes(msg))
done.append(fn)
if not args.apply:
print(f"\n[DRY-RUN] {len(docs)} center, nic nezapsáno. Ostrý: --apply")
else:
print(f"\n[APPLY] Vygenerováno {len(done)} připomínek do {OUT_DIR}")
if __name__ == "__main__":
main()