reporter
This commit is contained in:
268
#10 Download reports/30 Report ordinace.py
Normal file
268
#10 Download reports/30 Report ordinace.py
Normal file
@@ -0,0 +1,268 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import io
|
||||
|
||||
# UTF-8 console for Scheduled Tasks
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
|
||||
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
|
||||
|
||||
import mysql.connector
|
||||
from mysql.connector import Error
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
|
||||
from datetime import datetime, date as dt_date
|
||||
from decimal import Decimal
|
||||
from pathlib import Path
|
||||
# ==============================
|
||||
# DELETE OLD REPORTS (OPTION C)
|
||||
# ==============================
|
||||
|
||||
def delete_all_old_reports(directory: Path):
|
||||
"""Deletes all previously generated ordinace expense reports."""
|
||||
pattern = "*fio ordinace transactions.xlsx"
|
||||
deleted = 0
|
||||
|
||||
for f in directory.glob(pattern):
|
||||
try:
|
||||
f.unlink()
|
||||
deleted += 1
|
||||
print(f"🗑 Deleted old report: {f.name}")
|
||||
except Exception as e:
|
||||
print(f"❌ Could not delete {f.name}: {e}")
|
||||
|
||||
if deleted == 0:
|
||||
print("ℹ No old reports to delete.")
|
||||
else:
|
||||
print(f"✓ Deleted {deleted} old reports.")
|
||||
|
||||
|
||||
# ======================================================
|
||||
# CONFIG
|
||||
# ======================================================
|
||||
|
||||
DB = {
|
||||
"host": "192.168.1.76",
|
||||
"port": 3307,
|
||||
"user": "root",
|
||||
"password": "Vlado9674+",
|
||||
"database": "fio",
|
||||
}
|
||||
|
||||
ORDINACE_ACCOUNT = "2800046620"
|
||||
|
||||
REPORTOVAT = {
|
||||
"VZP": "1114007221",
|
||||
"VOZP": "2010009091",
|
||||
"ČPZP": "2054108761",
|
||||
"OZP": "2070101041",
|
||||
"ZPŠ": "2090309181",
|
||||
"ZPMV": "2112108031",
|
||||
}
|
||||
|
||||
OUTPUT_DIR = Path(r"z:\Dropbox\Ordinace\Reporty")
|
||||
|
||||
TEXT_COLUMNS = [
|
||||
"cislo_uctu", "protiucet", "kod_banky",
|
||||
"vs", "ks", "ss",
|
||||
"id_operace", "id_pokynu"
|
||||
]
|
||||
|
||||
|
||||
# ======================================================
|
||||
# FORMAT APPLYING (copied from main report)
|
||||
# ======================================================
|
||||
|
||||
def format_sheet(ws, rows, headers):
|
||||
|
||||
# ---------------------- HEADER -----------------------
|
||||
for col_idx in range(1, len(headers) + 1):
|
||||
cell = ws.cell(row=1, column=col_idx)
|
||||
cell.font = Font(bold=True)
|
||||
cell.fill = PatternFill(start_color="FFFF00", fill_type="solid")
|
||||
|
||||
# ---------------------- DATA ROWS --------------------
|
||||
for row in rows:
|
||||
excel_row = []
|
||||
for h in headers:
|
||||
val = row[h]
|
||||
|
||||
# Convert MySQL data types
|
||||
if isinstance(val, Decimal):
|
||||
val = float(val)
|
||||
elif isinstance(val, dt_date):
|
||||
val = val.strftime("%Y-%m-%d")
|
||||
|
||||
# For certain columns, force ="text"
|
||||
if h in TEXT_COLUMNS and val is not None:
|
||||
excel_row.append(f'="{val}"')
|
||||
else:
|
||||
excel_row.append(val)
|
||||
|
||||
ws.append(excel_row)
|
||||
|
||||
# ---------------------- COLORING ---------------------
|
||||
fill_red = PatternFill(start_color="FFFFDDDD", fill_type="solid")
|
||||
fill_green = PatternFill(start_color="FFEEFFEE", fill_type="solid")
|
||||
|
||||
try:
|
||||
amount_col = headers.index("amount") + 1
|
||||
except ValueError:
|
||||
amount_col = -1
|
||||
|
||||
if amount_col != -1:
|
||||
for r in range(2, len(rows) + 2):
|
||||
cell = ws.cell(row=r, column=amount_col)
|
||||
try:
|
||||
value = float(str(cell.value).strip('="'))
|
||||
except:
|
||||
value = 0
|
||||
|
||||
fill = fill_red if value < 0 else fill_green
|
||||
for c in range(1, len(headers) + 1):
|
||||
ws.cell(row=r, column=c).fill = fill
|
||||
|
||||
# ---------------------- COLUMN WIDTHS -----------------
|
||||
fixed_widths = [
|
||||
13, 14, 11, 14, 8, 14, 11, 30, 30, 25,
|
||||
13, 13, 13, 35, 30, 15, 13, 30, 20, 13,
|
||||
30, 20
|
||||
]
|
||||
if len(fixed_widths) < len(headers):
|
||||
fixed_widths.extend([15] * (len(headers) - len(fixed_widths)))
|
||||
|
||||
for i, width in enumerate(fixed_widths, start=1):
|
||||
letter = chr(64 + i)
|
||||
ws.column_dimensions[letter].width = width
|
||||
|
||||
# ---------------------- BORDERS & ALIGNMENT ----------
|
||||
thin = Side(border_style="thin", color="000000")
|
||||
border = Border(left=thin, right=thin, top=thin, bottom=thin)
|
||||
align_center = Alignment(horizontal="center")
|
||||
|
||||
center_cols = ["id_operace", "transaction_date", "currency", "kod_banky", "vs", "ks", "ss"]
|
||||
center_indices = [headers.index(c) + 1 for c in center_cols if c in headers]
|
||||
|
||||
total_rows = len(rows) + 1
|
||||
total_cols = len(headers)
|
||||
|
||||
for r in range(1, total_rows + 1):
|
||||
for c in range(1, total_cols + 1):
|
||||
cell = ws.cell(row=r, column=c)
|
||||
cell.border = border
|
||||
if c in center_indices:
|
||||
cell.alignment = align_center
|
||||
|
||||
ws.freeze_panes = "A2"
|
||||
ws.auto_filter.ref = ws.dimensions
|
||||
|
||||
|
||||
# ======================================================
|
||||
# EXPORT
|
||||
# ======================================================
|
||||
|
||||
def export_ordinace():
|
||||
print("Connecting MySQL...")
|
||||
conn = mysql.connector.connect(**DB)
|
||||
cur = conn.cursor(dictionary=True)
|
||||
|
||||
# ============================
|
||||
# Load ALL transactions for ordinace
|
||||
# ============================
|
||||
sql_all = f"""
|
||||
SELECT *
|
||||
FROM transactions
|
||||
WHERE cislo_uctu = '{ORDINACE_ACCOUNT}'
|
||||
ORDER BY transaction_date DESC;
|
||||
"""
|
||||
cur.execute(sql_all)
|
||||
all_rows = cur.fetchall()
|
||||
|
||||
if not all_rows:
|
||||
print("❌ No transactions found for ordinace account.")
|
||||
return
|
||||
|
||||
headers = list(all_rows[0].keys())
|
||||
|
||||
# Workbook
|
||||
wb = Workbook()
|
||||
wb.remove(wb.active)
|
||||
|
||||
# --------------------- ALL sheet ---------------------
|
||||
ws_all = wb.create_sheet("ALL ordinace")
|
||||
ws_all.append(headers)
|
||||
format_sheet(ws_all, all_rows, headers)
|
||||
|
||||
print(f"➡ ALL ordinace rows: {len(all_rows)}")
|
||||
|
||||
# --------------------- INSURANCE sheets ---------------
|
||||
summary = []
|
||||
|
||||
for name, acc in REPORTOVAT.items():
|
||||
print(f"➡ Pojišťovna {name} ({acc})")
|
||||
|
||||
sql = f"""
|
||||
SELECT *
|
||||
FROM transactions
|
||||
WHERE cislo_uctu = '{ORDINACE_ACCOUNT}'
|
||||
AND (
|
||||
protiucet <> '2070101041'
|
||||
OR (protiucet = '2070101041' AND amount > 0)
|
||||
)
|
||||
AND protiucet = '{acc}'
|
||||
ORDER BY transaction_date DESC;
|
||||
"""
|
||||
|
||||
cur.execute(sql)
|
||||
rows = cur.fetchall()
|
||||
|
||||
count = len(rows)
|
||||
summa = sum(float(r["amount"]) for r in rows) if rows else 0
|
||||
|
||||
summary.append({
|
||||
"Pojišťovna": name,
|
||||
"Účet": acc,
|
||||
"Počet transakcí": count,
|
||||
"Součet": summa
|
||||
})
|
||||
|
||||
if not rows:
|
||||
print(f" ⚠ No rows")
|
||||
continue
|
||||
|
||||
ws = wb.create_sheet(name)
|
||||
ws.append(headers)
|
||||
format_sheet(ws, rows, headers)
|
||||
|
||||
print(f" ✓ {count} rows, sum {summa:.2f} Kč")
|
||||
|
||||
# --------------------- SUMMARY sheet -----------------
|
||||
ws_s = wb.create_sheet("Přehled")
|
||||
ws_s.append(["Pojišťovna", "Účet", "Počet transakcí", "Součet Kč"])
|
||||
|
||||
for row in summary:
|
||||
ws_s.append([
|
||||
row["Pojišťovna"],
|
||||
row["Účet"],
|
||||
row["Počet transakcí"],
|
||||
f"{row['Součet']:.2f}"
|
||||
])
|
||||
|
||||
# ===========================
|
||||
# Save Excel
|
||||
# ===========================
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d %H-%M-%S")
|
||||
out_file = OUTPUT_DIR / f"{timestamp} FIO ordinace transactions.xlsx"
|
||||
|
||||
wb.save(out_file)
|
||||
print(f"\n✅ Export hotový:\n{out_file}")
|
||||
|
||||
|
||||
# ======================================================
|
||||
# MAIN
|
||||
# ======================================================
|
||||
|
||||
if __name__ == "__main__":
|
||||
delete_all_old_reports(OUTPUT_DIR)
|
||||
export_ordinace()
|
||||
Reference in New Issue
Block a user