Gereksinimler
1941 müşteriden oluşan bir ecza deposu için müşteri memnuniyeti ölçüm platformu gerekiyordu. Temel özellikler:
- Excel listesinden otomatik müşteri içe aktarma
- Her müşteri için tek kullanımlık anket token'ı
- Zamanlı toplu SMTP mail gönderimi
- Şehir, özel kod ve memnuniyet bazlı filtrelenebilir dashboard
- Excel raporu indirme
Token Sistemi
Her müşteri için 64 karakter hex token üretiliyor. Token tek kullanımlık: anket doldurulduktan sonra geçersiz oluyor.
function generateToken(): string {
return bin2hex(random_bytes(32)); // 64 char hex
}
function createCustomerToken(PDO $db, int $customer_id): string {
$token = generateToken();
$stmt = $db->prepare("
INSERT INTO survey_tokens (customer_id, token, expires_at)
VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 30 DAY))
ON DUPLICATE KEY UPDATE token = ?, expires_at = DATE_ADD(NOW(), INTERVAL 30 DAY)
");
$stmt->execute([$customer_id, $token, $token]);
return $token;
}
Mail Kuyruğu
Mail gönderimi direkt değil, kuyruk üzerinden yapılıyor. Böylece admin panelden "hemen gönder" veya ileriki bir tarih seçilebiliyor. Cron job dakikada bir kuyruğu işliyor.
// cron/process_mail_queue.php — dakikada bir çalışır
$pending = $db->query("
SELECT mq.*, c.email, c.company_name, st.token
FROM mail_queue mq
JOIN customers c ON mq.customer_id = c.id
JOIN survey_tokens st ON c.id = st.customer_id
WHERE mq.status = 'pending'
AND mq.scheduled_at <= NOW()
LIMIT 50
")->fetchAll();
foreach ($pending as $item) {
$link = SITE_URL . '/anket?t=' . $item['token'];
$html = renderMailTemplate($item['company_name'], $link);
$sent = sendMail($item['email'], 'Müşteri Memnuniyet Anketi', $html);
updateQueueStatus($db, $item['id'], $sent ? 'sent' : 'failed');
sleep(2); // SMTP flood koruması
}
Dashboard ve Grafikler
Dashboard tek sayfada birden fazla grafik gösteriyor: memnuniyet dağılımı (pasta), şehir bazlı tamamlanma oranı, özel kod bazlı analiz ve 7 günlük trend.
Tüm grafikler vanilla JS + Canvas API ile çizildi, harici kütüphane kullanılmadı. Bu sayfa yüklenme süresini ciddi düşürdü.
Excel Raporu
PhpSpreadsheet ile üretilen rapor iki sekmeli geliyor: müşteri listesi (cevaplayan/cevaplamayanlar) ve cevap detayları. Her sekme renklendirilmiş başlıklar ve dondurulmuş satır içeriyor.
Güvenlik
- CSRF token: Tüm formlarda zorunlu
- PDO prepared statements: SQL injection koruması
- Token tek kullanımlık: Aynı anket iki kez doldurulamaz
- Session timeout: 8 saat hareketsizlikte otomatik çıkış
- .htaccess: vendor/ ve includes/ dizinleri doğrudan erişime kapalı
1941 müşteriyi tek sorguda çekmek yerine sayfalama kullanın. Dashboard grafik verisini ayrı AJAX endpoint'lerinden çekmek sayfa yüklenme süresini yarıya düşürür.