227 lines
6.4 KiB
Python
227 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import pymysql
|
|
import openpyxl
|
|
from openpyxl.styles import PatternFill, Font
|
|
from openpyxl.utils import get_column_letter
|
|
|
|
from datetime import datetime
|
|
|
|
timestamp = datetime.now().strftime("%Y-%m-%d %H-%M-%S")
|
|
OUTPUT_PATH = fr"U:\Dropbox\!!!Days\Downloads Z230\{timestamp} medevio_patients_report.xlsx"
|
|
|
|
# ============================
|
|
# CONFIGURATION
|
|
# ============================
|
|
DB_CONFIG = {
|
|
"host": "192.168.1.76",
|
|
"port": 3307,
|
|
"user": "root",
|
|
"password": "Vlado9674+",
|
|
"database": "medevio",
|
|
"charset": "utf8mb4",
|
|
"cursorclass": pymysql.cursors.DictCursor,
|
|
}
|
|
|
|
# ============================
|
|
# FUNCTIONS
|
|
# ============================
|
|
|
|
from openpyxl.styles import Border, Side
|
|
|
|
thin_border = Border(
|
|
left=Side(style='thin'),
|
|
right=Side(style='thin'),
|
|
top=Side(style='thin'),
|
|
bottom=Side(style='thin')
|
|
)
|
|
|
|
def apply_thin_borders(ws):
|
|
"""Apply thin borders to all cells in the worksheet."""
|
|
for row in ws.iter_rows():
|
|
for cell in row:
|
|
cell.border = thin_border
|
|
|
|
def autofit_columns(ws):
|
|
"""Auto-adjust column widths based on longest cell content."""
|
|
for col in ws.columns:
|
|
max_length = 0
|
|
col_letter = get_column_letter(col[0].column)
|
|
for cell in col:
|
|
try:
|
|
if cell.value:
|
|
max_length = max(max_length, len(str(cell.value)))
|
|
except:
|
|
pass
|
|
ws.column_dimensions[col_letter].width = max_length + 2
|
|
|
|
def apply_header_style(ws):
|
|
"""Make header BRIGHT YELLOW and bold."""
|
|
fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")
|
|
font = Font(bold=True)
|
|
|
|
for cell in ws[1]:
|
|
cell.fill = fill
|
|
cell.font = font
|
|
|
|
def create_compact_row(row):
|
|
"""Produce compact record with merged pojistovna, with user_relationship after prijmeni."""
|
|
|
|
# insurance merged
|
|
code = row.get("pojistovna_code") or ""
|
|
naz = row.get("pojistovna_nazev") or ""
|
|
|
|
if code and naz:
|
|
poj = f"{code} ({naz})"
|
|
elif code:
|
|
poj = code
|
|
elif naz:
|
|
poj = naz
|
|
else:
|
|
poj = ""
|
|
|
|
return {
|
|
"id": row["id"],
|
|
"jmeno": row["jmeno"],
|
|
"prijmeni": row["prijmeni"],
|
|
|
|
# 🔹 inserted here
|
|
"user_relationship": row.get("user_relationship"),
|
|
|
|
"rodne_cislo": row["rodne_cislo"],
|
|
"dob": row["dob"],
|
|
"telefon": row["telefon"],
|
|
"email": row["email"],
|
|
"pojistovna": poj,
|
|
"status": row["status"],
|
|
"has_mobile_app": row["has_mobile_app"],
|
|
"registration_time": row["registration_time"],
|
|
"last_update": row["last_update"],
|
|
}
|
|
|
|
def create_pozadavky_rows(rows):
|
|
"""Convert raw pozadavky SQL rows into rows for the Excel sheet."""
|
|
output = []
|
|
for r in rows:
|
|
output.append({
|
|
# 🔹 First the ID
|
|
"id": r["id"],
|
|
|
|
# 🔹 Your 3 patient columns immediately after ID
|
|
"pacient_jmeno": r["pacient_jmeno"],
|
|
"pacient_prijmeni": r["pacient_prijmeni"],
|
|
"pacient_rodnecislo": r["pacient_rodnecislo"],
|
|
|
|
# 🔹 Then all other fields in any order you prefer
|
|
"displayTitle": r["displayTitle"],
|
|
"createdAt": r["createdAt"],
|
|
"updatedAt": r["updatedAt"],
|
|
"doneAt": r["doneAt"],
|
|
"removedAt": r["removedAt"],
|
|
"attachmentsProcessed": r["attachmentsProcessed"],
|
|
"messagesProcessed": r["messagesProcessed"],
|
|
"communicationprocessed": r["communicationprocessed"],
|
|
"questionnaireprocessed": r["questionnaireprocessed"],
|
|
"lastSync": r["lastSync"],
|
|
})
|
|
return output
|
|
|
|
|
|
# ============================
|
|
# MAIN
|
|
# ============================
|
|
|
|
def main():
|
|
print("📥 Connecting to MySQL...")
|
|
conn = pymysql.connect(**DB_CONFIG)
|
|
|
|
with conn:
|
|
with conn.cursor() as cur:
|
|
cur.execute("SELECT * FROM medevio_pacienti ORDER BY prijmeni, jmeno")
|
|
patients = cur.fetchall()
|
|
|
|
print(f"📊 Loaded {len(patients)} patients.")
|
|
|
|
# Load pozadavky
|
|
|
|
with conn.cursor() as cur:
|
|
cur.execute("SELECT * FROM pozadavky ORDER BY createdAt DESC")
|
|
pozadavky_rows = cur.fetchall()
|
|
|
|
print(f"📄 Loaded {len(pozadavky_rows)} pozadavky.")
|
|
|
|
wb = openpyxl.Workbook()
|
|
|
|
# ---------------------------------
|
|
# 1) FULL SHEET
|
|
# ---------------------------------
|
|
ws_full = wb.active
|
|
ws_full.title = "Patients FULL"
|
|
|
|
if patients:
|
|
headers = list(patients[0].keys())
|
|
ws_full.append(headers)
|
|
|
|
for row in patients:
|
|
ws_full.append([row.get(h) for h in headers])
|
|
|
|
apply_header_style(ws_full)
|
|
ws_full.freeze_panes = "A2"
|
|
ws_full.auto_filter.ref = ws_full.dimensions
|
|
autofit_columns(ws_full)
|
|
apply_thin_borders(ws_full)
|
|
|
|
# ---------------------------------
|
|
# 2) COMPACT SHEET
|
|
# ---------------------------------
|
|
ws_compact = wb.create_sheet("Patients COMPACT")
|
|
|
|
compact_rows = [create_compact_row(r) for r in patients]
|
|
compact_headers = list(compact_rows[0].keys())
|
|
|
|
ws_compact.append(compact_headers)
|
|
for row in compact_rows:
|
|
ws_compact.append([row.get(h) for h in compact_headers])
|
|
|
|
apply_header_style(ws_compact)
|
|
ws_compact.freeze_panes = "A2"
|
|
ws_compact.auto_filter.ref = ws_compact.dimensions
|
|
autofit_columns(ws_compact)
|
|
|
|
# >>> ADD THIS <<<
|
|
ur_col_index = compact_headers.index("user_relationship") + 1
|
|
col_letter = get_column_letter(ur_col_index)
|
|
ws_compact.column_dimensions[col_letter].width = 7.14
|
|
apply_thin_borders(ws_compact)
|
|
|
|
# ---------------------------------
|
|
# 3) POZADAVKY SHEET
|
|
# ---------------------------------
|
|
ws_p = wb.create_sheet("Pozadavky")
|
|
|
|
poz_list = create_pozadavky_rows(pozadavky_rows)
|
|
headers_p = list(poz_list[0].keys()) if poz_list else []
|
|
|
|
if headers_p:
|
|
ws_p.append(headers_p)
|
|
for row in poz_list:
|
|
ws_p.append([row.get(h) for h in headers_p])
|
|
|
|
apply_header_style(ws_p)
|
|
ws_p.freeze_panes = "A2"
|
|
ws_p.auto_filter.ref = ws_p.dimensions
|
|
autofit_columns(ws_p)
|
|
apply_thin_borders(ws_p)
|
|
|
|
|
|
# ---------------------------------
|
|
# SAVE
|
|
# ---------------------------------
|
|
|
|
wb.save(OUTPUT_PATH)
|
|
print(f"✅ Excel report saved to:\n{OUTPUT_PATH}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|