0; $cliente = null; $errors = []; $success = ''; // Labels for tramites $tipoLabels = [ 'visa' => 'Visa', 'sentri' => 'Sentri/Global', 'pasaporte' => 'Pasaporte', 'adelanto_cita' => 'Adelanto Cita', 'doble_nacionalidad' => 'Doble Nacionalidad', ]; $estadoLabels = [ 'nuevo' => 'Nuevo', 'en_proceso' => 'En Proceso', 'en_revision' => 'En Revisión', 'completado' => 'Completado', 'cancelado' => 'Cancelado', ]; // ── Handle POST actions ───────────────────────────────────────── if ($_SERVER['REQUEST_METHOD'] === 'POST' && csrfValidate()) { $action = $_POST['action'] ?? 'save_client'; switch ($action) { // ── Save client (create / update) ───────────────────────── case 'save_client': $nombre = trim($_POST['nombre'] ?? ''); $telefono = trim($_POST['telefono'] ?? ''); $email = trim($_POST['email'] ?? ''); $direccion = trim($_POST['direccion'] ?? ''); $notas = trim($_POST['notas'] ?? ''); if ($nombre === '') { $errors[] = 'El nombre es obligatorio.'; } if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) { $errors[] = 'El email no es válido.'; } if (empty($errors)) { if ($isEdit) { $stmt = $db->prepare("UPDATE clientes SET nombre=?, telefono=?, email=?, direccion=?, notas=? WHERE id=?"); $stmt->execute([$nombre, $telefono, $email, $direccion, $notas, $clienteId]); header("Location: cliente-detalle.php?id=$clienteId&saved=1"); exit; } else { $stmt = $db->prepare("INSERT INTO clientes (nombre, telefono, email, direccion, notas) VALUES (?,?,?,?,?)"); $stmt->execute([$nombre, $telefono, $email, $direccion, $notas]); $newId = $db->lastInsertId(); // If created from solicitud, link them $fromSolicitud = (int)($_POST['from_solicitud'] ?? 0); if ($fromSolicitud > 0) { $stmt2 = $db->prepare("UPDATE solicitudes SET cliente_id=?, estado='convertida' WHERE id=?"); $stmt2->execute([$newId, $fromSolicitud]); } header("Location: cliente-detalle.php?id=$newId&saved=1"); exit; } } break; // ── Add credential ──────────────────────────────────────── case 'add_credential': if (!$isEdit) break; $portal = trim($_POST['cred_portal'] ?? ''); $usuario = trim($_POST['cred_usuario'] ?? ''); $password = $_POST['cred_password'] ?? ''; $credNotas = trim($_POST['cred_notas'] ?? ''); if ($portal === '' || $usuario === '' || $password === '') { $errors[] = 'Portal, usuario y contraseña son obligatorios.'; } else { $passwordEnc = encryptData($password); $stmt = $db->prepare("INSERT INTO credenciales (cliente_id, portal, usuario, password_enc, notas) VALUES (?,?,?,?,?)"); $stmt->execute([$clienteId, $portal, $usuario, $passwordEnc, $credNotas]); header("Location: cliente-detalle.php?id=$clienteId&cred_saved=1#credenciales"); exit; } break; // ── Delete credential ───────────────────────────────────── case 'delete_credential': if (!$isEdit) break; $credId = (int)($_POST['cred_id'] ?? 0); if ($credId > 0) { $stmt = $db->prepare("DELETE FROM credenciales WHERE id=? AND cliente_id=?"); $stmt->execute([$credId, $clienteId]); } header("Location: cliente-detalle.php?id=$clienteId&cred_deleted=1#credenciales"); exit; // ── Upload document ─────────────────────────────────────── case 'upload_document': if (!$isEdit) break; $docNombre = trim($_POST['doc_nombre'] ?? ''); $file = $_FILES['doc_archivo'] ?? null; if ($docNombre === '') { $errors[] = 'El nombre del documento es obligatorio.'; } if (!$file || $file['error'] !== UPLOAD_ERR_OK) { $errors[] = 'Debe seleccionar un archivo válido.'; } else { // Validate extension $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); if (!in_array($ext, ALLOWED_EXTENSIONS)) { $errors[] = 'Tipo de archivo no permitido. Permitidos: ' . implode(', ', ALLOWED_EXTENSIONS); } // Validate size if ($file['size'] > MAX_FILE_SIZE) { $errors[] = 'El archivo excede el tamaño máximo de ' . (MAX_FILE_SIZE / 1024 / 1024) . ' MB.'; } } if (empty($errors)) { // Create client upload directory $uploadDir = UPLOAD_DIR . 'client_' . $clienteId . '/'; if (!is_dir($uploadDir)) { mkdir($uploadDir, 0755, true); } // Generate unique filename $safeFilename = preg_replace('/[^a-zA-Z0-9_\-.]/', '_', $file['name']); $filename = time() . '_' . $safeFilename; $destPath = $uploadDir . $filename; if (move_uploaded_file($file['tmp_name'], $destPath)) { $rutaArchivo = 'client_' . $clienteId . '/' . $filename; $stmt = $db->prepare("INSERT INTO documentos (cliente_id, nombre, ruta_archivo, tipo) VALUES (?,?,?,?)"); $stmt->execute([$clienteId, $docNombre, $rutaArchivo, $ext]); header("Location: cliente-detalle.php?id=$clienteId&doc_saved=1#documentos"); exit; } else { $errors[] = 'Error al subir el archivo. Intente de nuevo.'; } } break; // ── Delete document ─────────────────────────────────────── case 'delete_document': if (!$isEdit) break; $docId = (int)($_POST['doc_id'] ?? 0); if ($docId > 0) { // Get file path before deleting $stmt = $db->prepare("SELECT ruta_archivo FROM documentos WHERE id=? AND cliente_id=?"); $stmt->execute([$docId, $clienteId]); $doc = $stmt->fetch(); if ($doc) { // Remove file from disk $filePath = UPLOAD_DIR . $doc['ruta_archivo']; if (file_exists($filePath)) { unlink($filePath); } // Remove DB record $stmt = $db->prepare("DELETE FROM documentos WHERE id=? AND cliente_id=?"); $stmt->execute([$docId, $clienteId]); } } header("Location: cliente-detalle.php?id=$clienteId&doc_deleted=1#documentos"); exit; } } // ── Handle download (GET) ─────────────────────────────────────── if (isset($_GET['download']) && $isEdit) { $docId = (int)$_GET['download']; $stmt = $db->prepare("SELECT nombre, ruta_archivo, tipo FROM documentos WHERE id=? AND cliente_id=?"); $stmt->execute([$docId, $clienteId]); $doc = $stmt->fetch(); if ($doc) { $filePath = UPLOAD_DIR . $doc['ruta_archivo']; if (file_exists($filePath)) { $mimeTypes = [ 'pdf' => 'application/pdf', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'doc' => 'application/msword', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', ]; $mime = $mimeTypes[$doc['tipo']] ?? 'application/octet-stream'; $downloadName = $doc['nombre'] . '.' . $doc['tipo']; header('Content-Type: ' . $mime); header('Content-Disposition: attachment; filename="' . $downloadName . '"'); header('Content-Length: ' . filesize($filePath)); header('Cache-Control: no-cache, must-revalidate'); readfile($filePath); exit; } } // File not found — continue to page with error $errors[] = 'Documento no encontrado.'; } // ── Load client data for edit mode ────────────────────────────── if ($isEdit) { $stmt = $db->prepare("SELECT * FROM clientes WHERE id=?"); $stmt->execute([$clienteId]); $cliente = $stmt->fetch(); if (!$cliente) { header('Location: clientes.php'); exit; } // Fetch credentials $stmtCred = $db->prepare("SELECT * FROM credenciales WHERE cliente_id=? ORDER BY created_at DESC"); $stmtCred->execute([$clienteId]); $credenciales = $stmtCred->fetchAll(); // Fetch documents $stmtDoc = $db->prepare("SELECT * FROM documentos WHERE cliente_id=? ORDER BY created_at DESC"); $stmtDoc->execute([$clienteId]); $documentos = $stmtDoc->fetchAll(); // Fetch tramites $stmtTram = $db->prepare("SELECT * FROM tramites WHERE cliente_id=? ORDER BY fecha_solicitud DESC, created_at DESC"); $stmtTram->execute([$clienteId]); $tramites = $stmtTram->fetchAll(); } // ── Pre-fill from solicitud if creating new ───────────────────── $fromSolicitud = 0; $prefill = ['nombre' => '', 'telefono' => '', 'email' => '', 'direccion' => '', 'notas' => '']; if (!$isEdit && isset($_GET['from_solicitud'])) { $fromSolicitud = (int)$_GET['from_solicitud']; if ($fromSolicitud > 0) { $stmt = $db->prepare("SELECT nombre, telefono, email FROM solicitudes WHERE id=?"); $stmt->execute([$fromSolicitud]); $sol = $stmt->fetch(); if ($sol) { $prefill['nombre'] = $sol['nombre']; $prefill['telefono'] = $sol['telefono'] ?? ''; $prefill['email'] = $sol['email'] ?? ''; } } } // If POST had errors, preserve submitted data if (!empty($errors) && ($_POST['action'] ?? '') === 'save_client') { $prefill['nombre'] = $_POST['nombre'] ?? ''; $prefill['telefono'] = $_POST['telefono'] ?? ''; $prefill['email'] = $_POST['email'] ?? ''; $prefill['direccion'] = $_POST['direccion'] ?? ''; $prefill['notas'] = $_POST['notas'] ?? ''; } // Success messages from redirects if (isset($_GET['saved'])) $success = 'Datos del cliente guardados correctamente.'; if (isset($_GET['cred_saved'])) $success = 'Credencial agregada correctamente.'; if (isset($_GET['cred_deleted'])) $success = 'Credencial eliminada.'; if (isset($_GET['doc_saved'])) $success = 'Documento subido correctamente.'; if (isset($_GET['doc_deleted'])) $success = 'Documento eliminado.'; $pageTitle = $isEdit ? 'Cliente: ' . ($cliente['nombre'] ?? '') : 'Nuevo Cliente'; ?>

Volver a Clientes

Datos del Cliente

0): ?>
Registrado: — Actualizado:

Credenciales de Portales

Portal Usuario Contraseña Notas Acciones
••••••••

No hay credenciales registradas para este cliente.

Agregar Credencial

Documentos

Nombre Tipo Fecha Acciones

No hay documentos subidos para este cliente.

Subir Documento

Máx. MB. Formatos: PDF, JPG, PNG, DOC, DOCX

Historial de Trámites

Nuevo Trámite
Tipo Estado Fecha Solicitud Fecha Cita Precio Acción
Ver

No hay trámites registrados para este cliente.

Crear primer trámite