228 lines
7.6 KiB
Python
228 lines
7.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
# =============================================================================
|
|
# Nazev: report_77242113UCO2001_v1.2.py
|
|
# Verze: 1.2
|
|
# Datum: 2026-06-19
|
|
# Popis: Generator Excel reportu z Mongo feasibility.investigators.
|
|
# v1.2 - pridan PRVNI list "Prehled KROK": A=KROK, B=pocet,
|
|
# C=seznam jmen zkousejicich (oddeleno strednikem) v jedne bunce.
|
|
# List Investigators nasleduje jako druhy.
|
|
# v1.1 - sloupec KROK hned pred STATUS + barevne odliseni dle KROK.
|
|
# Projekt: 77242113UCO2001 (DAWN / spravny kod 77242113UCO3002)
|
|
# Vystup: u:\Dropbox\!!!Days\Downloads Z230\ (verzovany nazev s timestampem)
|
|
# =============================================================================
|
|
|
|
import os
|
|
from datetime import datetime
|
|
from pymongo import MongoClient
|
|
import openpyxl
|
|
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
|
|
from openpyxl.utils import get_column_letter
|
|
|
|
# --- Připojení k MongoDB ---
|
|
MONGO_URI = os.environ.get("MONGO_URI", "mongodb://192.168.1.76:27017")
|
|
client = MongoClient(MONGO_URI)
|
|
db = client["feasibility"]
|
|
col = db["investigators"]
|
|
|
|
# --- Načtení dat ---
|
|
docs = list(col.find({}))
|
|
print(f"Načteno {len(docs)} záznamů.")
|
|
|
|
# --- Cílová složka ---
|
|
OUTPUT_DIR = r"u:\Dropbox\!!!Days\Downloads Z230"
|
|
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
|
|
|
datum = datetime.now().strftime("%Y%m%d_%H%M")
|
|
filename = f"77242113UCO2001_investigators_{datum}.xlsx"
|
|
filepath = os.path.join(OUTPUT_DIR, filename)
|
|
|
|
# --- Definice sloupců ---
|
|
# Pořadí: jméno, email, KROK, STATUS, kriticka_poznamka, pak ostatní
|
|
# KROK je ZÁMĚRNĚ hned PŘED STATUS.
|
|
FIXED_COLS = [
|
|
("prijmeni", "Příjmení"),
|
|
("jmeno", "Jméno"),
|
|
("email", "Email"),
|
|
("KROK", "KROK"),
|
|
("STATUS", "STATUS"),
|
|
("kriticka_poznamka", "Kritická poznámka"),
|
|
("zeme", "Země"),
|
|
("pracoviste", "Pracoviště"),
|
|
("internet_summary","Internet summary"),
|
|
]
|
|
|
|
# Klíče, které přeskočíme (složité nested objekty)
|
|
SKIP_KEYS = {"_id", "excel", "sites_illuminator", "maf", "zdroje", "studie",
|
|
"Viper_Performance", "Viper_Contacts", "cda", "history",
|
|
"zpracovane_emaily", "sipiq"}
|
|
|
|
# Ostatní skalární pole
|
|
fixed_keys = {c[0] for c in FIXED_COLS}
|
|
extra_keys = set()
|
|
for doc in docs:
|
|
for k in doc.keys():
|
|
if k not in fixed_keys and k not in SKIP_KEYS:
|
|
extra_keys.add(k)
|
|
extra_keys = sorted(extra_keys)
|
|
|
|
ALL_COLS = FIXED_COLS + [(k, k) for k in extra_keys]
|
|
|
|
# --- Barvy podle KROK ---
|
|
def krok_color(krok):
|
|
if not krok:
|
|
return None
|
|
k = krok.strip()
|
|
if k.startswith("5") or k.startswith("6") or k.startswith("7"):
|
|
return "FFC6EFCE" # zelená - CDA podepsáno / SIPIQ
|
|
if k.startswith("4"):
|
|
return "FFB7E1CD" # tmavší zelená - CDA vyžádáno
|
|
if k.startswith("3.1"):
|
|
return "FFDDEBF7" # světle modrá - zájem
|
|
if k.startswith("3.2"):
|
|
return "FFFFC7CE" # červená - nezájem
|
|
if k.startswith("2"):
|
|
return "FFFFF2CC" # světle žlutá - připomenuto
|
|
if k.startswith("1"):
|
|
return "FFDCE6F1" # modrá - nabídka odeslána
|
|
if k.startswith("0"):
|
|
return "FFD9D9D9" # šedá - mimo
|
|
return None
|
|
|
|
# --- Pomocná funkce: setřídění KROK dle čísla prefixu ---
|
|
def krok_sort_key(krok):
|
|
k = (krok or "").strip()
|
|
num = ""
|
|
for ch in k:
|
|
if ch.isdigit() or ch == ".":
|
|
num += ch
|
|
else:
|
|
break
|
|
try:
|
|
return (0, float(num)) if num else (1, 0.0)
|
|
except ValueError:
|
|
return (1, 0.0)
|
|
|
|
# --- Agregace pro přehledový list ---
|
|
def cele_jmeno(doc):
|
|
p = (doc.get("prijmeni") or "").strip()
|
|
j = (doc.get("jmeno") or "").strip()
|
|
return (p + " " + j).strip() or "(bez jména)"
|
|
|
|
skupiny = {} # krok -> list jmen
|
|
for doc in docs:
|
|
krok = str(doc.get("KROK", "") or "").strip() or "(nezařazeno)"
|
|
skupiny.setdefault(krok, []).append(cele_jmeno(doc))
|
|
|
|
prehled_rows = []
|
|
for krok in sorted(skupiny, key=krok_sort_key):
|
|
jmena = sorted(skupiny[krok])
|
|
prehled_rows.append((krok, len(jmena), "; ".join(jmena)))
|
|
|
|
# --- Styly ---
|
|
header_font = Font(bold=True, color="FFFFFFFF")
|
|
header_fill = PatternFill("solid", fgColor="FF1F4E79")
|
|
header_align = Alignment(horizontal="center", vertical="center", wrap_text=True)
|
|
cell_align = Alignment(vertical="top", wrap_text=True)
|
|
thin = Side(style="thin", color="FFB0B0B0")
|
|
border = Border(left=thin, right=thin, top=thin, bottom=thin)
|
|
|
|
# --- Vytvoření workbooku ---
|
|
wb = openpyxl.Workbook()
|
|
|
|
# === LIST 1: Přehled KROK ===
|
|
ws_p = wb.active
|
|
ws_p.title = "Přehled KROK"
|
|
|
|
PREHLED_COLS = [("KROK", 30), ("Počet", 10), ("Zkoušející (jména)", 120)]
|
|
for col_idx, (label, w) in enumerate(PREHLED_COLS, 1):
|
|
c = ws_p.cell(row=1, column=col_idx, value=label)
|
|
c.font = header_font
|
|
c.fill = header_fill
|
|
c.alignment = header_align
|
|
c.border = border
|
|
ws_p.column_dimensions[get_column_letter(col_idx)].width = w
|
|
ws_p.row_dimensions[1].height = 26
|
|
|
|
for r, (krok, pocet, jmena) in enumerate(prehled_rows, 2):
|
|
bg = krok_color(krok)
|
|
vals = [krok, pocet, jmena]
|
|
for col_idx, val in enumerate(vals, 1):
|
|
c = ws_p.cell(row=r, column=col_idx, value=val)
|
|
c.alignment = cell_align
|
|
c.border = border
|
|
if bg:
|
|
c.fill = PatternFill("solid", fgColor=bg)
|
|
if col_idx == 1:
|
|
c.font = Font(bold=True)
|
|
if col_idx == 2:
|
|
c.alignment = Alignment(horizontal="center", vertical="top")
|
|
|
|
# Řádek CELKEM
|
|
tot_r = len(prehled_rows) + 2
|
|
ws_p.cell(row=tot_r, column=1, value="CELKEM").font = Font(bold=True)
|
|
tc = ws_p.cell(row=tot_r, column=2, value=sum(p for _, p, _ in prehled_rows))
|
|
tc.font = Font(bold=True)
|
|
tc.alignment = Alignment(horizontal="center")
|
|
for col_idx in range(1, 4):
|
|
ws_p.cell(row=tot_r, column=col_idx).border = border
|
|
|
|
ws_p.freeze_panes = "A2"
|
|
ws_p.auto_filter.ref = f"A1:C{len(prehled_rows) + 1}"
|
|
|
|
# === LIST 2: Investigators ===
|
|
ws = wb.create_sheet("Investigators")
|
|
|
|
# Záhlaví
|
|
for col_idx, (key, label) in enumerate(ALL_COLS, 1):
|
|
cell = ws.cell(row=1, column=col_idx, value=label)
|
|
cell.font = header_font
|
|
cell.fill = header_fill
|
|
cell.alignment = header_align
|
|
cell.border = border
|
|
ws.row_dimensions[1].height = 30
|
|
|
|
# Data
|
|
for row_idx, doc in enumerate(docs, 2):
|
|
krok_val = str(doc.get("KROK", "") or "")
|
|
bg = krok_color(krok_val)
|
|
|
|
for col_idx, (key, label) in enumerate(ALL_COLS, 1):
|
|
val = doc.get(key, "")
|
|
if isinstance(val, list):
|
|
val = ", ".join(str(v) for v in val)
|
|
elif isinstance(val, dict):
|
|
val = str(val)
|
|
elif val is None:
|
|
val = ""
|
|
else:
|
|
val = str(val)
|
|
|
|
cell = ws.cell(row=row_idx, column=col_idx, value=val)
|
|
cell.alignment = cell_align
|
|
cell.border = border
|
|
|
|
if bg:
|
|
cell.fill = PatternFill("solid", fgColor=bg)
|
|
if key == "KROK":
|
|
cell.font = Font(bold=True)
|
|
|
|
# Šířky sloupců
|
|
col_widths = {
|
|
"prijmeni": 18, "jmeno": 15, "email": 35,
|
|
"KROK": 26, "STATUS": 45, "kriticka_poznamka": 60,
|
|
"zeme": 12, "pracoviste": 35, "internet_summary": 60,
|
|
}
|
|
for col_idx, (key, label) in enumerate(ALL_COLS, 1):
|
|
w = col_widths.get(key, 20)
|
|
ws.column_dimensions[get_column_letter(col_idx)].width = w
|
|
|
|
ws.freeze_panes = "A2"
|
|
ws.auto_filter.ref = ws.dimensions
|
|
|
|
# --- Uložení ---
|
|
wb.save(filepath)
|
|
print(f"Ulozeno: {filepath}")
|
|
print(f"List 1 'Přehled KROK': {len(prehled_rows)} kroků, celkem {sum(p for _,p,_ in prehled_rows)} zkoušejících.")
|
|
print("List 2 'Investigators':", len(docs), "radku.")
|