false, 'message' => 'No autorizado']); exit; } if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode(['success' => false, 'message' => 'Método no permitido']); exit; } function cc_test_normalize_nullable_text(string $key, int $maxLen = 3000): ?string { $value = trim((string) ($_POST[$key] ?? '')); if ($value === '') { return null; } if (mb_strlen($value) > $maxLen) { throw new RuntimeException('El campo ' . $key . ' es demasiado largo.'); } return $value; } $sourceKey = trim((string) ($_POST['source_key'] ?? '')); $estado = cc_test_normalize_state(trim((string) ($_POST['estado'] ?? 'POR LLAMAR'))); $validStates = cc_test_valid_states(); if ($sourceKey === '' || !preg_match('/^[a-f0-9]{40}$/', $sourceKey)) { http_response_code(400); echo json_encode(['success' => false, 'message' => 'Pedido de prueba inválido']); exit; } if (!in_array($estado, $validStates, true)) { http_response_code(400); echo json_encode(['success' => false, 'message' => 'Estado inválido']); exit; } try { $nota = cc_test_normalize_nullable_text('nota_seguimiento', 3000); $direccion = cc_test_normalize_nullable_text('direccion', 1000); $referencia = cc_test_normalize_nullable_text('referencia', 1000); $sede = cc_test_normalize_nullable_text('sede', 120); $ciudad = cc_test_normalize_nullable_text('ciudad', 120); $distrito = cc_test_normalize_nullable_text('distrito', 120); $dni = cc_test_normalize_nullable_text('dni', 40); $observaciones = cc_test_normalize_nullable_text('observaciones', 3000); $pdo = db(); cc_test_ensure_tracking_table($pdo); $stmtCurrent = $pdo->prepare('SELECT estado, numero_cuenta_enviado_at FROM callcenter_test_tracking WHERE source_key = ? LIMIT 1'); $stmtCurrent->execute([$sourceKey]); $currentTracking = $stmtCurrent->fetch(PDO::FETCH_ASSOC) ?: null; $proximaRaw = trim((string) ($_POST['proxima_llamada_at'] ?? '')); $proximaLlamada = null; if ($proximaRaw !== '') { $proximaLlamada = DateTimeImmutable::createFromFormat('Y-m-d\TH:i', $proximaRaw); if (!$proximaLlamada) { throw new RuntimeException('La fecha de próxima llamada no es válida.'); } $proximaLlamada = $proximaLlamada->format('Y-m-d H:i:s'); } $fechaEntregaRaw = trim((string) ($_POST['fecha_entrega_programada'] ?? '')); $fechaEntrega = null; if ($fechaEntregaRaw !== '') { $fechaEntregaDate = DateTimeImmutable::createFromFormat('Y-m-d', $fechaEntregaRaw); if (!$fechaEntregaDate) { throw new RuntimeException('La fecha de entrega no es válida.'); } $fechaEntrega = $fechaEntregaDate->format('Y-m-d'); } if (cc_test_requires_delivery_date($estado) && $fechaEntrega === null) { throw new RuntimeException('Debes seleccionar la fecha de entrega para CONFIRMADO CONTRAENTREGA.'); } if (!in_array($estado, cc_test_open_states(), true)) { $proximaLlamada = null; } if (!cc_test_requires_delivery_date($estado)) { $fechaEntrega = null; } $numeroCuentaEnviadoAt = $currentTracking['numero_cuenta_enviado_at'] ?? null; $currentState = cc_test_normalize_state((string) ($currentTracking['estado'] ?? '')); if ($estado === 'SE ENVIO NUMERO DE CUENTA') { if ($currentState !== 'SE ENVIO NUMERO DE CUENTA' || trim((string) $numeroCuentaEnviadoAt) === '') { $numeroCuentaEnviadoAt = (new DateTimeImmutable('now'))->format('Y-m-d H:i:s'); } } $stmt = $pdo->prepare( 'INSERT INTO callcenter_test_tracking ( source_key, estado, nota_seguimiento, user_id, direccion, referencia, sede, ciudad, distrito, dni, observaciones, proxima_llamada_at, fecha_entrega_programada, numero_cuenta_enviado_at, ultima_gestion_at ) VALUES ( :source_key, :estado, :nota, :user_id, :direccion, :referencia, :sede, :ciudad, :distrito, :dni, :observaciones, :proxima_llamada_at, :fecha_entrega_programada, :numero_cuenta_enviado_at, CURRENT_TIMESTAMP ) ON DUPLICATE KEY UPDATE estado = VALUES(estado), nota_seguimiento = VALUES(nota_seguimiento), user_id = VALUES(user_id), direccion = VALUES(direccion), referencia = VALUES(referencia), sede = VALUES(sede), ciudad = VALUES(ciudad), distrito = VALUES(distrito), dni = VALUES(dni), observaciones = VALUES(observaciones), proxima_llamada_at = VALUES(proxima_llamada_at), fecha_entrega_programada = VALUES(fecha_entrega_programada), numero_cuenta_enviado_at = VALUES(numero_cuenta_enviado_at), ultima_gestion_at = CURRENT_TIMESTAMP, updated_at = CURRENT_TIMESTAMP' ); $stmt->execute([ ':source_key' => $sourceKey, ':estado' => $estado, ':nota' => $nota, ':user_id' => (int) $_SESSION['user_id'], ':direccion' => $direccion, ':referencia' => $referencia, ':sede' => $sede, ':ciudad' => $ciudad, ':distrito' => $distrito, ':dni' => $dni, ':observaciones' => $observaciones, ':proxima_llamada_at' => $proximaLlamada, ':fecha_entrega_programada' => $fechaEntrega, ':numero_cuenta_enviado_at' => $numeroCuentaEnviadoAt, ]); echo json_encode([ 'success' => true, 'message' => 'Gestión actualizada correctamente.', 'estado' => $estado, 'proxima_llamada_at' => $proximaLlamada, 'fecha_entrega_programada' => $fechaEntrega, 'numero_cuenta_enviado_at' => $numeroCuentaEnviadoAt, ]); } catch (Throwable $exception) { http_response_code(500); error_log('update_callcenter_test_tracking.php: ' . $exception->getMessage()); echo json_encode([ 'success' => false, 'message' => $exception instanceof RuntimeException ? $exception->getMessage() : 'No se pudo guardar la gestión.', ]); }