Preparando proyecto para migración a repositorio MVE

This commit is contained in:
2025-10-23 08:48:00 -06:00
parent b1b9e4a77c
commit d0af739ce2
75 changed files with 15875 additions and 4022 deletions

13
public/check_session.php Normal file
View File

@@ -0,0 +1,13 @@
<?php
session_start();
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'sesion_activa' => isset($_SESSION['usuario']),
'usuario_datos' => $_SESSION['usuario'] ?? null,
'session_id' => session_id(),
'session_status' => session_status(),
'cookie_params' => session_get_cookie_params(),
'todas_las_sesiones' => $_SESSION ?? []
], JSON_PRETTY_PRINT);
?>

26
public/debug.php Normal file
View File

@@ -0,0 +1,26 @@
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
echo "=== DEBUG IMPORTADOR ===\n";
echo "POST: " . print_r($_POST, true) . "\n";
echo "FILES: " . print_r($_FILES, true) . "\n";
echo "SESSION: " . print_r($_SESSION ?? [], true) . "\n";
// Test de conexión a base de datos
try {
require_once __DIR__ . '/../config/database.php';
echo "Config database cargado OK\n";
$conn = getConnection();
echo "Conexión exitosa\n";
sqlsrv_close($conn);
echo "Conexión cerrada OK\n";
} catch (Exception $e) {
echo "ERROR: " . $e->getMessage() . "\n";
}
echo "=== FIN DEBUG ===\n";
?>

152
public/debug_partidas.php Normal file
View File

@@ -0,0 +1,152 @@
<?php
session_start();
require_once '../config/database.php';
if (!isset($_SESSION['usuario_id'])) {
die("Error: No hay sesión activa");
}
echo "<!DOCTYPE html>
<html lang='es'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>Debug - Partidas de Pedimentos</title>
<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css' rel='stylesheet'>
</head>
<body>
<div class='container mt-4'>
<h2>Debug - Últimas Partidas Insertadas</h2>";
try {
$conn = conectarBD();
// Obtener las últimas partidas con información del pedimento
$sql = "SELECT TOP 20
pp.id,
pp.secuencia,
pp.fraccion_arancelaria,
pp.descripcion,
pp.cantidad,
pp.unidad,
pp.valor_unitario,
pp.valor_total,
pp.peso_neto,
pp.peso_bruto,
pp.fecha_creacion,
p.numero_pedimento
FROM pedimento_partidas pp
INNER JOIN pedimentos p ON pp.pedimento_id = p.id
ORDER BY pp.fecha_creacion DESC";
$stmt = sqlsrv_query($conn, $sql);
if ($stmt === false) {
throw new Exception("Error en consulta: " . print_r(sqlsrv_errors(), true));
}
echo "<div class='table-responsive'>
<table class='table table-striped table-hover'>
<thead class='table-dark'>
<tr>
<th>ID</th>
<th>Pedimento</th>
<th>Secuencia</th>
<th>Fracción</th>
<th>Descripción</th>
<th>Cantidad</th>
<th>Unidad</th>
<th>Valor Unit.</th>
<th>Valor Total</th>
<th>Peso Neto</th>
<th>Peso Bruto</th>
<th>Fecha</th>
</tr>
</thead>
<tbody>";
$contador = 0;
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$contador++;
echo "<tr>
<td>{$row['id']}</td>
<td><strong>{$row['numero_pedimento']}</strong></td>
<td>{$row['secuencia']}</td>
<td><code>{$row['fraccion_arancelaria']}</code></td>
<td>" . (strlen($row['descripcion']) > 50 ? substr($row['descripcion'], 0, 50) . '...' : $row['descripcion']) . "</td>
<td>" . number_format($row['cantidad'], 4) . "</td>
<td>{$row['unidad']}</td>
<td>" . number_format($row['valor_unitario'], 4) . "</td>
<td>" . number_format($row['valor_total'], 4) . "</td>
<td>" . ($row['peso_neto'] ? number_format($row['peso_neto'], 4) : 'NULL') . "</td>
<td>" . ($row['peso_bruto'] ? number_format($row['peso_bruto'], 4) : 'NULL') . "</td>
<td>{$row['fecha_creacion']->format('Y-m-d H:i:s')}</td>
</tr>";
}
echo "</tbody></table></div>";
if ($contador == 0) {
echo "<div class='alert alert-warning'>No se encontraron partidas en la base de datos.</div>";
} else {
echo "<div class='alert alert-info'>Se encontraron $contador partidas.</div>";
}
// Estadísticas adicionales
$sql_stats = "SELECT
COUNT(*) as total_partidas,
COUNT(DISTINCT pedimento_id) as total_pedimentos,
AVG(cantidad) as promedio_cantidad,
AVG(valor_unitario) as promedio_valor_unitario
FROM pedimento_partidas";
$stmt_stats = sqlsrv_query($conn, $sql_stats);
if ($stmt_stats && $stats = sqlsrv_fetch_array($stmt_stats, SQLSRV_FETCH_ASSOC)) {
echo "<div class='row mt-4'>
<div class='col-md-3'>
<div class='card text-center'>
<div class='card-body'>
<h5 class='card-title'>Total Partidas</h5>
<p class='card-text display-6'>{$stats['total_partidas']}</p>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center'>
<div class='card-body'>
<h5 class='card-title'>Total Pedimentos</h5>
<p class='card-text display-6'>{$stats['total_pedimentos']}</p>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center'>
<div class='card-body'>
<h5 class='card-title'>Promedio Cantidad</h5>
<p class='card-text display-6'>" . number_format($stats['promedio_cantidad'], 2) . "</p>
</div>
</div>
</div>
<div class='col-md-3'>
<div class='card text-center'>
<div class='card-body'>
<h5 class='card-title'>Promedio Valor Unit.</h5>
<p class='card-text display-6'>" . number_format($stats['promedio_valor_unitario'], 2) . "</p>
</div>
</div>
</div>
</div>";
}
sqlsrv_close($conn);
} catch (Exception $e) {
echo "<div class='alert alert-danger'>Error: " . $e->getMessage() . "</div>";
}
echo "</div>
<script src='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js'></script>
</body>
</html>";
?>

View File

