z230
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
sipiq_thankyou_v1.0.py
|
||||
======================
|
||||
Verze: 1.0
|
||||
Datum: 2026-06-18
|
||||
Autor: Claude Code (pro MUDr. Vladimíra Buzalku)
|
||||
|
||||
Popis
|
||||
-----
|
||||
Vygeneruje .eml draft PODĚKOVÁNÍ za vyplnění SIPIQ (studie 77242113UCO3002 / DAWN)
|
||||
pro jedno centrum. Struktura (domluva 18JUN2026, BEZ Shrnutí):
|
||||
1) úvod (poděkování + „dotazník už nelze editovat; při chybějících/nejasných/nekonzistentních
|
||||
položkách si vyžádáme upřesnění e-mailem"; odkaz na plné odpovědi pod podpisem),
|
||||
2) podpis,
|
||||
3) ÚPLNĚ POD PODPISEM = kompletní výpis vyplněného SIPIQ (sekce → otázka → odpověď,
|
||||
seřazené dle struktury dotazníku; vynechána sekce Confidentiality; jen neprázdné).
|
||||
|
||||
Cc = koordinátorky (AKocourk + EBartoso). To = e-maily lékaře z investigators (email + email2),
|
||||
fallback pi_email z odpovědi. from = vbuzalka@its.jnj.com. Výstup do …\\UploadToJNJ.
|
||||
Draft ≠ odesláno — STATUS „poděkováno" psát až po ověření odeslání.
|
||||
|
||||
Použití:
|
||||
python sipiq_thankyou_v1.0.py --last Bruncak # dry-run (náhled)
|
||||
python sipiq_thankyou_v1.0.py --last Bruncak --apply # zapíše .eml
|
||||
|
||||
Mongo 192.168.1.76:27017, bez auth, pymongo.
|
||||
"""
|
||||
import argparse
|
||||
import os
|
||||
from datetime import datetime
|
||||
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"
|
||||
SKIP_SECTIONS = {"Confidentiality Statement"}
|
||||
SUBJECT = "77242113UCO3002 (DAWN) — poděkování za vyplnění feasibility dotazníku SIPIQ"
|
||||
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")
|
||||
|
||||
|
||||
def esc(s):
|
||||
return str(s).replace("&", "&").replace("<", "<").replace(">", ">")
|
||||
|
||||
|
||||
def build_sipiq_html(db, resp):
|
||||
ans = resp.get("answers") or {}
|
||||
qs = list(db.sipiq_questions.find().sort("order", 1))
|
||||
out, cur = [], None
|
||||
for q in qs:
|
||||
sec = q.get("section") or "Other"
|
||||
if sec in SKIP_SECTIONS:
|
||||
continue
|
||||
items = q.get("items") or []
|
||||
pairs = []
|
||||
if not items:
|
||||
v = ans.get(q["_id"])
|
||||
if v not in (None, ""):
|
||||
pairs.append((None, v))
|
||||
else:
|
||||
for it in items:
|
||||
v = ans.get(it["key"])
|
||||
if v not in (None, ""):
|
||||
pairs.append((it.get("label") or "(odpověď)", v))
|
||||
if not pairs:
|
||||
continue
|
||||
if sec != cur:
|
||||
cur = sec
|
||||
out.append(f'<h3 style="margin:16px 0 4px;color:#1F4E78">{esc(sec)}</h3>')
|
||||
stem = esc((q.get("text") or "").replace("\n", " "))
|
||||
out.append(f'<p style="margin:6px 0 1px"><b>[{q["_id"]}]</b> {stem}</p>')
|
||||
if len(pairs) == 1 and pairs[0][0] is None:
|
||||
out.append(f'<p style="margin:0 0 0 18px"><b>{esc(pairs[0][1])}</b></p>')
|
||||
else:
|
||||
out.append('<ul style="margin:2px 0 6px">')
|
||||
for lbl, v in pairs:
|
||||
out.append(f'<li>{esc(lbl)}: <b>{esc(v)}</b></li>' if lbl
|
||||
else f'<li><b>{esc(v)}</b></li>')
|
||||
out.append('</ul>')
|
||||
return "\n".join(out)
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--last", required=True, help="příjmení v sipiq_responses (pi_last_name)")
|
||||
ap.add_argument("--apply", action="store_true")
|
||||
args = ap.parse_args()
|
||||
|
||||
db = MongoClient("mongodb://192.168.1.76:27017", serverSelectionTimeoutMS=8000).feasibility
|
||||
resp = db.sipiq_responses.find_one({"pi_last_name": args.last})
|
||||
if not resp:
|
||||
raise SystemExit(f"CHYBA: centrum '{args.last}' nenalezeno v sipiq_responses.")
|
||||
inv = db.investigators.find_one({"_id": resp.get("investigator_oid")},
|
||||
{"email": 1, "email2": 1, "prijmeni": 1, "jmeno": 1})
|
||||
tos = [e for e in [(inv or {}).get("email"), (inv or {}).get("email2")] if e]
|
||||
if not tos and resp.get("pi_email"):
|
||||
tos = [resp["pi_email"]]
|
||||
to = ", ".join(tos)
|
||||
|
||||
intro = (
|
||||
'<p>Vážený pane doktore,</p>'
|
||||
'<p>děkujeme za zaslání vyplněného dotazníku SIPIQ studie '
|
||||
'<b>77242113UCO3002 (DAWN)</b>. Vaše odpovědi uvádíme pro úplnost v plném znění '
|
||||
'níže, pod podpisem. Odeslaný dotazník již není možné editovat, takže kdybychom '
|
||||
'při dalším zpracování našli položky chybějící, nejasné nebo nekonzistentní, '
|
||||
'ještě bychom si vyžádali upřesnění e-mailem.</p>'
|
||||
)
|
||||
sig = f'<p>S pozdravem,<br>{SIG}</p>'
|
||||
sipiq = build_sipiq_html(db, resp)
|
||||
body = (intro + sig +
|
||||
'<hr>'
|
||||
'<p style="color:#888;font-style:italic">Vyplněné SIPIQ (kopie Vašich odpovědí):</p>'
|
||||
+ sipiq)
|
||||
|
||||
print(f"Centrum: {resp.get('pi_first_name')} {resp.get('pi_last_name')} | {resp.get('site_name')}")
|
||||
print(f"To: {to}\nCc: {CC}\nSubject: {SUBJECT}")
|
||||
print(f"SIPIQ – sekcí: {sipiq.count('<h3')} | délka těla: {len(body)} znaků")
|
||||
|
||||
if not args.apply:
|
||||
print("[DRY-RUN] .eml nezapsáno. Ostrý běh: --apply")
|
||||
return
|
||||
|
||||
msg = EmailMessage()
|
||||
msg["From"] = FROM
|
||||
msg["To"] = to
|
||||
msg["Cc"] = CC
|
||||
msg["Subject"] = SUBJECT
|
||||
msg["X-Unsent"] = "1"
|
||||
msg.set_content("Tento e-mail je ve formátu HTML.", subtype="plain", charset="utf-8")
|
||||
msg.add_alternative(f"<html><body style=\"font-family:Calibri,Arial,sans-serif;font-size:11pt\">{body}</body></html>",
|
||||
subtype="html", charset="utf-8")
|
||||
|
||||
os.makedirs(OUT_DIR, exist_ok=True)
|
||||
fname = f"podekovani_sipiq_{args.last.lower()}_{datetime.now().strftime('%d%b%Y').upper()}.eml"
|
||||
path = os.path.join(OUT_DIR, fname)
|
||||
with open(path, "wb") as f:
|
||||
f.write(bytes(msg))
|
||||
print(f"Uloženo: {path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user