303 lines
11 KiB
PHP
303 lines
11 KiB
PHP
<?php
|
|
|
|
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, $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');
|
|
}
|
|
}
|
|
|
|
?>
|