@@ -0,0 +1,134 @@
<?php
session_start();
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
// Función de logging mejorada
function logDebug($mensaje) {
error_log("[IMPORT_DEBUG] " . $mensaje);
}
try {
logDebug("=== INICIO DIAGNÓSTICO ===");
// 1. Verificar sesión
logDebug("Verificando sesión...");
$usuario_info = "No hay sesión";
if (isset($_SESSION['usuario_id'])) {
$usuario_info = "Usuario ID: " . $_SESSION['usuario_id'] .
", Tipo: " . ($_SESSION['tipo_usuario'] ?? 'sin_tipo');
}
logDebug("Estado sesión: " . $usuario_info);
// 2. Verificar método
logDebug("Método HTTP: " . $_SERVER['REQUEST_METHOD']);
// 3. Verificar archivo
$archivo_info = "No hay archivo";
if (isset($_FILES['archivo'])) {
$archivo_info = "Archivo: " . $_FILES['archivo']['name'] .
", Tamaño: " . $_FILES['archivo']['size'] .
", Error: " . $_FILES['archivo']['error'];
}
logDebug("Estado archivo: " . $archivo_info);
// 4. Verificar conexión a base de datos
logDebug("Verificando conexión DB...");
require_once __DIR__ . '/../config/database.php';
$conn = getConnection();
$db_info = $conn ? "Conexión exitosa" : "Error de conexión";
logDebug("Estado DB: " . $db_info);
// 5. Verificar directorio temporal
$temp_dir = __DIR__ . '/../storage/temp/';
logDebug("Directorio temp: " . $temp_dir);
logDebug("Existe directorio temp: " . (is_dir($temp_dir) ? "" : "NO"));
logDebug("Permisos escritura temp: " . (is_writable($temp_dir) ? "" : "NO"));
// Respuesta de diagnóstico
$respuesta = [
'success' => true,
'diagnostico' => 'Análisis completado',
'timestamp' => date('Y-m-d H:i:s'),
'checks' => [
'sesion' => isset($_SESSION['usuario_id']),
'usuario_id' => $_SESSION['usuario_id'] ?? null,
'tipo_usuario' => $_SESSION['tipo_usuario'] ?? null,
'metodo_post' => $_SERVER['REQUEST_METHOD'] === 'POST',
'archivo_recibido' => isset($_FILES['archivo']),
'archivo_nombre' => $_FILES['archivo']['name'] ?? null,
'archivo_error' => $_FILES['archivo']['error'] ?? null,
'conexion_db' => $conn !== false,
'directorio_temp_existe' => is_dir($temp_dir),
'directorio_temp_escribible' => is_writable($temp_dir)
],
'errores_potenciales' => []
];
// Detectar problemas
if (!isset($_SESSION['usuario_id'])) {
$respuesta['errores_potenciales'][] = "No hay usuario_id en sesión";
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
$respuesta['errores_potenciales'][] = "Método no es POST";
}
if (!isset($_FILES['archivo'])) {
$respuesta['errores_potenciales'][] = "No se recibió archivo";
} elseif ($_FILES['archivo']['error'] !== UPLOAD_ERR_OK) {
$respuesta['errores_potenciales'][] = "Error en upload: " . $_FILES['archivo']['error'];
}
if (!$conn) {
$respuesta['errores_potenciales'][] = "Error de conexión a base de datos";
}
if (!is_dir($temp_dir)) {
$respuesta['errores_potenciales'][] = "Directorio temporal no existe";
} elseif (!is_writable($temp_dir)) {
$respuesta['errores_potenciales'][] = "Directorio temporal no tiene permisos de escritura";
}
// Si no hay errores potenciales, intentar procesar
if (empty($respuesta['errores_potenciales']) && isset($_FILES['archivo'])) {
logDebug("Intentando procesar archivo...");
// Mover archivo temporal
$archivo_temporal = $temp_dir . 'test_' . time() . '_' . $_FILES['archivo']['name'];
if (move_uploaded_file($_FILES['archivo']['tmp_name'], $archivo_temporal)) {
$respuesta['archivo_procesado'] = true;
$respuesta['archivo_temporal'] = $archivo_temporal;
// Leer primeras líneas
$contenido = file_get_contents($archivo_temporal);
if ($contenido !== false) {
$lineas = explode("\n", array_slice(explode("\n", $contenido), 0, 5));
$respuesta['primeras_lineas'] = $lineas;
$respuesta['total_lineas'] = count(explode("\n", $contenido));
}
// Limpiar archivo
unlink($archivo_temporal);
} else {
$respuesta['errores_potenciales'][] = "No se pudo mover archivo temporal";
}
}
logDebug("Respuesta: " . json_encode($respuesta));
echo json_encode($respuesta, JSON_PRETTY_PRINT);
} catch (Exception $e) {
logDebug("EXCEPCIÓN: " . $e->getMessage());
logDebug("Stack trace: " . $e->getTraceAsString());
http_response_code(500);
echo json_encode([
'success' => false,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
], JSON_PRETTY_PRINT);
}
?>

View File

@@ -0,0 +1,89 @@
<?php
session_start();
// Forzar no cache
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
// Log de debug
error_log("=== NUEVO CONTROLADOR FUNCIONAL ===");
error_log("Método: " . $_SERVER['REQUEST_METHOD']);
error_log("POST data: " . print_r($_POST, true));
error_log("FILES data: " . print_r($_FILES, true));
try {
// Verificar método
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
throw new Exception("Método no permitido: " . $_SERVER['REQUEST_METHOD']);
}
// Verificar sesión (comentado temporalmente para test)
// if (!isset($_SESSION['usuario_id'])) {
// throw new Exception("Usuario no autenticado");
// }
$validar_duplicados = isset($_POST['validar_duplicados']) && $_POST['validar_duplicados'] === 'on';
error_log("Validar duplicados: " . ($validar_duplicados ? 'SÍ' : 'NO'));
// Contar archivos recibidos
$total_archivos = 0;
if (isset($_FILES['archivos']) && is_array($_FILES['archivos']['name'])) {
$total_archivos = count($_FILES['archivos']['name']);
error_log("Archivos múltiples detectados: " . $total_archivos);
} elseif (isset($_FILES['archivo'])) {
$total_archivos = 1;
error_log("Archivo individual detectado");
}
error_log("Total de archivos a procesar: " . $total_archivos);
if ($total_archivos === 0) {
throw new Exception("No se recibieron archivos para procesar");
}
// Simulación de procesamiento (reemplazar con lógica real después)
$estadisticas = [
'pedimentos_procesados' => $total_archivos * 2,
'facturas_procesadas' => $total_archivos * 3,
'partidas_procesadas' => $total_archivos * 5,
'duplicados' => 0,
'errores' => 0,
'total_lineas' => $total_archivos * 100
];
$respuesta = [
'success' => true,
'message' => 'Archivos procesados correctamente (MODO SIMULACIÓN)',
'estadisticas' => $estadisticas,
'archivos_procesados' => $total_archivos,
'archivos_con_errores' => [],
'debug_info' => [
'timestamp' => date('Y-m-d H:i:s'),
'total_archivos_recibidos' => $total_archivos,
'validar_duplicados' => $validar_duplicados
]
];
error_log("Enviando respuesta exitosa: " . json_encode($respuesta));
echo json_encode($respuesta);
} catch (Exception $e) {
error_log("ERROR: " . $e->getMessage());
$respuesta_error = [
'success' => false,
'message' => $e->getMessage(),
'debug_info' => [
'timestamp' => date('Y-m-d H:i:s'),
'error_file' => $e->getFile(),
'error_line' => $e->getLine()
]
];
http_response_code(500);
echo json_encode($respuesta_error);
}
?>

View File

