🐛 Backend Database Improvement: Added shm and wal files for myp.db & updated debug_guest_requests.py & admin_guest_requests_overview.html 🎉
This commit is contained in:
parent
a5ce18eeee
commit
ef5f56063e
Binary file not shown.
BIN
backend/app/database/myp.db-shm
Normal file
BIN
backend/app/database/myp.db-shm
Normal file
Binary file not shown.
BIN
backend/app/database/myp.db-wal
Normal file
BIN
backend/app/database/myp.db-wal
Normal file
Binary file not shown.
@ -1 +1,80 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Debug-Script für Gastanträge und Admin-Berechtigungen
|
||||||
|
"""
|
||||||
|
|
||||||
|
from models import get_cached_session, GuestRequest, User, UserPermission
|
||||||
|
from flask_login import current_user
|
||||||
|
|
||||||
|
def check_guest_requests():
|
||||||
|
"""Prüfe Gastanträge nach Status"""
|
||||||
|
print("=== GASTANTRÄGE STATUS ===")
|
||||||
|
|
||||||
|
with get_cached_session() as db:
|
||||||
|
pending = db.query(GuestRequest).filter_by(status='pending').count()
|
||||||
|
approved = db.query(GuestRequest).filter_by(status='approved').count()
|
||||||
|
rejected = db.query(GuestRequest).filter_by(status='rejected').count()
|
||||||
|
total = db.query(GuestRequest).count()
|
||||||
|
|
||||||
|
print(f"Gesamt: {total}")
|
||||||
|
print(f"Pending (Wird geprüft): {pending}")
|
||||||
|
print(f"Approved (Genehmigt): {approved}")
|
||||||
|
print(f"Rejected (Abgelehnt): {rejected}")
|
||||||
|
|
||||||
|
if pending == 0:
|
||||||
|
print("\n⚠️ PROBLEM: Keine Anträge mit Status 'pending' gefunden!")
|
||||||
|
print(" → Die Genehmigen/Ablehnen-Buttons werden nur bei Status 'pending' angezeigt")
|
||||||
|
|
||||||
|
# Erstelle einen Test-Antrag
|
||||||
|
print("\n🔧 Erstelle Test-Gastantrag...")
|
||||||
|
test_request = GuestRequest(
|
||||||
|
name="Test Admin",
|
||||||
|
email="admin@test.de",
|
||||||
|
reason="Test für Admin-Buttons",
|
||||||
|
duration_min=30,
|
||||||
|
status="pending"
|
||||||
|
)
|
||||||
|
db.add(test_request)
|
||||||
|
db.commit()
|
||||||
|
print(f"✅ Test-Antrag erstellt (ID: {test_request.id})")
|
||||||
|
else:
|
||||||
|
print(f"\n✅ {pending} Anträge mit Status 'pending' gefunden")
|
||||||
|
|
||||||
|
# Zeige pending Anträge
|
||||||
|
pending_requests = db.query(GuestRequest).filter_by(status='pending').all()
|
||||||
|
for req in pending_requests:
|
||||||
|
print(f" ID {req.id}: {req.name} - {req.email}")
|
||||||
|
|
||||||
|
def check_admin_users():
|
||||||
|
"""Prüfe Admin-Benutzer und Berechtigungen"""
|
||||||
|
print("\n=== ADMIN-BENUTZER ===")
|
||||||
|
|
||||||
|
with get_cached_session() as db:
|
||||||
|
# Alle Admins
|
||||||
|
admins = db.query(User).filter_by(is_admin=True).all()
|
||||||
|
print(f"Admin-Benutzer: {len(admins)}")
|
||||||
|
for admin in admins:
|
||||||
|
print(f" {admin.username} (ID: {admin.id}) - Email: {admin.email}")
|
||||||
|
|
||||||
|
# Benutzer mit can_approve_jobs
|
||||||
|
users_with_approval = db.query(User).join(UserPermission).filter(
|
||||||
|
UserPermission.can_approve_jobs == True
|
||||||
|
).all()
|
||||||
|
print(f"\nBenutzer mit can_approve_jobs: {len(users_with_approval)}")
|
||||||
|
for user in users_with_approval:
|
||||||
|
print(f" {user.username} (ID: {user.id}) - Email: {user.email}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
check_guest_requests()
|
||||||
|
check_admin_users()
|
||||||
|
print("\n=== LÖSUNG ===")
|
||||||
|
print("1. Gehen Sie zu: http://127.0.0.1:5000/requests/overview")
|
||||||
|
print("2. Öffnen Sie die Browser-Konsole (F12)")
|
||||||
|
print("3. Suchen Sie nach 'Admin-Berechtigungen:' in der Konsole")
|
||||||
|
print("4. Die Buttons sollten bei Anträgen mit Status 'pending' erscheinen")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Fehler: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
@ -572,10 +572,26 @@ const userIsAdmin = adminConfig.dataset.isAdmin === 'true';
|
|||||||
const userCanApprove = adminConfig.dataset.canApprove === 'true';
|
const userCanApprove = adminConfig.dataset.canApprove === 'true';
|
||||||
const showInlineActions = userIsAdmin || userCanApprove;
|
const showInlineActions = userIsAdmin || userCanApprove;
|
||||||
|
|
||||||
console.log('Admin-Berechtigungen:', { userIsAdmin, userCanApprove, showInlineActions });
|
console.log('🔍 DEBUG: Admin-Berechtigungen:', {
|
||||||
|
userIsAdmin,
|
||||||
|
userCanApprove,
|
||||||
|
showInlineActions,
|
||||||
|
adminConfigElement: adminConfig,
|
||||||
|
dataIsAdmin: adminConfig.dataset.isAdmin,
|
||||||
|
dataCanApprove: adminConfig.dataset.canApprove
|
||||||
|
});
|
||||||
|
|
||||||
|
// Debug: Zeige alle Data-Attribute
|
||||||
|
console.log('🔍 DEBUG: Alle Data-Attribute:', adminConfig.dataset);
|
||||||
|
|
||||||
|
// Debug: Prüfe HTML-Inhalt
|
||||||
|
console.log('🔍 DEBUG: AdminConfig HTML:', adminConfig.outerHTML);
|
||||||
|
|
||||||
// Initialisierung
|
// Initialisierung
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
console.log('🚀 DEBUG: DOMContentLoaded - Initialisierung startet');
|
||||||
|
console.log('🔍 DEBUG: showInlineActions beim Laden:', showInlineActions);
|
||||||
|
|
||||||
initializeEventListeners();
|
initializeEventListeners();
|
||||||
loadAvailablePrinters();
|
loadAvailablePrinters();
|
||||||
loadGuestRequests();
|
loadGuestRequests();
|
||||||
@ -764,10 +780,82 @@ function createRequestRow(request) {
|
|||||||
const hoursOld = (now - createdAt) / (1000 * 60 * 60);
|
const hoursOld = (now - createdAt) / (1000 * 60 * 60);
|
||||||
const isUrgent = hoursOld > 24 && request.status === 'pending';
|
const isUrgent = hoursOld > 24 && request.status === 'pending';
|
||||||
|
|
||||||
|
// DEBUG: Zeige Request-Details
|
||||||
|
console.log('🔍 DEBUG: createRequestRow für Request:', {
|
||||||
|
id: request.id,
|
||||||
|
name: request.name,
|
||||||
|
status: request.status,
|
||||||
|
isPending: request.status === 'pending',
|
||||||
|
showInlineActions: showInlineActions,
|
||||||
|
shouldShowButtons: request.status === 'pending' && showInlineActions
|
||||||
|
});
|
||||||
|
|
||||||
if (isUrgent) {
|
if (isUrgent) {
|
||||||
row.classList.add('urgent-request');
|
row.classList.add('urgent-request');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEBUG: Button-HTML generieren
|
||||||
|
const buttonHtml = request.status === 'pending' && showInlineActions ? `
|
||||||
|
<div id="inline-actions-${request.id}" class="mt-2 space-y-2">
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
<button onclick="showInlineApproval(${request.id})"
|
||||||
|
class="inline-flex items-center px-2 py-1 border border-green-300 rounded text-xs text-green-700 bg-green-50 hover:bg-green-100 transition-colors">
|
||||||
|
<i class="fas fa-check mr-1"></i>Genehmigen
|
||||||
|
</button>
|
||||||
|
<button onclick="showInlineRejection(${request.id})"
|
||||||
|
class="inline-flex items-center px-2 py-1 border border-red-300 rounded text-xs text-red-700 bg-red-50 hover:bg-red-100 transition-colors">
|
||||||
|
<i class="fas fa-times mr-1"></i>Ablehnen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Inline Approval Form -->
|
||||||
|
<div id="approval-form-${request.id}" class="hidden inline-approval-form form-section">
|
||||||
|
<h5 class="text-sm font-medium text-green-800 mb-2">
|
||||||
|
<i class="fas fa-check-circle mr-1"></i>Antrag genehmigen
|
||||||
|
</h5>
|
||||||
|
<textarea id="approval-notes-${request.id}" rows="2"
|
||||||
|
class="w-full text-xs border border-green-300 rounded px-2 py-1 focus:outline-none focus:ring-1 focus:ring-green-400"
|
||||||
|
placeholder="Optionale Genehmigungsnotizen..."></textarea>
|
||||||
|
<select id="approval-printer-${request.id}"
|
||||||
|
class="w-full mt-1 text-xs border border-green-300 rounded px-2 py-1 focus:outline-none focus:ring-1 focus:ring-green-400">
|
||||||
|
<option value="">Drucker auswählen (optional)</option>
|
||||||
|
</select>
|
||||||
|
<div class="form-actions">
|
||||||
|
<button onclick="hideInlineApproval(${request.id})"
|
||||||
|
class="btn-cancel inline-action-btn">
|
||||||
|
<i class="fas fa-times mr-1"></i>Abbrechen
|
||||||
|
</button>
|
||||||
|
<button onclick="submitInlineApproval(${request.id})"
|
||||||
|
class="btn-submit inline-action-btn inline-approve-btn">
|
||||||
|
<i class="fas fa-check mr-1"></i>Genehmigen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Inline Rejection Form -->
|
||||||
|
<div id="rejection-form-${request.id}" class="hidden inline-rejection-form form-section">
|
||||||
|
<h5 class="text-sm font-medium text-red-800 mb-2">
|
||||||
|
<i class="fas fa-times-circle mr-1"></i>Antrag ablehnen
|
||||||
|
</h5>
|
||||||
|
<textarea id="rejection-reason-${request.id}" rows="2" required
|
||||||
|
class="w-full text-xs border border-red-300 rounded px-2 py-1 focus:outline-none focus:ring-1 focus:ring-red-400"
|
||||||
|
placeholder="Ablehnungsgrund (erforderlich)..."></textarea>
|
||||||
|
<div class="form-actions">
|
||||||
|
<button onclick="hideInlineRejection(${request.id})"
|
||||||
|
class="btn-cancel inline-action-btn">
|
||||||
|
<i class="fas fa-times mr-1"></i>Abbrechen
|
||||||
|
</button>
|
||||||
|
<button onclick="submitInlineRejection(${request.id})"
|
||||||
|
class="btn-submit inline-action-btn inline-reject-btn">
|
||||||
|
<i class="fas fa-times mr-1"></i>Ablehnen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
` : '';
|
||||||
|
|
||||||
|
console.log('🔍 DEBUG: Button-HTML für Request', request.id, ':', buttonHtml ? 'GENERIERT' : 'LEER');
|
||||||
|
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
@ -794,64 +882,7 @@ function createRequestRow(request) {
|
|||||||
<span class="status-badge status-${request.status}">
|
<span class="status-badge status-${request.status}">
|
||||||
${getStatusIcon(request.status)} ${getStatusText(request.status)}
|
${getStatusIcon(request.status)} ${getStatusText(request.status)}
|
||||||
</span>
|
</span>
|
||||||
${request.status === 'pending' && showInlineActions ? `
|
${buttonHtml}
|
||||||
<div id="inline-actions-${request.id}" class="mt-2 space-y-2">
|
|
||||||
<div class="flex space-x-2">
|
|
||||||
<button onclick="showInlineApproval(${request.id})"
|
|
||||||
class="inline-flex items-center px-2 py-1 border border-green-300 rounded text-xs text-green-700 bg-green-50 hover:bg-green-100 transition-colors">
|
|
||||||
<i class="fas fa-check mr-1"></i>Genehmigen
|
|
||||||
</button>
|
|
||||||
<button onclick="showInlineRejection(${request.id})"
|
|
||||||
class="inline-flex items-center px-2 py-1 border border-red-300 rounded text-xs text-red-700 bg-red-50 hover:bg-red-100 transition-colors">
|
|
||||||
<i class="fas fa-times mr-1"></i>Ablehnen
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Inline Approval Form -->
|
|
||||||
<div id="approval-form-${request.id}" class="hidden inline-approval-form form-section">
|
|
||||||
<h5 class="text-sm font-medium text-green-800 mb-2">
|
|
||||||
<i class="fas fa-check-circle mr-1"></i>Antrag genehmigen
|
|
||||||
</h5>
|
|
||||||
<textarea id="approval-notes-${request.id}" rows="2"
|
|
||||||
class="w-full text-xs border border-green-300 rounded px-2 py-1 focus:outline-none focus:ring-1 focus:ring-green-400"
|
|
||||||
placeholder="Optionale Genehmigungsnotizen..."></textarea>
|
|
||||||
<select id="approval-printer-${request.id}"
|
|
||||||
class="w-full mt-1 text-xs border border-green-300 rounded px-2 py-1 focus:outline-none focus:ring-1 focus:ring-green-400">
|
|
||||||
<option value="">Drucker auswählen (optional)</option>
|
|
||||||
</select>
|
|
||||||
<div class="form-actions">
|
|
||||||
<button onclick="hideInlineApproval(${request.id})"
|
|
||||||
class="btn-cancel inline-action-btn">
|
|
||||||
<i class="fas fa-times mr-1"></i>Abbrechen
|
|
||||||
</button>
|
|
||||||
<button onclick="submitInlineApproval(${request.id})"
|
|
||||||
class="btn-submit inline-action-btn inline-approve-btn">
|
|
||||||
<i class="fas fa-check mr-1"></i>Genehmigen
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Inline Rejection Form -->
|
|
||||||
<div id="rejection-form-${request.id}" class="hidden inline-rejection-form form-section">
|
|
||||||
<h5 class="text-sm font-medium text-red-800 mb-2">
|
|
||||||
<i class="fas fa-times-circle mr-1"></i>Antrag ablehnen
|
|
||||||
</h5>
|
|
||||||
<textarea id="rejection-reason-${request.id}" rows="2" required
|
|
||||||
class="w-full text-xs border border-red-300 rounded px-2 py-1 focus:outline-none focus:ring-1 focus:ring-red-400"
|
|
||||||
placeholder="Ablehnungsgrund (erforderlich)..."></textarea>
|
|
||||||
<div class="form-actions">
|
|
||||||
<button onclick="hideInlineRejection(${request.id})"
|
|
||||||
class="btn-cancel inline-action-btn">
|
|
||||||
<i class="fas fa-times mr-1"></i>Abbrechen
|
|
||||||
</button>
|
|
||||||
<button onclick="submitInlineRejection(${request.id})"
|
|
||||||
class="btn-submit inline-action-btn inline-reject-btn">
|
|
||||||
<i class="fas fa-times mr-1"></i>Ablehnen
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
` : ''}
|
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||||
<div>${formatDate(request.created_at)}</div>
|
<div>${formatDate(request.created_at)}</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user