requireAdmin();
$db = Database::getInstance();
$appTitle = $db->getSetting('app_title', 'UniFi Voucher System');
// AJAX: Statistiken abrufen (immer aus DB, optional vorher Live-Sync)
if (isset($_GET['ajax_stats'])) {
header('Content-Type: application/json');
$syncFirst = isset($_GET['sync']) && $_GET['sync'] == '1';
try {
$sites = $db->fetchAll("SELECT * FROM sites WHERE is_active = 1");
$siteData = [];
$totalStats = [
'total' => 0,
'valid' => 0,
'used' => 0,
'expired' => 0
];
$syncErrors = [];
// Bei sync=1: Erst alle Sites live synchronisieren
if ($syncFirst) {
foreach ($sites as $site) {
try {
$controller = new UniFiController(
$site['unifi_controller_url'],
$site['unifi_username'],
$site['unifi_password'],
$site['site_id']
);
$controller->syncVouchersToDatabase($db, $site['id']);
} catch (Exception $e) {
$syncErrors[$site['id']] = $e->getMessage();
}
}
// Last sync time aktualisieren
$db->execute(
"INSERT INTO settings (setting_key, setting_value) VALUES ('last_cron_sync', NOW())
ON DUPLICATE KEY UPDATE setting_value = NOW()"
);
}
// Immer aus Datenbank abrufen
foreach ($sites as $site) {
$siteStats = $db->fetchOne(
"SELECT
COUNT(*) as total,
SUM(CASE WHEN status = 'valid' THEN 1 ELSE 0 END) as valid,
SUM(CASE WHEN status = 'used' THEN 1 ELSE 0 END) as used,
SUM(CASE WHEN status = 'expired' THEN 1 ELSE 0 END) as expired
FROM vouchers WHERE site_id = ?",
[$site['id']]
);
$siteData[] = [
'site_id' => $site['id'],
'site_name' => $site['name'],
'stats' => [
'total' => (int)($siteStats['total'] ?? 0),
'valid' => (int)($siteStats['valid'] ?? 0),
'used' => (int)($siteStats['used'] ?? 0),
'expired' => (int)($siteStats['expired'] ?? 0)
],
'error' => $syncErrors[$site['id']] ?? null
];
$totalStats['total'] += (int)($siteStats['total'] ?? 0);
$totalStats['valid'] += (int)($siteStats['valid'] ?? 0);
$totalStats['used'] += (int)($siteStats['used'] ?? 0);
$totalStats['expired'] += (int)($siteStats['expired'] ?? 0);
}
$lastSync = $db->getSetting('last_cron_sync', '');
echo json_encode([
'success' => true,
'synced' => $syncFirst,
'sites' => $siteData,
'total' => $totalStats,
'last_sync' => $lastSync ? date('d.m.Y H:i:s', strtotime($lastSync)) : null,
'timestamp' => date('H:i:s')
]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
exit;
}
// Basis-Statistiken (aus Datenbank für initiale Anzeige)
$stats = [
'total_sites' => $db->fetchOne("SELECT COUNT(*) as count FROM sites WHERE is_active = 1")['count'],
'total_users' => $db->fetchOne("SELECT COUNT(*) as count FROM users WHERE is_active = 1")['count'],
'total_vouchers_today' => $db->fetchOne("SELECT COUNT(*) as count FROM vouchers WHERE DATE(created_at) = CURDATE()")['count'],
'total_vouchers_month' => $db->fetchOne("SELECT COUNT(*) as count FROM vouchers WHERE MONTH(created_at) = MONTH(CURDATE()) AND YEAR(created_at) = YEAR(CURDATE())")['count'],
];
// Sites für Live-Anzeige mit gecachten Statistiken
$sites = $db->fetchAll("SELECT * FROM sites WHERE is_active = 1");
// Voucher-Statistiken aus DB (gecached durch Cron)
$voucherStats = $db->fetchOne(
"SELECT
COUNT(*) as total,
SUM(CASE WHEN status = 'valid' THEN 1 ELSE 0 END) as valid,
SUM(CASE WHEN status = 'used' THEN 1 ELSE 0 END) as used,
SUM(CASE WHEN status = 'expired' THEN 1 ELSE 0 END) as expired
FROM vouchers"
);
// Pro-Site-Statistiken aus DB
$siteStats = [];
foreach ($sites as $site) {
$siteStat = $db->fetchOne(
"SELECT
COUNT(*) as total,
SUM(CASE WHEN status = 'valid' THEN 1 ELSE 0 END) as valid,
SUM(CASE WHEN status = 'used' THEN 1 ELSE 0 END) as used,
SUM(CASE WHEN status = 'expired' THEN 1 ELSE 0 END) as expired
FROM vouchers WHERE site_id = ?",
[$site['id']]
);
$siteStats[$site['id']] = $siteStat;
}
// Letzte Synchronisation
$lastCronSync = $db->getSetting('last_cron_sync', '');
// Vouchers für Diagramm (letzte 7 Tage)
$chartData = [];
for ($i = 6; $i >= 0; $i--) {
$date = date('Y-m-d', strtotime("-$i days"));
$count = $db->fetchOne(
"SELECT COUNT(*) as count FROM vouchers WHERE DATE(created_at) = ?",
[$date]
)['count'];
$chartData[] = [
'date' => date('d.m', strtotime($date)),
'count' => $count
];
}
// Top 5 Benutzer (meiste Vouchers)
$topUsers = $db->fetchAll(
"SELECT u.name, u.email, COUNT(v.id) as voucher_count
FROM users u
LEFT JOIN vouchers v ON u.id = v.user_id
WHERE v.created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY u.id
ORDER BY voucher_count DESC
LIMIT 5"
);
// Letzte Vouchers (aus DB)
$recentVouchers = $db->fetchAll(
"SELECT v.*, s.name as site_name, u.name as user_name
FROM vouchers v
LEFT JOIN sites s ON v.site_id = s.id
LEFT JOIN users u ON v.user_id = u.id
ORDER BY v.created_at DESC
LIMIT 10"
);
$currentUser = $auth->getCurrentUser();
?>
Administration - = htmlspecialchars($appTitle) ?>
= $stats['total_sites'] ?>
= $stats['total_users'] ?>
= (int)($voucherStats['valid'] ?? 0) ?>
Letzte Sync: = $lastCronSync ? date('H:i', strtotime($lastCronSync)) : 'nie' ?>
= (int)($voucherStats['used'] ?? 0) ?>
Quota ausgeschöpft
= (int)($voucherStats['expired'] ?? 0) ?>
Im Controller
= (int)($voucherStats['total'] ?? 0) ?>
Alle Sites
0, 'valid' => 0, 'used' => 0, 'expired' => 0];
?>
= (int)$ss['valid'] ?>
Gültig
= (int)$ss['used'] ?>
Verwendet
= (int)$ss['expired'] ?>
Abgelaufen
Noch keine Daten verfügbar
Noch keine Vouchers erstellt
| Erstellt |
Code |
Name |
Site |
Status |
Ersteller |
| = date('d.m.Y H:i', strtotime($voucher['created_at'])) ?> |
= htmlspecialchars($voucher['voucher_code']) ?> |
= htmlspecialchars($voucher['voucher_name']) ?> |
= htmlspecialchars($voucher['site_name']) ?> |
= $statusText ?>
|
= $voucher['user_name'] ? htmlspecialchars($voucher['user_name']) : 'Öffentlich' ?> |