Export-Funktion
Dieser Commit ist enthalten in:
@@ -1,9 +1,12 @@
|
||||
import os
|
||||
import psycopg2
|
||||
from flask import Flask, render_template, request, redirect, session, url_for
|
||||
from flask import Flask, render_template, request, redirect, session, url_for, send_file
|
||||
from flask_session import Session
|
||||
from functools import wraps
|
||||
from dotenv import load_dotenv
|
||||
import pandas as pd
|
||||
from datetime import datetime
|
||||
import io
|
||||
|
||||
load_dotenv()
|
||||
|
||||
@@ -544,5 +547,166 @@ def end_session(session_id):
|
||||
|
||||
return redirect("/sessions")
|
||||
|
||||
@app.route("/export/licenses")
|
||||
@login_required
|
||||
def export_licenses():
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
|
||||
# Alle Lizenzen mit Kundeninformationen abrufen
|
||||
cur.execute("""
|
||||
SELECT l.id, l.license_key, c.name as customer_name, c.email as customer_email,
|
||||
l.license_type, l.valid_from, l.valid_until, l.is_active,
|
||||
CASE
|
||||
WHEN l.valid_until < CURRENT_DATE THEN 'Abgelaufen'
|
||||
WHEN l.valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'Läuft bald ab'
|
||||
ELSE 'Aktiv'
|
||||
END as status
|
||||
FROM licenses l
|
||||
JOIN customers c ON l.customer_id = c.id
|
||||
ORDER BY l.id
|
||||
""")
|
||||
|
||||
# Spaltennamen
|
||||
columns = ['ID', 'Lizenzschlüssel', 'Kunde', 'E-Mail', 'Typ',
|
||||
'Gültig von', 'Gültig bis', 'Aktiv', 'Status']
|
||||
|
||||
# Daten in DataFrame
|
||||
data = cur.fetchall()
|
||||
df = pd.DataFrame(data, columns=columns)
|
||||
|
||||
# Datumsformatierung
|
||||
df['Gültig von'] = pd.to_datetime(df['Gültig von']).dt.strftime('%d.%m.%Y')
|
||||
df['Gültig bis'] = pd.to_datetime(df['Gültig bis']).dt.strftime('%d.%m.%Y')
|
||||
|
||||
# Typ und Aktiv Status anpassen
|
||||
df['Typ'] = df['Typ'].replace({'full': 'Vollversion', 'test': 'Testversion'})
|
||||
df['Aktiv'] = df['Aktiv'].replace({True: 'Ja', False: 'Nein'})
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
# Export Format
|
||||
export_format = request.args.get('format', 'excel')
|
||||
filename = f'lizenzen_export_{datetime.now().strftime("%Y%m%d_%H%M%S")}'
|
||||
|
||||
if export_format == 'csv':
|
||||
# CSV Export
|
||||
output = io.StringIO()
|
||||
df.to_csv(output, index=False, encoding='utf-8-sig', sep=';')
|
||||
output.seek(0)
|
||||
|
||||
return send_file(
|
||||
io.BytesIO(output.getvalue().encode('utf-8-sig')),
|
||||
mimetype='text/csv',
|
||||
as_attachment=True,
|
||||
download_name=f'{filename}.csv'
|
||||
)
|
||||
else:
|
||||
# Excel Export
|
||||
output = io.BytesIO()
|
||||
with pd.ExcelWriter(output, engine='openpyxl') as writer:
|
||||
df.to_excel(writer, sheet_name='Lizenzen', index=False)
|
||||
|
||||
# Formatierung
|
||||
worksheet = writer.sheets['Lizenzen']
|
||||
for column in worksheet.columns:
|
||||
max_length = 0
|
||||
column_letter = column[0].column_letter
|
||||
for cell in column:
|
||||
try:
|
||||
if len(str(cell.value)) > max_length:
|
||||
max_length = len(str(cell.value))
|
||||
except:
|
||||
pass
|
||||
adjusted_width = min(max_length + 2, 50)
|
||||
worksheet.column_dimensions[column_letter].width = adjusted_width
|
||||
|
||||
output.seek(0)
|
||||
|
||||
return send_file(
|
||||
output,
|
||||
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
as_attachment=True,
|
||||
download_name=f'{filename}.xlsx'
|
||||
)
|
||||
|
||||
@app.route("/export/customers")
|
||||
@login_required
|
||||
def export_customers():
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
|
||||
# Alle Kunden mit Lizenzstatistiken
|
||||
cur.execute("""
|
||||
SELECT c.id, c.name, c.email, c.created_at,
|
||||
COUNT(l.id) as total_licenses,
|
||||
COUNT(CASE WHEN l.is_active = TRUE AND l.valid_until >= CURRENT_DATE THEN 1 END) as active_licenses,
|
||||
COUNT(CASE WHEN l.valid_until < CURRENT_DATE THEN 1 END) as expired_licenses
|
||||
FROM customers c
|
||||
LEFT JOIN licenses l ON c.id = l.customer_id
|
||||
GROUP BY c.id, c.name, c.email, c.created_at
|
||||
ORDER BY c.id
|
||||
""")
|
||||
|
||||
# Spaltennamen
|
||||
columns = ['ID', 'Name', 'E-Mail', 'Erstellt am',
|
||||
'Lizenzen gesamt', 'Aktive Lizenzen', 'Abgelaufene Lizenzen']
|
||||
|
||||
# Daten in DataFrame
|
||||
data = cur.fetchall()
|
||||
df = pd.DataFrame(data, columns=columns)
|
||||
|
||||
# Datumsformatierung
|
||||
df['Erstellt am'] = pd.to_datetime(df['Erstellt am']).dt.strftime('%d.%m.%Y %H:%M')
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
# Export Format
|
||||
export_format = request.args.get('format', 'excel')
|
||||
filename = f'kunden_export_{datetime.now().strftime("%Y%m%d_%H%M%S")}'
|
||||
|
||||
if export_format == 'csv':
|
||||
# CSV Export
|
||||
output = io.StringIO()
|
||||
df.to_csv(output, index=False, encoding='utf-8-sig', sep=';')
|
||||
output.seek(0)
|
||||
|
||||
return send_file(
|
||||
io.BytesIO(output.getvalue().encode('utf-8-sig')),
|
||||
mimetype='text/csv',
|
||||
as_attachment=True,
|
||||
download_name=f'{filename}.csv'
|
||||
)
|
||||
else:
|
||||
# Excel Export
|
||||
output = io.BytesIO()
|
||||
with pd.ExcelWriter(output, engine='openpyxl') as writer:
|
||||
df.to_excel(writer, sheet_name='Kunden', index=False)
|
||||
|
||||
# Formatierung
|
||||
worksheet = writer.sheets['Kunden']
|
||||
for column in worksheet.columns:
|
||||
max_length = 0
|
||||
column_letter = column[0].column_letter
|
||||
for cell in column:
|
||||
try:
|
||||
if len(str(cell.value)) > max_length:
|
||||
max_length = len(str(cell.value))
|
||||
except:
|
||||
pass
|
||||
adjusted_width = min(max_length + 2, 50)
|
||||
worksheet.column_dimensions[column_letter].width = adjusted_width
|
||||
|
||||
output.seek(0)
|
||||
|
||||
return send_file(
|
||||
output,
|
||||
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
as_attachment=True,
|
||||
download_name=f'{filename}.xlsx'
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=443, ssl_context='adhoc')
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren