z230
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+161
-13
@@ -39,7 +39,9 @@ EVEN_FILL = PatternFill("solid", fgColor="EBF3FB")
|
|||||||
ODD_FILL = PatternFill("solid", fgColor="FFFFFF")
|
ODD_FILL = PatternFill("solid", fgColor="FFFFFF")
|
||||||
NOTRCV_FILL = PatternFill("solid", fgColor="FCE4D6")
|
NOTRCV_FILL = PatternFill("solid", fgColor="FCE4D6")
|
||||||
CANCELLED_FILL = PatternFill("solid", fgColor="F2F2F2")
|
CANCELLED_FILL = PatternFill("solid", fgColor="F2F2F2")
|
||||||
OPEN_FILL = PatternFill("solid", fgColor="FFC7CE")
|
OPEN_FILL = PatternFill("solid", fgColor="FFC7CE")
|
||||||
|
OPEN_QUERY_FILL = PatternFill("solid", fgColor="FFD966")
|
||||||
|
HYPERLINK_FONT = Font(name="Arial", size=10, color="0563C1", underline="single")
|
||||||
|
|
||||||
CENTER = Alignment(horizontal="center", vertical="center")
|
CENTER = Alignment(horizontal="center", vertical="center")
|
||||||
LEFT = Alignment(horizontal="left", vertical="center")
|
LEFT = Alignment(horizontal="left", vertical="center")
|
||||||
@@ -84,6 +86,33 @@ def load_data():
|
|||||||
return pd.DataFrame(rows, columns=cols)
|
return pd.DataFrame(rows, columns=cols)
|
||||||
|
|
||||||
|
|
||||||
|
def load_equery_data():
|
||||||
|
conn = mysql.connector.connect(
|
||||||
|
host=db_config.DB_HOST, port=db_config.DB_PORT,
|
||||||
|
user=db_config.DB_USER, password=db_config.DB_PASSWORD,
|
||||||
|
database=db_config.DB_NAME,
|
||||||
|
)
|
||||||
|
sql = """
|
||||||
|
SELECT site_code, investigator_name, subject, visit,
|
||||||
|
accession, visit_collection_date, equery_id,
|
||||||
|
create_date, response_datetime, issue_type, status,
|
||||||
|
time_before_response, user_name, study_role
|
||||||
|
FROM covance_equeries
|
||||||
|
WHERE import_id = (
|
||||||
|
SELECT MAX(import_id) FROM iwrs_import
|
||||||
|
WHERE study = %s AND report_type = 'covance_equeries'
|
||||||
|
)
|
||||||
|
ORDER BY site_code ASC, create_date DESC
|
||||||
|
"""
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute(sql, (STUDY,))
|
||||||
|
cols = [d[0] for d in cursor.description]
|
||||||
|
rows = cursor.fetchall()
|
||||||
|
cursor.close()
|
||||||
|
conn.close()
|
||||||
|
return pd.DataFrame(rows, columns=cols)
|
||||||
|
|
||||||
|
|
||||||
def load_kit_data():
|
def load_kit_data():
|
||||||
conn = mysql.connector.connect(
|
conn = mysql.connector.connect(
|
||||||
host=db_config.DB_HOST, port=db_config.DB_PORT,
|
host=db_config.DB_HOST, port=db_config.DB_PORT,
|
||||||
@@ -137,7 +166,9 @@ def write_title(ws, text, ncols):
|
|||||||
|
|
||||||
# ── sheet 1: Přehled ─────────────────────────────────────────────────────────
|
# ── sheet 1: Přehled ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
def write_prehled(wb, df):
|
def write_prehled(wb, df, accession_eq_row=None):
|
||||||
|
if accession_eq_row is None:
|
||||||
|
accession_eq_row = {}
|
||||||
ws = wb.create_sheet("Přehled")
|
ws = wb.create_sheet("Přehled")
|
||||||
ws.sheet_view.showGridLines = False
|
ws.sheet_view.showGridLines = False
|
||||||
|
|
||||||
@@ -163,16 +194,24 @@ def write_prehled(wb, df):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for r_idx, row in agg.iterrows():
|
for r_idx, row in agg.iterrows():
|
||||||
excel_row = r_idx + 3
|
excel_row = r_idx + 3
|
||||||
has_missing = row["not_received"] > 0
|
has_missing = row["not_received"] > 0
|
||||||
fill = NOTRCV_FILL if has_missing else (EVEN_FILL if r_idx % 2 == 0 else ODD_FILL)
|
accession = row["accession"]
|
||||||
|
eq_row = accession_eq_row.get(accession) # None pokud nemá Open query
|
||||||
|
|
||||||
|
if eq_row:
|
||||||
|
fill = OPEN_QUERY_FILL
|
||||||
|
elif has_missing:
|
||||||
|
fill = NOTRCV_FILL
|
||||||
|
else:
|
||||||
|
fill = EVEN_FILL if r_idx % 2 == 0 else ODD_FILL
|
||||||
|
|
||||||
col_date = row["collection_date"]
|
col_date = row["collection_date"]
|
||||||
date_str = col_date.strftime("%d-%b-%Y") if hasattr(col_date, "strftime") else str(col_date)
|
date_str = col_date.strftime("%d-%b-%Y") if hasattr(col_date, "strftime") else str(col_date)
|
||||||
|
|
||||||
values = [
|
values = [
|
||||||
row["investigator_no"], row["investigator_name"], row["patient_no"],
|
row["investigator_no"], row["investigator_name"], row["patient_no"],
|
||||||
row["protocol_visit_code"], row["accession"], date_str,
|
row["protocol_visit_code"], accession, date_str,
|
||||||
int(row["celkem"]), int(row["received"]), int(row["not_received"]),
|
int(row["celkem"]), int(row["received"]), int(row["not_received"]),
|
||||||
]
|
]
|
||||||
for c_idx, val in enumerate(values, 1):
|
for c_idx, val in enumerate(values, 1):
|
||||||
@@ -180,7 +219,11 @@ def write_prehled(wb, df):
|
|||||||
cell.fill = fill
|
cell.fill = fill
|
||||||
cell.border = BORDER
|
cell.border = BORDER
|
||||||
cell.alignment = CENTER if c_idx in (1, 4, 5, 6, 7, 8, 9) else LEFT
|
cell.alignment = CENTER if c_idx in (1, 4, 5, 6, 7, 8, 9) else LEFT
|
||||||
if c_idx == 9 and has_missing:
|
|
||||||
|
if c_idx == 5 and eq_row:
|
||||||
|
cell.hyperlink = f"#'eQueries'!A{eq_row}"
|
||||||
|
cell.font = HYPERLINK_FONT
|
||||||
|
elif c_idx == 9 and has_missing:
|
||||||
cell.font = RED_FONT
|
cell.font = RED_FONT
|
||||||
else:
|
else:
|
||||||
cell.font = NORMAL_FONT
|
cell.font = NORMAL_FONT
|
||||||
@@ -359,9 +402,66 @@ def write_kity(wb, df_kits):
|
|||||||
ws.freeze_panes = "A3"
|
ws.freeze_panes = "A3"
|
||||||
|
|
||||||
|
|
||||||
# ── sheet 4: ZDROJ (samples) ─────────────────────────────────────────────────
|
# ── sheet 4: eQueries ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
# ── sheet 5: ZDROJ Kity ──────────────────────────────────────────────────────
|
def write_equeries(wb, df_eq):
|
||||||
|
ws = wb.create_sheet("eQueries")
|
||||||
|
ws.sheet_view.showGridLines = False
|
||||||
|
|
||||||
|
today = datetime.date.today().strftime("%d-%b-%Y")
|
||||||
|
write_title(ws, f"eQueries — {STUDY} ({today})", 14)
|
||||||
|
|
||||||
|
headers = ["Site", "Investigátor", "Pacient", "Visit", "Accession",
|
||||||
|
"Visit Datum", "eQuery ID", "Vytvořeno", "Odpovězeno",
|
||||||
|
"Issue Type", "Status", "Čas odpovědi", "Uživatel", "Role"]
|
||||||
|
widths = [9, 22, 14, 26, 13, 13, 10, 16, 16, 20, 9, 13, 22, 13]
|
||||||
|
write_headers(ws, headers, widths)
|
||||||
|
|
||||||
|
def fmt_dt(val, fmt="%d-%b-%Y %H:%M"):
|
||||||
|
if val is None or (isinstance(val, float) and val != val):
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
if pd.isna(val):
|
||||||
|
return None
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
pass
|
||||||
|
if hasattr(val, "strftime"):
|
||||||
|
return val.strftime(fmt)
|
||||||
|
return str(val)
|
||||||
|
|
||||||
|
for r_idx, row in df_eq.iterrows():
|
||||||
|
excel_row = r_idx + 3
|
||||||
|
is_open = str(row.get("status", "")).strip().lower() == "open"
|
||||||
|
fill = OPEN_FILL if is_open else (EVEN_FILL if r_idx % 2 == 0 else ODD_FILL)
|
||||||
|
font = Font(name="Arial", bold=True, size=10, color="9C0006") if is_open else NORMAL_FONT
|
||||||
|
|
||||||
|
values = [
|
||||||
|
row["site_code"], row["investigator_name"], row["subject"],
|
||||||
|
row["visit"], row["accession"],
|
||||||
|
fmt_dt(row["visit_collection_date"], "%d-%b-%Y"),
|
||||||
|
row["equery_id"],
|
||||||
|
fmt_dt(row["create_date"]),
|
||||||
|
fmt_dt(row["response_datetime"]),
|
||||||
|
row["issue_type"], row["status"],
|
||||||
|
row["time_before_response"], row["user_name"], row["study_role"],
|
||||||
|
]
|
||||||
|
for c_idx, val in enumerate(values, 1):
|
||||||
|
if isinstance(val, float) and val != val:
|
||||||
|
val = None
|
||||||
|
cell = ws.cell(row=excel_row, column=c_idx, value=val)
|
||||||
|
cell.fill = fill
|
||||||
|
cell.border = BORDER
|
||||||
|
cell.font = font
|
||||||
|
cell.alignment = CENTER if c_idx in (1, 6, 7, 8, 9, 11, 12) else LEFT
|
||||||
|
ws.row_dimensions[excel_row].height = 16
|
||||||
|
|
||||||
|
ws.freeze_panes = "A3"
|
||||||
|
ws.auto_filter.ref = f"A2:N{len(df_eq) + 2}"
|
||||||
|
|
||||||
|
|
||||||
|
# ── sheet 5: ZDROJ Vzorky ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
# ── sheet 6: ZDROJ Kity ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
def write_zdroj_kity(wb, df_kits):
|
def write_zdroj_kity(wb, df_kits):
|
||||||
ws = wb.create_sheet("ZDROJ Kity")
|
ws = wb.create_sheet("ZDROJ Kity")
|
||||||
@@ -427,6 +527,41 @@ def write_zdroj(wb, df):
|
|||||||
ws.auto_filter.ref = f"A1:{get_column_letter(len(headers))}1"
|
ws.auto_filter.ref = f"A1:{get_column_letter(len(headers))}1"
|
||||||
|
|
||||||
|
|
||||||
|
def write_zdroj_equeries(wb, df_eq):
|
||||||
|
ws = wb.create_sheet("ZDROJ eQuery")
|
||||||
|
ws.sheet_view.showGridLines = True
|
||||||
|
|
||||||
|
headers = list(df_eq.columns)
|
||||||
|
for c, h in enumerate(headers, 1):
|
||||||
|
cell = ws.cell(row=1, column=c, value=h)
|
||||||
|
cell.font = Font(name="Arial", bold=True, size=9, color="FFFFFF")
|
||||||
|
cell.fill = PatternFill("solid", fgColor="404040")
|
||||||
|
cell.alignment = LEFT
|
||||||
|
cell.border = BORDER
|
||||||
|
ws.column_dimensions[get_column_letter(c)].width = 20
|
||||||
|
|
||||||
|
for r_idx, (_, row) in enumerate(df_eq.iterrows(), 2):
|
||||||
|
fill = EVEN_FILL if r_idx % 2 == 0 else ODD_FILL
|
||||||
|
for c_idx, col in enumerate(headers, 1):
|
||||||
|
val = row[col]
|
||||||
|
try:
|
||||||
|
is_na = pd.isna(val)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
is_na = False
|
||||||
|
if is_na or val is None:
|
||||||
|
val = ""
|
||||||
|
elif hasattr(val, "strftime"):
|
||||||
|
val = val.strftime("%Y-%m-%d %H:%M")
|
||||||
|
cell = ws.cell(row=r_idx, column=c_idx, value=val)
|
||||||
|
cell.font = Font(name="Arial", size=9)
|
||||||
|
cell.fill = fill
|
||||||
|
cell.border = BORDER
|
||||||
|
cell.alignment = LEFT
|
||||||
|
|
||||||
|
ws.freeze_panes = "A2"
|
||||||
|
ws.auto_filter.ref = f"A1:{get_column_letter(len(headers))}1"
|
||||||
|
|
||||||
|
|
||||||
# ── main ─────────────────────────────────────────────────────────────────────
|
# ── main ─────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -435,20 +570,33 @@ def main():
|
|||||||
print("Načítám data z MySQL...")
|
print("Načítám data z MySQL...")
|
||||||
df = load_data()
|
df = load_data()
|
||||||
df_kits = load_kit_data()
|
df_kits = load_kit_data()
|
||||||
print(f" Vzorky: {len(df)} řádků, {df['patient_no'].nunique()} pacientů")
|
df_eq = load_equery_data()
|
||||||
print(f" Kity: {len(df_kits)} kitů, {df_kits['site_code'].nunique()} center")
|
print(f" Vzorky: {len(df)} řádků, {df['patient_no'].nunique()} pacientů")
|
||||||
|
print(f" Kity: {len(df_kits)} kitů, {df_kits['site_code'].nunique()} center")
|
||||||
|
print(f" eQueries: {len(df_eq)} záznamů ({(df_eq['status']=='Open').sum()} Open)")
|
||||||
|
|
||||||
|
# mapping accession → řádek v listu eQueries (jen Open queries, první výskyt)
|
||||||
|
open_accs = set(df_eq[df_eq["status"] == "Open"]["accession"].dropna())
|
||||||
|
accession_eq_row = {}
|
||||||
|
for r_idx, row in df_eq.iterrows():
|
||||||
|
acc = row.get("accession")
|
||||||
|
if acc and acc in open_accs and acc not in accession_eq_row:
|
||||||
|
accession_eq_row[acc] = r_idx + 3 # řádek 1=title, 2=header, data od 3
|
||||||
|
|
||||||
wb = Workbook()
|
wb = Workbook()
|
||||||
wb.remove(wb.active)
|
wb.remove(wb.active)
|
||||||
|
|
||||||
write_prehled(wb, df)
|
write_prehled(wb, df, accession_eq_row)
|
||||||
write_chybejici(wb, df)
|
write_chybejici(wb, df)
|
||||||
write_kity(wb, df_kits)
|
write_kity(wb, df_kits)
|
||||||
|
write_equeries(wb, df_eq)
|
||||||
write_zdroj(wb, df)
|
write_zdroj(wb, df)
|
||||||
write_zdroj_kity(wb, df_kits)
|
write_zdroj_kity(wb, df_kits)
|
||||||
|
write_zdroj_equeries(wb, df_eq)
|
||||||
|
|
||||||
today = datetime.date.today().strftime("%Y-%m-%d")
|
now = datetime.datetime.now()
|
||||||
out_path = unique_path(f"{today} {STUDY} Covance Samples")
|
stamp = now.strftime("%Y-%m-%d %H%M%S")
|
||||||
|
out_path = unique_path(f"{stamp} {STUDY} Covance")
|
||||||
wb.save(out_path)
|
wb.save(out_path)
|
||||||
print(f"Uloženo: {out_path}")
|
print(f"Uloženo: {out_path}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user