From 46c03d53b841ffaf4982efbfe0528e695286b7bb Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 6 Jun 2026 05:43:09 +0000 Subject: [PATCH] =?UTF-8?q?Batch-CSV-Import:=20admin/import.php=20(Name,Ma?= =?UTF-8?q?xGer=C3=A4te,Minuten;=20max=20200=20Zeilen)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/import.php | 148 +++++++++++++++++++++++++++++++++++++++++ includes/admin_nav.php | 3 + lang/de.php | 1 + lang/en.php | 1 + 4 files changed, 153 insertions(+) create mode 100644 admin/import.php diff --git a/admin/import.php b/admin/import.php new file mode 100644 index 0000000..dfb9725 --- /dev/null +++ b/admin/import.php @@ -0,0 +1,148 @@ +requireAdmin(); +I18n::init(); + +$db = Database::getInstance(); +$appTitle = $db->getSetting('app_title', 'UniFi Voucher System'); +$defaultExpire = max(1, (int)$db->getSetting('default_expire_minutes', 480)); +$defaultMaxUses = max(1, (int)$db->getSetting('default_max_uses', 1)); + +$error = ''; +$success = ''; +$results = []; + +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['do_import'])) { + if (!$auth->validateCsrfToken($_POST['csrf_token'] ?? '')) { + $error = __('error_csrf'); + } else { + try { + $siteId = (int)($_POST['site_id'] ?? 0); + $site = $db->fetchOne("SELECT * FROM sites WHERE id=? AND is_active=1", [$siteId]); + if (!$site) throw new Exception('Site nicht gefunden'); + + // CSV-Quelle: Datei bevorzugt, sonst Textarea + $raw = ''; + if (!empty($_FILES['csv']['tmp_name'])) { + $raw = file_get_contents($_FILES['csv']['tmp_name']); + } else { + $raw = (string)($_POST['csv_text'] ?? ''); + } + $lines = preg_split('/\r\n|\r|\n/', trim($raw)); + if (count($lines) > 200) throw new Exception('Maximal 200 Zeilen pro Import.'); + + $controller = new UniFiController( + $site['unifi_controller_url'], $site['unifi_username'], + Crypto::decrypt($site['unifi_password']), $site['site_id'] + ); + + $created = 0; + foreach ($lines as $i => $line) { + $line = trim($line); + if ($line === '') continue; + $cols = str_getcsv($line); + $name = trim((string)($cols[0] ?? '')); + if ($name === '' || strtolower($name) === 'name') continue; // Header/leer überspringen + $maxUses = isset($cols[1]) && $cols[1] !== '' ? max(1, (int)$cols[1]) : $defaultMaxUses; + $expire = isset($cols[2]) && $cols[2] !== '' ? max(1, (int)$cols[2]) : $defaultExpire; + try { + $v = $controller->createVoucher(date('Y-m-d') . '_' . $name, $maxUses, $expire); + if (!is_array($v) || empty($v['formatted_code'])) throw new Exception('ungültige Antwort'); + $db->execute( + "INSERT INTO vouchers (site_id, user_id, voucher_code, voucher_name, max_uses, expire_minutes, unifi_voucher_id) + VALUES (?, ?, ?, ?, ?, ?, ?)", + [$siteId, $_SESSION['user_id'], $v['code'], date('Y-m-d') . '_' . $name, $maxUses, $expire, $v['unifi_id'] ?? null] + ); + $results[] = ['name' => $name, 'code' => $v['formatted_code'], 'ok' => true]; + $created++; + } catch (Exception $e) { + $results[] = ['name' => $name, 'code' => $e->getMessage(), 'ok' => false]; + } + } + if ($created > 0) { + Notifier::voucherCreated($created, $site['name'], $_SESSION['user_name'] ?? null); + $auth->writeAuditLog($_SESSION['user_id'], 'voucher_import', 'site', $siteId, "$created Voucher importiert"); + } + $success = "$created Voucher erstellt."; + } catch (Exception $e) { + $error = $e->getMessage(); + } + } +} + +$sites = $db->fetchAll("SELECT * FROM sites WHERE is_active=1 ORDER BY name"); +$csrf = $auth->getCsrfToken(); +$currentPage = 'import'; +$adminBase = ''; +?> + + + + + +CSV-Import – <?= htmlspecialchars($appTitle) ?> + + + + +

📥 Voucher-Import (CSV)

+ +
+
+ +
+

Mehrere Voucher erstellen

+

Eine Zeile pro Voucher: Name,MaxGeräte,Minuten – MaxGeräte und Minuten sind optional (Standardwerte greifen). Max. 200 Zeilen. Beispiel:
+ Gast Müller,1,480 · Konferenzraum A,5,240 · Tagespass

+
+ + + + + + + + +
+
+ + +
+

Ergebnis

+ + + + +
NameCode / FehlerStatus
+
+ + + + + + diff --git a/includes/admin_nav.php b/includes/admin_nav.php index 93489d2..2c39349 100644 --- a/includes/admin_nav.php +++ b/includes/admin_nav.php @@ -113,6 +113,9 @@ $lang = I18n::getLanguage();
  • +
  • + +
  • diff --git a/lang/de.php b/lang/de.php index aab548d..6e71868 100644 --- a/lang/de.php +++ b/lang/de.php @@ -8,6 +8,7 @@ return [ 'nav_templates' => 'Voucher-Profile', 'nav_audit_log' => 'Audit-Log', 'nav_reports' => 'Reporting', + 'nav_import' => 'Voucher-Import', 'nav_settings' => 'Einstellungen', 'nav_api_keys' => 'API-Schlüssel', 'nav_security' => 'Sicherheit (2FA)', diff --git a/lang/en.php b/lang/en.php index d92a83a..4651fb9 100644 --- a/lang/en.php +++ b/lang/en.php @@ -8,6 +8,7 @@ return [ 'nav_templates' => 'Voucher Profiles', 'nav_audit_log' => 'Audit Log', 'nav_reports' => 'Reporting', + 'nav_import' => 'Voucher Import', 'nav_settings' => 'Settings', 'nav_api_keys' => 'API Keys', 'nav_security' => 'Security (2FA)',