From 860b2ef08f05e623eb182a3a6173de5c2ed3c07e Mon Sep 17 00:00:00 2001 From: UserIsMH Date: Wed, 18 Jun 2025 02:34:07 +0200 Subject: [PATCH] =?UTF-8?q?Problem=20Kunden=20gel=C3=B6scht?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- v2_adminpanel/routes/customer_routes.py | 72 +++++++++++++++++-- .../templates/customers_licenses.html | 14 +++- v2_adminpanel/test_api.html | 38 ++++++++++ 3 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 v2_adminpanel/test_api.html diff --git a/v2_adminpanel/routes/customer_routes.py b/v2_adminpanel/routes/customer_routes.py index 3f1c69f..9ec4507 100644 --- a/v2_adminpanel/routes/customer_routes.py +++ b/v2_adminpanel/routes/customer_routes.py @@ -296,10 +296,25 @@ def api_customer_licenses(customer_id): (SELECT COUNT(*) FROM sessions s WHERE s.license_key = l.license_key AND s.is_active = true) as active_sessions, (SELECT COUNT(DISTINCT hardware_id) FROM sessions s WHERE s.license_key = l.license_key) as registered_devices, CASE - WHEN l.valid_until < CURRENT_DATE THEN 'expired' - WHEN l.is_active = false THEN 'inactive' - ELSE 'active' - END as status + WHEN l.valid_until < CURRENT_DATE THEN 'abgelaufen' + WHEN l.valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'läuft bald ab' + WHEN l.is_active = false THEN 'inaktiv' + ELSE 'aktiv' + END as status, + l.domain_count, + l.ipv4_count, + l.phone_count, + (SELECT COUNT(*) FROM device_registrations WHERE license_id = l.id AND is_active = TRUE) as active_devices, + -- Actual resource counts + (SELECT COUNT(*) FROM license_resources lr + JOIN resource_pools rp ON lr.resource_id = rp.id + WHERE lr.license_id = l.id AND lr.is_active = true AND rp.resource_type = 'domain') as actual_domain_count, + (SELECT COUNT(*) FROM license_resources lr + JOIN resource_pools rp ON lr.resource_id = rp.id + WHERE lr.license_id = l.id AND lr.is_active = true AND rp.resource_type = 'ipv4') as actual_ipv4_count, + (SELECT COUNT(*) FROM license_resources lr + JOIN resource_pools rp ON lr.resource_id = rp.id + WHERE lr.license_id = l.id AND lr.is_active = true AND rp.resource_type = 'phone') as actual_phone_count FROM licenses l WHERE l.customer_id = %s ORDER BY l.created_at DESC @@ -307,11 +322,47 @@ def api_customer_licenses(customer_id): licenses = [] for row in cur.fetchall(): + license_id = row[0] + + # Hole die konkreten zugewiesenen Ressourcen für diese Lizenz + conn2 = get_connection() + cur2 = conn2.cursor() + cur2.execute(""" + SELECT rp.id, rp.resource_type, rp.resource_value, lr.assigned_at + FROM resource_pools rp + JOIN license_resources lr ON rp.id = lr.resource_id + WHERE lr.license_id = %s AND lr.is_active = true + ORDER BY rp.resource_type, rp.resource_value + """, (license_id,)) + + resources = { + 'domains': [], + 'ipv4s': [], + 'phones': [] + } + + for res_row in cur2.fetchall(): + resource_data = { + 'id': res_row[0], + 'value': res_row[2], + 'assigned_at': res_row[3].strftime('%Y-%m-%d %H:%M:%S') if res_row[3] else None + } + + if res_row[1] == 'domain': + resources['domains'].append(resource_data) + elif res_row[1] == 'ipv4': + resources['ipv4s'].append(resource_data) + elif res_row[1] == 'phone': + resources['phones'].append(resource_data) + + cur2.close() + conn2.close() + licenses.append({ 'id': row[0], 'license_key': row[1], 'license_type': row[2], - 'active': row[3], + 'is_active': row[3], # Korrigiert von 'active' zu 'is_active' 'is_test': row[4], 'valid_from': row[5].strftime('%Y-%m-%d') if row[5] else None, 'valid_until': row[6].strftime('%Y-%m-%d') if row[6] else None, @@ -319,10 +370,19 @@ def api_customer_licenses(customer_id): 'created_at': row[8].strftime('%Y-%m-%d %H:%M:%S') if row[8] else None, 'active_sessions': row[9], 'registered_devices': row[10], - 'status': row[11] + 'status': row[11], + 'domain_count': row[12], + 'ipv4_count': row[13], + 'phone_count': row[14], + 'active_devices': row[15], + 'actual_domain_count': row[16], + 'actual_ipv4_count': row[17], + 'actual_phone_count': row[18], + 'resources': resources }) return jsonify({ + 'success': True, # Wichtig: Frontend erwartet dieses Feld 'customer': { 'id': customer['id'], 'name': customer['name'], diff --git a/v2_adminpanel/templates/customers_licenses.html b/v2_adminpanel/templates/customers_licenses.html index e10a62d..d80010f 100644 --- a/v2_adminpanel/templates/customers_licenses.html +++ b/v2_adminpanel/templates/customers_licenses.html @@ -295,8 +295,15 @@ function loadCustomerLicenses(customerId) { container.innerHTML = '
'; fetch(`{{ url_for('customers.api_customer_licenses', customer_id=0) }}`.replace('0', customerId)) - .then(response => response.json()) + .then(response => { + console.log('API Response Status:', response.status); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.json(); + }) .then(data => { + console.log('API Response Data:', data); if (data.success) { // Update header with customer info const customerItem = document.querySelector(`[data-customer-id="${customerId}"]`); @@ -320,11 +327,14 @@ function loadCustomerLicenses(customerId) { `; updateLicenseView(customerId, data.licenses); + } else { + console.error('API returned success: false', data); + container.innerHTML = '
Keine Lizenzdaten gefunden
'; } }) .catch(error => { console.error('Error:', error); - container.innerHTML = '
Fehler beim Laden der Lizenzen
'; + container.innerHTML = `
Fehler beim Laden der Lizenzen: ${error.message}
`; }); } diff --git a/v2_adminpanel/test_api.html b/v2_adminpanel/test_api.html new file mode 100644 index 0000000..06029dd --- /dev/null +++ b/v2_adminpanel/test_api.html @@ -0,0 +1,38 @@ + + + + API Test + + +

Test Customer Licenses API

+ +

+
+    
+
+
\ No newline at end of file