@@ -0,0 +1,739 @@
<?php
session_start();
require_once __DIR__ . '/../config/database.php';
// Headers para AJAX
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');
// Log para debugging
error_log("=== INICIO IMPORTACIÓN ===");
error_log("Usuario ID en sesión: " . (isset($_SESSION['usuario_id']) ? $_SESSION['usuario_id'] : 'NO_USUARIO'));
error_log("Tipo usuario: " . (isset($_SESSION['tipo_usuario']) ? $_SESSION['tipo_usuario'] : 'NO_TIPO'));
error_log("Método: " . $_SERVER['REQUEST_METHOD']);
error_log("POST recibido: " . print_r($_POST, true));
error_log("FILES recibido: " . print_r($_FILES, true));
error_log("Tiene archivo individual: " . (isset($_FILES['archivo']) ? 'SÍ' : 'NO'));
error_log("Tiene archivos múltiples: " . (isset($_FILES['archivos']) ? 'SÍ' : 'NO'));
// Verificar que el usuario esté logueado
if (!isset($_SESSION['usuario_id'])) {
error_log("ERROR: Usuario no autenticado - no hay usuario_id en sesión");
http_response_code(401);
echo json_encode(['success' => false, 'message' => 'Usuario no autenticado']);
exit;
}
// Verificar que sea una petición POST
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['success' => false, 'message' => 'Método no permitido']);
exit;
}
// Verificar que se haya subido un archivo (individual o múltiple)
if (!isset($_FILES['archivo']) && !isset($_FILES['archivos'])) {
error_log("ERROR: No se encontraron archivos. FILES: " . print_r($_FILES, true));
http_response_code(400);
echo json_encode([
'success' => false,
'message' => 'No se ha recibido ningún archivo válido',
'debug' => $_FILES
]);
exit;
}
class ImportadorPedimentos {
private $conn;
private $estadisticas = [
'total_lineas' => 0,
'pedimentos_procesados' => 0,
'facturas_procesadas' => 0,
'partidas_procesadas' => 0,
'errores' => 0,
'duplicados' => 0
];
private $errores_detalle = [];
private $pedimentos_creados = [];
public function __construct($connection) {
$this->conn = $connection;
}
public function procesarArchivo($archivo_path, $validar_duplicados = true) {
// Reiniciar estadísticas y acumuladores por archivo para evitar sobreconteo entre múltiples archivos
$this->estadisticas = [
'total_lineas' => 0,
'pedimentos_procesados' => 0,
'facturas_procesadas' => 0,
'partidas_procesadas' => 0,
'errores' => 0,
'duplicados' => 0
];
$this->errores_detalle = [];
$this->pedimentos_creados = [];
$inicio_tiempo = time();
$nombre_archivo = basename($archivo_path);
try {
$contenido = file_get_contents($archivo_path);
if ($contenido === false) {
throw new Exception("No se pudo leer el archivo");
}
// Convertir encoding si es necesario (muchos archivos julianos usan Latin1)
if (!mb_check_encoding($contenido, 'UTF-8')) {
$contenido = mb_convert_encoding($contenido, 'UTF-8', 'ISO-8859-1');
}
$lineas = explode("\n", $contenido);
$this->estadisticas['total_lineas'] = count($lineas);
$pedimento_actual = null;
$facturas_pedimento = [];
$partidas_pedimento = [];
foreach ($lineas as $numero_linea => $linea) {
$linea = trim($linea);
if (empty($linea)) continue;
try {
$codigo = substr($linea, 0, 3);
switch ($codigo) {
case '500':
// Línea de header - ignorar por ahora
break;
case '501':
// Si hay un pedimento anterior, procesarlo
if ($pedimento_actual) {
$this->procesarPedimento($pedimento_actual, $facturas_pedimento, $partidas_pedimento, $validar_duplicados);
$facturas_pedimento = [];
$partidas_pedimento = [];
}
$pedimento_actual = $this->parsearLinea501Real($linea);
break;
case '505':
if ($pedimento_actual) {
try {
$factura = $this->parsearLinea505Real($linea);
$facturas_pedimento[] = $factura;
error_log("Factura 505 procesada exitosamente: " . $factura['numero_factura']);
} catch (Exception $e) {
error_log("ERROR procesando línea 505: " . $e->getMessage());
error_log("Línea problemática: " . $linea);
$this->estadisticas['errores']++;
// Continuar con la siguiente línea
}
}
break;
case '551':
if ($pedimento_actual) {
try {
$partida = $this->parsearLinea551Real($linea);
$partidas_pedimento[] = $partida;
error_log("Partida 551 procesada exitosamente: secuencia " . $partida['secuencia']);
} catch (Exception $e) {
error_log("ERROR procesando línea 551: " . $e->getMessage());
error_log("Línea problemática: " . $linea);
$this->estadisticas['errores']++;
// Continuar con la siguiente línea en lugar de fallar completamente
}
}
break;
case '506':
case '509':
case '510':
case '511':
case '553':
case '554':
case '556':
case '557':
case '558':
case '800':
case '801':
// Otros códigos del formato real - ignorar por ahora
break;
}
} catch (Exception $e) {
$this->errores_detalle[] = "Línea " . ($numero_linea + 1) . ": " . $e->getMessage();
$this->estadisticas['errores']++;
}
}
// Procesar el último pedimento
if ($pedimento_actual) {
$this->procesarPedimento($pedimento_actual, $facturas_pedimento, $partidas_pedimento, $validar_duplicados);
}
// Registrar log de importación
$tiempo_procesamiento = time() - $inicio_tiempo;
$this->registrarLog($nombre_archivo, $tiempo_procesamiento,
count($this->errores_detalle) > 0 ? 'con_errores' : 'exitoso');
return [
'success' => true,
'estadisticas' => $this->estadisticas,
'errores' => $this->errores_detalle,
'pedimentos_creados' => $this->pedimentos_creados
];
} catch (Exception $e) {
// Registrar log de error
$tiempo_procesamiento = time() - $inicio_tiempo;
$this->registrarLog($nombre_archivo, $tiempo_procesamiento, 'fallido', $e->getMessage());
return [
'success' => false,
'message' => $e->getMessage()
];
}
}
private function registrarLog($archivo_nombre, $tiempo_procesamiento, $estado, $error_mensaje = null) {
try {
$sql = "INSERT INTO importacion_logs (
usuario_id, archivo_nombre, total_lineas, pedimentos_procesados,
facturas_procesadas, partidas_procesadas, errores, duplicados,
tiempo_procesamiento, estado, detalles_errores
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$detalles_errores = null;
if (!empty($this->errores_detalle)) {
$detalles_errores = implode("\n", $this->errores_detalle);
} else if ($error_mensaje) {
$detalles_errores = $error_mensaje;
}
$params = [
isset($_SESSION['usuario_id']) ? $_SESSION['usuario_id'] : null,
$archivo_nombre,
$this->estadisticas['total_lineas'],
$this->estadisticas['pedimentos_procesados'],
$this->estadisticas['facturas_procesadas'],
$this->estadisticas['partidas_procesadas'],
$this->estadisticas['errores'],
$this->estadisticas['duplicados'],
$tiempo_procesamiento,
$estado,
$detalles_errores
];
$stmt = sqlsrv_query($this->conn, $sql, $params);
if ($stmt) {
sqlsrv_free_stmt($stmt);
}
} catch (Exception $e) {
// No hacer nada si falla el log, no queremos interrumpir el proceso principal
}
}
private function parsearLinea501($linea) {
// Formato: 501|numero_pedimento|patente|aduana|anio|clave_documento|rfc_importador|...
$campos = explode('|', $linea);
if (count($campos) < 7) {
throw new Exception("Formato inválido en línea 501");
}
return [
'numero_pedimento' => trim($campos[1]),
'patente' => trim($campos[2]),
'aduana' => trim($campos[3]),
'anio' => trim($campos[4]),
'clave_documento' => trim($campos[5]),
'rfc_importador' => trim($campos[6]),
'fecha_creacion' => date('Y-m-d H:i:s'),
'usuario_id' => $_SESSION['usuario_id']
];
}
private function parsearLinea501Real($linea) {
// Formato real: 501|patente|numero_pedimento|aduana|tipo|clave_documento|aduana2||rfc_importador|nombre_importador|...
$campos = explode('|', $linea);
if (count($campos) < 10) {
throw new Exception("Formato inválido en línea 501 real - campos insuficientes: " . count($campos));
}
error_log("Parseando 501 real: " . $linea);
error_log("Campos: " . print_r(array_slice($campos, 0, 10), true));
return [
'numero_pedimento' => trim($campos[2]), // Campo 2: numero de pedimento
'patente' => trim($campos[1]), // Campo 1: patente
'aduana' => trim($campos[3]), // Campo 3: aduana
'anio' => date('Y'), // Usar año actual
'clave_documento' => trim($campos[5]), // Campo 5: clave documento
'rfc_importador' => trim($campos[8]), // Campo 8: RFC importador
'fecha_creacion' => date('Y-m-d H:i:s'),
'usuario_id' => $_SESSION['usuario_id']
];
}
private function parsearLinea505($linea) {
// Formato: 505|numero_factura|fecha_factura|valor_dolares|valor_factura|...
$campos = explode('|', $linea);
if (count($campos) < 5) {
throw new Exception("Formato inválido en línea 505");
}
return [
'numero_factura' => trim($campos[1]),
'fecha_factura' => $this->convertirFecha(trim($campos[2])),
'valor_dolares' => floatval(trim($campos[3])),
'valor_factura' => floatval(trim($campos[4]))
];
}
private function parsearLinea505Real($linea) {
// Formato oficial 505: 505|numero_pedimento|fecha_cfdi|numero_cfdi_cove|termino_facturacion|moneda|valor_dolares|valor_total|pais|entidad_federativa|rfc_proveedor|nombre_proveedor|calle|num_int|num_ext|cp|municipio|...
$campos = explode('|', $linea);
if (count($campos) < 12) {
throw new Exception("Formato inválido en línea 505 - campos insuficientes: " . count($campos) . " (mínimo: 12)");
}
error_log("DEBUG 505 - Total campos: " . count($campos));
error_log("DEBUG 505 - Primeros 12 campos: " . implode(' | ', array_slice($campos, 0, 12)));
// Extraer datos según documentación oficial SAT
$numero_pedimento = trim($campos[1]); // Campo 1: Número de Pedimento
$fecha_cfdi = trim($campos[2]); // Campo 2: Fecha de CFDI
$numero_cfdi_cove = trim($campos[3]); // Campo 3: Número de CFDI (COVE) - 40 caracteres max
$termino_facturacion = trim($campos[4]); // Campo 4: Término de Facturación - 3 caracteres
$moneda = trim($campos[5]); // Campo 5: Moneda - 3 caracteres
$valor_dolares = floatval(trim($campos[6])); // Campo 6: Valor Total en Dólares USD
$valor_total = floatval(trim($campos[7])); // Campo 7: Valor Total en moneda del CFDI
$pais = trim($campos[8]); // Campo 8: País del CFDI - 3 caracteres
$entidad_federativa = trim($campos[9]); // Campo 9: Entidad Federativa - 3 caracteres
$rfc_proveedor = trim($campos[10]); // Campo 10: RFC Proveedor - 30 caracteres max
$nombre_proveedor = trim($campos[11]); // Campo 11: Nombre Proveedor - 120 caracteres max
error_log("DEBUG 505 - Datos oficiales extraídos:");
error_log(" - Número CFDI/COVE: '$numero_cfdi_cove'");
error_log(" - Fecha CFDI: '$fecha_cfdi'");
error_log(" - Término facturación: '$termino_facturacion'");
error_log(" - Moneda: '$moneda'");
error_log(" - Valor USD: $valor_dolares");
error_log(" - Valor total: $valor_total");
error_log(" - RFC Proveedor: '$rfc_proveedor'");
error_log(" - Nombre Proveedor: '$nombre_proveedor'");
return [
'numero_factura' => $numero_cfdi_cove, // Campo 3: Número de CFDI/COVE
'fecha_factura' => $this->convertirFechaReal($fecha_cfdi), // Campo 2: Fecha CFDI
'valor_dolares' => $valor_dolares, // Campo 6: Valor en USD
'valor_factura' => $valor_total, // Campo 7: Valor total en moneda CFDI
'cove' => $numero_cfdi_cove, // Campo 3: COVE (mismo que número factura)
'moneda' => $moneda, // Campo 5: Moneda
'proveedor' => $nombre_proveedor // Campo 11: Nombre del proveedor
];
}
private function parsearLinea551($linea) {
// Formato: 551|secuencia|fraccion_arancelaria|descripcion|cantidad|unidad|valor_unitario|...
$campos = explode('|', $linea);
if (count($campos) < 7) {
throw new Exception("Formato inválido en línea 551");
}
return [
'secuencia' => intval(trim($campos[1])),
'fraccion_arancelaria' => trim($campos[2]),
'descripcion' => trim($campos[3]),
'cantidad' => floatval(trim($campos[4])),
'unidad' => trim($campos[5]),
'valor_unitario' => floatval(trim($campos[6]))
];
}
private function parsearLinea551Real($linea) {
// Formato oficial 551: 551|numero_pedimento|fraccion_arancelaria|numero_partida|subdivision|descripcion|precio_unitario|valor_aduana|valor_comercial|valor_dolares|cantidad_umc|unidad_comercial|...
$campos = explode('|', $linea);
if (count($campos) < 12) {
throw new Exception("Formato inválido en línea 551 - campos insuficientes: " . count($campos) . " (mínimo: 12)");
}
error_log("DEBUG 551 - Total campos: " . count($campos));
error_log("DEBUG 551 - Primeros 12 campos: " . implode(' | ', array_slice($campos, 0, 12)));
// Extraer datos según documentación oficial
$numero_pedimento = isset($campos[1]) ? trim($campos[1]) : '';
$fraccion_arancelaria = isset($campos[2]) ? trim($campos[2]) : '';
$numero_partida = isset($campos[3]) ? intval(trim($campos[3])) : 0;
$subdivision = isset($campos[4]) ? trim($campos[4]) : '';
$descripcion = isset($campos[5]) ? trim($campos[5]) : '';
$precio_unitario = isset($campos[6]) ? floatval(trim($campos[6])) : 0;
$valor_aduana = isset($campos[7]) ? floatval(trim($campos[7])) : 0;
$valor_comercial = isset($campos[8]) ? floatval(trim($campos[8])) : 0;
$valor_dolares = isset($campos[9]) ? floatval(trim($campos[9])) : 0;
$cantidad_umc = isset($campos[10]) ? floatval(trim($campos[10])) : 0;
$unidad_comercial = isset($campos[11]) ? trim($campos[11]) : '';
// Aplicar valores por defecto según documentación oficial
if (empty($fraccion_arancelaria)) {
error_log("WARNING 551: Fracción arancelaria vacía, usando valor por defecto");
$fraccion_arancelaria = 'PENDIENTE';
}
if ($numero_partida <= 0) {
error_log("WARNING 551: Número de partida inválido, generando secuencial");
static $contador_partida = 1;
$numero_partida = $contador_partida++;
}
if (empty($descripcion)) {
error_log("WARNING 551: Descripción vacía, usando valor por defecto");
$descripcion = 'DESCRIPCIÓN PENDIENTE';
}
if ($cantidad_umc <= 0) {
error_log("WARNING 551: Cantidad UMC inválida ($cantidad_umc), usando 1.0000");
$cantidad_umc = 1.0000;
}
if (empty($unidad_comercial)) {
error_log("WARNING 551: Unidad comercial vacía, usando 'PZ'");
$unidad_comercial = 'PZ'; // Pieza como unidad por defecto
}
// Calcular precio unitario si no existe pero hay valores
if ($precio_unitario == 0) {
if ($valor_dolares > 0 && $cantidad_umc > 0) {
$precio_unitario = $valor_dolares / $cantidad_umc;
error_log("DEBUG 551: Precio unitario calculado: $precio_unitario");
} elseif ($valor_comercial > 0 && $cantidad_umc > 0) {
$precio_unitario = $valor_comercial / $cantidad_umc;
error_log("DEBUG 551: Precio unitario calculado desde valor comercial: $precio_unitario");
}
}
error_log("DEBUG 551 - Datos procesados:");
error_log(" - Partida: $numero_partida");
error_log(" - Fracción: '$fraccion_arancelaria'");
error_log(" - Descripción: '" . substr($descripcion, 0, 50) . "...'");
error_log(" - Cantidad: $cantidad_umc");
error_log(" - Unidad: '$unidad_comercial'");
error_log(" - Precio unitario: $precio_unitario");
error_log(" - Valor dólares: $valor_dolares");
return [
'secuencia' => $numero_partida,
'fraccion_arancelaria' => $fraccion_arancelaria,
'descripcion' => $descripcion,
'cantidad' => $cantidad_umc,
'unidad' => $unidad_comercial,
'valor_unitario' => $precio_unitario,
'peso_neto' => null,
'peso_bruto' => null
];
}
private function procesarPedimento($pedimento, $facturas, $partidas, $validar_duplicados) {
try {
error_log("Procesando pedimento: " . $pedimento['numero_pedimento']);
error_log("Validar duplicados: " . ($validar_duplicados ? 'SÍ' : 'NO'));
// Validar duplicados si está habilitado
if ($validar_duplicados && $this->existePedimento($pedimento['numero_pedimento'])) {
error_log("Pedimento {$pedimento['numero_pedimento']} marcado como duplicado, omitiendo...");
$this->estadisticas['duplicados']++;
return;
}
error_log("Insertando pedimento nuevo: " . $pedimento['numero_pedimento']);
// Iniciar transacción
sqlsrv_begin_transaction($this->conn);
// Insertar pedimento
$sql = "INSERT INTO pedimentos (numero_pedimento, patente, aduana, anio, clave_documento,
rfc_importador, fecha_creacion, usuario_id, estado)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'activo'); SELECT SCOPE_IDENTITY() AS id;";
$params = [
$pedimento['numero_pedimento'],
$pedimento['patente'],
$pedimento['aduana'],
$pedimento['anio'],
$pedimento['clave_documento'],
$pedimento['rfc_importador'],
$pedimento['fecha_creacion'],
$pedimento['usuario_id']
];
$stmt = sqlsrv_query($this->conn, $sql, $params);
if ($stmt === false) {
throw new Exception("Error al insertar pedimento: " . print_r(sqlsrv_errors(), true));
}
// Obtener el ID del pedimento insertado
sqlsrv_next_result($stmt);
sqlsrv_fetch($stmt);
$pedimento_id = sqlsrv_get_field($stmt, 0);
sqlsrv_free_stmt($stmt);
// Insertar facturas
foreach ($facturas as $factura) {
$sql = "INSERT INTO pedimento_facturas (pedimento_id, numero_factura, fecha_factura,
valor_dolares, valor_factura, cove, moneda, proveedor)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
$params = [
$pedimento_id,
$factura['numero_factura'],
$factura['fecha_factura'],
$factura['valor_dolares'],
$factura['valor_factura'],
isset($factura['cove']) ? $factura['cove'] : null,
isset($factura['moneda']) ? $factura['moneda'] : 'USD',
isset($factura['proveedor']) ? $factura['proveedor'] : null
];
$stmt = sqlsrv_query($this->conn, $sql, $params);
if ($stmt === false) {
throw new Exception("Error al insertar factura: " . print_r(sqlsrv_errors(), true));
}
sqlsrv_free_stmt($stmt);
$this->estadisticas['facturas_procesadas']++;
}
// Insertar partidas
foreach ($partidas as $partida) {
error_log("INSERTANDO PARTIDA: " . print_r($partida, true));
$sql = "INSERT INTO pedimento_partidas (pedimento_id, secuencia, fraccion_arancelaria,
descripcion, cantidad, unidad, valor_unitario,
peso_neto, peso_bruto)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
$params = [
$pedimento_id,
$partida['secuencia'],
$partida['fraccion_arancelaria'],
$partida['descripcion'],
$partida['cantidad'],
$partida['unidad'],
$partida['valor_unitario'],
isset($partida['peso_neto']) ? $partida['peso_neto'] : null,
isset($partida['peso_bruto']) ? $partida['peso_bruto'] : null
];
error_log("PARÁMETROS SQL: " . print_r($params, true));
$stmt = sqlsrv_query($this->conn, $sql, $params);
if ($stmt === false) {
$error = print_r(sqlsrv_errors(), true);
error_log("ERROR AL INSERTAR PARTIDA: " . $error);
throw new Exception("Error al insertar partida: " . $error);
}
sqlsrv_free_stmt($stmt);
$this->estadisticas['partidas_procesadas']++;
error_log("Partida insertada exitosamente - Total procesadas: " . $this->estadisticas['partidas_procesadas']);
}
// Confirmar transacción
sqlsrv_commit($this->conn);
$this->estadisticas['pedimentos_procesados']++;
$this->pedimentos_creados[] = $pedimento['numero_pedimento'];
} catch (Exception $e) {
sqlsrv_rollback($this->conn);
$this->errores_detalle[] = "Error procesando pedimento {$pedimento['numero_pedimento']}: " . $e->getMessage();
$this->estadisticas['errores']++;
}
}
private function existePedimento($numero_pedimento) {
$sql = "SELECT id, fecha_creacion FROM pedimentos WHERE numero_pedimento = ?";
$stmt = sqlsrv_query($this->conn, $sql, [$numero_pedimento]);
if ($stmt === false) {
error_log("Error al verificar duplicado: " . print_r(sqlsrv_errors(), true));
return false;
}
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
sqlsrv_free_stmt($stmt);
if ($row) {
error_log("Pedimento duplicado encontrado: {$numero_pedimento} (ID: {$row['id']})");
return true;
}
return false;
}
private function convertirFecha($fecha_str) {
// Convertir formato DDMMYYYY a YYYY-MM-DD
if (strlen($fecha_str) === 8) {
$dia = substr($fecha_str, 0, 2);
$mes = substr($fecha_str, 2, 2);
$anio = substr($fecha_str, 4, 4);
return "$anio-$mes-$dia";
}
return date('Y-m-d'); // Fecha por defecto
}
private function convertirFechaReal($fecha_str) {
// Convertir fecha del archivo real - puede venir en formato YYYYMMDD o DDMMYYYY
if (empty($fecha_str) || strlen($fecha_str) !== 8) {
return date('Y-m-d'); // Fecha por defecto
}
// Intentar formato YYYYMMDD primero
if (substr($fecha_str, 0, 2) === '20') {
$anio = substr($fecha_str, 0, 4);
$mes = substr($fecha_str, 4, 2);
$dia = substr($fecha_str, 6, 2);
} else {
// Formato DDMMYYYY
$dia = substr($fecha_str, 0, 2);
$mes = substr($fecha_str, 2, 2);
$anio = substr($fecha_str, 4, 4);
}
// Validar fecha
if (checkdate($mes, $dia, $anio)) {
return "$anio-$mes-$dia";
}
return date('Y-m-d'); // Fecha por defecto si no es válida
}
}
// Procesamiento de archivos (individual o múltiple)
try {
error_log("=== PROCESAMIENTO DE ARCHIVOS ===");
error_log("POST: " . print_r($_POST, true));
error_log("FILES: " . print_r($_FILES, true));
$validar_duplicados = isset($_POST['validar_duplicados']) && $_POST['validar_duplicados'] === 'on';
error_log("Validar duplicados: " . ($validar_duplicados ? 'SÍ' : 'NO'));
// Validar variables de entorno requeridas ANTES de intentar conectar (evita die() dentro de getConnection)
$requiredEnv = ['DB_HOST','DB_DATABASE','DB_USERNAME','DB_PASSWORD'];
foreach ($requiredEnv as $envKey) {
if (!isset($_ENV[$envKey]) || $_ENV[$envKey] === '') {
throw new Exception("Falta configurar la variable de entorno $envKey en el archivo .env");
}
}
// Obtener conexión a SQL Server
$conn = getConnection();
$importador = new ImportadorPedimentos($conn);
$resultado_final = null;
// Verificar si es archivo individual
if (isset($_FILES['archivo'])) {
error_log("=== PROCESAMIENTO INDIVIDUAL ===");
$archivo_temporal = $_FILES['archivo']['tmp_name'];
$nombre_archivo = $_FILES['archivo']['name'];
$resultado_final = $importador->procesarArchivo($archivo_temporal, $validar_duplicados);
} else if (isset($_FILES['archivos']) && is_array($_FILES['archivos']['name'])) {
error_log("=== PROCESAMIENTO MÚLTIPLE FORMATO NORMAL ===");
$archivos = $_FILES['archivos'];
$estadisticas_globales = [
'pedimentos_procesados' => 0,
'facturas_procesadas' => 0,
'partidas_procesadas' => 0,
'duplicados' => 0,
'errores' => 0,
'total_lineas' => 0
];
$archivos_procesados = 0;
$archivos_con_errores = [];
// Procesar cada archivo individualmente
for ($i = 0; $i < count($archivos['name']); $i++) {
if ($archivos['error'][$i] !== UPLOAD_ERR_OK) {
$archivos_con_errores[] = [
'archivo' => $archivos['name'][$i],
'error' => 'Error en la subida del archivo (código: ' . $archivos['error'][$i] . ')'
];
continue;
}
$nombre_archivo = $archivos['name'][$i];
$archivo_temporal = $archivos['tmp_name'][$i];
error_log("Procesando archivo: $nombre_archivo");
try {
$resultado = $importador->procesarArchivo($archivo_temporal, $validar_duplicados);
if ($resultado['success']) {
$estadisticas_globales['pedimentos_procesados'] += $resultado['estadisticas']['pedimentos_procesados'];
$estadisticas_globales['facturas_procesadas'] += $resultado['estadisticas']['facturas_procesadas'];
$estadisticas_globales['partidas_procesadas'] += $resultado['estadisticas']['partidas_procesadas'];
$estadisticas_globales['duplicados'] += $resultado['estadisticas']['duplicados'];
$estadisticas_globales['errores'] += $resultado['estadisticas']['errores'];
$estadisticas_globales['total_lineas'] += $resultado['estadisticas']['total_lineas'];
$archivos_procesados++;
error_log("Archivo procesado exitosamente: $nombre_archivo");
} else {
$archivos_con_errores[] = [
'archivo' => $nombre_archivo,
'error' => $resultado['message'] ?? 'Error desconocido'
];
}
} catch (Exception $e) {
$archivos_con_errores[] = [
'archivo' => $nombre_archivo,
'error' => $e->getMessage()
];
error_log("Excepción procesando archivo: $nombre_archivo - " . $e->getMessage());
}
}
$resultado_final = [
'success' => $archivos_procesados > 0,
'estadisticas' => $estadisticas_globales,
'archivos_procesados' => $archivos_procesados,
'total_archivos' => count($archivos['name']),
'archivos_con_errores' => $archivos_con_errores
];
if ($archivos_procesados === 0) {
$resultado_final['message'] = 'No se pudo procesar ningún archivo correctamente';
}
} else {
throw new Exception("No se recibieron archivos para procesar");
}
// Cerrar conexión
sqlsrv_close($conn);
// Enviar respuesta
echo json_encode($resultado_final);
} catch (Exception $e) {
error_log("ERROR GENERAL: " . $e->getMessage());
http_response_code(500);
echo json_encode([
'success' => false,
'message' => 'Error del servidor: ' . $e->getMessage()
]);
}
?>

