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, $timestamp_importacion = null) { $inicio_tiempo = time(); $nombre_archivo = basename($archivo_path); if ($timestamp_importacion === null) { $timestamp_importacion = date('Y-m-d H:i:s'); } try { $contenido = file_get_contents($archivo_path); if ($contenido === false) { throw new Exception("No se pudo leer el archivo"); } // Convertir encoding si es necesario 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': // Header - ignorar 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, $timestamp_importacion); break; case '505': if ($pedimento_actual) { $factura = $this->parsearLinea505Real($linea); $facturas_pedimento[] = $factura; } break; case '551': if ($pedimento_actual) { $partida = $this->parsearLinea551Real($linea); $partidas_pedimento[] = $partida; } 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); } return [ 'success' => true, 'estadisticas' => $this->estadisticas, 'errores' => $this->errores_detalle, 'pedimentos_creados' => $this->pedimentos_creados ]; } catch (Exception $e) { return [ 'success' => false, 'message' => $e->getMessage() ]; } } private function parsearLinea501Real($linea, $timestamp_importacion) { $campos = explode('|', $linea); if (count($campos) < 10) { throw new Exception("Formato inválido en línea 501"); } return [ 'numero_pedimento' => trim($campos[2]), 'patente' => trim($campos[1]), 'aduana' => trim($campos[3]), 'anio' => date('Y'), 'clave_documento' => trim($campos[5]), 'rfc_importador' => trim($campos[8]), 'fecha_creacion' => $timestamp_importacion, 'usuario_id' => $_SESSION['usuario_id'] ]; } private function parsearLinea505Real($linea) { $campos = explode('|', $linea); if (count($campos) < 12) { throw new Exception("Formato inválido en línea 505"); } return [ 'numero_factura' => trim($campos[3]), 'fecha_factura' => $this->convertirFechaReal(trim($campos[2])), 'valor_dolares' => floatval(trim($campos[6])), 'valor_factura' => floatval(trim($campos[7])), 'cove' => trim($campos[3]), 'moneda' => trim($campos[5]), 'proveedor' => trim($campos[11]) ]; } private function parsearLinea551Real($linea) { $campos = explode('|', $linea); if (count($campos) < 12) { throw new Exception("Formato inválido en línea 551"); } static $contador = 1; return [ 'secuencia' => $contador++, 'fraccion_arancelaria' => trim($campos[2]) ?: 'PENDIENTE', 'descripcion' => trim($campos[5]) ?: 'DESCRIPCIÓN PENDIENTE', 'cantidad' => floatval(trim($campos[10])) ?: 1.0, 'unidad' => trim($campos[11]) ?: 'PZ', 'valor_unitario' => floatval(trim($campos[6])), 'peso_neto' => null, 'peso_bruto' => null ]; } private function procesarPedimento($pedimento, $facturas, $partidas, $validar_duplicados) { try { if ($validar_duplicados && $this->existePedimento($pedimento['numero_pedimento'])) { $this->estadisticas['duplicados']++; return; } 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"); } 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'], $factura['cove'], $factura['moneda'], $factura['proveedor'] ]; $stmt = sqlsrv_query($this->conn, $sql, $params); if ($stmt === false) { throw new Exception("Error al insertar factura"); } sqlsrv_free_stmt($stmt); $this->estadisticas['facturas_procesadas']++; } // Insertar partidas foreach ($partidas as $partida) { $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'], $partida['peso_neto'], $partida['peso_bruto'] ]; $stmt = sqlsrv_query($this->conn, $sql, $params); if ($stmt === false) { throw new Exception("Error al insertar partida"); } sqlsrv_free_stmt($stmt); $this->estadisticas['partidas_procesadas']++; } 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 FROM pedimentos WHERE numero_pedimento = ?"; $stmt = sqlsrv_query($this->conn, $sql, [$numero_pedimento]); if ($stmt === false) { return false; } $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); sqlsrv_free_stmt($stmt); return $row !== false; } private function convertirFechaReal($fecha_str) { if (empty($fecha_str) || strlen($fecha_str) !== 8) { return date('Y-m-d'); } 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 { $dia = substr($fecha_str, 0, 2); $mes = substr($fecha_str, 2, 2); $anio = substr($fecha_str, 4, 4); } if (checkdate($mes, $dia, $anio)) { return "$anio-$mes-$dia"; } return date('Y-m-d'); } } ?>