Files
reporty/50 Dekurs.py
2025-10-22 16:45:33 +02:00

163 lines
5.6 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Export DEKURS records from Medicus Firebird DB into Excel.
- Includes only last 2 months from current date
- RTF text decoded and cleaned (Excel-safe, preserved newlines)
- Výkony of the same day concatenated into 'VYKONY DNE'
- Příjmení + Jméno merged into 'PACIENT'
- Proper column order and naming
- Bright yellow header, thin black borders, auto column widths
- Timestamped Excel filename
"""
import re
import pandas as pd
import firebirdsql as fb
from datetime import datetime, timedelta
from pathlib import Path
from striprtf.striprtf import rtf_to_text
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from openpyxl.utils import get_column_letter
# ================== CONFIGURATION ==================
FDB_PATH = r"z:\Medicus 3\data\MEDICUS.FDB"
EXPORT_DIR = Path(r"u:\Dropbox\!!!Days\Downloads Z230")
# calculate last 2 months dynamically
DATE_FROM = (datetime.now() - timedelta(days=10)).strftime("%Y-%m-%d")
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
xlsx_path = EXPORT_DIR / f"{timestamp}_Dekurz (poslední rok).xlsx"
# ================== FIREBIRD CONNECTION ==================
conn = fb.connect(
host="192.168.1.4",
port=3050,
database=FDB_PATH,
user="SYSDBA",
password="masterkey",
charset="WIN1250",
)
def query_df(sql, params=None):
cur = conn.cursor()
cur.execute(sql, params or ())
rows = cur.fetchall()
cols = [d[0].strip() for d in cur.description]
return pd.DataFrame(rows, columns=cols)
# ================== QUERY ==================
sql = f"""
SELECT
d.id,
k.prijmeni,
k.jmeno,
k.rodcis,
u.zkratka,
d.datum,
d.dekurs,
(
SELECT LIST(dd.kod, ', ')
FROM dokladd dd
WHERE dd.rodcis = k.rodcis
AND CAST(dd.datose AS DATE) = CAST(d.datum AS DATE)
) AS vykony_dne
FROM dekurs d
JOIN kar k ON d.idpac = k.idpac
JOIN uzivatel u ON d.iduzi = u.iduzi
WHERE d.datum >= DATE '{DATE_FROM}'
ORDER BY d.datum DESC
"""
df = query_df(sql)
conn.close()
# ================== DATA CLEANING ==================
def safe_rtf_to_text(x):
if isinstance(x, str) and x.strip():
try:
return rtf_to_text(x)
except Exception:
return x
return ""
df["DEKURS"] = df["DEKURS"].apply(safe_rtf_to_text)
df.replace({r'(\r\n|\r|\n)': r'\r\n'}, regex=True, inplace=True)
df.replace({r'[\ud800-\udfff\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]+': ''},
regex=True, inplace=True)
df.replace({r'(\r\n){2,}': r'\r\n', r'(\r\n)+$': ''},
regex=True, inplace=True)
df["PACIENT"] = df["PRIJMENI"].fillna("") + ", " + df["JMENO"].fillna("")
df.drop(columns=["PRIJMENI", "JMENO"], inplace=True)
df.rename(columns={"ZKRATKA": "LEKAR", "VYKONY_DNE": "VYKONY DNE"}, inplace=True)
df["DATUM"] = pd.to_datetime(df["DATUM"], errors="coerce").dt.date
df.drop(columns=[c for c in df.columns if "ASCII" in c.upper()], inplace=True, errors="ignore")
desired_order = ["DATUM", "RODCIS", "PACIENT", "LEKAR", "VYKONY DNE", "DEKURS"]
df = df[[c for c in desired_order if c in df.columns]]
# ================== CLEANUP OLD FILES ==================
for old_file in EXPORT_DIR.glob("*Dekurz (poslední rok)*.xlsx"):
try:
old_file.unlink()
print(f"🧹 Deleted old file: {old_file.name}")
except Exception as e:
print(f"⚠️ Could not delete {old_file.name}: {e}")
# ================== EXPORT TO EXCEL ==================
with pd.ExcelWriter(xlsx_path, engine="openpyxl") as writer:
df.to_excel(writer, index=False, sheet_name="Dekurz")
ws = writer.sheets["Dekurz"]
# ----- Bright yellow header -----
header_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")
for cell in ws[1]:
cell.font = Font(bold=True, color="000000")
cell.alignment = Alignment(horizontal="center", vertical="center")
cell.fill = header_fill
# ----- Format Datum column -----
for cell in ws["A"][1:]:
if hasattr(cell.value, "date"):
cell.value = cell.value.date()
cell.number_format = "DD.MM.YYYY"
# ----- Vertical centering for key columns -----
vertically_centered = {"DATUM", "RODCIS", "PACIENT", "LEKAR", "VYKONY DNE"}
for row in ws.iter_rows(min_row=2, max_row=ws.max_row):
for cell in row:
header = ws.cell(row=1, column=cell.column).value
if header in vertically_centered:
align = cell.alignment
cell.alignment = Alignment(
horizontal=align.horizontal or "left",
vertical="center",
wrap_text=align.wrap_text
)
elif isinstance(cell.value, str) and "\n" in cell.value:
cell.alignment = Alignment(wrap_text=True, vertical="top")
# ----- Column widths -----
for col in ws.columns:
header = col[0].value
col_letter = get_column_letter(col[0].column)
if header and "DEKURS" in str(header).upper():
ws.column_dimensions[col_letter].width = 110
else:
max_len = max(len(str(cell.value)) if cell.value else 0 for cell in col)
ws.column_dimensions[col_letter].width = min(max_len + 2, 80)
# ----- Thin black borders -----
thin = Side(border_style="thin", color="000000")
border = Border(top=thin, left=thin, right=thin, bottom=thin)
for row in ws.iter_rows(min_row=1, max_row=ws.max_row,
min_col=1, max_col=ws.max_column):
for cell in row:
cell.border = border
print(f"✅ Export hotov: {xlsx_path}")
print(f"📅 Dotaz zahrnuje data od: {DATE_FROM}")