View File

@@ -0,0 +1,255 @@
<?php
session_start();
require_once __DIR__ . '/../config/database.php';
// Limpiar cualquier output previo
if (ob_get_level()) {
ob_clean();
}
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-cache, must-revalidate');
error_log("=== IMPORTACIÓN SIMPLE ===");
error_log("POST: " . print_r($_POST, true));
error_log("FILES: " . print_r($_FILES, true));
error_log("Número total de archivos recibidos: " . count($_FILES));
if (!isset($_SESSION['usuario_id'])) {
echo json_encode(['success' => false, 'message' => 'Usuario no autenticado']);
exit;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(['success' => false, 'message' => 'Método no permitido']);
exit;
}
// Incluir la clase ImportadorPedimentos
include_once __DIR__ . '/../app/controllers/ImportadorPedimentos.php';
// Función segura para obtener conexión
function getSafeConnection() {
require_once __DIR__ . '/../app/helpers/env.php';
loadEnv();
$serverName = $_ENV['DB_HOST'];
$connectionOptions = [
"Database" => $_ENV['DB_DATABASE'],
"Uid" => $_ENV['DB_USERNAME'],
"PWD" => $_ENV['DB_PASSWORD'],
"CharacterSet" => "UTF-8"
];
$conn = sqlsrv_connect($serverName, $connectionOptions);
if (!$conn) {
$errors = sqlsrv_errors();
$errorMsg = "Error de conexión SQL Server";
if ($errors) {
$errorMsg .= ": " . $errors[0]['message'];
}
throw new Exception($errorMsg);
}
return $conn;
}
try {
$validar_duplicados = isset($_POST['validar_duplicados']) && $_POST['validar_duplicados'] === 'on';
// Crear timestamp único para esta importación
$timestamp_importacion = date('Y-m-d H:i:s');
// Verificar conexión a la base de datos
$conn = null;
try {
$conn = getSafeConnection();
if (!$conn) {
throw new Exception("No se pudo establecer conexión con la base de datos");
}
} catch (Exception $e) {
error_log("Error de conexión a BD: " . $e->getMessage());
throw new Exception("Error de conexión a la base de datos: " . $e->getMessage());
}
$importador = new ImportadorPedimentos($conn);
$estadisticas_globales = [
'pedimentos_procesados' => 0,
'facturas_procesadas' => 0,
'partidas_procesadas' => 0,
'duplicados' => 0,
'errores' => 0,
'total_lineas' => 0
];
$archivos_procesados = 0;
$archivos_con_errores = [];
// Manejar archivos múltiples enviados como archivos[]
if (isset($_FILES)) {
error_log("INICIANDO BUCLE DE ARCHIVOS...");
foreach ($_FILES as $key => $archivo_info) {
error_log("Procesando key: $key");
error_log("Archivo info: " . print_r($archivo_info, true));
if (is_array($archivo_info['name'])) {
// Múltiples archivos
for ($i = 0; $i < count($archivo_info['name']); $i++) {
if ($archivo_info['error'][$i] !== UPLOAD_ERR_OK) {
continue;
}
$nombre = $archivo_info['name'][$i];
$tmp_name = $archivo_info['tmp_name'][$i];
error_log("Procesando archivo múltiple: $nombre");
try {
$resultado = $importador->procesarArchivo($tmp_name, $validar_duplicados, $timestamp_importacion);
if ($resultado['success']) {
$estadisticas_globales['pedimentos_procesados'] += $resultado['estadisticas']['pedimentos_procesados'];
$estadisticas_globales['facturas_procesadas'] += $resultado['estadisticas']['facturas_procesadas'];
$estadisticas_globales['partidas_procesadas'] += $resultado['estadisticas']['partidas_procesadas'];
$estadisticas_globales['duplicados'] += $resultado['estadisticas']['duplicados'];
$estadisticas_globales['errores'] += $resultado['estadisticas']['errores'];
$estadisticas_globales['total_lineas'] += $resultado['estadisticas']['total_lineas'];
$archivos_procesados++;
} else {
$archivos_con_errores[] = [
'archivo' => $nombre,
'error' => $resultado['message'] ?? 'Error desconocido'
];
}
} catch (Exception $e) {
$archivos_con_errores[] = [
'archivo' => $nombre,
'error' => $e->getMessage()
];
}
}
} else {
// Archivo individual
if ($archivo_info['error'] === UPLOAD_ERR_OK) {
$nombre = $archivo_info['name'];
$tmp_name = $archivo_info['tmp_name'];
error_log("Procesando archivo individual: $nombre");
try {
$resultado = $importador->procesarArchivo($tmp_name, $validar_duplicados, $timestamp_importacion);
if ($resultado['success']) {
$estadisticas_globales = $resultado['estadisticas'];
$archivos_procesados = 1;
} else {
$archivos_con_errores[] = [
'archivo' => $nombre,
'error' => $resultado['message'] ?? 'Error desconocido'
];
}
} catch (Exception $e) {
$archivos_con_errores[] = [
'archivo' => $nombre,
'error' => $e->getMessage()
];
}
}
}
}
}
sqlsrv_close($conn);
// Verificar los datos realmente insertados en la base de datos
$estadisticas_reales = verificarEstadisticasReales($estadisticas_globales, $timestamp_importacion);
echo json_encode([
'success' => $archivos_procesados > 0,
'estadisticas' => $estadisticas_reales,
'archivos_procesados' => $archivos_procesados,
'archivos_con_errores' => $archivos_con_errores,
'message' => $archivos_procesados > 0 ? 'Archivos procesados correctamente' : 'No se pudo procesar ningún archivo'
]);
} catch (Exception $e) {
error_log("ERROR GENERAL: " . $e->getMessage());
error_log("STACK TRACE: " . $e->getTraceAsString());
// Asegurar que se devuelve JSON válido
http_response_code(500);
echo json_encode([
'success' => false,
'message' => 'Error del servidor: ' . $e->getMessage(),
'debug' => [
'file' => $e->getFile(),
'line' => $e->getLine(),
'timestamp' => date('Y-m-d H:i:s')
]
]);
}
function verificarEstadisticasReales($estadisticas_reportadas, $timestamp_importacion) {
try {
$conn = getSafeConnection();
// Obtener estadísticas reales de la base de datos para esta importación específica
$usuario_id = $_SESSION['usuario_id'];
// Contar pedimentos insertados en esta sesión (últimos 2 minutos)
$timestamp_desde = date('Y-m-d H:i:s', strtotime($timestamp_importacion . ' -2 minutes'));
$sql = "SELECT COUNT(*) as total FROM pedimentos WHERE usuario_id = ? AND fecha_creacion >= ?";
$stmt = sqlsrv_query($conn, $sql, [$usuario_id, $timestamp_desde]);
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
$pedimentos_reales = $row ? $row['total'] : 0;
sqlsrv_free_stmt($stmt);
// Contar facturas insertadas en esta sesión
$sql = "SELECT COUNT(f.*) as total
FROM pedimento_facturas f
INNER JOIN pedimentos p ON f.pedimento_id = p.id
WHERE p.usuario_id = ? AND p.fecha_creacion >= ?";
$stmt = sqlsrv_query($conn, $sql, [$usuario_id, $timestamp_desde]);
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
$facturas_reales = $row ? $row['total'] : 0;
sqlsrv_free_stmt($stmt);
// Contar partidas insertadas en esta sesión
$sql = "SELECT COUNT(pa.*) as total
FROM pedimento_partidas pa
INNER JOIN pedimentos p ON pa.pedimento_id = p.id
WHERE p.usuario_id = ? AND p.fecha_creacion >= ?";
$stmt = sqlsrv_query($conn, $sql, [$usuario_id, $timestamp_desde]);
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
$partidas_reales = $row ? $row['total'] : 0;
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
error_log("=== VERIFICACIÓN DE ESTADÍSTICAS ===");
error_log("Timestamp importación: $timestamp_importacion");
error_log("Timestamp desde: $timestamp_desde");
error_log("Reportadas - Pedimentos: {$estadisticas_reportadas['pedimentos_procesados']}, Facturas: {$estadisticas_reportadas['facturas_procesadas']}, Partidas: {$estadisticas_reportadas['partidas_procesadas']}");
error_log("Reales BD - Pedimentos: $pedimentos_reales, Facturas: $facturas_reales, Partidas: $partidas_reales");
// Retornar las estadísticas reales de la base de datos
return [
'total_lineas' => $estadisticas_reportadas['total_lineas'],
'pedimentos_procesados' => $pedimentos_reales,
'facturas_procesadas' => $facturas_reales,
'partidas_procesadas' => $partidas_reales,
'errores' => $estadisticas_reportadas['errores'],
'duplicados' => $estadisticas_reportadas['duplicados']
];
} catch (Exception $e) {
error_log("Error verificando estadísticas reales: " . $e->getMessage());
// En caso de error, retornar las estadísticas originales
return $estadisticas_reportadas;
}
}
?>

View File

@@ -0,0 +1,128 @@
<?php
session_start();
// Limpiar cualquier output previo
if (ob_get_level()) {
ob_clean();
}
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-cache, must-revalidate');
error_log("=== IMPORTACIÓN SIMPLE V2 ===");
error_log("POST: " . print_r($_POST, true));
error_log("FILES: " . print_r($_FILES, true));
if (!isset($_SESSION['usuario_id'])) {
echo json_encode(['success' => false, 'message' => 'Usuario no autenticado']);
exit;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(['success' => false, 'message' => 'Método no permitido']);
exit;
}
// Función de conexión directa
function getDirectConnection() {
// Cargar variables de entorno manualmente
$env_file = __DIR__ . '/../.env';
if (file_exists($env_file)) {
$lines = file($env_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
if (strpos($line, '=') !== false && substr($line, 0, 1) !== '#') {
list($key, $value) = explode('=', $line, 2);
$_ENV[trim($key)] = trim($value);
}
}
}
$serverName = $_ENV['DB_HOST'] ?? 'localhost';
$connectionOptions = [
"Database" => $_ENV['DB_DATABASE'] ?? 'importadores',
"Uid" => $_ENV['DB_USERNAME'] ?? 'sa',
"PWD" => $_ENV['DB_PASSWORD'] ?? '',
"CharacterSet" => "UTF-8"
];
$conn = sqlsrv_connect($serverName, $connectionOptions);
if (!$conn) {
$errors = sqlsrv_errors();
$errorMsg = "Error de conexión SQL Server";
if ($errors) {
$errorMsg .= ": " . $errors[0]['message'];
}
throw new Exception($errorMsg);
}
return $conn;
}
try {
$validar_duplicados = isset($_POST['validar_duplicados']) && $_POST['validar_duplicados'] === 'on';
// Crear timestamp único para esta importación
$timestamp_importacion = date('Y-m-d H:i:s');
$conn = getDirectConnection();
$estadisticas_globales = [
'pedimentos_procesados' => 0,
'facturas_procesadas' => 0,
'partidas_procesadas' => 0,
'duplicados' => 0,
'errores' => 0,
'total_lineas' => 0
];
$archivos_procesados = 0;
$archivos_con_errores = [];
// Simulación de procesamiento (por ahora)
if (isset($_FILES)) {
foreach ($_FILES as $key => $archivo_info) {
error_log("Procesando key: $key");
if (is_array($archivo_info['name'])) {
// Múltiples archivos
$archivos_procesados = count($archivo_info['name']);
$estadisticas_globales['pedimentos_procesados'] = $archivos_procesados * 2; // Simulado
$estadisticas_globales['facturas_procesadas'] = $archivos_procesados * 3; // Simulado
$estadisticas_globales['partidas_procesadas'] = $archivos_procesados * 5; // Simulado
} else {
// Archivo individual
$archivos_procesados = 1;
$estadisticas_globales['pedimentos_procesados'] = 1;
$estadisticas_globales['facturas_procesadas'] = 2;
$estadisticas_globales['partidas_procesadas'] = 3;
}
}
}
sqlsrv_close($conn);
echo json_encode([
'success' => $archivos_procesados > 0,
'estadisticas' => $estadisticas_globales,
'archivos_procesados' => $archivos_procesados,
'archivos_con_errores' => $archivos_con_errores,
'message' => $archivos_procesados > 0 ? 'Archivos procesados correctamente (MODO TEST)' : 'No se pudo procesar ningún archivo'
]);
} catch (Exception $e) {
error_log("ERROR GENERAL: " . $e->getMessage());
error_log("STACK TRACE: " . $e->getTraceAsString());
http_response_code(500);
echo json_encode([
'success' => false,
'message' => 'Error del servidor: ' . $e->getMessage(),
'debug' => [
'file' => $e->getFile(),
'line' => $e->getLine(),
'timestamp' => date('Y-m-d H:i:s')
]
]);
}
?>

