Initial commit
Dieser Commit ist enthalten in:
203
v2_adminpanel/utils/export.py
Normale Datei
203
v2_adminpanel/utils/export.py
Normale Datei
@ -0,0 +1,203 @@
|
||||
import pandas as pd
|
||||
from io import BytesIO, StringIO
|
||||
from datetime import datetime
|
||||
from zoneinfo import ZoneInfo
|
||||
from openpyxl.utils import get_column_letter
|
||||
from flask import send_file
|
||||
import csv
|
||||
|
||||
|
||||
def create_excel_export(data, columns, filename_prefix="export"):
|
||||
"""Create an Excel file from data"""
|
||||
df = pd.DataFrame(data, columns=columns)
|
||||
|
||||
# Create Excel file in memory
|
||||
output = BytesIO()
|
||||
with pd.ExcelWriter(output, engine='openpyxl') as writer:
|
||||
df.to_excel(writer, index=False, sheet_name='Data')
|
||||
|
||||
# Auto-adjust column widths
|
||||
worksheet = writer.sheets['Data']
|
||||
for idx, col in enumerate(df.columns):
|
||||
max_length = max(df[col].astype(str).map(len).max(), len(col)) + 2
|
||||
worksheet.column_dimensions[get_column_letter(idx + 1)].width = min(max_length, 50)
|
||||
|
||||
output.seek(0)
|
||||
|
||||
# Generate filename with timestamp
|
||||
timestamp = datetime.now(ZoneInfo("Europe/Berlin")).strftime('%Y%m%d_%H%M%S')
|
||||
filename = f"{filename_prefix}_{timestamp}.xlsx"
|
||||
|
||||
return send_file(
|
||||
output,
|
||||
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
as_attachment=True,
|
||||
download_name=filename
|
||||
)
|
||||
|
||||
|
||||
def create_csv_export(data, columns, filename_prefix="export"):
|
||||
"""Create a CSV file from data"""
|
||||
# Create CSV in memory
|
||||
output = StringIO()
|
||||
writer = csv.writer(output)
|
||||
|
||||
# Write header
|
||||
writer.writerow(columns)
|
||||
|
||||
# Write data
|
||||
writer.writerows(data)
|
||||
|
||||
# Convert to bytes
|
||||
output.seek(0)
|
||||
output_bytes = BytesIO(output.getvalue().encode('utf-8-sig')) # UTF-8 with BOM for Excel compatibility
|
||||
|
||||
# Generate filename with timestamp
|
||||
timestamp = datetime.now(ZoneInfo("Europe/Berlin")).strftime('%Y%m%d_%H%M%S')
|
||||
filename = f"{filename_prefix}_{timestamp}.csv"
|
||||
|
||||
return send_file(
|
||||
output_bytes,
|
||||
mimetype='text/csv',
|
||||
as_attachment=True,
|
||||
download_name=filename
|
||||
)
|
||||
|
||||
|
||||
def format_datetime_for_export(dt):
|
||||
"""Format datetime for export"""
|
||||
if dt:
|
||||
if isinstance(dt, str):
|
||||
try:
|
||||
dt = datetime.fromisoformat(dt)
|
||||
except:
|
||||
return dt
|
||||
# Remove timezone info for Excel compatibility
|
||||
if hasattr(dt, 'replace') and dt.tzinfo is not None:
|
||||
dt = dt.replace(tzinfo=None)
|
||||
return dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
return ''
|
||||
|
||||
|
||||
def prepare_license_export_data(licenses):
|
||||
"""Prepare license data for export"""
|
||||
export_data = []
|
||||
for license in licenses:
|
||||
export_data.append([
|
||||
license[0], # ID
|
||||
license[1], # Key
|
||||
license[2], # Customer Name
|
||||
license[3], # Email
|
||||
'Aktiv' if license[4] else 'Inaktiv', # Active
|
||||
license[5], # Max Users
|
||||
format_datetime_for_export(license[6]), # Valid From
|
||||
format_datetime_for_export(license[7]), # Valid Until
|
||||
format_datetime_for_export(license[8]), # Created At
|
||||
license[9], # Device Limit
|
||||
license[10] or 0, # Current Devices
|
||||
'Fake' if license[11] else 'Full' # Is Test License
|
||||
])
|
||||
return export_data
|
||||
|
||||
|
||||
def prepare_customer_export_data(customers):
|
||||
"""Prepare customer data for export"""
|
||||
export_data = []
|
||||
for customer in customers:
|
||||
export_data.append([
|
||||
customer[0], # ID
|
||||
customer[1], # Name
|
||||
customer[2], # Email
|
||||
customer[3], # Company
|
||||
customer[4], # Address
|
||||
customer[5], # Phone
|
||||
format_datetime_for_export(customer[6]), # Created At
|
||||
customer[7] or 0, # License Count
|
||||
customer[8] or 0 # Active License Count
|
||||
])
|
||||
return export_data
|
||||
|
||||
|
||||
def prepare_session_export_data(sessions):
|
||||
"""Prepare session data for export"""
|
||||
export_data = []
|
||||
for session in sessions:
|
||||
export_data.append([
|
||||
session[0], # ID
|
||||
session[1], # License Key
|
||||
session[2], # Username
|
||||
session[3], # Computer Name
|
||||
session[4], # Hardware ID
|
||||
format_datetime_for_export(session[5]), # Login Time
|
||||
format_datetime_for_export(session[6]), # Last Activity
|
||||
'Aktiv' if session[7] else 'Beendet', # Active
|
||||
session[8], # IP Address
|
||||
session[9], # App Version
|
||||
session[10], # Customer Name
|
||||
session[11] # Email
|
||||
])
|
||||
return export_data
|
||||
|
||||
|
||||
def prepare_audit_export_data(audit_logs):
|
||||
"""Prepare audit log data for export"""
|
||||
export_data = []
|
||||
for log in audit_logs:
|
||||
export_data.append([
|
||||
log['id'],
|
||||
format_datetime_for_export(log['timestamp']),
|
||||
log['username'],
|
||||
log['action'],
|
||||
log['entity_type'],
|
||||
log['entity_id'] or '',
|
||||
log['ip_address'] or '',
|
||||
log['user_agent'] or '',
|
||||
str(log['old_values']) if log['old_values'] else '',
|
||||
str(log['new_values']) if log['new_values'] else '',
|
||||
log['additional_info'] or ''
|
||||
])
|
||||
return export_data
|
||||
|
||||
|
||||
def create_batch_export(licenses):
|
||||
"""Create Excel export for batch licenses"""
|
||||
export_data = []
|
||||
|
||||
for license in licenses:
|
||||
export_data.append({
|
||||
'Lizenzschlüssel': license['license_key'],
|
||||
'Kunde': license.get('customer_name', ''),
|
||||
'Email': license.get('customer_email', ''),
|
||||
'Lizenztyp': license.get('license_type', 'full').upper(),
|
||||
'Geräte-Limit': license.get('device_limit', 3),
|
||||
'Gültig von': format_datetime_for_export(license.get('valid_from')),
|
||||
'Gültig bis': format_datetime_for_export(license.get('valid_until')),
|
||||
'Status': 'Aktiv' if license.get('is_active', True) else 'Inaktiv',
|
||||
'Fake-Lizenz': 'Ja' if license.get('is_test', False) else 'Nein'
|
||||
})
|
||||
|
||||
df = pd.DataFrame(export_data)
|
||||
|
||||
# Create Excel file in memory
|
||||
output = BytesIO()
|
||||
with pd.ExcelWriter(output, engine='openpyxl') as writer:
|
||||
df.to_excel(writer, index=False, sheet_name='Batch-Lizenzen')
|
||||
|
||||
# Auto-adjust column widths
|
||||
worksheet = writer.sheets['Batch-Lizenzen']
|
||||
for idx, col in enumerate(df.columns):
|
||||
max_length = max(df[col].astype(str).map(len).max(), len(col)) + 2
|
||||
worksheet.column_dimensions[get_column_letter(idx + 1)].width = min(max_length, 50)
|
||||
|
||||
output.seek(0)
|
||||
|
||||
# Generate filename with timestamp
|
||||
timestamp = datetime.now(ZoneInfo("Europe/Berlin")).strftime('%Y%m%d_%H%M%S')
|
||||
filename = f"batch_licenses_{timestamp}.xlsx"
|
||||
|
||||
return send_file(
|
||||
output,
|
||||
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
as_attachment=True,
|
||||
download_name=filename
|
||||
)
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren