64 lines
3.8 KiB
PHP
64 lines
3.8 KiB
PHP
<?php
|
||
// Direkter Web-Zugriff wird geblockt (nur CLI oder Einbindung aus dem Backend/Pseudo-Cron).
|
||
if (php_sapi_name() !== 'cli' && !defined('DESKHUB_CRON_RUNNER')) { http_response_code(403); exit('Kein Web-Zugriff.'); }
|
||
/**
|
||
* cron/remind_customers.php
|
||
*
|
||
* Schickt Kunden eine freundliche Erinnerung, wenn sie auf eine Antwort (Status "Beantwortet") mehrere Tage nicht reagiert haben.
|
||
* Pro Antwort wird nur eine Erinnerung gesendet. Ist das automatische Schließen eingeschaltet, nennt die Mail, wann das Ticket
|
||
* geschlossen wird. Einstellbar unter Einstellungen → Allgemein ("Kunden erinnern").
|
||
*/
|
||
require_once __DIR__ . '/../includes/bootstrap.php';
|
||
|
||
/** @return array{sent:int, log:string[]} */
|
||
function run_remind_customers(PDO $pdo, bool $verbose = false): array
|
||
{
|
||
$log = [];
|
||
if (!customer_reminder_enabled()) {
|
||
return ['sent' => 0, 'log' => ['[' . date('Y-m-d H:i:s') . '] Kundenerinnerung ist deaktiviert – nichts zu tun.']];
|
||
}
|
||
$days = customer_reminder_days();
|
||
$threshold = date('Y-m-d H:i:s', time() - $days * 86400);
|
||
$closeDays = get_setting('auto_close_enabled', '0') === '1' ? max(1, (int) get_setting('auto_close_days', '7')) : 0;
|
||
|
||
$stmt = $pdo->prepare(
|
||
"SELECT t.*, d.name AS department_name FROM tickets t LEFT JOIN departments d ON d.id = t.department_id
|
||
WHERE t.status = 'answered' AND t.is_spam = 0 AND t.source <> 'chat' AND t.updated_at < ?
|
||
AND (t.reminder_sent_at IS NULL OR t.reminder_sent_at < t.updated_at)
|
||
AND (t.snoozed_until IS NULL OR t.snoozed_until <= ?)
|
||
ORDER BY t.updated_at LIMIT 100"
|
||
);
|
||
$stmt->execute([$threshold, db_now()]);
|
||
$sent = 0;
|
||
foreach ($stmt->fetchAll() as $t) {
|
||
if (empty($t['requester_email']) || !filter_var($t['requester_email'], FILTER_VALIDATE_EMAIL)) continue;
|
||
$closeNote = '';
|
||
if ($closeDays > $days) {
|
||
$closeNote = '<p style="margin:16px 0 0;color:#475569;font-size:14px;">Hören wir bis dahin nichts von Ihnen, schließen wir das Ticket in ' . ($closeDays - $days) . ' ' . (($closeDays - $days) === 1 ? 'Tag' : 'Tagen') . ' automatisch. Sie können es jederzeit wieder öffnen, indem Sie antworten.</p>';
|
||
} elseif ($closeDays > 0) {
|
||
$closeNote = '<p style="margin:16px 0 0;color:#475569;font-size:14px;">Hören wir von Ihnen nichts mehr, schließen wir das Ticket in Kürze automatisch. Sie können es jederzeit wieder öffnen, indem Sie antworten.</p>';
|
||
}
|
||
[$subject, $body] = render_email_template('customer_reminder', [
|
||
'ticket_number' => $t['ticket_number'],
|
||
'subject' => e($t['subject']),
|
||
'customer_name' => e($t['requester_name'] ?? ''),
|
||
'ticket_url' => e(ticket_access_url($t)),
|
||
'close_note' => $closeNote,
|
||
], "Erinnerung zu Ihrem Ticket [#{$t['ticket_number']}]", email_customer_reminder_default_body());
|
||
$from = resolve_from_address($t['department_id'] ?? null, $t['priority_id'] ?? null);
|
||
email_send_and_log($t['requester_email'], $subject, email_wrap($body), $from, 'Erinnerung an den Kunden', $t['ticket_number']);
|
||
// updated_at bleibt unverändert, damit das automatische Schließen seine Frist behält
|
||
$pdo->prepare('UPDATE tickets SET reminder_sent_at = ?, updated_at = updated_at WHERE id = ?')->execute([db_now(), $t['id']]);
|
||
log_activity($pdo, (int) $t['id'], null, 'Erinnerung an den Kunden gesendet');
|
||
$sent++;
|
||
if ($verbose) $log[] = "[ok] Erinnerung für Ticket #{$t['ticket_number']}";
|
||
}
|
||
set_setting('cron_remind_customers_last_run', db_now());
|
||
$log[] = '[' . date('Y-m-d H:i:s') . "] Kundenerinnerung: {$sent} Mail(s) gesendet (nach {$days} Tagen ohne Reaktion).";
|
||
return ['sent' => $sent, 'log' => $log];
|
||
}
|
||
|
||
if (php_sapi_name() === 'cli') {
|
||
foreach (run_remind_customers(get_db(), true)['log'] as $line) echo $line . "\n";
|
||
}
|