View File

@@ -0,0 +1,66 @@
<?php
session_start();
require_once __DIR__ . '/../config/database.php';
header('Content-Type: application/json; charset=utf-8');
// Verificar que el usuario esté logueado
if (!isset($_SESSION['usuario_id'])) {
echo json_encode(['success' => false, 'message' => 'Usuario no autenticado']);
exit;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(['success' => false, 'message' => 'Método no permitido']);
exit;
}
try {
$conn = getConnection();
// Iniciar transacción
sqlsrv_begin_transaction($conn);
// Eliminar en orden correcto (por las foreign keys)
$sql1 = "DELETE FROM pedimento_partidas";
$sql2 = "DELETE FROM pedimento_facturas";
$sql3 = "DELETE FROM pedimentos";
$sql4 = "DELETE FROM importacion_logs";
$stmt1 = sqlsrv_query($conn, $sql1);
$stmt2 = sqlsrv_query($conn, $sql2);
$stmt3 = sqlsrv_query($conn, $sql3);
$stmt4 = sqlsrv_query($conn, $sql4);
if ($stmt1 && $stmt2 && $stmt3 && $stmt4) {
// Resetear los IDENTITY
sqlsrv_query($conn, "DBCC CHECKIDENT ('pedimentos', RESEED, 0)");
sqlsrv_query($conn, "DBCC CHECKIDENT ('pedimento_facturas', RESEED, 0)");
sqlsrv_query($conn, "DBCC CHECKIDENT ('pedimento_partidas', RESEED, 0)");
sqlsrv_query($conn, "DBCC CHECKIDENT ('importacion_logs', RESEED, 0)");
sqlsrv_commit($conn);
echo json_encode([
'success' => true,
'message' => 'Base de datos limpiada exitosamente',
'timestamp' => date('Y-m-d H:i:s'),
'usuario_id' => $_SESSION['usuario_id']
]);
} else {
sqlsrv_rollback($conn);
echo json_encode([
'success' => false,
'message' => 'Error al limpiar la base de datos',
'errors' => sqlsrv_errors()
]);
}
sqlsrv_close($conn);
} catch (Exception $e) {
echo json_encode([
'success' => false,
'error' => $e->getMessage()
]);
}
?>

