diff --git a/app/controllers/productos_frecuentes.php b/app/controllers/productos_frecuentes.php index 9bf9a34..7ab4da0 100644 --- a/app/controllers/productos_frecuentes.php +++ b/app/controllers/productos_frecuentes.php @@ -5,8 +5,61 @@ require_once __DIR__ . '/../../config/database.php'; require_once __DIR__ . '/../../vendor/autoload.php'; // 2) Carga nuestro helper de entorno y dispara la carga de .env require_once __DIR__ . '/../helpers/env.php'; + loadEnv(); +/** Obtiene (y cachea en sesión) el JWT de la API usando las credenciales de $_ENV **/ +/** Obtiene (y cachea) el JWT de la API usando credenciales de $_ENV + * Gestiona expiración: asume 1 hora de vida y renueva si ha pasado. **/ +function getApiToken(): ?string +{ + // Duración en segundos del token (60 min) + $ttl = 3600; + + // 1) Si ya tenemos token y no ha expirado, lo devolvemos + if (!empty($_SESSION['api_token']) && !empty($_SESSION['api_token_time'])) { + $age = time() - $_SESSION['api_token_time']; + if ($age < $ttl) { + error_log("[getApiToken] Usando token en caché (edad: {$age}s)"); + return $_SESSION['api_token']; + } + error_log("[getApiToken] Token expirado (edad: {$age}s), obteniendo uno nuevo"); + } + + // 2) Sí o sí hacemos login en la API + $url = rtrim($_ENV['API_URL'] ?? '', '/') . '/auth/login'; + $user = $_ENV['API_USER'] ?? ''; + $pass = $_ENV['API_PASS'] ?? ''; + $body = json_encode(['username' => $user, 'password' => $pass]); + + error_log("[getApiToken] POST $url"); + + $ch = curl_init($url); + curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_HTTPHEADER => ['Content-Type: application/json'], + CURLOPT_POSTFIELDS => $body, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 5, + ]); + $resp = curl_exec($ch); + $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + error_log("[getApiToken] HTTP $http"); + + if ($http === 200 && ($data = json_decode($resp, true)) && !empty($data['token'])) { + // 3) Guardamos token y tiempo actual + $_SESSION['api_token'] = $data['token']; + $_SESSION['api_token_time'] = time(); + return $data['token']; + } + + // 4) Si no se pudo obtener, devolvemos null + error_log('[getApiToken] No se pudo obtener token de la API'); + return null; +} + /** GET /IMPORTADORES/productos_frecuentes * Muestra el listado **/ function index() @@ -14,6 +67,90 @@ function index() lista(); } +function lista() +{ + if (empty($_SESSION['usuario_id'])) { + header('Location: /IMPORTADORES/login'); + exit; + } + + $conn = getConnection(); + + // === Obtener proveedores desde API === + $token = getApiToken(); + $proveedoresApi = []; + + if ($token) { + $apiBase = rtrim($_ENV['API_URL'] ?? '', '/'); + $url = $apiBase . '/proveedores'; + + $ch = curl_init($url); + curl_setopt_array($ch, [ + CURLOPT_HTTPHEADER => ["Authorization: Bearer $token", 'Accept: application/json'], + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 5, + ]); + $resp = curl_exec($ch); + $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($status === 200 && ($json = json_decode($resp, true)) && is_array($json)) { + foreach ($json as $p) { + $clave = $p['Clave'] ?? ''; + $nombre = $p['Nombre'] ?? ''; + if ($clave) { + $proveedoresApi[$clave] = $nombre; + } + } + } + } + + // === Consulta de productos frecuentes === + $sql = "SELECT + pf.id_producto_frecuente, + pf.sinonimo, + pf.fraccion, + pf.nico, + pf.numero_parte, + pf.proveedor AS proveedor_guardado, + u.descripcion AS unidad_de_medida, + por.nombre AS pais_origen_destino, + pc.nombre AS pais_comprador_vendedor, + pf.uso_mercancia, + pf.estado_mercancia, + pf.preferencia, + pf.frecuencia_uso + FROM dbo.productos_frecuentes pf + LEFT JOIN dbo.unidades_medida_apendice7 u + ON pf.umc_id = u.id + LEFT JOIN dbo.paises por + ON pf.pais_origen_destino = por.nombre + LEFT JOIN dbo.paises pc + ON pf.pais_comprador_vendedor = pc.nombre + WHERE pf.id_importador = ? + AND pf.status = 1 + ORDER BY pf.fecha_alta DESC + "; + $stmt = sqlsrv_query($conn, $sql, [$_SESSION['usuario_id']]); + + if ($stmt === false) { + echo '
', print_r(sqlsrv_errors(), true), ''; + exit; + } + + // === Construir arreglo de productos con nombre de proveedor === + $productos = []; + + while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { + $clave = $row['proveedor_guardado']; + $row['nombre_proveedor'] = $proveedoresApi[$clave] ?? 'N/D'; + $productos[] = $row; + } + + // === Cargar la vista con productos y nombres de proveedor === + include __DIR__ . '/../../views/productos_frecuentes/lista.php'; +} + function ajax_paises() { // Sólo importadores pueden usarlo @@ -58,7 +195,7 @@ function ajax_proveedores() $ch = curl_init($url); curl_setopt_array($ch, [ - CURLOPT_HTTPHEADER => ["Authorization: $token", 'Accept: application/json'], + CURLOPT_HTTPHEADER => ["Authorization: Bearer $token", 'Accept: application/json'], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5, ]); @@ -84,14 +221,30 @@ function ajax_proveedores() exit; } -function lista() +function ajax_unidades() { - if (empty($_SESSION['usuario_id'])) { - header('Location: /IMPORTADORES/login'); + // Sólo importadores pueden usarlo + if (empty($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador') { + http_response_code(401); + echo json_encode(['results' => []]); exit; } - include __DIR__ . '/../../views/productos_frecuentes/lista.php'; + $conn = getConnection(); + + $sql = "SELECT id, descripcion FROM dbo.unidades_medida_apendice7 ORDER BY descripcion"; + $stmt = sqlsrv_query($conn, $sql); + + $out = ['results' => []]; + while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { + $out['results'][] = [ + 'id' => $row['id'], + 'text' => $row['descripcion'] + ]; + } + + echo json_encode($out); + exit; } /** GET /IMPORTADORES/productos_frecuentes/alta @@ -117,38 +270,118 @@ function guardar() $conn = getConnection(); + $errores = []; + $id_importador = $_SESSION['usuario_id']; + // Recoger y sanear $sinonimo = trim($_POST['sinonimo'] ?? ''); $fraccion = trim($_POST['fraccion'] ?? ''); $nico = trim($_POST['nico'] ?? ''); - $numero_parte = trim($_POST['numero_parte'] ?? null); - $descripcion = trim($_POST['descripcion'] ?? null); + $numero_parte = trim($_POST['numero_parte'] ?? ''); + $descripcion = trim($_POST['descripcion'] ?? ''); $umc_id = intval($_POST['umc_id'] ?? 0); - $pais_origen_destino = trim($_POST['pais_origen_destino'] ?? null); - $pais_comprador_vendedor = trim($_POST['pais_comprador_vendedor'] ?? null); - $uso_mercancia = trim($_POST['uso_mercancia'] ?? null); - $estado_mercancia = trim($_POST['estado_mercancia'] ?? null); - $vinculacion = trim($_POST['vinculacion'] ?? null); - $observaciones = trim($_POST['observaciones'] ?? null); - $preferencia = trim($_POST['preferencia'] ?? null); - $criterio_preferencia = trim($_POST['criterio_preferencia'] ?? null); - $uso_producto = trim($_POST['uso_producto'] ?? null); - $descripcion_producto = trim($_POST['descripcion_producto'] ?? null); - $certificado_origen = isset($_POST['certificado_origen']) ? 1 : 0; - $tipo_mercancia = trim($_POST['tipo_mercancia'] ?? null); + $pais_origen_destino = trim($_POST['pais_origen_destino'] ?? ''); + $pais_comprador_vendedor = trim($_POST['pais_comprador_vendedor'] ?? ''); + $uso_mercancia = trim($_POST['uso_mercancia'] ?? ''); + $estado_mercancia = trim($_POST['estado_mercancia'] ?? ''); + $vinculacion = trim($_POST['vinculacion'] ?? ''); + $observaciones = trim($_POST['observaciones'] ?? ''); + $preferencia = trim($_POST['preferencia'] ?? ''); + $criterio_preferencia = trim($_POST['criterio_preferencia'] ?? ''); + $uso_producto = trim($_POST['uso_producto'] ?? ''); + $descripcion_producto = trim($_POST['descripcion_producto'] ?? ''); + $certificado_origen = trim($_POST['certificado_origen'] ?? ''); + $tipo_mercancia = trim($_POST['tipo_mercancia'] ?? ''); $documento_en_original = isset($_POST['documento_en_original']) ? 1 : 0; - $proveedor = trim($_POST['proveedor'] ?? null); - $id_importador = intval($_SESSION['usuario_id']); - $status = 1; + $proveedor = trim($_POST['proveedor'] ?? ''); + $status = intval($_POST['status'] ?? 1); $frecuencia_uso = intval($_POST['frecuencia_uso'] ?? 1); - // Validación mínima - if ($sinonimo === '' || $fraccion === '' || $nico === '' || $umc_id <= 0) { - $_SESSION['flash_error'] = 'Sinónimo, Fracción, NICO y Unidad de Medida son obligatorios.'; + // Validación de campos obligatorios (según tu formulario) + if ($sinonimo === '') { + $errores[] = 'El sinónimo es obligatorio'; + } + if ($fraccion === '') { + $errores[] = 'La fracción es obligatoria'; + } + if ($nico === '') { + $errores[] = 'El NICO es obligatorio'; + } + if ($numero_parte === '') { + $errores[] = 'El número de parte es obligatorio'; + } + if ($pais_origen_destino === '') { + $errores[] = 'El país de origen/destino es obligatorio'; + } + if ($pais_comprador_vendedor === '') { + $errores[] = 'El país comprador/vendedor es obligatorio'; + } + if ($umc_id <= 0) { + $errores[] = 'La unidad de medida es obligatoria'; + } + + // Validar que NICO solo contenga números + if (!preg_match('/^[0-9]+$/', $nico)) { + $errores[] = 'El NICO solo puede contener números'; + } + + // **SOLUCIÓN PRINCIPAL: Convertir IDs de países a nombres** + $pais_origen_nombre = null; + $pais_comprador_nombre = null; + + if (!empty($pais_origen_destino)) { + $sql_pais = "SELECT nombre FROM dbo.paises WHERE id_pais = ?"; + $stmt_pais = sqlsrv_query($conn, $sql_pais, [intval($pais_origen_destino)]); + + if ($stmt_pais && $row = sqlsrv_fetch_array($stmt_pais, SQLSRV_FETCH_ASSOC)) { + $pais_origen_nombre = $row['nombre']; + } else { + $errores[] = 'País de origen/destino no válido'; + } + } + + if (!empty($pais_comprador_vendedor)) { + $sql_pais = "SELECT nombre FROM dbo.paises WHERE id_pais = ?"; + $stmt_pais = sqlsrv_query($conn, $sql_pais, [intval($pais_comprador_vendedor)]); + + if ($stmt_pais && $row = sqlsrv_fetch_array($stmt_pais, SQLSRV_FETCH_ASSOC)) { + $pais_comprador_nombre = $row['nombre']; + } else { + $errores[] = 'País comprador/vendedor no válido'; + } + } + + // Validar que existe la unidad de medida + $sql_umc = "SELECT COUNT(*) as count FROM dbo.unidades_medida_apendice7 WHERE id = ?"; + $stmt_umc = sqlsrv_query($conn, $sql_umc, [$umc_id]); + + if ($stmt_umc && $row = sqlsrv_fetch_array($stmt_umc, SQLSRV_FETCH_ASSOC)) { + if ($row['count'] == 0) { + $errores[] = 'Unidad de medida no válida'; + } + } + + // Si hay errores, regresar + if (!empty($errores)) { + $_SESSION['flash_error'] = implode('. ', $errores); header('Location: /IMPORTADORES/productos_frecuentes/alta'); exit; } + // Convertir valores vacíos a NULL para campos opcionales + if ($numero_parte === '') $numero_parte = null; + if ($descripcion === '') $descripcion = null; + if ($uso_mercancia === '') $uso_mercancia = null; + if ($estado_mercancia === '') $estado_mercancia = null; + if ($vinculacion === '') $vinculacion = null; + if ($observaciones === '') $observaciones = null; + if ($preferencia === '') $preferencia = null; + if ($criterio_preferencia === '') $criterio_preferencia = null; + if ($uso_producto === '') $uso_producto = null; + if ($descripcion_producto === '') $descripcion_producto = null; + if ($tipo_mercancia === '') $tipo_mercancia = null; + if ($proveedor === '') $proveedor = null; + // INSERT $sql = "INSERT INTO dbo.productos_frecuentes (sinonimo, fraccion, nico, numero_parte, descripcion, umc_id, @@ -160,20 +393,26 @@ function guardar() "; $params = [ $sinonimo, $fraccion, $nico, $numero_parte, $descripcion, $umc_id, - $pais_origen_destino, $pais_comprador_vendedor, $uso_mercancia, $estado_mercancia, $vinculacion, + $pais_origen_nombre, $pais_comprador_nombre, $uso_mercancia, $estado_mercancia, $vinculacion, $observaciones, $preferencia, $criterio_preferencia, $uso_producto, $descripcion_producto, $certificado_origen, $tipo_mercancia, $documento_en_original, $proveedor, $id_importador, $status, $frecuencia_uso ]; + + // Para debug - remover en producción + error_log("Datos a insertar: " . print_r($params, true)); + $stmt = sqlsrv_query($conn, $sql, $params); if ($stmt === false) { - $_SESSION['flash_error'] = 'Error al guardar el producto frecuente.'; + $errors = sqlsrv_errors(); + error_log("Error en SQL: " . print_r($errors, true)); + $_SESSION['flash_error'] = 'Error al guardar el producto.'; header('Location: /IMPORTADORES/productos_frecuentes/alta'); exit; } - $_SESSION['flash_success'] = 'Producto frecuente registrado correctamente.'; + $_SESSION['flash_success'] = 'Producto registrado correctamente.'; header('Location: /IMPORTADORES/productos_frecuentes'); exit; } @@ -205,6 +444,17 @@ function editar() exit; } + // Recuperar IDs reales desde nombres de país + foreach (['pais_origen_destino', 'pais_comprador_vendedor'] as $campo) { + $nombre = $producto[$campo]; + $stmtPais = sqlsrv_query($conn, "SELECT id_pais FROM dbo.paises WHERE nombre = ?", [$nombre]); + if ($stmtPais && ($row = sqlsrv_fetch_array($stmtPais, SQLSRV_FETCH_ASSOC))) { + $producto[$campo] = $row['id_pais']; + } else { + $producto[$campo] = null; + } + } + include __DIR__ . '/../../views/productos_frecuentes/editar.php'; } @@ -219,29 +469,91 @@ function actualizar() $conn = getConnection(); - $id = intval($_POST['id_producto_frecuente'] ?? 0); - $sinonimo = trim($_POST['sinonimo'] ?? ''); + $errores = []; + $id = intval($_POST['id_producto_frecuente'] ?? 0); + $sinonimo = trim($_POST['sinonimo'] ?? ''); + $fraccion = trim($_POST['fraccion'] ?? ''); + $nico = trim($_POST['nico'] ?? ''); + $numero_parte = trim($_POST['numero_parte'] ?? ''); + $descripcion = trim($_POST['descripcion'] ?? ''); + $umc_id = intval($_POST['umc_id'] ?? 0); + $pais_origen_destino = trim($_POST['pais_origen_destino'] ?? ''); + $pais_comprador_vendedor = trim($_POST['pais_comprador_vendedor'] ?? ''); + $uso_mercancia = trim($_POST['uso_mercancia'] ?? ''); + $estado_mercancia = trim($_POST['estado_mercancia'] ?? ''); + $vinculacion = trim($_POST['vinculacion'] ?? ''); + $observaciones = trim($_POST['observaciones'] ?? ''); + $preferencia = trim($_POST['preferencia'] ?? ''); + $criterio_preferencia = trim($_POST['criterio_preferencia'] ?? ''); + $uso_producto = trim($_POST['uso_producto'] ?? ''); + $descripcion_producto = trim($_POST['descripcion_producto'] ?? ''); + $certificado_origen = trim($_POST['certificado_origen'] ?? ''); + $tipo_mercancia = trim($_POST['tipo_mercancia'] ?? ''); + $documento_en_original = isset($_POST['documento_en_original']) ? 1 : 0; + $proveedor = trim($_POST['proveedor'] ?? ''); + + // Validar países + $pais_origen_nombre = null; + $pais_comprador_nombre = null; + + if (!empty($pais_origen_destino)) { + $sql_pais = "SELECT nombre FROM dbo.paises WHERE id_pais = ?"; + $stmt_pais = sqlsrv_query($conn, $sql_pais, [intval($pais_origen_destino)]); + if ($stmt_pais && ($row = sqlsrv_fetch_array($stmt_pais, SQLSRV_FETCH_ASSOC))) { + $pais_origen_nombre = $row['nombre']; + } else { + $errores[] = 'País de origen/destino no válido'; + } + } + + if (!empty($pais_comprador_vendedor)) { + $sql_pais = "SELECT nombre FROM dbo.paises WHERE id_pais = ?"; + $stmt_pais = sqlsrv_query($conn, $sql_pais, [intval($pais_comprador_vendedor)]); + if ($stmt_pais && ($row = sqlsrv_fetch_array($stmt_pais, SQLSRV_FETCH_ASSOC))) { + $pais_comprador_nombre = $row['nombre']; + } else { + $errores[] = 'País comprador/vendedor no válido'; + } + } + + // Validar unidad + $sql_umc = "SELECT COUNT(*) as count FROM dbo.unidades_medida_apendice7 WHERE id = ?"; + $stmt_umc = sqlsrv_query($conn, $sql_umc, [$umc_id]); + if (!$stmt_umc || ($row = sqlsrv_fetch_array($stmt_umc, SQLSRV_FETCH_ASSOC))['count'] == 0) { + $errores[] = 'Unidad de medida no válida'; + } + + // Si hay errores + if (!empty($errores)) { + $_SESSION['flash_error'] = implode('. ', $errores); + header("Location: /IMPORTADORES/productos_frecuentes/editar?id=$id"); + exit; + } + + // UPDATE $sql = "UPDATE dbo.productos_frecuentes SET - sinonimo = ?, fraccion = ?, nico = ?, numero_parte = ?, descripcion = ?, umc_id = ?, - pais_origen_destino = ?, pais_comprador_vendedor = ?, uso_mercancia = ?, estado_mercancia = ?, vinculacion = ?, - observaciones = ?, preferencia = ?, criterio_preferencia = ?, uso_producto = ?, descripcion_producto = ?, - certificado_origen = ?, tipo_mercancia = ?, documento_en_original = ?, proveedor = ? + sinonimo = ?, fraccion = ?, nico = ?, numero_parte = ?, descripcion = ?, + umc_id = ?, pais_origen_destino = ?, pais_comprador_vendedor = ?, + uso_mercancia = ?, estado_mercancia = ?, vinculacion = ?, observaciones = ?, + preferencia = ?, criterio_preferencia = ?, uso_producto = ?, descripcion_producto = ?, + certificado_origen = ?, tipo_mercancia = ?, documento_en_original = ?, proveedor = ? WHERE id_producto_frecuente = ? "; $params = [ - $sinonimo, $fraccion, $nico, $numero_parte, $descripcion, $umc_id, - $pais_origen_destino, $pais_comprador_vendedor, $uso_mercancia, $estado_mercancia, $vinculacion, - $observaciones, $preferencia, $criterio_preferencia, $uso_producto, $descripcion_producto, - $certificado_origen, $tipo_mercancia, $documento_en_original, $proveedor, $id + $sinonimo, $fraccion, $nico, $numero_parte, $descripcion, $umc_id, + $pais_origen_nombre, $pais_comprador_nombre, $uso_mercancia, $estado_mercancia, $vinculacion, + $observaciones, $preferencia, $criterio_preferencia, $uso_producto, $descripcion_producto, + $certificado_origen, $tipo_mercancia, $documento_en_original, $proveedor, $id ]; $stmt = sqlsrv_query($conn, $sql, $params); if ($stmt === false) { - $_SESSION['flash_error'] = 'Error al actualizar el producto frecuente.'; + $_SESSION['flash_error'] = 'Error al actualizar el producto.'; } else { - $_SESSION['flash_success'] = 'Producto frecuente actualizado correctamente.'; + $_SESSION['flash_success'] = 'Producto actualizado correctamente.'; } + header('Location: /IMPORTADORES/productos_frecuentes'); exit; } @@ -258,32 +570,6 @@ function importacion_csv() include __DIR__ . '/../../views/productos_frecuentes/importacion_csv.php'; } -function ajax_unidades() -{ - // Sólo importadores pueden usarlo - if (empty($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador') { - http_response_code(401); - echo json_encode(['results' => []]); - exit; - } - - $conn = getConnection(); - - $sql = "SELECT id, descripcion FROM dbo.unidades_medida_apendice7 ORDER BY descripcion"; - $stmt = sqlsrv_query($conn, $sql); - - $out = ['results' => []]; - while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { - $out['results'][] = [ - 'id' => $row['id'], - 'text' => $row['descripcion'] - ]; - } - - echo json_encode($out); - exit; -} - /** POST /IMPORTADORES/productos_frecuentes/procesar_csv * Procesa el upload y la inserción de CSV **/ function procesar_csv() @@ -320,4 +606,34 @@ function procesar_csv() $_SESSION['flash_success'] = 'Importación completada.'; header('Location: /IMPORTADORES/productos_frecuentes'); exit; +} + +function eliminar() +{ + if (empty($_SESSION['usuario_id'])) { + header('Location: /IMPORTADORES/login'); + exit; + } + + $id = $_GET['id'] ?? null; + + if (!$id || !is_numeric($id)) { + http_response_code(400); + echo "ID inválido"; + return; + } + + $conn = getConnection(); + + $sql = "UPDATE productos_frecuentes SET status = 0 WHERE id_producto_frecuente = ? AND id_importador = ?"; + $params = [$id, $_SESSION['usuario_id']]; + $stmt = sqlsrv_query($conn, $sql, $params); + + if ($stmt === false) { + echo '
', print_r(sqlsrv_errors(), true), ''; + exit; + } + + header('Location: /IMPORTADORES/productos_frecuentes?deleted=ok'); + exit; } \ No newline at end of file diff --git a/app/controllers/solicitud_importacion.php b/app/controllers/solicitud_importacion.php index 306ca0f..0e66f73 100644 --- a/app/controllers/solicitud_importacion.php +++ b/app/controllers/solicitud_importacion.php @@ -931,7 +931,7 @@ function generarPedimentoDesdeSolicitud($conn, $id, $usuarioId, $token) $ch = curl_init($urlPed); curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => 'POST', - CURLOPT_HTTPHEADER => ["Authorization: $token", 'Content-Type: application/json'], + CURLOPT_HTTPHEADER => ["Authorization: Bearer $token", 'Content-Type: application/json'], CURLOPT_POSTFIELDS => $jsonPayload, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, @@ -1025,7 +1025,7 @@ function ajax_lista() // 4) Ejecutamos cURL $ch = curl_init($url); curl_setopt_array($ch, [ - CURLOPT_HTTPHEADER => ["Authorization: $token", 'Accept: application/json'], + CURLOPT_HTTPHEADER => ["Authorization: Bearer $token", 'Accept: application/json'], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5, ]); @@ -1332,7 +1332,7 @@ function update_status() curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_HTTPHEADER => [ - "Authorization: $token", + "Authorization: Bearer $token", 'Content-Type: application/json' ], CURLOPT_POSTFIELDS => $jsonPayload, @@ -1448,15 +1448,15 @@ function enviarNotificacionCambioStatus($email, $nombreCompleto, $datosSolicitud /** Obtiene información del status (descripción y emoji) **/ function obtenerInfoStatus($status) { $statusMap = [ - 1 => ['emoji' => '🔄', 'descripcion' => 'En proceso', 'color' => '#17a2b8'], + 1 => ['emoji' => '🔄', 'descripcion' => 'En proceso', 'color' => '#17a2b8'], 2 => ['emoji' => '📋', 'descripcion' => 'Solicitar importación', 'color' => '#ffc107'], - 3 => ['emoji' => '🏢', 'descripcion' => 'Con agencia aduana', 'color' => '#6f42c1'], - 4 => ['emoji' => '💳', 'descripcion' => 'En proceso de pago', 'color' => '#fd7e14'], - 5 => ['emoji' => '✅', 'descripcion' => 'Pedimento generado', 'color' => '#28a745'], - 6 => ['emoji' => '📦', 'descripcion' => 'En tránsito', 'color' => '#007bff'], - 7 => ['emoji' => '🏁', 'descripcion' => 'Entregado', 'color' => '#28a745'], - 8 => ['emoji' => '❌', 'descripcion' => 'Cancelado', 'color' => '#dc3545'], - 9 => ['emoji' => '⏸️', 'descripcion' => 'Suspendido', 'color' => '#6c757d'] + 3 => ['emoji' => '🏢', 'descripcion' => 'Con agencia aduanal', 'color' => '#6f42c1'], + 4 => ['emoji' => '💳', 'descripcion' => 'En proceso de pago', 'color' => '#fd7e14'], + 5 => ['emoji' => '✅', 'descripcion' => 'Pedimento generado', 'color' => '#28a745'], + 6 => ['emoji' => '📦', 'descripcion' => 'En tránsito', 'color' => '#007bff'], + 7 => ['emoji' => '🏁', 'descripcion' => 'Entregado', 'color' => '#28a745'], + 8 => ['emoji' => '❌', 'descripcion' => 'Cancelado', 'color' => '#dc3545'], + 9 => ['emoji' => '⏸️', 'descripcion' => 'Suspendido', 'color' => '#6c757d'] ]; return $statusMap[$status] ?? [ @@ -1703,7 +1703,7 @@ function obtenerProveedorPorClave($clave) { // Ejecutar cURL para obtener todos los proveedores $ch = curl_init($url); curl_setopt_array($ch, [ - CURLOPT_HTTPHEADER => ["Authorization: $token", 'Accept: application/json'], + CURLOPT_HTTPHEADER => ["Authorization: Bearer $token", 'Accept: application/json'], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, ]); diff --git a/productos_frecuentes.txt b/productos_frecuentes.txt new file mode 100644 index 0000000..d700944 --- /dev/null +++ b/productos_frecuentes.txt @@ -0,0 +1,11 @@ +-- 1. Elimina la restricción DEFAULT +ALTER TABLE [Importaciones_HC].[dbo].[productos_frecuentes] +DROP CONSTRAINT [DF__productos__certi__3EDC53F0]; + +-- 2. Modifica el tipo de dato +ALTER TABLE [Importaciones_HC].[dbo].[productos_frecuentes] +ALTER COLUMN [certificado_origen] NVARCHAR(100); + +-- 3. (Opcional) Si quieres volver a agregar un valor por defecto +ALTER TABLE [Importaciones_HC].[dbo].[productos_frecuentes] +ADD CONSTRAINT DF_productos_certificado_origen DEFAULT '' FOR [certificado_origen]; diff --git a/views/choferes/crear.php b/views/choferes/crear.php index 0f534b4..c71641e 100644 --- a/views/choferes/crear.php +++ b/views/choferes/crear.php @@ -319,8 +319,7 @@ return; } if (!soloNumerosRegex.test(numero_licencia)) { - Swal.fire({ icon: 'error', title: 'Número de Licencia inválido', text: 'El número de licencia solo puede contener números', confirmButtonColor: '#dc3545' - }); + Swal.fire({ icon: 'error', title: 'Número de Licencia inválido', text: 'El número de licencia solo puede contener números', confirmButtonColor: '#dc3545' }); document.getElementById('numero_licencia').focus(); return; } diff --git a/views/partials/sidebar_importador.php b/views/partials/sidebar_importador.php index 8fd77f5..d014752 100644 --- a/views/partials/sidebar_importador.php +++ b/views/partials/sidebar_importador.php @@ -168,12 +168,14 @@ - • Editar Producto + • Ver Productos + @@ -364,12 +366,14 @@ - • Editar Producto + • Ver Productos + diff --git a/views/productos_frecuentes/alta.php b/views/productos_frecuentes/alta.php index 1ae708f..40ce835 100644 --- a/views/productos_frecuentes/alta.php +++ b/views/productos_frecuentes/alta.php @@ -1,23 +1,12 @@ 'No existe', - '1' => 'Existe, no afecta', - '2' => 'Existe y afecta' - ]; - $criterios = [ - 'A' => 'Criterio A', - 'B' => 'Criterio B', - 'C' => 'Criterio C', - 'D' => 'Criterio D', - 'E' => 'Criterio E', - 'F' => 'Criterio F' - ]; + $vinculaciones = [ '0' => 'No existe', '1' => 'Existe, no afecta', '2' => 'Existe y afecta' ]; + $criterios = [ 'A' => 'Criterio A', 'B' => 'Criterio B', 'C' => 'Criterio C', 'D' => 'Criterio D', 'E' => 'Criterio E', 'F' => 'Criterio F' ]; // Proveedores, unidades y países se cargan por AJAX ?> + @@ -48,9 +37,8 @@ .card-hover:hover { transform: translateY(-8px) scale(1.02); box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.15) !important; } .btn-pulse { animation: pulse 2s infinite; } @keyframes pulse { - 0% { transform: scale(1); } - 50% { transform: scale(1.05); } - 100% { transform: scale(1); } + 0%, 100% { transform: scale(1); } + 50% { transform: scale(1.05); } } .fade-in-up { animation: fadeInUp 0.8s ease-out; } @keyframes fadeInUp { @@ -137,27 +125,28 @@