Gereksinimler

1941 müşteriden oluşan bir ecza deposu için müşteri memnuniyeti ölçüm platformu gerekiyordu. Temel özellikler:

1941
Müşteri
93
Şehir
4
Kategori
%100
PHP Native

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

💡 PERFORMANS

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.