File: /home/muratemr/theotto.tr/api/admin/customers.php
<?php
/**
* api/admin/customers.php
*/
declare(strict_types=1);
require_once __DIR__ . '/../../includes/db.php';
require_once __DIR__ . '/../../includes/auth.php';
require_once __DIR__ . '/../../includes/functions.php';
require_once __DIR__ . '/../../includes/csrf.php';
require_permission('customers');
header('Content-Type: application/json');
set_exception_handler(function(Throwable $e) {
http_response_code(500);
header("Content-Type: application/json");
echo json_encode(["success" => false, "message" => "Sunucu hatası: " . $e->getMessage()]);
exit;
});
$action = post_str('action') ?: get_str('action');
$id = post_int('id') ?: get_int('id');
// Okuma işlemleri için CSRF gerekmez
$read_actions = ['get_detail'];
if (!in_array($action, $read_actions)) {
csrf_required();
}
switch ($action) {
case 'set_tag':
if (!$id) json_response(false, 'Geçersiz ID.');
$tag_id = post_int('tag_id') ?: null;
// Etikete ait auto_note varsa müşterinin notuna ekle
if ($tag_id) {
$tag = db_row('SELECT auto_note FROM customer_tags WHERE id=?', [$tag_id]);
if ($tag && $tag['auto_note']) {
$customer = db_row('SELECT admin_note FROM customers WHERE id=?', [$id]);
$date = date('d.m.Y');
$append = "\n[$date] " . $tag['auto_note'];
$new_note = ($customer['admin_note'] ?? '') . $append;
db_run('UPDATE customers SET tag_id=?, admin_note=? WHERE id=?', [$tag_id, $new_note, $id]);
json_response(true, 'Etiket atandı ve not eklendi.');
}
}
db_run('UPDATE customers SET tag_id=? WHERE id=?', [$tag_id, $id]);
json_response(true, 'Etiket güncellendi.');
case 'set_note':
if (!$id) json_response(false, 'Geçersiz ID.');
db_run('UPDATE customers SET admin_note=? WHERE id=?', [post_str('admin_note'), $id]);
json_response(true, 'Not güncellendi.');
case 'create':
if (!is_admin()) json_response(false, 'Yetki gerekli.');
$full_name = trim(post_str('full_name'));
$phone_raw = trim(post_str('phone'));
$admin_note = trim(post_str('admin_note'));
if (!$full_name) json_response(false, 'Ad Soyad zorunlu.');
if (!$phone_raw) json_response(false, 'Telefon zorunlu.');
$phone = normalize_phone($phone_raw);
if (strlen($phone) < 10) json_response(false, 'Geçerli bir telefon numarası girin.');
// Aynı numarada müşteri var mı?
$variants = [$phone, '0'.$phone, '90'.$phone];
$ph = implode(',', array_fill(0, count($variants), '?'));
$exists = db_value("SELECT COUNT(*) FROM customers WHERE phone IN ($ph)", $variants);
if ($exists) json_response(false, 'Bu telefon numarasına ait müşteri zaten kayıtlı.');
$new_id = db_insert(
"INSERT INTO customers (full_name, phone, admin_note) VALUES (?, ?, ?)",
[$full_name, $phone, $admin_note ?: null]
);
json_response(true, 'Müşteri oluşturuldu.', ['id' => (int)$new_id]);
case 'update':
if (!is_admin()) json_response(false, 'Yetki gerekli.');
if (!$id) json_response(false, 'Geçersiz ID.');
$full_name = trim(post_str('full_name'));
$phone_raw = trim(post_str('phone'));
$admin_note = trim(post_str('admin_note'));
if (!$full_name) json_response(false, 'Ad Soyad zorunlu.');
if (!$phone_raw) json_response(false, 'Telefon zorunlu.');
$phone = normalize_phone($phone_raw);
if (strlen($phone) < 10) json_response(false, 'Geçerli bir telefon numarası girin.');
// Aynı telefon başka müşteride var mı?
$variants = [$phone, '0'.$phone, '90'.$phone];
$ph = implode(',', array_fill(0, count($variants), '?'));
$dup = db_value("SELECT COUNT(*) FROM customers WHERE phone IN ($ph) AND id != ?",
array_merge($variants, [$id]));
if ($dup) json_response(false, 'Bu telefon numarası başka bir müşteriye ait.');
$customer = db_row("SELECT id FROM customers WHERE id = ?", [$id]);
if (!$customer) json_response(false, 'Müşteri bulunamadı.');
db_run(
"UPDATE customers SET full_name=?, phone=?, admin_note=? WHERE id=?",
[$full_name, $phone, $admin_note ?: null, $id]
);
// Rezervasyonlardaki isim ve telefonu da güncelle
db_run("UPDATE reservations SET full_name=?, phone=? WHERE customer_id=?",
[$full_name, $phone, $id]);
json_response(true, 'Müşteri güncellendi.');
case 'delete':
if (!is_admin()) json_response(false, 'Yetki gerekli.');
if (!$id) json_response(false, 'Geçersiz ID.');
$customer = db_row("SELECT id, full_name FROM customers WHERE id = ?", [$id]);
if (!$customer) json_response(false, 'Müşteri bulunamadı.');
// Rezervasyon sayısını bildir ama silmeyi engelleme
$res_count = (int)db_value("SELECT COUNT(*) FROM reservations WHERE customer_id = ?", [$id]);
// Rezervasyonları müşteriden kopar (customer_id null yap, isim/telefon korunur)
db_run("UPDATE reservations SET customer_id = NULL WHERE customer_id = ?", [$id]);
db_run("DELETE FROM customers WHERE id = ?", [$id]);
$msg = 'Müşteri silindi.';
if ($res_count > 0) $msg .= " ($res_count rezervasyon kaydı müşterisiz bırakıldı.)";
json_response(true, $msg);
case 'get_detail':
// CSRF gerekmez - GET ile çağrılabilir
$cid = get_int('id') ?: post_int('id');
if (!$cid) json_response(false, 'ID gerekli.');
$cust = db_row(
"SELECT id, full_name, phone, admin_note FROM customers WHERE id=?",
[$cid]
);
if (!$cust) json_response(false, 'Müşteri bulunamadı.');
// admin_note'u log satırları + temiz not olarak ayır
$name_log_pattern = '/^\d{2}\.\d{2}\.\d{4}: /';
$note_lines = array_filter(explode("\n", $cust['admin_note'] ?? ''), 'strlen');
$log_lines = array_filter($note_lines, fn($l) => preg_match($name_log_pattern, ltrim($l)));
$clean_lines = array_filter($note_lines, fn($l) => !preg_match($name_log_pattern, ltrim($l)));
// Log satırlarını parse et
$parsed_logs = [];
foreach ($log_lines as $log) {
// "03.05.2026: "Yeni" adıyla rezervasyon yaptı (eski: "Eski")"
if (preg_match('/^(\d{2}\.\d{2}\.\d{4}): "([^"]+)" adıyla rezervasyon yaptı \(eski: "([^"]+)"\)/', trim($log), $m)) {
$parsed_logs[] = ['date' => $m[1], 'new_name' => $m[2], 'old_name' => $m[3]];
}
}
$cust['admin_note_clean'] = implode("\n", $clean_lines);
$cust['name_logs'] = $parsed_logs;
// Rezervasyon geçmişi
$reservations = db_rows(
"SELECT full_name, DATE_FORMAT(date,'%d.%m.%Y') AS date,
TIME_FORMAT(time,'%H:%i') AS time, guest_count, status
FROM reservations WHERE customer_id=? ORDER BY date DESC LIMIT 30",
[$cid]
);
json_response(true, '', [
'customer' => $cust,
'reservations' => $reservations,
'name_logs' => $parsed_logs,
]);
case 'set_name':
if (!is_admin()) json_response(false, 'Yetki gerekli.');
if (!$id) json_response(false, 'ID gerekli.');
$new_name = trim(post_str('full_name'));
if (!$new_name) json_response(false, 'İsim boş olamaz.');
db_run("UPDATE customers SET full_name=? WHERE id=?", [$new_name, $id]);
json_response(true, 'Müşteri ismi güncellendi.');
default:
json_response(false, 'Geçersiz işlem.');
}