This commit is contained in:
michaela.buzalkova
2025-10-24 18:56:12 +02:00
parent 6d2b4e9858
commit eda5ec3d82
3 changed files with 311 additions and 142 deletions

162
50 Dekurz pro reporter.py Normal file
View File

@@ -0,0 +1,162 @@
#!/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"M:\Medicus\Data\Medicus.fdb"
EXPORT_DIR = Path(r"z:\Dropbox\Ordinace\Reporty")
# calculate last 2 months dynamically
DATE_FROM = (datetime.now() - timedelta(days=2)).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.10",
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}")

147
60 DXA pro reporter.py Normal file
View File

@@ -0,0 +1,147 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Report: DXA requisitions (Medicus → Dropbox)
--------------------------------------------
- Selects all histdoc records for year 2025 containing "DXA"
- Finds matching PDF files in Dropbox (by rod_cis + "dxa" in name)
- Outputs Excel report: datum, idpaci, rod_cis, prijmeni, jmeno, file
"""
import os
import firebirdsql as fb
import pandas as pd
from pathlib import Path
from datetime import datetime
# ================== CONFIGURATION ==================
FDB_PATH = r"M:\Medicus\Data\Medicus.fdb"
EXPORT_DIR = Path(r"z:\Dropbox\Ordinace\Reporty")
DOC_DIR = Path(r"z:\Dropbox\Ordinace\Dokumentace_zpracovaná")
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
xlsx_path = EXPORT_DIR / f"{timestamp} DXA report.xlsx"
# ================== DATABASE QUERY ==================
conn = fb.connect(
host="192.168.1.10",
port=3050,
database=FDB_PATH,
user="SYSDBA",
password="masterkey",
charset="WIN1250",
)
sql = """
SELECT
h.datum,
h.idpaci,
k.rodcis,
k.prijmeni,
k.jmeno,
(
SELECT LIST(
CAST(dd.datose AS DATE) || ':' || dd.kod, ', '
)
FROM dokladd dd
WHERE dd.rodcis = k.rodcis
AND EXTRACT(YEAR FROM dd.datose) = 2025
AND dd.kod STARTING WITH '1132'
) AS vykony_1132_2025
FROM histdoc h
JOIN kar k ON h.idpaci = k.idpac
WHERE EXTRACT(YEAR FROM h.datum) = 2025
AND h.data CONTAINING 'dxa'
ORDER BY h.datum DESC
"""
df = pd.read_sql(sql, conn)
conn.close()
# ================== REMOVE DUPLICATES AND SORT ==================
# Convert to datetime → drop duplicates → keep newest per patient → sort descending
df["DATUM"] = pd.to_datetime(df["DATUM"], errors="coerce")
# Drop duplicates, keep the newest by date
df = (
df.sort_values("DATUM", ascending=False)
.drop_duplicates(subset="RODCIS", keep="first")
.sort_values("DATUM", ascending=False)
.reset_index(drop=True)
)
# Convert to pure date (no time portion)
df["DATUM"] = df["DATUM"].dt.date
# ================== FIND MATCHING PDF FILES ==================
def find_dxa_file(rod_cis: str) -> str:
"""Return first matching DXA file for given rod_cis or ''."""
if not rod_cis:
return ""
rod_cis = rod_cis.strip()
# Case-insensitive search for files like "1234567890 [DXA] something.pdf"
for file in DOC_DIR.iterdir():
name = file.name.lower()
if (
file.suffix.lower() == ".pdf"
and name.startswith(rod_cis.lower())
and "[dxa]" in name
):
return file.name
return ""
df["FILE"] = df["RODCIS"].apply(find_dxa_file)
# ================== CLEAN OLD REPORTS ==================
for f in EXPORT_DIR.glob("* DXA report.xlsx"):
try:
f.unlink()
print(f"🗑️ Deleted old report: {f.name}")
except Exception as e:
print(f"⚠️ Could not delete {f.name}: {e}")
# ================== EXPORT TO EXCEL ==================
with pd.ExcelWriter(xlsx_path, engine="openpyxl") as writer:
df.to_excel(writer, index=False, sheet_name="DXA")
ws = writer.sheets["DXA"]
# Format header
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
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
# Auto column width, but hardcode FILE column to 120
from openpyxl.utils import get_column_letter
for col in ws.columns:
col_letter = get_column_letter(col[0].column)
header = ws.cell(row=1, column=col[0].column).value
if header == "FILE":
ws.column_dimensions[col_letter].width = 120
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)
# 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"✅ Report created: {xlsx_path}")
print(f"📂 Source folder scanned: {DOC_DIR}")
print(f"🩻 {df['FILE'].astype(bool).sum()} matching DXA PDFs found")

144
pomoc.py
View File

@@ -1,142 +1,2 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pathlib import Path
import time
import fdb
import pandas as pd
from openpyxl import load_workbook
from openpyxl.worksheet.table import Table, TableStyleInfo
from openpyxl.styles import Font, PatternFill, Alignment
from openpyxl.utils import get_column_letter
# ================== Výstupní cesta ==================
BASE_DIR = Path(r"..") # uprav dle potřeby
timestamp = time.strftime("%Y-%m-%d %H-%M-%S")
xlsx_name = f"Pacienti očkování {timestamp}.xlsx"
xlsx_path = BASE_DIR / xlsx_name
# ================== Připojení k DB ==================
con = fdb.connect(
host='192.168.1.4',
database=r'z:\\MEDICUS 3\\data\\medicus.FDB',
user='sysdba',
password='masterkey',
charset='WIN1250'
)
# ================== SQL dotaz ==================
# Pozn.: CAST(ockzaz.datum AS DATE) pro přesné párování na lecd.datose (DATE).
sql = """
SELECT
kar.rodcis AS "Rodné číslo",
kar.prijmeni AS "Příjmení",
kar.jmeno AS "Jméno",
ockzaz.datum AS "Datum očkování",
ockzaz.kodmz AS "Kód MZ",
ockzaz.poznamka AS "Šarže",
ockzaz.latka AS "Látka",
ockzaz.nazev AS "Název",
ockzaz.expire AS "Expirace",
/* --- VŠECHNY KÓDY Z TABULKY LECD PRO TOHO PACIENTA A TENTÝŽ DEN --- */
(
SELECT LIST(l.kod, ', ')
FROM lecd l
WHERE l.rodcis = kar.rodcis
AND l.datose = CAST(ockzaz.datum AS DATE)
) AS "LECD kódy (ten den)",
/* --- VŠECHNY KÓDY Z TABULKY vykonu dokladd PRO TOHO PACIENTA A TENTÝŽ DEN --- */
(
SELECT LIST(d.kod, ', ')
FROM dokladd d
WHERE d.rodcis = kar.rodcis
AND d.datose = CAST(ockzaz.datum AS DATE)
) AS "Vykony (ten den)"
FROM registr
JOIN kar ON registr.idpac = kar.idpac
JOIN ockzaz ON registr.idpac = ockzaz.idpac
WHERE
registr.datum_zruseni IS NULL
AND kar.vyrazen <> 'A'
AND kar.rodcis IS NOT NULL
AND idicp <> 0
and EXTRACT(YEAR FROM ockzaz.datum)=2025
ORDER BY ockzaz.datum DESC
"""
#and nazev containing 'chřipka'
# ================== Načtení do DataFrame ==================
df = pd.read_sql(sql, con)
con.close()
# Textové sloupce jako string
for col in ["Kód MZ", "Šarže", "Rodné číslo", "Látka", "Název", "Příjmení", "Jméno", "LECD kódy","Výkony"]:
if col in df.columns:
df[col] = df[col].astype("string")
# Převod dat na datetime
for dcol in ["Datum očkování", "Expirace"]:
if dcol in df.columns:
df[dcol] = pd.to_datetime(df[dcol], errors="coerce")
# ================== Uložení do Excelu ==================
with pd.ExcelWriter(xlsx_path, engine="openpyxl") as writer:
df.to_excel(writer, index=False, sheet_name="Očkování")
# ================== Formátování ==================
wb = load_workbook(xlsx_path)
def autosize_columns(ws):
for col_idx in range(1, ws.max_column + 1):
col_letter = get_column_letter(col_idx)
max_len = 0
for cell in ws[col_letter]:
val = "" if cell.value is None else str(cell.value)
if len(val) > max_len:
max_len = len(val)
ws.column_dimensions[col_letter].width = min(max(12, max_len + 2), 60)
def style_table(ws, table_name: str):
max_row = ws.max_row
max_col = ws.max_column
if max_col == 0:
return
# Hlavička vzhled
header_fill = PatternFill("solid", fgColor="D9E1F2")
for cell in ws[1]:
cell.font = Font(bold=True)
cell.fill = header_fill
cell.alignment = Alignment(vertical="center")
# Freeze top row
ws.freeze_panes = "A2"
# Tabulka jen pokud jsou data
if max_row < 2:
autosize_columns(ws)
return
ref = f"A1:{get_column_letter(max_col)}{max_row}"
tbl = Table(displayName=table_name, ref=ref)
tbl.tableStyleInfo = TableStyleInfo(
name="TableStyleMedium9", showRowStripes=True, showColumnStripes=False
)
ws.add_table(tbl)
autosize_columns(ws)
def format_dates(ws, columns_names):
header = [c.value for c in ws[1]]
date_cols = [header.index(name) + 1 for name in columns_names if name in header]
for col_idx in date_cols:
for row in ws.iter_rows(min_row=2, min_col=col_idx, max_col=col_idx, max_row=ws.max_row):
row[0].number_format = "DD.MM.YYYY"
ws_main = wb["Očkování"]
style_table(ws_main, "Ockovani")
format_dates(ws_main, ["Datum očkování", "Expirace"])
wb.save(xlsx_path)
print(f"Hotovo. Uloženo do: {xlsx_path.resolve()}")
import socket
print(socket.gethostname().strip())