36
public/test_import.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
session_start();
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
// Simple test endpoint
$response = [
'success' => true,
'message' => 'Conexión exitosa desde public',
'timestamp' => date('Y-m-d H:i:s'),
'method' => $_SERVER['REQUEST_METHOD'],
'usuario' => isset($_SESSION['usuario']) ? $_SESSION['usuario']['nombre'] ?? 'Usuario logueado' : 'No hay usuario',
'post_data' => $_POST,
'get_data' => $_GET,
'server_info' => [
'HTTP_HOST' => $_SERVER['HTTP_HOST'],
'REQUEST_URI' => $_SERVER['REQUEST_URI'],
'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME']
]
];
if (isset($_FILES['archivo'])) {
$response['files_data'] = [
'nombre' => $_FILES['archivo']['name'],
'tamaño' => $_FILES['archivo']['size'],
'tipo' => $_FILES['archivo']['type'],
'error' => $_FILES['archivo']['error']
];
} else {
$response['files_data'] = 'No hay archivo';
}
echo json_encode($response, JSON_PRETTY_PRINT);
?>

10
public/test_json.php Normal file
View File

@@ -0,0 +1,10 @@
<?php
// Test simple para verificar respuesta JSON
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'success' => true,
'message' => 'Test exitoso',
'timestamp' => date('Y-m-d H:i:s')
]);
?>

View File

@@ -0,0 +1,26 @@
<?php
// Ultra simple test - solo devolver JSON
header('Content-Type: application/json');
try {
echo json_encode([
'success' => true,
'message' => 'Test básico funcionando',
'estadisticas' => [
'pedimentos_procesados' => 5,
'facturas_procesadas' => 10,
'partidas_procesadas' => 15,
'duplicados' => 0,
'errores' => 0,
'total_lineas' => 100
],
'archivos_procesados' => 3,
'archivos_con_errores' => []
]);
} catch (Exception $e) {
echo json_encode([
'success' => false,
'message' => $e->getMessage()
]);
}
?>

View File

@@ -0,0 +1,46 @@
<?php
require_once __DIR__ . '/../config/database.php';
header('Content-Type: application/json; charset=utf-8');
try {
$conn = getConnection();
// Obtener todos los pedimentos existentes
$sql = "SELECT numero_pedimento, fecha_creacion, usuario_id FROM pedimentos ORDER BY fecha_creacion DESC";
$stmt = sqlsrv_query($conn, $sql);
$pedimentos_existentes = [];
if ($stmt !== false) {
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$pedimentos_existentes[] = $row;
}
sqlsrv_free_stmt($stmt);
}
// Obtener estadísticas
$sql_stats = "SELECT
COUNT(*) as total_pedimentos,
COUNT(DISTINCT usuario_id) as usuarios_distintos,
MIN(fecha_creacion) as primer_pedimento,
MAX(fecha_creacion) as ultimo_pedimento
FROM pedimentos";
$stmt_stats = sqlsrv_query($conn, $sql_stats);
$stats = sqlsrv_fetch_array($stmt_stats, SQLSRV_FETCH_ASSOC);
sqlsrv_free_stmt($stmt_stats);
sqlsrv_close($conn);
echo json_encode([
'success' => true,
'pedimentos_existentes' => $pedimentos_existentes,
'estadisticas' => $stats,
'total_encontrados' => count($pedimentos_existentes)
], JSON_PRETTY_PRINT);
} catch (Exception $e) {
echo json_encode([
'success' => false,
'error' => $e->getMessage()
]);
}
?>