Dashboard - redundante Informationen entfernt
Dieser Commit ist enthalten in:
28
JOURNAL.md
28
JOURNAL.md
@@ -1121,3 +1121,31 @@ Die Session-Daten werden erst gefüllt, wenn der License Server API implementier
|
|||||||
- ✅ Alle Lizenzen haben nun automatisch einen Erstellungszeitstempel
|
- ✅ Alle Lizenzen haben nun automatisch einen Erstellungszeitstempel
|
||||||
- ✅ Batch-Generierung funktioniert wieder
|
- ✅ Batch-Generierung funktioniert wieder
|
||||||
- ✅ Konsistente Zeitstempel für Audit-Zwecke
|
- ✅ Konsistente Zeitstempel für Audit-Zwecke
|
||||||
|
|
||||||
|
## 2025-01-06: Status "Deaktiviert" für manuell abgeschaltete Lizenzen
|
||||||
|
|
||||||
|
**Problem:**
|
||||||
|
- Dashboard zeigte nur "aktiv" und "abgelaufen" als Status
|
||||||
|
- Manuell deaktivierte Lizenzen (is_active = FALSE) wurden nicht korrekt angezeigt
|
||||||
|
- Filter für "inactive" existierte, aber Status wurde nicht richtig berechnet
|
||||||
|
|
||||||
|
**Lösung:**
|
||||||
|
1. **Status-Berechnung erweitert:**
|
||||||
|
- CASE-Statement prüft zuerst `is_active = FALSE`
|
||||||
|
- Status "deaktiviert" wird vor anderen Status geprüft
|
||||||
|
- Reihenfolge: deaktiviert → abgelaufen → läuft bald ab → aktiv
|
||||||
|
2. **Dashboard-Statistik erweitert:**
|
||||||
|
- Neue Zählung für deaktivierte Lizenzen
|
||||||
|
- Variable `inactive_licenses` im stats Dictionary
|
||||||
|
|
||||||
|
**Änderungen:**
|
||||||
|
- `app.py`: Dashboard - Status-Berechnung für letzte 5 Lizenzen
|
||||||
|
- `app.py`: Lizenzübersicht - Status-Berechnung in der Hauptabfrage
|
||||||
|
- `app.py`: Export - Status-Berechnung für CSV/Excel Export
|
||||||
|
- `app.py`: Dashboard - Neue Statistik für deaktivierte Lizenzen
|
||||||
|
|
||||||
|
**Status:**
|
||||||
|
- ✅ "Deaktiviert" wird korrekt als Status angezeigt
|
||||||
|
- ✅ Dashboard zeigt Anzahl deaktivierter Lizenzen
|
||||||
|
- ✅ Export enthält korrekten Status
|
||||||
|
- ✅ Konsistente Status-Anzeige überall
|
||||||
@@ -877,6 +877,13 @@ def dashboard():
|
|||||||
""")
|
""")
|
||||||
expired_licenses = cur.fetchone()[0]
|
expired_licenses = cur.fetchone()[0]
|
||||||
|
|
||||||
|
# Deaktivierte Lizenzen
|
||||||
|
cur.execute("""
|
||||||
|
SELECT COUNT(*) FROM licenses
|
||||||
|
WHERE is_active = FALSE
|
||||||
|
""")
|
||||||
|
inactive_licenses = cur.fetchone()[0]
|
||||||
|
|
||||||
# Lizenzen die in den nächsten 30 Tagen ablaufen
|
# Lizenzen die in den nächsten 30 Tagen ablaufen
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT COUNT(*) FROM licenses
|
SELECT COUNT(*) FROM licenses
|
||||||
@@ -898,6 +905,7 @@ def dashboard():
|
|||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT l.id, l.license_key, c.name, l.valid_until,
|
SELECT l.id, l.license_key, c.name, l.valid_until,
|
||||||
CASE
|
CASE
|
||||||
|
WHEN l.is_active = FALSE THEN 'deaktiviert'
|
||||||
WHEN l.valid_until < CURRENT_DATE THEN 'abgelaufen'
|
WHEN l.valid_until < CURRENT_DATE THEN 'abgelaufen'
|
||||||
WHEN l.valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'läuft bald ab'
|
WHEN l.valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'läuft bald ab'
|
||||||
ELSE 'aktiv'
|
ELSE 'aktiv'
|
||||||
@@ -990,6 +998,7 @@ def dashboard():
|
|||||||
'total_licenses': total_licenses,
|
'total_licenses': total_licenses,
|
||||||
'active_licenses': active_licenses,
|
'active_licenses': active_licenses,
|
||||||
'expired_licenses': expired_licenses,
|
'expired_licenses': expired_licenses,
|
||||||
|
'inactive_licenses': inactive_licenses,
|
||||||
'expiring_soon': expiring_soon,
|
'expiring_soon': expiring_soon,
|
||||||
'full_licenses': license_types.get('full', 0),
|
'full_licenses': license_types.get('full', 0),
|
||||||
'test_licenses': license_types.get('test', 0),
|
'test_licenses': license_types.get('test', 0),
|
||||||
@@ -1319,6 +1328,7 @@ def licenses():
|
|||||||
SELECT l.id, l.license_key, c.name, c.email, l.license_type,
|
SELECT l.id, l.license_key, c.name, c.email, l.license_type,
|
||||||
l.valid_from, l.valid_until, l.is_active,
|
l.valid_from, l.valid_until, l.is_active,
|
||||||
CASE
|
CASE
|
||||||
|
WHEN l.is_active = FALSE THEN 'deaktiviert'
|
||||||
WHEN l.valid_until < CURRENT_DATE THEN 'abgelaufen'
|
WHEN l.valid_until < CURRENT_DATE THEN 'abgelaufen'
|
||||||
WHEN l.valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'läuft bald ab'
|
WHEN l.valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'läuft bald ab'
|
||||||
ELSE 'aktiv'
|
ELSE 'aktiv'
|
||||||
@@ -1732,6 +1742,7 @@ def export_licenses():
|
|||||||
SELECT l.id, l.license_key, c.name as customer_name, c.email as customer_email,
|
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,
|
l.license_type, l.valid_from, l.valid_until, l.is_active,
|
||||||
CASE
|
CASE
|
||||||
|
WHEN l.is_active = FALSE THEN 'Deaktiviert'
|
||||||
WHEN l.valid_until < CURRENT_DATE THEN 'Abgelaufen'
|
WHEN l.valid_until < CURRENT_DATE THEN 'Abgelaufen'
|
||||||
WHEN l.valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'Läuft bald ab'
|
WHEN l.valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'Läuft bald ab'
|
||||||
ELSE 'Aktiv'
|
ELSE 'Aktiv'
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
.status-aktiv { color: #28a745; }
|
.status-aktiv { color: #28a745; }
|
||||||
.status-ablaufend { color: #ffc107; }
|
.status-ablaufend { color: #ffc107; }
|
||||||
.status-abgelaufen { color: #dc3545; }
|
.status-abgelaufen { color: #dc3545; }
|
||||||
|
.status-deaktiviert { color: #6c757d; }
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
@@ -33,7 +34,7 @@
|
|||||||
|
|
||||||
<!-- Statistik-Karten -->
|
<!-- Statistik-Karten -->
|
||||||
<div class="row g-3 mb-4">
|
<div class="row g-3 mb-4">
|
||||||
<div class="col-md-3">
|
<div class="col-md-4">
|
||||||
<div class="card stat-card h-100">
|
<div class="card stat-card h-100">
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<h5 class="card-title">👥 Kunden</h5>
|
<h5 class="card-title">👥 Kunden</h5>
|
||||||
@@ -42,7 +43,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-4">
|
||||||
<div class="card stat-card h-100">
|
<div class="card stat-card h-100">
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<h5 class="card-title">📋 Lizenzen</h5>
|
<h5 class="card-title">📋 Lizenzen</h5>
|
||||||
@@ -51,16 +52,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-4">
|
||||||
<div class="card stat-card h-100">
|
|
||||||
<div class="card-body text-center">
|
|
||||||
<h5 class="card-title">✅ Aktiv</h5>
|
|
||||||
<h2 class="text-success">{{ stats.active_licenses }}</h2>
|
|
||||||
<p class="text-muted mb-0">Gültige Lizenzen</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="card stat-card h-100">
|
<div class="card stat-card h-100">
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<h5 class="card-title">🟢 Sessions</h5>
|
<h5 class="card-title">🟢 Sessions</h5>
|
||||||
@@ -95,14 +87,18 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Lizenzstatus</h5>
|
<h5 class="card-title">Lizenzstatus</h5>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-6 text-center">
|
<div class="col-4 text-center">
|
||||||
<h3 class="text-success">{{ stats.active_licenses }}</h3>
|
<h3 class="text-success">{{ stats.active_licenses }}</h3>
|
||||||
<p class="text-muted">Aktiv</p>
|
<p class="text-muted">Aktiv</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 text-center">
|
<div class="col-4 text-center">
|
||||||
<h3 class="text-danger">{{ stats.expired_licenses }}</h3>
|
<h3 class="text-danger">{{ stats.expired_licenses }}</h3>
|
||||||
<p class="text-muted">Abgelaufen</p>
|
<p class="text-muted">Abgelaufen</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-4 text-center">
|
||||||
|
<h3 class="text-secondary">{{ stats.inactive_licenses }}</h3>
|
||||||
|
<p class="text-muted">Deaktiviert</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -273,7 +269,9 @@
|
|||||||
<td>{{ license[2] }}</td>
|
<td>{{ license[2] }}</td>
|
||||||
<td><small><code>{{ license[1][:8] }}...</code></small></td>
|
<td><small><code>{{ license[1][:8] }}...</code></small></td>
|
||||||
<td>
|
<td>
|
||||||
{% if license[4] == 'abgelaufen' %}
|
{% if license[4] == 'deaktiviert' %}
|
||||||
|
<span class="status-deaktiviert">🚫 Deaktiviert</span>
|
||||||
|
{% elif license[4] == 'abgelaufen' %}
|
||||||
<span class="status-abgelaufen">⚠️ Abgelaufen</span>
|
<span class="status-abgelaufen">⚠️ Abgelaufen</span>
|
||||||
{% elif license[4] == 'läuft bald ab' %}
|
{% elif license[4] == 'läuft bald ab' %}
|
||||||
<span class="status-ablaufend">⏰ Läuft bald ab</span>
|
<span class="status-ablaufend">⏰ Läuft bald ab</span>
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren