Preparando proyecto para migración a repositorio MVE
This commit is contained in:
303
app/controllers/ImportadorPedimentos.php
Normal file
303
app/controllers/ImportadorPedimentos.php
Normal file
@@ -0,0 +1,303 @@
|
||||
<?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');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -359,44 +359,16 @@ function ajax_lista()
|
||||
$id_usuario = $_SESSION['usuario_id'];
|
||||
$conn = getConnection();
|
||||
|
||||
// Obtener RFC del importador para filtrar solo sus pedimentos
|
||||
$sqlImportador = "SELECT rfc FROM informacion_general WHERE id_usuario = ?";
|
||||
$stmtImportador = sqlsrv_query($conn, $sqlImportador, [$id_usuario]);
|
||||
|
||||
if ($stmtImportador === false) {
|
||||
echo json_encode([
|
||||
"draw" => intval($_GET['draw'] ?? 0),
|
||||
"recordsTotal" => 0,
|
||||
"recordsFiltered" => 0,
|
||||
"data" => [],
|
||||
"error" => "Error al consultar información del importador"
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$importador = sqlsrv_fetch_array($stmtImportador, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if (!$importador) {
|
||||
echo json_encode([
|
||||
"draw" => intval($_GET['draw'] ?? 0),
|
||||
"recordsTotal" => 0,
|
||||
"recordsFiltered" => 0,
|
||||
"data" => []
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Parámetros de DataTables
|
||||
$draw = intval($_GET['draw'] ?? 0);
|
||||
$start = intval($_GET['start'] ?? 0);
|
||||
$length = intval($_GET['length'] ?? 10);
|
||||
$search = $_GET['search']['value'] ?? '';
|
||||
|
||||
// Total registros sin filtro
|
||||
$sqlTotal = "SELECT COUNT(*) AS total FROM PREVIOS_COMPARTIDOS_WS WHERE ClienteRFC = ?";
|
||||
$stmt = sqlsrv_query($conn, $sqlTotal, [$importador['rfc']]);
|
||||
|
||||
if ($stmt === false) {
|
||||
// Total registros sin filtro en nuevas tablas
|
||||
$sqlTotal = "SELECT COUNT(*) AS total FROM pedimentos WHERE usuario_id = ?";
|
||||
$stmtTotal = sqlsrv_query($conn, $sqlTotal, [$id_usuario]);
|
||||
if ($stmtTotal === false) {
|
||||
echo json_encode([
|
||||
"draw" => $draw,
|
||||
"recordsTotal" => 0,
|
||||
@@ -406,24 +378,21 @@ function ajax_lista()
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
$recordsTotal = (int)($row['total'] ?? 0);
|
||||
|
||||
// Construir condiciones de filtro
|
||||
$where = "ClienteRFC = ?";
|
||||
$params = [$importador['rfc']];
|
||||
$rowT = sqlsrv_fetch_array($stmtTotal, SQLSRV_FETCH_ASSOC);
|
||||
$recordsTotal = (int)($rowT['total'] ?? 0);
|
||||
|
||||
// Filtro y búsqueda
|
||||
$where = "p.usuario_id = ?";
|
||||
$params = [$id_usuario];
|
||||
if ($search !== '') {
|
||||
$where .= " AND (Pedimento LIKE ? OR ClienteNombre LIKE ? OR ClavePed LIKE ?)";
|
||||
$where .= " AND (p.numero_pedimento LIKE ? OR p.rfc_importador LIKE ? OR p.clave_documento LIKE ? OR p.patente LIKE ? OR p.aduana LIKE ?)";
|
||||
$like = "%{$search}%";
|
||||
$params = array_merge($params, [$like, $like, $like]);
|
||||
$params = array_merge($params, [$like, $like, $like, $like, $like]);
|
||||
}
|
||||
|
||||
// Total registros filtrados
|
||||
$sqlFiltered = "SELECT COUNT(*) AS total FROM PREVIOS_COMPARTIDOS_WS WHERE $where";
|
||||
// Total filtrado
|
||||
$sqlFiltered = "SELECT COUNT(*) AS total FROM pedimentos p WHERE $where";
|
||||
$stmtF = sqlsrv_query($conn, $sqlFiltered, $params);
|
||||
|
||||
if ($stmtF === false) {
|
||||
echo json_encode([
|
||||
"draw" => $draw,
|
||||
@@ -434,34 +403,41 @@ function ajax_lista()
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$rowF = sqlsrv_fetch_array($stmtF, SQLSRV_FETCH_ASSOC);
|
||||
$recordsFiltered = (int)($rowF['total'] ?? 0);
|
||||
|
||||
// Datos de la página
|
||||
$sqlData = "SELECT IdPrevio, Pedimento, ClienteRFC, ClienteNombre, Timestamp, Status
|
||||
FROM PREVIOS_COMPARTIDOS_WS
|
||||
WHERE $where
|
||||
ORDER BY Timestamp DESC
|
||||
// Datos paginados
|
||||
$sqlData = "SELECT p.id, p.numero_pedimento, p.rfc_importador, p.fecha_creacion, p.estado,
|
||||
ig.nombre AS nombre_importador
|
||||
FROM pedimentos p
|
||||
LEFT JOIN informacion_general ig ON ig.id_usuario = p.usuario_id
|
||||
WHERE $where
|
||||
ORDER BY p.fecha_creacion DESC
|
||||
OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
|
||||
$params[] = $start;
|
||||
$params[] = $length;
|
||||
|
||||
$stmtD = sqlsrv_query($conn, $sqlData, $params);
|
||||
$paramsData = array_merge($params, [$start, $length]);
|
||||
$stmtD = sqlsrv_query($conn, $sqlData, $paramsData);
|
||||
|
||||
$data = [];
|
||||
if ($stmtD !== false) {
|
||||
while ($r = sqlsrv_fetch_array($stmtD, SQLSRV_FETCH_ASSOC)) {
|
||||
$timestamp = $r['Timestamp'] instanceof DateTime ? $r['Timestamp']->format('Y-m-d H:i:s') : '';
|
||||
$status_text = $r['Status'] == 1 ? 'Activo' : 'Inactivo';
|
||||
|
||||
$fecha = '';
|
||||
if (isset($r['fecha_creacion'])) {
|
||||
if ($r['fecha_creacion'] instanceof DateTime) {
|
||||
$fecha = $r['fecha_creacion']->format('Y-m-d H:i:s');
|
||||
} elseif (is_array($r['fecha_creacion']) && isset($r['fecha_creacion']['date'])) {
|
||||
// Por si viene como array (SQLSRV con print_r)
|
||||
$fecha = substr($r['fecha_creacion']['date'], 0, 19);
|
||||
}
|
||||
}
|
||||
$estado = strtolower((string)$r['estado']) === 'activo' || $r['estado'] === 1 ? 'Activo' : 'Inactivo';
|
||||
|
||||
$data[] = [
|
||||
$r['IdPrevio'],
|
||||
$r['Pedimento'],
|
||||
$r['ClienteRFC'],
|
||||
$r['ClienteNombre'],
|
||||
$timestamp,
|
||||
$status_text
|
||||
$r['id'],
|
||||
$r['numero_pedimento'],
|
||||
$r['rfc_importador'],
|
||||
$r['nombre_importador'] ?? '',
|
||||
$fecha,
|
||||
$estado
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -555,4 +531,157 @@ function buscar_pedimentos()
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
echo json_encode($pedimentos, JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Devuelve información general del pedimento (cabecera)
|
||||
* GET /IMPORTADORES/catalogo_pedimentos/ajax_pedimento?id=123
|
||||
*/
|
||||
function ajax_pedimento()
|
||||
{
|
||||
if (!($_SESSION['usuario_id'] ?? false)) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['success' => false, 'message' => 'No autorizado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id_usuario = $_SESSION['usuario_id'];
|
||||
$pedimento_id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
if ($pedimento_id <= 0) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'ID inválido']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$conn = getConnection();
|
||||
$sql = "SELECT p.id, p.numero_pedimento, p.patente, p.aduana, p.anio, p.clave_documento,
|
||||
p.rfc_importador, p.fecha_creacion, p.estado
|
||||
FROM pedimentos p
|
||||
WHERE p.id = ? AND p.usuario_id = ?";
|
||||
$stmt = sqlsrv_query($conn, $sql, [$pedimento_id, $id_usuario]);
|
||||
if ($stmt === false) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'message' => 'Error de base de datos']);
|
||||
exit;
|
||||
}
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
sqlsrv_free_stmt($stmt);
|
||||
|
||||
if (!$row) {
|
||||
echo json_encode(['success' => false, 'message' => 'No encontrado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Formatear fecha si es DateTime
|
||||
if (isset($row['fecha_creacion']) && $row['fecha_creacion'] instanceof DateTime) {
|
||||
$row['fecha_creacion'] = $row['fecha_creacion']->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true, 'data' => $row]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Devuelve las facturas del pedimento
|
||||
* GET /IMPORTADORES/catalogo_pedimentos/ajax_facturas?pedimento_id=123
|
||||
*/
|
||||
function ajax_facturas()
|
||||
{
|
||||
if (!($_SESSION['usuario_id'] ?? false)) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['success' => false, 'message' => 'No autorizado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id_usuario = $_SESSION['usuario_id'];
|
||||
$pedimento_id = isset($_GET['pedimento_id']) ? (int)$_GET['pedimento_id'] : 0;
|
||||
if ($pedimento_id <= 0) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'ID inválido']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$conn = getConnection();
|
||||
// Verificar propiedad
|
||||
$chk = sqlsrv_query($conn, "SELECT 1 FROM pedimentos WHERE id = ? AND usuario_id = ?", [$pedimento_id, $id_usuario]);
|
||||
$own = $chk && sqlsrv_fetch_array($chk) ? true : false;
|
||||
if ($chk) sqlsrv_free_stmt($chk);
|
||||
if (!$own) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['success' => false, 'message' => 'Pedimento no encontrado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "SELECT id, numero_factura, fecha_factura, valor_dolares, valor_factura, cove, moneda, proveedor
|
||||
FROM pedimento_facturas
|
||||
WHERE pedimento_id = ?
|
||||
ORDER BY fecha_factura ASC, id ASC";
|
||||
$stmt = sqlsrv_query($conn, $sql, [$pedimento_id]);
|
||||
if ($stmt === false) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'message' => 'Error de base de datos']);
|
||||
exit;
|
||||
}
|
||||
$items = [];
|
||||
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
if ($r['fecha_factura'] instanceof DateTime) {
|
||||
$r['fecha_factura'] = $r['fecha_factura']->format('Y-m-d');
|
||||
}
|
||||
$items[] = $r;
|
||||
}
|
||||
sqlsrv_free_stmt($stmt);
|
||||
|
||||
echo json_encode(['success' => true, 'data' => $items]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Devuelve las partidas del pedimento
|
||||
* GET /IMPORTADORES/catalogo_pedimentos/ajax_partidas?pedimento_id=123
|
||||
*/
|
||||
function ajax_partidas()
|
||||
{
|
||||
if (!($_SESSION['usuario_id'] ?? false)) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['success' => false, 'message' => 'No autorizado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id_usuario = $_SESSION['usuario_id'];
|
||||
$pedimento_id = isset($_GET['pedimento_id']) ? (int)$_GET['pedimento_id'] : 0;
|
||||
if ($pedimento_id <= 0) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'ID inválido']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$conn = getConnection();
|
||||
// Verificar propiedad
|
||||
$chk = sqlsrv_query($conn, "SELECT 1 FROM pedimentos WHERE id = ? AND usuario_id = ?", [$pedimento_id, $id_usuario]);
|
||||
$own = $chk && sqlsrv_fetch_array($chk) ? true : false;
|
||||
if ($chk) sqlsrv_free_stmt($chk);
|
||||
if (!$own) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['success' => false, 'message' => 'Pedimento no encontrado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "SELECT id, secuencia, fraccion_arancelaria, descripcion, cantidad, unidad, valor_unitario, peso_neto, peso_bruto
|
||||
FROM pedimento_partidas
|
||||
WHERE pedimento_id = ?
|
||||
ORDER BY secuencia ASC, id ASC";
|
||||
$stmt = sqlsrv_query($conn, $sql, [$pedimento_id]);
|
||||
if ($stmt === false) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'message' => 'Error de base de datos']);
|
||||
exit;
|
||||
}
|
||||
$items = [];
|
||||
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
$items[] = $r;
|
||||
}
|
||||
sqlsrv_free_stmt($stmt);
|
||||
|
||||
echo json_encode(['success' => true, 'data' => $items]);
|
||||
exit;
|
||||
}
|
||||
170
app/controllers/cove.php
Normal file
170
app/controllers/cove.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../config/database.php';
|
||||
require_once __DIR__ . '/../helpers/session.php';
|
||||
|
||||
/**
|
||||
* GET /IMPORTADORES/cove/ajax_estado_facturas?pedimento_id=123
|
||||
* Devuelve estado de COVE por factura del pedimento actual del usuario.
|
||||
*/
|
||||
function ajax_estado_facturas()
|
||||
{
|
||||
if (!($_SESSION['usuario_id'] ?? false)) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['success' => false, 'message' => 'No autorizado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$usuario_id = (int)$_SESSION['usuario_id'];
|
||||
$pedimento_id = isset($_GET['pedimento_id']) ? (int)$_GET['pedimento_id'] : 0;
|
||||
if ($pedimento_id <= 0) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'ID inválido']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$conn = getConnection();
|
||||
// Verificar propiedad del pedimento
|
||||
$chk = sqlsrv_query($conn, "SELECT 1 FROM pedimentos WHERE id = ? AND usuario_id = ?", [$pedimento_id, $usuario_id]);
|
||||
$own = $chk && sqlsrv_fetch_array($chk) ? true : false;
|
||||
if ($chk) sqlsrv_free_stmt($chk);
|
||||
if (!$own) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['success' => false, 'message' => 'Pedimento no encontrado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "SELECT f.id AS factura_id,
|
||||
CASE WHEN cr.id IS NULL THEN 0 ELSE 1 END AS respondido,
|
||||
cr.estado AS estado,
|
||||
cr.fecha_actualizacion AS fecha
|
||||
FROM pedimento_facturas f
|
||||
LEFT JOIN cove_respuestas cr
|
||||
ON cr.factura_id = f.id AND cr.usuario_id = ?
|
||||
WHERE f.pedimento_id = ?
|
||||
ORDER BY f.id";
|
||||
$stmt = sqlsrv_query($conn, $sql, [$usuario_id, $pedimento_id]);
|
||||
if ($stmt === false) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'message' => 'Error de base de datos']);
|
||||
exit;
|
||||
}
|
||||
$data = [];
|
||||
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
if (isset($r['fecha']) && $r['fecha'] instanceof DateTime) {
|
||||
$r['fecha'] = $r['fecha']->format('Y-m-d H:i:s');
|
||||
}
|
||||
$data[] = $r;
|
||||
}
|
||||
sqlsrv_free_stmt($stmt);
|
||||
|
||||
echo json_encode(['success' => true, 'data' => $data]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /IMPORTADORES/cove/ajax_guardar_respuestas
|
||||
* Guarda/actualiza respuestas de COVE para una factura concreta.
|
||||
* Body: pedimento_id, factura_id, respuestas (JSON string), estado (opcional)
|
||||
*/
|
||||
function ajax_guardar_respuestas()
|
||||
{
|
||||
if (!($_SESSION['usuario_id'] ?? false)) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['success' => false, 'message' => 'No autorizado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$usuario_id = (int)$_SESSION['usuario_id'];
|
||||
$pedimento_id = isset($_POST['pedimento_id']) ? (int)$_POST['pedimento_id'] : 0;
|
||||
$factura_id = isset($_POST['factura_id']) ? (int)$_POST['factura_id'] : 0;
|
||||
$respuestas = $_POST['respuestas'] ?? '{}';
|
||||
$estado = $_POST['estado'] ?? 'respondido';
|
||||
if ($pedimento_id <= 0 || $factura_id <= 0) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Parámetros inválidos']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$conn = getConnection();
|
||||
// Verificar propiedad del pedimento
|
||||
$chk = sqlsrv_query($conn, "SELECT 1 FROM pedimentos WHERE id = ? AND usuario_id = ?", [$pedimento_id, $usuario_id]);
|
||||
$own = $chk && sqlsrv_fetch_array($chk) ? true : false;
|
||||
if ($chk) sqlsrv_free_stmt($chk);
|
||||
if (!$own) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['success' => false, 'message' => 'Pedimento no encontrado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Upsert manual: si existe update, si no insert
|
||||
$sel = sqlsrv_query($conn, "SELECT id FROM cove_respuestas WHERE factura_id = ? AND usuario_id = ?", [$factura_id, $usuario_id]);
|
||||
$row = $sel ? sqlsrv_fetch_array($sel, SQLSRV_FETCH_ASSOC) : null;
|
||||
if ($sel) sqlsrv_free_stmt($sel);
|
||||
|
||||
if ($row) {
|
||||
$sql = "UPDATE cove_respuestas
|
||||
SET respuestas = ?, estado = ?, fecha_actualizacion = SYSDATETIME()
|
||||
WHERE id = ?";
|
||||
$stmt = sqlsrv_query($conn, $sql, [$respuestas, $estado, $row['id']]);
|
||||
} else {
|
||||
$sql = "INSERT INTO cove_respuestas (pedimento_id, factura_id, usuario_id, respuestas, estado, fecha_creacion)
|
||||
VALUES (?, ?, ?, ?, ?, SYSDATETIME())";
|
||||
$stmt = sqlsrv_query($conn, $sql, [$pedimento_id, $factura_id, $usuario_id, $respuestas, $estado]);
|
||||
}
|
||||
|
||||
if ($stmt === false) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'message' => 'No se pudieron guardar las respuestas']);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Estado agregado por pedimento: total de facturas vs respondidas/solicitadas
|
||||
function ajax_estado_pedimentos()
|
||||
{
|
||||
if (!($_SESSION['usuario_id'] ?? false)) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['success' => false, 'message' => 'No autorizado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$usuario_id = (int)$_SESSION['usuario_id'];
|
||||
$conn = getConnection();
|
||||
|
||||
$sql = "
|
||||
SELECT p.id AS pedimento_id,
|
||||
COUNT(f.id) AS total_facturas,
|
||||
SUM(CASE WHEN cr.estado IN ('respondido','solicitado') THEN 1 ELSE 0 END) AS respondidas
|
||||
FROM pedimentos p
|
||||
LEFT JOIN pedimento_facturas f ON f.pedimento_id = p.id
|
||||
LEFT JOIN cove_respuestas cr ON cr.factura_id = f.id AND cr.usuario_id = p.usuario_id
|
||||
WHERE p.usuario_id = ?
|
||||
GROUP BY p.id
|
||||
";
|
||||
$stmt = sqlsrv_query($conn, $sql, [$usuario_id]);
|
||||
if ($stmt === false) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'message' => 'Error de base de datos']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = [];
|
||||
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
$total = (int)($r['total_facturas'] ?? 0);
|
||||
$resp = (int)($r['respondidas'] ?? 0);
|
||||
$completo = ($total > 0 && $resp >= $total) ? 1 : 0;
|
||||
$data[] = [
|
||||
'pedimento_id' => (int)$r['pedimento_id'],
|
||||
'total_facturas' => $total,
|
||||
'respondidas' => $resp,
|
||||
'completo' => $completo
|
||||
];
|
||||
}
|
||||
sqlsrv_free_stmt($stmt);
|
||||
|
||||
echo json_encode(['success' => true, 'data' => $data]);
|
||||
exit;
|
||||
}
|
||||
22
app/controllers/debug_paths.php
Normal file
22
app/controllers/debug_paths.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
// Debug para ver rutas
|
||||
echo "<h3>Información de rutas del servidor:</h3>";
|
||||
echo "<p><strong>DOCUMENT_ROOT:</strong> " . $_SERVER['DOCUMENT_ROOT'] . "</p>";
|
||||
echo "<p><strong>SCRIPT_NAME:</strong> " . $_SERVER['SCRIPT_NAME'] . "</p>";
|
||||
echo "<p><strong>REQUEST_URI:</strong> " . $_SERVER['REQUEST_URI'] . "</p>";
|
||||
echo "<p><strong>HTTP_HOST:</strong> " . $_SERVER['HTTP_HOST'] . "</p>";
|
||||
echo "<p><strong>__FILE__:</strong> " . __FILE__ . "</p>";
|
||||
echo "<p><strong>__DIR__:</strong> " . __DIR__ . "</p>";
|
||||
|
||||
// Verificar si los archivos existen
|
||||
$test_file = __DIR__ . '/test_connection.php';
|
||||
$import_file = __DIR__ . '/importar_pedimentos.php';
|
||||
|
||||
echo "<h3>Verificación de archivos:</h3>";
|
||||
echo "<p><strong>test_connection.php:</strong> " . (file_exists($test_file) ? '✅ Existe' : '❌ No existe') . "</p>";
|
||||
echo "<p><strong>importar_pedimentos.php:</strong> " . (file_exists($import_file) ? '✅ Existe' : '❌ No existe') . "</p>";
|
||||
|
||||
echo "<h3>URLs sugeridas:</h3>";
|
||||
$base_url = "http" . (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] === "on" ? "s" : "") . "://" . $_SERVER["HTTP_HOST"];
|
||||
echo "<p><strong>Test URL:</strong> <a href='{$base_url}/IMPORTADORES/app/controllers/test_connection.php' target='_blank'>{$base_url}/IMPORTADORES/app/controllers/test_connection.php</a></p>";
|
||||
?>
|
||||
@@ -3,6 +3,29 @@ require_once __DIR__ . '/../helpers/session.php';
|
||||
require_once __DIR__ . '/../../config/database.php';
|
||||
require_once __DIR__ . '/../helpers/env.php';
|
||||
|
||||
// Formatea el pedimento como: YY-AA-PPPP-PPPPPPP
|
||||
function format_pedimento_display($anio, $aduana, $patente, $numero)
|
||||
{
|
||||
$yy = substr((string)$anio, -2);
|
||||
$ad = substr(preg_replace('/\D/', '', (string)$aduana), 0, 2);
|
||||
$pat = str_pad(preg_replace('/\D/', '', (string)$patente), 4, '0', STR_PAD_LEFT);
|
||||
$num = str_pad(preg_replace('/\D/', '', (string)$numero), 7, '0', STR_PAD_LEFT);
|
||||
$yy = $yy !== '' ? $yy : '00';
|
||||
$ad = str_pad($ad, 2, '0', STR_PAD_LEFT);
|
||||
return "$yy-$ad-$pat-$num";
|
||||
}
|
||||
|
||||
function ensure_expediente_schema($conn) {
|
||||
// Agregar columna pedimento_id si no existe (compatibilidad con esquema nuevo)
|
||||
$chk = sqlsrv_query($conn, "SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'expediente_archivos' AND COLUMN_NAME = 'pedimento_id'");
|
||||
$exists = $chk && sqlsrv_fetch_array($chk) ? true : false;
|
||||
if ($chk) sqlsrv_free_stmt($chk);
|
||||
if (!$exists) {
|
||||
@sqlsrv_query($conn, "ALTER TABLE expediente_archivos ADD pedimento_id INT NULL");
|
||||
@sqlsrv_query($conn, "CREATE INDEX IX_expediente_archivos_pedimento ON expediente_archivos(pedimento_id)");
|
||||
}
|
||||
}
|
||||
|
||||
// Mostrar tabla de expedientes
|
||||
function index()
|
||||
{
|
||||
@@ -12,29 +35,50 @@ function index()
|
||||
}
|
||||
|
||||
$conn = getConnection();
|
||||
ensure_expediente_schema($conn);
|
||||
|
||||
$id_importador = $_SESSION['usuario_id'];
|
||||
|
||||
$sql = "SELECT
|
||||
sif.id_solicitud, sif.numero_pedimento, sif.fecha_factura, sif.aduana, sif.proveedor_clave,
|
||||
COUNT(ea.id) AS total_archivos,
|
||||
ISNULL(SUM(ea.tamano_archivo), 0) AS total_tamano
|
||||
FROM solicitud_importacion_factura sif
|
||||
LEFT JOIN expediente_archivos ea
|
||||
ON ea.id_solicitud = sif.id_solicitud
|
||||
WHERE sif.numero_pedimento IS NOT NULL
|
||||
AND sif.id_importador = ?
|
||||
AND sif.status > 0
|
||||
GROUP BY sif.id_solicitud, sif.numero_pedimento, sif.fecha_factura, sif.aduana, sif.proveedor_clave
|
||||
ORDER BY sif.fecha_factura DESC
|
||||
";
|
||||
// Nuevo origen: pedimentos (cabecera) + facturas para fecha/proveedor + archivos por pedimento
|
||||
$sql = "
|
||||
WITH fact AS (
|
||||
SELECT
|
||||
f.pedimento_id,
|
||||
MAX(f.fecha_factura) AS fecha_factura,
|
||||
MIN(COALESCE(NULLIF(LTRIM(RTRIM(f.proveedor)), ''), '-')) AS proveedor
|
||||
FROM pedimento_facturas f
|
||||
GROUP BY f.pedimento_id
|
||||
), arch AS (
|
||||
SELECT pedimento_id, COUNT(*) AS total_archivos, ISNULL(SUM(tamano_archivo), 0) AS total_tamano
|
||||
FROM expediente_archivos
|
||||
WHERE pedimento_id IS NOT NULL
|
||||
GROUP BY pedimento_id
|
||||
)
|
||||
SELECT
|
||||
p.id AS pedimento_id,
|
||||
p.numero_pedimento,
|
||||
p.patente,
|
||||
p.aduana,
|
||||
p.anio,
|
||||
f.fecha_factura,
|
||||
f.proveedor,
|
||||
ISNULL(a.total_archivos, 0) AS total_archivos,
|
||||
ISNULL(a.total_tamano, 0) AS total_tamano
|
||||
FROM pedimentos p
|
||||
LEFT JOIN fact f ON f.pedimento_id = p.id
|
||||
LEFT JOIN arch a ON a.pedimento_id = p.id
|
||||
WHERE p.usuario_id = ?
|
||||
ORDER BY COALESCE(f.fecha_factura, p.fecha_creacion) DESC, p.id DESC
|
||||
";
|
||||
$stmt = sqlsrv_query($conn, $sql, [$id_importador]);
|
||||
|
||||
$expedientes = [];
|
||||
if ($stmt) {
|
||||
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
$row['pedimento_display'] = format_pedimento_display($row['anio'] ?? '', $row['aduana'] ?? '', $row['patente'] ?? '', $row['numero_pedimento'] ?? '');
|
||||
$expedientes[] = $row;
|
||||
}
|
||||
sqlsrv_free_stmt($stmt);
|
||||
}
|
||||
|
||||
include __DIR__ . '/../../views/expediente/index.php';
|
||||
@@ -45,27 +89,50 @@ function subir($id_solicitud)
|
||||
include __DIR__ . '/../../views/expediente/subir.php';
|
||||
}
|
||||
|
||||
// Vista subir para pedimento nuevo
|
||||
function subir_pedimento($pedimento_id)
|
||||
{
|
||||
if (!isset($_SESSION['usuario_id'])) { header('Location: /IMPORTADORES/login'); exit; }
|
||||
$conn = getConnection();
|
||||
// Validar propiedad del pedimento
|
||||
$chk = sqlsrv_query($conn, "SELECT 1 FROM pedimentos WHERE id = ? AND usuario_id = ?", [$pedimento_id, $_SESSION['usuario_id']]);
|
||||
if (!$chk || !sqlsrv_fetch($chk)) { http_response_code(403); echo "No autorizado"; exit; }
|
||||
if ($chk) sqlsrv_free_stmt($chk);
|
||||
$GLOBALS['pedimento_id'] = (int)$pedimento_id;
|
||||
include __DIR__ . '/../../views/expediente/subir.php';
|
||||
}
|
||||
|
||||
function subir_handler()
|
||||
{
|
||||
if (!isset($_POST['id_solicitud']) || !isset($_FILES['archivos']) || !isset($_SESSION['usuario_id'])) {
|
||||
die("❌ Solicitud inválida.");
|
||||
}
|
||||
if (!isset($_FILES['archivos']) || !isset($_SESSION['usuario_id'])) { die("❌ Solicitud inválida."); }
|
||||
|
||||
$conn = getConnection();
|
||||
ensure_expediente_schema($conn);
|
||||
|
||||
$id_solicitud = (int) $_POST['id_solicitud'];
|
||||
$id_importador = $_SESSION['usuario_id'];
|
||||
|
||||
// Validar propiedad de la solicitud
|
||||
$validStmt = sqlsrv_query($conn, "SELECT 1 FROM solicitud_importacion_factura WHERE id_solicitud = ? AND id_importador = ?", [$id_solicitud, $id_importador]);
|
||||
if (!sqlsrv_fetch($validStmt)) {
|
||||
die("❌ No tienes permisos para esta solicitud.");
|
||||
$id_solicitud = isset($_POST['id_solicitud']) ? (int) $_POST['id_solicitud'] : null;
|
||||
$pedimento_id = isset($_POST['pedimento_id']) ? (int) $_POST['pedimento_id'] : null;
|
||||
|
||||
if ($pedimento_id) {
|
||||
// Validar propiedad del pedimento
|
||||
$validStmt = sqlsrv_query($conn, "SELECT 1 FROM pedimentos WHERE id = ? AND usuario_id = ?", [$pedimento_id, $id_importador]);
|
||||
if (!$validStmt || !sqlsrv_fetch($validStmt)) { die("❌ No tienes permisos para este pedimento."); }
|
||||
if ($validStmt) sqlsrv_free_stmt($validStmt);
|
||||
} elseif ($id_solicitud) {
|
||||
// Validar propiedad de la solicitud (legacy)
|
||||
$validStmt = sqlsrv_query($conn, "SELECT 1 FROM solicitud_importacion_factura WHERE id_solicitud = ? AND id_importador = ?", [$id_solicitud, $id_importador]);
|
||||
if (!$validStmt || !sqlsrv_fetch($validStmt)) { die("❌ No tienes permisos para esta solicitud."); }
|
||||
if ($validStmt) sqlsrv_free_stmt($validStmt);
|
||||
} else {
|
||||
die("❌ Falta identificador de pedimento.");
|
||||
}
|
||||
|
||||
$archivos = $_FILES['archivos'];
|
||||
$usuario = $_SESSION['usuario_nombre'] ?? 'sistema';
|
||||
|
||||
$uploadDir = __DIR__ . '/../../uploads/expedientes/' . $id_solicitud;
|
||||
$folderKey = $pedimento_id ? ('pedimento_' . $pedimento_id) : ('solicitud_' . $id_solicitud);
|
||||
$uploadDir = __DIR__ . '/../../uploads/expedientes/' . $folderKey;
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0775, true);
|
||||
}
|
||||
@@ -79,19 +146,29 @@ function subir_handler()
|
||||
|
||||
move_uploaded_file($archivos['tmp_name'][$i], $rutaFinal);
|
||||
|
||||
$rutaDb = "uploads/expedientes/$id_solicitud/$nombreSeguro";
|
||||
$rutaDb = "uploads/expedientes/$folderKey/$nombreSeguro";
|
||||
$tamanoKb = round(filesize($rutaFinal) / 1024, 2);
|
||||
$tipoArchivo = mime_content_type($rutaFinal);
|
||||
|
||||
$sql = "INSERT INTO expediente_archivos
|
||||
(id_solicitud, nombre_archivo, ruta_archivo, tipo_archivo, tamano_archivo, creado_por)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
";
|
||||
$params = [$id_solicitud, $nombreOriginal, $rutaDb, $tipoArchivo, $tamanoKb, $usuario];
|
||||
if ($pedimento_id) {
|
||||
$sql = "INSERT INTO expediente_archivos
|
||||
(pedimento_id, nombre_archivo, ruta_archivo, tipo_archivo, tamano_archivo, creado_por)
|
||||
VALUES (?, ?, ?, ?, ?, ?)";
|
||||
$params = [$pedimento_id, $nombreOriginal, $rutaDb, $tipoArchivo, $tamanoKb, $usuario];
|
||||
} else {
|
||||
$sql = "INSERT INTO expediente_archivos
|
||||
(id_solicitud, nombre_archivo, ruta_archivo, tipo_archivo, tamano_archivo, creado_por)
|
||||
VALUES (?, ?, ?, ?, ?, ?)";
|
||||
$params = [$id_solicitud, $nombreOriginal, $rutaDb, $tipoArchivo, $tamanoKb, $usuario];
|
||||
}
|
||||
sqlsrv_query($conn, $sql, $params);
|
||||
}
|
||||
|
||||
header("Location: /IMPORTADORES/expediente/ver/$id_solicitud");
|
||||
if ($pedimento_id) {
|
||||
header("Location: /IMPORTADORES/expediente/ver_pedimento/$pedimento_id");
|
||||
} else {
|
||||
header("Location: /IMPORTADORES/expediente/ver/$id_solicitud");
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -119,6 +196,51 @@ function ver($id_solicitud)
|
||||
}
|
||||
}
|
||||
|
||||
$GLOBALS['pedimento'] = null; // vista usa variable opcional
|
||||
include __DIR__ . '/../../views/expediente/ver.php';
|
||||
}
|
||||
|
||||
function ver_pedimento($pedimento_id)
|
||||
{
|
||||
if (!isset($_SESSION['usuario_id'])) {
|
||||
header('Location: /IMPORTADORES/login');
|
||||
exit;
|
||||
}
|
||||
|
||||
$conn = getConnection();
|
||||
ensure_expediente_schema($conn);
|
||||
|
||||
$id_importador = $_SESSION['usuario_id'];
|
||||
|
||||
// Validar propiedad
|
||||
$chk = sqlsrv_query($conn, "SELECT 1 FROM pedimentos WHERE id = ? AND usuario_id = ?", [$pedimento_id, $id_importador]);
|
||||
if (!$chk || !sqlsrv_fetch($chk)) { http_response_code(404); echo "No autorizado o no encontrado"; exit; }
|
||||
if ($chk) sqlsrv_free_stmt($chk);
|
||||
|
||||
// Datos del pedimento para cabecera
|
||||
$stmtPed = sqlsrv_query($conn, "SELECT id, numero_pedimento, patente, aduana, anio, clave_documento, rfc_importador, fecha_creacion FROM pedimentos WHERE id = ?", [$pedimento_id]);
|
||||
$pedimento = $stmtPed ? sqlsrv_fetch_array($stmtPed, SQLSRV_FETCH_ASSOC) : null;
|
||||
if ($stmtPed) sqlsrv_free_stmt($stmtPed);
|
||||
if ($pedimento) {
|
||||
$pedimento['pedimento_display'] = format_pedimento_display($pedimento['anio'] ?? '', $pedimento['aduana'] ?? '', $pedimento['patente'] ?? '', $pedimento['numero_pedimento'] ?? '');
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM expediente_archivos WHERE pedimento_id = ? ORDER BY creado_en DESC";
|
||||
$stmt = sqlsrv_query($conn, $sql, [$pedimento_id]);
|
||||
|
||||
$archivos = [];
|
||||
if ($stmt) {
|
||||
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
if (isset($row['creado_en']) && is_string($row['creado_en'])) {
|
||||
$row['creado_en'] = new DateTime($row['creado_en']);
|
||||
}
|
||||
$archivos[] = $row;
|
||||
}
|
||||
sqlsrv_free_stmt($stmt);
|
||||
}
|
||||
|
||||
$GLOBALS['pedimento_id'] = (int)$pedimento_id;
|
||||
$GLOBALS['pedimento'] = $pedimento;
|
||||
include __DIR__ . '/../../views/expediente/ver.php';
|
||||
}
|
||||
|
||||
@@ -131,9 +253,24 @@ function ver_archivo($id_archivo)
|
||||
|
||||
$conn = getConnection();
|
||||
|
||||
$sql = "SELECT ea.*, sif.id_importador FROM expediente_archivos ea JOIN solicitud_importacion_factura sif ON sif.id_solicitud = ea.id_solicitud WHERE ea.id = ?";
|
||||
$stmt = sqlsrv_query($conn, $sql, [$id_archivo]);
|
||||
$archivo = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
ensure_expediente_schema($conn);
|
||||
// Intentar resolver por pedimento (nuevo) y si no, por solicitud (legacy)
|
||||
$sql = "SELECT ea.*, p.usuario_id AS id_importador
|
||||
FROM expediente_archivos ea
|
||||
JOIN pedimentos p ON p.id = ea.pedimento_id
|
||||
WHERE ea.id = ? AND ea.pedimento_id IS NOT NULL";
|
||||
$stmt = sqlsrv_query($conn, $sql, [$id_archivo]);
|
||||
$archivo = $stmt ? sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) : null;
|
||||
if ($stmt) sqlsrv_free_stmt($stmt);
|
||||
if (!$archivo) {
|
||||
$sqlL = "SELECT ea.*, sif.id_importador
|
||||
FROM expediente_archivos ea
|
||||
JOIN solicitud_importacion_factura sif ON sif.id_solicitud = ea.id_solicitud
|
||||
WHERE ea.id = ?";
|
||||
$stmtL = sqlsrv_query($conn, $sqlL, [$id_archivo]);
|
||||
$archivo = $stmtL ? sqlsrv_fetch_array($stmtL, SQLSRV_FETCH_ASSOC) : null;
|
||||
if ($stmtL) sqlsrv_free_stmt($stmtL);
|
||||
}
|
||||
|
||||
if (!$archivo || $archivo['id_importador'] != $_SESSION['usuario_id']) {
|
||||
http_response_code(403);
|
||||
@@ -224,4 +361,50 @@ function descargar_zip($id_solicitud)
|
||||
readfile($zip_file);
|
||||
unlink($zip_file);
|
||||
exit;
|
||||
}
|
||||
|
||||
function descargar_zip_pedimento($pedimento_id)
|
||||
{
|
||||
if (!isset($_SESSION['usuario_id'])) {
|
||||
http_response_code(403);
|
||||
echo "No autorizado.";
|
||||
exit;
|
||||
}
|
||||
|
||||
$conn = getConnection();
|
||||
ensure_expediente_schema($conn);
|
||||
|
||||
$id_importador = $_SESSION['usuario_id'];
|
||||
|
||||
// Validar propiedad
|
||||
$chk = sqlsrv_query($conn, "SELECT 1 FROM pedimentos WHERE id = ? AND usuario_id = ?", [$pedimento_id, $id_importador]);
|
||||
if (!$chk || !sqlsrv_fetch($chk)) { http_response_code(404); echo "No autorizado"; exit; }
|
||||
if ($chk) sqlsrv_free_stmt($chk);
|
||||
|
||||
$stmt = sqlsrv_query($conn, "SELECT nombre_archivo, ruta_archivo FROM expediente_archivos WHERE pedimento_id = ?", [$pedimento_id]);
|
||||
if (!$stmt) { http_response_code(500); echo "Error al consultar archivos."; exit; }
|
||||
|
||||
$archivos = [];
|
||||
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
$ruta_absoluta = __DIR__ . '/../../' . $row['ruta_archivo'];
|
||||
if (file_exists($ruta_absoluta)) {
|
||||
$archivos[] = [ 'ruta' => $ruta_absoluta, 'nombre' => $row['nombre_archivo'] ];
|
||||
}
|
||||
}
|
||||
sqlsrv_free_stmt($stmt);
|
||||
|
||||
if (empty($archivos)) { http_response_code(404); echo "No hay archivos válidos para comprimir."; exit; }
|
||||
|
||||
$zip_file = tempnam(sys_get_temp_dir(), 'expediente_') . '.zip';
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open($zip_file, ZipArchive::CREATE) !== true) { http_response_code(500); echo "No se pudo crear el archivo ZIP."; exit; }
|
||||
foreach ($archivos as $a) { $zip->addFile($a['ruta'], $a['nombre']); }
|
||||
$zip->close();
|
||||
|
||||
header('Content-Type: application/zip');
|
||||
header('Content-Disposition: attachment; filename="expediente_pedimento_' . $pedimento_id . '.zip"');
|
||||
header('Content-Length: ' . filesize($zip_file));
|
||||
readfile($zip_file);
|
||||
unlink($zip_file);
|
||||
exit;
|
||||
}
|
||||
@@ -142,20 +142,22 @@ function obtenerCatalogosVisibles($idUsuario)
|
||||
function obtenerIconoCatalogo($nombre)
|
||||
{
|
||||
$iconos = [
|
||||
'Locaciones' => '📍',
|
||||
'Vinculación' => '🔗',
|
||||
'Transportistas' => '🚚',
|
||||
'Transportes' => '🚛',
|
||||
'Choferes' => '👨✈️',
|
||||
'Proveedores' => '🏭',
|
||||
'Productos frecuentes' => '⭐',
|
||||
'Solicitudes importación' => '📄',
|
||||
'Expediente electrónico' => '📁',
|
||||
'Configuración' => '⚙️',
|
||||
'Cerrar sesión' => '🚪'
|
||||
'Locaciones' => 'fas fa-map-marker-alt',
|
||||
'Vinculación' => 'fas fa-link',
|
||||
'Transportistas' => 'fas fa-truck',
|
||||
'Transportes' => 'fas fa-shipping-fast',
|
||||
'Choferes' => 'fas fa-user-tie',
|
||||
'Proveedores' => 'fas fa-industry',
|
||||
'Productos frecuentes' => 'fas fa-star',
|
||||
'Solicitudes importación' => 'fas fa-file-alt',
|
||||
'Expediente electrónico' => 'fas fa-folder',
|
||||
'Configuración' => 'fas fa-cog',
|
||||
'Cerrar sesión' => 'fas fa-sign-out-alt',
|
||||
'Agencias' => 'fas fa-building',
|
||||
'Importadores' => 'fas fa-boxes'
|
||||
];
|
||||
|
||||
return $iconos[$nombre] ?? '📁';
|
||||
return $iconos[$nombre] ?? 'fas fa-folder';
|
||||
}
|
||||
|
||||
// Función para el dashboard del importador
|
||||
|
||||
636
app/controllers/importar_pedimentos.php
Normal file
636
app/controllers/importar_pedimentos.php
Normal file
@@ -0,0 +1,636 @@
|
||||
<?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("Archivos recibidos: " . print_r($_FILES, true));
|
||||
|
||||
// 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
|
||||
if (!isset($_FILES['archivo']) || $_FILES['archivo']['error'] !== UPLOAD_ERR_OK) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'No se ha recibido ningún archivo válido']);
|
||||
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) {
|
||||
$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)
|
||||
VALUES (?, ?, ?, ?, ?, ?)";
|
||||
|
||||
$params = [
|
||||
$pedimento_id,
|
||||
$factura['numero_factura'],
|
||||
$factura['fecha_factura'],
|
||||
$factura['valor_dolares'],
|
||||
$factura['valor_factura'],
|
||||
isset($factura['cove']) ? $factura['cove'] : 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
|
||||
}
|
||||
}
|
||||
|
||||
// Procesar la importación
|
||||
try {
|
||||
$archivo = $_FILES['archivo'];
|
||||
$validar_duplicados = isset($_POST['validar_duplicados']) && $_POST['validar_duplicados'] === 'on';
|
||||
|
||||
// Crear directorio temporal si no existe
|
||||
$upload_dir = __DIR__ . '/../storage/temp/';
|
||||
if (!is_dir($upload_dir)) {
|
||||
mkdir($upload_dir, 0755, true);
|
||||
}
|
||||
|
||||
// Mover archivo a directorio temporal
|
||||
$archivo_temporal = $upload_dir . 'import_' . time() . '_' . $archivo['name'];
|
||||
if (!move_uploaded_file($archivo['tmp_name'], $archivo_temporal)) {
|
||||
throw new Exception("Error al procesar el archivo subido");
|
||||
}
|
||||
|
||||
// Obtener conexión a SQL Server
|
||||
$conn = getConnection();
|
||||
|
||||
// Procesar archivo
|
||||
$importador = new ImportadorPedimentos($conn);
|
||||
$resultado = $importador->procesarArchivo($archivo_temporal, $validar_duplicados);
|
||||
|
||||
// Cerrar conexión
|
||||
sqlsrv_close($conn);
|
||||
|
||||
// Limpiar archivo temporal
|
||||
unlink($archivo_temporal);
|
||||
|
||||
// Enviar respuesta
|
||||
echo json_encode($resultado);
|
||||
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Error del servidor: ' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
?>
|
||||
@@ -2,44 +2,163 @@
|
||||
require_once __DIR__ . '/../../config/database.php';
|
||||
require_once __DIR__ . '/../helpers/session.php';
|
||||
|
||||
function index() {
|
||||
// Formatea el pedimento como: YY-AA-PPPP-PPPPPPP
|
||||
function mve_format_pedimento_display($anio, $aduana, $patente, $numero)
|
||||
{
|
||||
$yy = substr((string)$anio, -2);
|
||||
$ad = substr(preg_replace('/\D/', '', (string)$aduana), 0, 2);
|
||||
$pat = str_pad(preg_replace('/\D/', '', (string)$patente), 4, '0', STR_PAD_LEFT);
|
||||
$num = str_pad(preg_replace('/\D/', '', (string)$numero), 7, '0', STR_PAD_LEFT);
|
||||
$yy = $yy !== '' ? $yy : '00';
|
||||
$ad = str_pad($ad, 2, '0', STR_PAD_LEFT);
|
||||
return "$yy-$ad-$pat-$num";
|
||||
}
|
||||
|
||||
// Garantiza que expediente_archivos tenga la columna pedimento_id
|
||||
function mve_ensure_expediente_schema($conn)
|
||||
{
|
||||
$chk = sqlsrv_query($conn, "SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'expediente_archivos' AND COLUMN_NAME = 'pedimento_id'");
|
||||
$exists = $chk && sqlsrv_fetch_array($chk) ? true : false;
|
||||
if ($chk) sqlsrv_free_stmt($chk);
|
||||
if (!$exists) {
|
||||
@sqlsrv_query($conn, "ALTER TABLE expediente_archivos ADD pedimento_id INT NULL");
|
||||
@sqlsrv_query($conn, "CREATE INDEX IX_expediente_archivos_pedimento ON expediente_archivos(pedimento_id)");
|
||||
}
|
||||
}
|
||||
|
||||
// Genera documentos de prueba (Acuse y Detalle) en el expediente del pedimento
|
||||
function mve_generar_documentos_expediente($conn, $pedimento_id, $usuario_nombre = 'sistema')
|
||||
{
|
||||
mve_ensure_expediente_schema($conn);
|
||||
|
||||
// Obtener datos del pedimento para el encabezado
|
||||
$stmt = sqlsrv_query($conn, "SELECT numero_pedimento, patente, aduana, anio, rfc_importador, clave_documento, fecha_creacion FROM pedimentos WHERE id = ?", [$pedimento_id]);
|
||||
$ped = $stmt ? sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) : null;
|
||||
if ($stmt) sqlsrv_free_stmt($stmt);
|
||||
if (!$ped) return; // nada que hacer
|
||||
|
||||
$display = mve_format_pedimento_display($ped['anio'] ?? '', $ped['aduana'] ?? '', $ped['patente'] ?? '', $ped['numero_pedimento'] ?? '');
|
||||
|
||||
// Directorio destino
|
||||
$folderKey = 'pedimento_' . (int)$pedimento_id;
|
||||
$uploadDir = __DIR__ . '/../../uploads/expedientes/' . $folderKey;
|
||||
if (!is_dir($uploadDir)) { @mkdir($uploadDir, 0775, true); }
|
||||
|
||||
// Contenidos HTML simples
|
||||
$now = date('Y-m-d H:i');
|
||||
$htmlAcuse = "<html><head><meta charset='utf-8'><style>body{font-family:sans-serif} h1{font-size:18px} .m{font-family:monospace}</style></head><body>"
|
||||
."<h1>Acuse de Manifestación de Valor</h1>"
|
||||
."<p><strong>Pedimento:</strong> <span class='m'>{$display}</span></p>"
|
||||
."<p><strong>RFC:</strong> ".htmlspecialchars($ped['rfc_importador'] ?? '-', ENT_QUOTES, 'UTF-8')."</p>"
|
||||
."<p><strong>Clave:</strong> ".htmlspecialchars($ped['clave_documento'] ?? '-', ENT_QUOTES, 'UTF-8')."</p>"
|
||||
."<p><strong>Generado:</strong> {$now}</p>"
|
||||
."<p>Documento de prueba generado automáticamente.</p>"
|
||||
."</body></html>";
|
||||
|
||||
$htmlDetalle = "<html><head><meta charset='utf-8'><style>body{font-family:sans-serif} h1{font-size:18px} .m{font-family:monospace}</style></head><body>"
|
||||
."<h1>Detalle de Manifestación de Valor</h1>"
|
||||
."<p><strong>Pedimento:</strong> <span class='m'>{$display}</span></p>"
|
||||
."<p>Este es un detalle de ejemplo para pruebas.</p>"
|
||||
."<ul><li>Sección 65/66 capturada (mock)</li><li>Precios pagados y por pagar (mock)</li><li>Compensaciones (mock)</li></ul>"
|
||||
."<p><strong>Generado:</strong> {$now}</p>"
|
||||
."</body></html>";
|
||||
|
||||
// Intentar generar PDF con Dompdf; fallback a .txt si no está disponible
|
||||
$docs = [
|
||||
[ 'nombre' => 'Acuse Manifestacion de Valor', 'html' => $htmlAcuse ],
|
||||
[ 'nombre' => 'Detalle Manifestacion de Valor', 'html' => $htmlDetalle ],
|
||||
];
|
||||
|
||||
$dompdfOk = false;
|
||||
try {
|
||||
@require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
if (class_exists('Dompdf\\Dompdf')) { $dompdfOk = true; }
|
||||
} catch (\Throwable $e) { $dompdfOk = false; }
|
||||
|
||||
foreach ($docs as $d) {
|
||||
$safeBase = preg_replace('/[^A-Za-z0-9._\- ]/', '_', $d['nombre']);
|
||||
$filename = $safeBase . '_' . time() . ($dompdfOk ? '.pdf' : '.txt');
|
||||
$fullPath = $uploadDir . '/' . $filename;
|
||||
$rutaDb = 'uploads/expedientes/' . $folderKey . '/' . $filename;
|
||||
|
||||
if ($dompdfOk) {
|
||||
try {
|
||||
$dompdf = new Dompdf\Dompdf([ 'isRemoteEnabled' => false ]);
|
||||
$dompdf->loadHtml($d['html']);
|
||||
$dompdf->setPaper('letter', 'portrait');
|
||||
$dompdf->render();
|
||||
file_put_contents($fullPath, $dompdf->output());
|
||||
$tipo = 'application/pdf';
|
||||
} catch (\Throwable $e) {
|
||||
// Fallback a texto
|
||||
file_put_contents($fullPath, strip_tags($d['html']));
|
||||
$tipo = 'text/plain';
|
||||
}
|
||||
} else {
|
||||
file_put_contents($fullPath, strip_tags($d['html']));
|
||||
$tipo = 'text/plain';
|
||||
}
|
||||
|
||||
$tamanoKb = file_exists($fullPath) ? round(filesize($fullPath) / 1024, 2) : 0;
|
||||
// Insertar en expediente_archivos
|
||||
sqlsrv_query($conn,
|
||||
"INSERT INTO expediente_archivos (pedimento_id, nombre_archivo, ruta_archivo, tipo_archivo, tamano_archivo, creado_por) VALUES (?,?,?,?,?,?)",
|
||||
[$pedimento_id, $d['nombre'] . ($dompdfOk ? '.pdf' : '.txt'), $rutaDb, $tipo, $tamanoKb, $usuario_nombre]
|
||||
);
|
||||
}
|
||||
}
|
||||
function index()
|
||||
{
|
||||
include __DIR__ . '/../../views/mve/lista.php';
|
||||
}
|
||||
|
||||
function ajax_guardar_datos_factura() {
|
||||
try {
|
||||
// Validar que el usuario esté autenticado
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
echo json_encode(['success' => false, 'message' => 'Usuario no autenticado']);
|
||||
return;
|
||||
}
|
||||
// Guarda en bloque los datos enviados (se usa por el botón Guardar)
|
||||
function ajax_guardar_datos_factura()
|
||||
{
|
||||
if (!($_SESSION['usuario_id'] ?? false)) {
|
||||
echo json_encode(['success' => false, 'message' => 'No autorizado']);
|
||||
return;
|
||||
}
|
||||
|
||||
$id_factura = $_POST['id_factura'] ?? null;
|
||||
$id_pedimento = $_POST['id_pedimento'] ?? null;
|
||||
$datos_art65 = json_decode($_POST['datos_art65'] ?? '{}', true);
|
||||
$datos_art66 = json_decode($_POST['datos_art66'] ?? '{}', true);
|
||||
$usuario_id = (int)$_SESSION['usuario_id'];
|
||||
$id_factura = isset($_POST['id_factura']) ? (int)$_POST['id_factura'] : 0;
|
||||
$id_pedimento = isset($_POST['id_pedimento']) ? (int)$_POST['id_pedimento'] : 0;
|
||||
$datos_art65 = json_decode($_POST['datos_art65'] ?? '{}', true);
|
||||
$datos_art66 = json_decode($_POST['datos_art66'] ?? '{}', true);
|
||||
$datos_precio_pagado = json_decode($_POST['datos_precio_pagado'] ?? '{}', true);
|
||||
$datos_precio_pagar = json_decode($_POST['datos_precio_pagar'] ?? '{}', true);
|
||||
$datos_compenso = json_decode($_POST['datos_compenso'] ?? '{}', true);
|
||||
|
||||
if (!$id_factura || !$id_pedimento) {
|
||||
echo json_encode(['success' => false, 'message' => 'Faltan datos requeridos']);
|
||||
return;
|
||||
}
|
||||
if ($id_factura <= 0 || $id_pedimento <= 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'Parámetros inválidos']);
|
||||
return;
|
||||
}
|
||||
|
||||
$db = getDB();
|
||||
|
||||
// Verificar si ya existen datos para esta factura
|
||||
$stmt = $db->prepare("SELECT id FROM mve_facturas_datos WHERE id_pedimento = ? AND id_factura = ?");
|
||||
$stmt->execute([$id_pedimento, $id_factura]);
|
||||
$existe = $stmt->fetch();
|
||||
$conn = getConnection();
|
||||
|
||||
if ($existe) {
|
||||
// Actualizar registro existente
|
||||
$sql = "UPDATE mve_facturas_datos SET
|
||||
// Verificar propiedad del pedimento y que la factura le pertenezca
|
||||
$chk = sqlsrv_query($conn, "SELECT 1 FROM pedimentos p JOIN pedimento_facturas f ON f.pedimento_id = p.id WHERE p.id = ? AND f.id = ? AND p.usuario_id = ?", [$id_pedimento, $id_factura, $usuario_id]);
|
||||
$own = $chk && sqlsrv_fetch_array($chk) ? true : false;
|
||||
if ($chk) sqlsrv_free_stmt($chk);
|
||||
if (!$own) {
|
||||
echo json_encode(['success' => false, 'message' => 'No autorizado o no encontrado']);
|
||||
return;
|
||||
}
|
||||
|
||||
// ¿Existe registro para esta factura?
|
||||
$sel = sqlsrv_query($conn, "SELECT id FROM mve_facturas_datos WHERE id_pedimento = ? AND id_factura = ?", [$id_pedimento, $id_factura]);
|
||||
$row = $sel ? sqlsrv_fetch_array($sel, SQLSRV_FETCH_ASSOC) : null;
|
||||
if ($sel) sqlsrv_free_stmt($sel);
|
||||
|
||||
if ($row) {
|
||||
// UPDATE
|
||||
$sql = "UPDATE mve_facturas_datos SET
|
||||
art65_fecha_transporte = ?, art65_importe_transporte = ?,
|
||||
art65_fecha_descuentos = ?, art65_importe_descuentos = ?,
|
||||
art65_fecha_posteriores = ?, art65_importe_posteriores = ?,
|
||||
art65_fecha_contribuciones = ?, art65_importe_contribuciones = ?,
|
||||
art65_fecha_pagos_vendedor = ?, art65_importe_pagos_vendedor = ?,
|
||||
|
||||
|
||||
art66_fecha_comisiones = ?, art66_importe_comisiones = ?, art66_cargo_comisiones = ?,
|
||||
art66_fecha_envases = ?, art66_importe_envases = ?, art66_cargo_envases = ?,
|
||||
art66_fecha_embalaje = ?, art66_importe_embalaje = ?, art66_cargo_embalaje = ?,
|
||||
@@ -47,37 +166,64 @@ function ajax_guardar_datos_factura() {
|
||||
art66_fecha_ingenieria = ?, art66_importe_ingenieria = ?, art66_cargo_ingenieria = ?,
|
||||
art66_fecha_regalias = ?, art66_importe_regalias = ?, art66_cargo_regalias = ?,
|
||||
art66_fecha_producto = ?, art66_importe_producto = ?, art66_cargo_producto = ?,
|
||||
|
||||
fecha_actualizacion = NOW()
|
||||
WHERE id_pedimento = ? AND id_factura = ?";
|
||||
|
||||
$params = [
|
||||
$datos_art65['fecha_transporte'] ?: null, $datos_art65['importe_transporte'] ?: null,
|
||||
$datos_art65['fecha_descuentos'] ?: null, $datos_art65['importe_descuentos'] ?: null,
|
||||
$datos_art65['fecha_posteriores'] ?: null, $datos_art65['importe_posteriores'] ?: null,
|
||||
$datos_art65['fecha_contribuciones'] ?: null, $datos_art65['importe_contribuciones'] ?: null,
|
||||
$datos_art65['fecha_pagos_vendedor'] ?: null, $datos_art65['importe_pagos_vendedor'] ?: null,
|
||||
|
||||
$datos_art66['fecha_comisiones'] ?: null, $datos_art66['importe_comisiones'] ?: null, $datos_art66['cargo_comisiones'] ?: null,
|
||||
$datos_art66['fecha_envases'] ?: null, $datos_art66['importe_envases'] ?: null, $datos_art66['cargo_envases'] ?: null,
|
||||
$datos_art66['fecha_embalaje'] ?: null, $datos_art66['importe_embalaje'] ?: null, $datos_art66['cargo_embalaje'] ?: null,
|
||||
$datos_art66['fecha_transporte_dec'] ?: null, $datos_art66['importe_transporte_dec'] ?: null, $datos_art66['cargo_transporte_dec'] ?: null,
|
||||
$datos_art66['fecha_ingenieria'] ?: null, $datos_art66['importe_ingenieria'] ?: null, $datos_art66['cargo_ingenieria'] ?: null,
|
||||
$datos_art66['fecha_regalias'] ?: null, $datos_art66['importe_regalias'] ?: null, $datos_art66['cargo_regalias'] ?: null,
|
||||
$datos_art66['fecha_producto'] ?: null, $datos_art66['importe_producto'] ?: null, $datos_art66['cargo_producto'] ?: null,
|
||||
|
||||
$id_pedimento, $id_factura
|
||||
];
|
||||
} else {
|
||||
// Crear nuevo registro
|
||||
$sql = "INSERT INTO mve_facturas_datos (
|
||||
|
||||
precio_pagado_fecha_pago = ?, precio_pagado_importe = ?, precio_pagado_moneda = ?,
|
||||
precio_pagado_forma_pago = ?, precio_pagado_referencia = ?,
|
||||
|
||||
precio_pagar_fecha_limite = ?, precio_pagar_importe = ?, precio_pagar_moneda = ?,
|
||||
precio_pagar_terminos = ?, precio_pagar_observaciones = ?,
|
||||
|
||||
compenso_fecha = ?, compenso_importe = ?, compenso_tipo = ?,
|
||||
compenso_motivo = ?, compenso_documentos = ?, compenso_descripcion = ?
|
||||
WHERE id = ?";
|
||||
|
||||
$params = [
|
||||
$datos_art65['fecha_transporte'] ?? null, $datos_art65['importe_transporte'] ?? null,
|
||||
$datos_art65['fecha_descuentos'] ?? null, $datos_art65['importe_descuentos'] ?? null,
|
||||
$datos_art65['fecha_posteriores'] ?? null, $datos_art65['importe_posteriores'] ?? null,
|
||||
$datos_art65['fecha_contribuciones'] ?? null, $datos_art65['importe_contribuciones'] ?? null,
|
||||
$datos_art65['fecha_pagos_vendedor'] ?? null, $datos_art65['importe_pagos_vendedor'] ?? null,
|
||||
|
||||
$datos_art66['fecha_comisiones'] ?? null, $datos_art66['importe_comisiones'] ?? null, $datos_art66['cargo_comisiones'] ?? null,
|
||||
$datos_art66['fecha_envases'] ?? null, $datos_art66['importe_envases'] ?? null, $datos_art66['cargo_envases'] ?? null,
|
||||
$datos_art66['fecha_embalaje'] ?? null, $datos_art66['importe_embalaje'] ?? null, $datos_art66['cargo_embalaje'] ?? null,
|
||||
$datos_art66['fecha_transporte_dec'] ?? null, $datos_art66['importe_transporte_dec'] ?? null, $datos_art66['cargo_transporte_dec'] ?? null,
|
||||
$datos_art66['fecha_ingenieria'] ?? null, $datos_art66['importe_ingenieria'] ?? null, $datos_art66['cargo_ingenieria'] ?? null,
|
||||
$datos_art66['fecha_regalias'] ?? null, $datos_art66['importe_regalias'] ?? null, $datos_art66['cargo_regalias'] ?? null,
|
||||
$datos_art66['fecha_producto'] ?? null, $datos_art66['importe_producto'] ?? null, $datos_art66['cargo_producto'] ?? null,
|
||||
|
||||
$datos_precio_pagado['fecha_precio_pagado'] ?? null,
|
||||
$datos_precio_pagado['importe_precio_pagado'] ?? null,
|
||||
$datos_precio_pagado['moneda_precio_pagado'] ?? null,
|
||||
$datos_precio_pagado['forma_pago_precio_pagado'] ?? null,
|
||||
$datos_precio_pagado['referencia_precio_pagado'] ?? null,
|
||||
|
||||
$datos_precio_pagar['fecha_limite_pago'] ?? null,
|
||||
$datos_precio_pagar['importe_precio_pagar'] ?? null,
|
||||
$datos_precio_pagar['moneda_precio_pagar'] ?? null,
|
||||
$datos_precio_pagar['terminos_precio_pagar'] ?? null,
|
||||
$datos_precio_pagar['observaciones_precio_pagar'] ?? null,
|
||||
|
||||
$datos_compenso['fecha_compenso'] ?? null,
|
||||
$datos_compenso['importe_compenso'] ?? null,
|
||||
$datos_compenso['tipo_compenso'] ?? null,
|
||||
$datos_compenso['motivo_compenso'] ?? null,
|
||||
$datos_compenso['documentos_compenso'] ?? null,
|
||||
$datos_compenso['descripcion_compenso'] ?? null,
|
||||
$row['id']
|
||||
];
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
} else {
|
||||
// INSERT
|
||||
$sql = "INSERT INTO mve_facturas_datos (
|
||||
id_pedimento, id_factura, numero_factura,
|
||||
art65_fecha_transporte, art65_importe_transporte,
|
||||
art65_fecha_descuentos, art65_importe_descuentos,
|
||||
art65_fecha_posteriores, art65_importe_posteriores,
|
||||
art65_fecha_contribuciones, art65_importe_contribuciones,
|
||||
art65_fecha_pagos_vendedor, art65_importe_pagos_vendedor,
|
||||
|
||||
|
||||
art66_fecha_comisiones, art66_importe_comisiones, art66_cargo_comisiones,
|
||||
art66_fecha_envases, art66_importe_envases, art66_cargo_envases,
|
||||
art66_fecha_embalaje, art66_importe_embalaje, art66_cargo_embalaje,
|
||||
@@ -85,106 +231,447 @@ function ajax_guardar_datos_factura() {
|
||||
art66_fecha_ingenieria, art66_importe_ingenieria, art66_cargo_ingenieria,
|
||||
art66_fecha_regalias, art66_importe_regalias, art66_cargo_regalias,
|
||||
art66_fecha_producto, art66_importe_producto, art66_cargo_producto,
|
||||
|
||||
|
||||
precio_pagado_fecha_pago, precio_pagado_importe, precio_pagado_moneda,
|
||||
precio_pagado_forma_pago, precio_pagado_referencia,
|
||||
|
||||
precio_pagar_fecha_limite, precio_pagar_importe, precio_pagar_moneda,
|
||||
precio_pagar_terminos, precio_pagar_observaciones,
|
||||
|
||||
compenso_fecha, compenso_importe, compenso_tipo,
|
||||
compenso_motivo, compenso_documentos, compenso_descripcion,
|
||||
|
||||
usuario_creacion
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
|
||||
// Obtener número de factura opcional
|
||||
$num = null;
|
||||
$nf = sqlsrv_query($conn, "SELECT numero_factura FROM pedimento_facturas WHERE id = ?", [$id_factura]);
|
||||
if ($nf && ($r = sqlsrv_fetch_array($nf, SQLSRV_FETCH_ASSOC))) { $num = $r['numero_factura']; }
|
||||
if ($nf) sqlsrv_free_stmt($nf);
|
||||
|
||||
$params = [
|
||||
$id_pedimento, $id_factura, $num,
|
||||
$datos_art65['fecha_transporte'] ?? null, $datos_art65['importe_transporte'] ?? null,
|
||||
$datos_art65['fecha_descuentos'] ?? null, $datos_art65['importe_descuentos'] ?? null,
|
||||
$datos_art65['fecha_posteriores'] ?? null, $datos_art65['importe_posteriores'] ?? null,
|
||||
$datos_art65['fecha_contribuciones'] ?? null, $datos_art65['importe_contribuciones'] ?? null,
|
||||
$datos_art65['fecha_pagos_vendedor'] ?? null, $datos_art65['importe_pagos_vendedor'] ?? null,
|
||||
|
||||
$datos_art66['fecha_comisiones'] ?? null, $datos_art66['importe_comisiones'] ?? null, $datos_art66['cargo_comisiones'] ?? null,
|
||||
$datos_art66['fecha_envases'] ?? null, $datos_art66['importe_envases'] ?? null, $datos_art66['cargo_envases'] ?? null,
|
||||
$datos_art66['fecha_embalaje'] ?? null, $datos_art66['importe_embalaje'] ?? null, $datos_art66['cargo_embalaje'] ?? null,
|
||||
$datos_art66['fecha_transporte_dec'] ?? null, $datos_art66['importe_transporte_dec'] ?? null, $datos_art66['cargo_transporte_dec'] ?? null,
|
||||
$datos_art66['fecha_ingenieria'] ?? null, $datos_art66['importe_ingenieria'] ?? null, $datos_art66['cargo_ingenieria'] ?? null,
|
||||
$datos_art66['fecha_regalias'] ?? null, $datos_art66['importe_regalias'] ?? null, $datos_art66['cargo_regalias'] ?? null,
|
||||
$datos_art66['fecha_producto'] ?? null, $datos_art66['importe_producto'] ?? null, $datos_art66['cargo_producto'] ?? null,
|
||||
|
||||
$datos_precio_pagado['fecha_precio_pagado'] ?? null,
|
||||
$datos_precio_pagado['importe_precio_pagado'] ?? null,
|
||||
$datos_precio_pagado['moneda_precio_pagado'] ?? null,
|
||||
$datos_precio_pagado['forma_pago_precio_pagado'] ?? null,
|
||||
$datos_precio_pagado['referencia_precio_pagado'] ?? null,
|
||||
|
||||
$datos_precio_pagar['fecha_limite_pago'] ?? null,
|
||||
$datos_precio_pagar['importe_precio_pagar'] ?? null,
|
||||
$datos_precio_pagar['moneda_precio_pagar'] ?? null,
|
||||
$datos_precio_pagar['terminos_precio_pagar'] ?? null,
|
||||
$datos_precio_pagar['observaciones_precio_pagar'] ?? null,
|
||||
|
||||
$datos_compenso['fecha_compenso'] ?? null,
|
||||
$datos_compenso['importe_compenso'] ?? null,
|
||||
$datos_compenso['tipo_compenso'] ?? null,
|
||||
$datos_compenso['motivo_compenso'] ?? null,
|
||||
$datos_compenso['documentos_compenso'] ?? null,
|
||||
$datos_compenso['descripcion_compenso'] ?? null,
|
||||
|
||||
(string)$usuario_id
|
||||
];
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
}
|
||||
|
||||
if ($stmt === false) {
|
||||
echo json_encode(['success' => false, 'message' => 'Error al guardar']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Marcar estado de MVE/COVE como respondido (para el badge)
|
||||
upsert_cove_respuesta_min($conn, $id_pedimento, $id_factura, $usuario_id);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
}
|
||||
|
||||
// Autosave por sección: seccion in ['65','66','precio_pagado','precio_pagar','compenso']
|
||||
function ajax_guardar_seccion()
|
||||
{
|
||||
if (!($_SESSION['usuario_id'] ?? false)) {
|
||||
echo json_encode(['success' => false, 'message' => 'No autorizado']);
|
||||
return;
|
||||
}
|
||||
|
||||
$usuario_id = (int)$_SESSION['usuario_id'];
|
||||
$id_factura = isset($_POST['id_factura']) ? (int)$_POST['id_factura'] : 0;
|
||||
$id_pedimento = isset($_POST['id_pedimento']) ? (int)$_POST['id_pedimento'] : 0;
|
||||
$seccion = $_POST['seccion'] ?? '';
|
||||
$datos = json_decode($_POST['datos'] ?? '{}', true);
|
||||
if ($id_factura <= 0 || $id_pedimento <= 0 || !$seccion) {
|
||||
echo json_encode(['success' => false, 'message' => 'Parámetros inválidos']);
|
||||
return;
|
||||
}
|
||||
|
||||
$conn = getConnection();
|
||||
// Verificar propiedad
|
||||
$chk = sqlsrv_query($conn, "SELECT 1 FROM pedimentos p JOIN pedimento_facturas f ON f.pedimento_id = p.id WHERE p.id = ? AND f.id = ? AND p.usuario_id = ?", [$id_pedimento, $id_factura, $usuario_id]);
|
||||
$own = $chk && sqlsrv_fetch_array($chk) ? true : false;
|
||||
if ($chk) sqlsrv_free_stmt($chk);
|
||||
if (!$own) { echo json_encode(['success' => false, 'message' => 'No autorizado']); return; }
|
||||
|
||||
// Garantizar que exista el registro base
|
||||
$sel = sqlsrv_query($conn, "SELECT id FROM mve_facturas_datos WHERE id_pedimento = ? AND id_factura = ?", [$id_pedimento, $id_factura]);
|
||||
$row = $sel ? sqlsrv_fetch_array($sel, SQLSRV_FETCH_ASSOC) : null; if ($sel) sqlsrv_free_stmt($sel);
|
||||
if (!$row) {
|
||||
// Crear registro vacío
|
||||
$num = null; $nf = sqlsrv_query($conn, "SELECT numero_factura FROM pedimento_facturas WHERE id = ?", [$id_factura]);
|
||||
if ($nf && ($r = sqlsrv_fetch_array($nf, SQLSRV_FETCH_ASSOC))) { $num = $r['numero_factura']; }
|
||||
if ($nf) sqlsrv_free_stmt($nf);
|
||||
$ins = sqlsrv_query($conn, "INSERT INTO mve_facturas_datos (id_pedimento, id_factura, numero_factura, usuario_creacion) VALUES (?,?,?,?)", [$id_pedimento, $id_factura, $num, (string)$usuario_id]);
|
||||
if ($ins === false) { echo json_encode(['success' => false, 'message' => 'Error al iniciar registro']); return; }
|
||||
$sel2 = sqlsrv_query($conn, "SELECT id FROM mve_facturas_datos WHERE id_pedimento = ? AND id_factura = ?", [$id_pedimento, $id_factura]);
|
||||
$row = $sel2 ? sqlsrv_fetch_array($sel2, SQLSRV_FETCH_ASSOC) : null; if ($sel2) sqlsrv_free_stmt($sel2);
|
||||
}
|
||||
|
||||
if (!$row) { echo json_encode(['success' => false, 'message' => 'No se pudo crear el registro']); return; }
|
||||
|
||||
$id = (int)$row['id'];
|
||||
$sql = '';
|
||||
$params = [];
|
||||
switch ($seccion) {
|
||||
case '65':
|
||||
$sql = "UPDATE mve_facturas_datos SET
|
||||
art65_fecha_transporte = ?, art65_importe_transporte = ?,
|
||||
art65_fecha_descuentos = ?, art65_importe_descuentos = ?,
|
||||
art65_fecha_posteriores = ?, art65_importe_posteriores = ?,
|
||||
art65_fecha_contribuciones = ?, art65_importe_contribuciones = ?,
|
||||
art65_fecha_pagos_vendedor = ?, art65_importe_pagos_vendedor = ?
|
||||
WHERE id = ?";
|
||||
$params = [
|
||||
$id_pedimento, $id_factura, "FACTURA-$id_factura",
|
||||
$datos_art65['fecha_transporte'] ?: null, $datos_art65['importe_transporte'] ?: null,
|
||||
$datos_art65['fecha_descuentos'] ?: null, $datos_art65['importe_descuentos'] ?: null,
|
||||
$datos_art65['fecha_posteriores'] ?: null, $datos_art65['importe_posteriores'] ?: null,
|
||||
$datos_art65['fecha_contribuciones'] ?: null, $datos_art65['importe_contribuciones'] ?: null,
|
||||
$datos_art65['fecha_pagos_vendedor'] ?: null, $datos_art65['importe_pagos_vendedor'] ?: null,
|
||||
|
||||
$datos_art66['fecha_comisiones'] ?: null, $datos_art66['importe_comisiones'] ?: null, $datos_art66['cargo_comisiones'] ?: null,
|
||||
$datos_art66['fecha_envases'] ?: null, $datos_art66['importe_envases'] ?: null, $datos_art66['cargo_envases'] ?: null,
|
||||
$datos_art66['fecha_embalaje'] ?: null, $datos_art66['importe_embalaje'] ?: null, $datos_art66['cargo_embalaje'] ?: null,
|
||||
$datos_art66['fecha_transporte_dec'] ?: null, $datos_art66['importe_transporte_dec'] ?: null, $datos_art66['cargo_transporte_dec'] ?: null,
|
||||
$datos_art66['fecha_ingenieria'] ?: null, $datos_art66['importe_ingenieria'] ?: null, $datos_art66['cargo_ingenieria'] ?: null,
|
||||
$datos_art66['fecha_regalias'] ?: null, $datos_art66['importe_regalias'] ?: null, $datos_art66['cargo_regalias'] ?: null,
|
||||
$datos_art66['fecha_producto'] ?: null, $datos_art66['importe_producto'] ?: null, $datos_art66['cargo_producto'] ?: null,
|
||||
|
||||
$_SESSION['user_id']
|
||||
$datos['fecha_transporte'] ?? null, $datos['importe_transporte'] ?? null,
|
||||
$datos['fecha_descuentos'] ?? null, $datos['importe_descuentos'] ?? null,
|
||||
$datos['fecha_posteriores'] ?? null, $datos['importe_posteriores'] ?? null,
|
||||
$datos['fecha_contribuciones'] ?? null, $datos['importe_contribuciones'] ?? null,
|
||||
$datos['fecha_pagos_vendedor'] ?? null, $datos['importe_pagos_vendedor'] ?? null,
|
||||
$id
|
||||
];
|
||||
break;
|
||||
case '66':
|
||||
$sql = "UPDATE mve_facturas_datos SET
|
||||
art66_fecha_comisiones = ?, art66_importe_comisiones = ?, art66_cargo_comisiones = ?,
|
||||
art66_fecha_envases = ?, art66_importe_envases = ?, art66_cargo_envases = ?,
|
||||
art66_fecha_embalaje = ?, art66_importe_embalaje = ?, art66_cargo_embalaje = ?,
|
||||
art66_fecha_transporte_dec = ?, art66_importe_transporte_dec = ?, art66_cargo_transporte_dec = ?,
|
||||
art66_fecha_ingenieria = ?, art66_importe_ingenieria = ?, art66_cargo_ingenieria = ?,
|
||||
art66_fecha_regalias = ?, art66_importe_regalias = ?, art66_cargo_regalias = ?,
|
||||
art66_fecha_producto = ?, art66_importe_producto = ?, art66_cargo_producto = ?
|
||||
WHERE id = ?";
|
||||
$params = [
|
||||
$datos['fecha_comisiones'] ?? null, $datos['importe_comisiones'] ?? null, $datos['cargo_comisiones'] ?? null,
|
||||
$datos['fecha_envases'] ?? null, $datos['importe_envases'] ?? null, $datos['cargo_envases'] ?? null,
|
||||
$datos['fecha_embalaje'] ?? null, $datos['importe_embalaje'] ?? null, $datos['cargo_embalaje'] ?? null,
|
||||
$datos['fecha_transporte_dec'] ?? null, $datos['importe_transporte_dec'] ?? null, $datos['cargo_transporte_dec'] ?? null,
|
||||
$datos['fecha_ingenieria'] ?? null, $datos['importe_ingenieria'] ?? null, $datos['cargo_ingenieria'] ?? null,
|
||||
$datos['fecha_regalias'] ?? null, $datos['importe_regalias'] ?? null, $datos['cargo_regalias'] ?? null,
|
||||
$datos['fecha_producto'] ?? null, $datos['importe_producto'] ?? null, $datos['cargo_producto'] ?? null,
|
||||
$id
|
||||
];
|
||||
break;
|
||||
case 'precio_pagado':
|
||||
$sql = "UPDATE mve_facturas_datos SET
|
||||
precio_pagado_fecha_pago = ?, precio_pagado_importe = ?, precio_pagado_moneda = ?,
|
||||
precio_pagado_forma_pago = ?, precio_pagado_referencia = ?
|
||||
WHERE id = ?";
|
||||
$params = [
|
||||
$datos['fecha_precio_pagado'] ?? null,
|
||||
$datos['importe_precio_pagado'] ?? null,
|
||||
$datos['moneda_precio_pagado'] ?? null,
|
||||
$datos['forma_pago_precio_pagado'] ?? null,
|
||||
$datos['referencia_precio_pagado'] ?? null,
|
||||
$id
|
||||
];
|
||||
break;
|
||||
case 'precio_pagar':
|
||||
$sql = "UPDATE mve_facturas_datos SET
|
||||
precio_pagar_fecha_limite = ?, precio_pagar_importe = ?, precio_pagar_moneda = ?,
|
||||
precio_pagar_terminos = ?, precio_pagar_observaciones = ?
|
||||
WHERE id = ?";
|
||||
$params = [
|
||||
$datos['fecha_limite_pago'] ?? null,
|
||||
$datos['importe_precio_pagar'] ?? null,
|
||||
$datos['moneda_precio_pagar'] ?? null,
|
||||
$datos['terminos_precio_pagar'] ?? null,
|
||||
$datos['observaciones_precio_pagar'] ?? null,
|
||||
$id
|
||||
];
|
||||
break;
|
||||
case 'compenso':
|
||||
$sql = "UPDATE mve_facturas_datos SET
|
||||
compenso_fecha = ?, compenso_importe = ?, compenso_tipo = ?,
|
||||
compenso_motivo = ?, compenso_documentos = ?, compenso_descripcion = ?
|
||||
WHERE id = ?";
|
||||
$params = [
|
||||
$datos['fecha_compenso'] ?? null,
|
||||
$datos['importe_compenso'] ?? null,
|
||||
$datos['tipo_compenso'] ?? null,
|
||||
$datos['motivo_compenso'] ?? null,
|
||||
$datos['documentos_compenso'] ?? null,
|
||||
$datos['descripcion_compenso'] ?? null,
|
||||
$id
|
||||
];
|
||||
break;
|
||||
default:
|
||||
echo json_encode(['success' => false, 'message' => 'Sección inválida']);
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
if ($stmt === false) {
|
||||
echo json_encode(['success' => false, 'message' => 'Error al guardar sección']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Marcar estado para badge
|
||||
upsert_cove_respuesta_min($conn, $id_pedimento, $id_factura, $usuario_id);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
}
|
||||
|
||||
function ajax_obtener_datos_factura()
|
||||
{
|
||||
$id_factura = isset($_GET['id_factura']) ? (int)$_GET['id_factura'] : 0;
|
||||
if ($id_factura <= 0) { echo json_encode(['success' => false, 'message' => 'ID inválido']); return; }
|
||||
|
||||
$conn = getConnection();
|
||||
$stmt = sqlsrv_query($conn, "SELECT * FROM mve_facturas_datos WHERE id_factura = ?", [$id_factura]);
|
||||
if ($stmt === false) { echo json_encode(['success' => false, 'message' => 'Error DB']); return; }
|
||||
$datos = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if ($stmt) sqlsrv_free_stmt($stmt);
|
||||
|
||||
if ($datos) {
|
||||
// Formateador de fechas seguro para JSON
|
||||
$fmtDate = function($v) {
|
||||
if ($v instanceof DateTime) return $v->format('Y-m-d');
|
||||
if (is_string($v)) return substr($v, 0, 10);
|
||||
return $v ?: null;
|
||||
};
|
||||
if (isset($datos['fecha_actualizacion']) && $datos['fecha_actualizacion'] instanceof DateTime) {
|
||||
$datos['fecha_actualizacion'] = $datos['fecha_actualizacion']->format('Y-m-d H:i:s');
|
||||
}
|
||||
$datosEstructurados = [
|
||||
'art65' => [
|
||||
'fecha_transporte' => $fmtDate($datos['art65_fecha_transporte'] ?? null),
|
||||
'importe_transporte' => $datos['art65_importe_transporte'] ?? null,
|
||||
'fecha_descuentos' => $fmtDate($datos['art65_fecha_descuentos'] ?? null),
|
||||
'importe_descuentos' => $datos['art65_importe_descuentos'] ?? null,
|
||||
'fecha_posteriores' => $fmtDate($datos['art65_fecha_posteriores'] ?? null),
|
||||
'importe_posteriores' => $datos['art65_importe_posteriores'] ?? null,
|
||||
'fecha_contribuciones' => $fmtDate($datos['art65_fecha_contribuciones'] ?? null),
|
||||
'importe_contribuciones' => $datos['art65_importe_contribuciones'] ?? null,
|
||||
'fecha_pagos_vendedor' => $fmtDate($datos['art65_fecha_pagos_vendedor'] ?? null),
|
||||
'importe_pagos_vendedor' => $datos['art65_importe_pagos_vendedor'] ?? null,
|
||||
],
|
||||
'art66' => [
|
||||
'fecha_comisiones' => $fmtDate($datos['art66_fecha_comisiones'] ?? null),
|
||||
'importe_comisiones' => $datos['art66_importe_comisiones'] ?? null,
|
||||
'cargo_comisiones' => $datos['art66_cargo_comisiones'] ?? null,
|
||||
'fecha_envases' => $fmtDate($datos['art66_fecha_envases'] ?? null),
|
||||
'importe_envases' => $datos['art66_importe_envases'] ?? null,
|
||||
'cargo_envases' => $datos['art66_cargo_envases'] ?? null,
|
||||
'fecha_embalaje' => $fmtDate($datos['art66_fecha_embalaje'] ?? null),
|
||||
'importe_embalaje' => $datos['art66_importe_embalaje'] ?? null,
|
||||
'cargo_embalaje' => $datos['art66_cargo_embalaje'] ?? null,
|
||||
'fecha_transporte_dec' => $fmtDate($datos['art66_fecha_transporte_dec'] ?? null),
|
||||
'importe_transporte_dec' => $datos['art66_importe_transporte_dec'] ?? null,
|
||||
'cargo_transporte_dec' => $datos['art66_cargo_transporte_dec'] ?? null,
|
||||
'fecha_ingenieria' => $fmtDate($datos['art66_fecha_ingenieria'] ?? null),
|
||||
'importe_ingenieria' => $datos['art66_importe_ingenieria'] ?? null,
|
||||
'cargo_ingenieria' => $datos['art66_cargo_ingenieria'] ?? null,
|
||||
'fecha_regalias' => $fmtDate($datos['art66_fecha_regalias'] ?? null),
|
||||
'importe_regalias' => $datos['art66_importe_regalias'] ?? null,
|
||||
'cargo_regalias' => $datos['art66_cargo_regalias'] ?? null,
|
||||
'fecha_producto' => $fmtDate($datos['art66_fecha_producto'] ?? null),
|
||||
'importe_producto' => $datos['art66_importe_producto'] ?? null,
|
||||
'cargo_producto' => $datos['art66_cargo_producto'] ?? null,
|
||||
],
|
||||
'precio_pagado' => [
|
||||
'fecha_precio_pagado' => $fmtDate($datos['precio_pagado_fecha_pago'] ?? null),
|
||||
'importe_precio_pagado' => $datos['precio_pagado_importe'] ?? null,
|
||||
'moneda_precio_pagado' => $datos['precio_pagado_moneda'] ?? null,
|
||||
'forma_pago_precio_pagado' => $datos['precio_pagado_forma_pago'] ?? null,
|
||||
'referencia_precio_pagado' => $datos['precio_pagado_referencia'] ?? null,
|
||||
],
|
||||
'precio_pagar' => [
|
||||
'fecha_limite_pago' => $fmtDate($datos['precio_pagar_fecha_limite'] ?? null),
|
||||
'importe_precio_pagar' => $datos['precio_pagar_importe'] ?? null,
|
||||
'moneda_precio_pagar' => $datos['precio_pagar_moneda'] ?? null,
|
||||
'terminos_precio_pagar' => $datos['precio_pagar_terminos'] ?? null,
|
||||
'observaciones_precio_pagar' => $datos['precio_pagar_observaciones'] ?? null,
|
||||
],
|
||||
'compenso' => [
|
||||
'fecha_compenso' => $fmtDate($datos['compenso_fecha'] ?? null),
|
||||
'importe_compenso' => $datos['compenso_importe'] ?? null,
|
||||
'tipo_compenso' => $datos['compenso_tipo'] ?? null,
|
||||
'motivo_compenso' => $datos['compenso_motivo'] ?? null,
|
||||
'documentos_compenso' => $datos['compenso_documentos'] ?? null,
|
||||
'descripcion_compenso' => $datos['compenso_descripcion'] ?? null,
|
||||
]
|
||||
];
|
||||
|
||||
$stmt = $db->prepare($sql);
|
||||
$resultado = $stmt->execute($params);
|
||||
|
||||
if ($resultado) {
|
||||
echo json_encode(['success' => true, 'message' => 'Datos guardados correctamente']);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Error al guardar los datos']);
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['success' => false, 'message' => 'Error interno: ' . $e->getMessage()]);
|
||||
echo json_encode(['success' => true, 'datos' => $datosEstructurados]);
|
||||
} else {
|
||||
echo json_encode(['success' => true, 'datos' => null]);
|
||||
}
|
||||
}
|
||||
|
||||
function ajax_obtener_datos_factura() {
|
||||
try {
|
||||
$id_factura = $_GET['id_factura'] ?? null;
|
||||
// Utilidad: marca/crea un registro mínimo en cove_respuestas para encender el badge
|
||||
function upsert_cove_respuesta_min($conn, $pedimento_id, $factura_id, $usuario_id)
|
||||
{
|
||||
$sel = sqlsrv_query($conn, "SELECT id FROM cove_respuestas WHERE factura_id = ? AND usuario_id = ?", [$factura_id, $usuario_id]);
|
||||
$row = $sel ? sqlsrv_fetch_array($sel, SQLSRV_FETCH_ASSOC) : null; if ($sel) sqlsrv_free_stmt($sel);
|
||||
if ($row) {
|
||||
sqlsrv_query($conn, "UPDATE cove_respuestas SET estado = 'respondido', fecha_actualizacion = SYSDATETIME() WHERE id = ?", [$row['id']]);
|
||||
} else {
|
||||
sqlsrv_query($conn, "INSERT INTO cove_respuestas (pedimento_id, factura_id, usuario_id, respuestas, estado, fecha_creacion) VALUES (?,?,?,?,?,SYSDATETIME())",
|
||||
[$pedimento_id, $factura_id, $usuario_id, '{}', 'respondido']);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$id_factura) {
|
||||
echo json_encode(['success' => false, 'message' => 'ID de factura requerido']);
|
||||
// Registra la solicitud de MVE con aceptación de declaración del importador
|
||||
function ajax_registrar_solicitud()
|
||||
{
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
if (!($_SESSION['usuario_id'] ?? false)) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['success' => false, 'message' => 'No autorizado']);
|
||||
return;
|
||||
}
|
||||
|
||||
$usuario_id = (int)$_SESSION['usuario_id'];
|
||||
$pedimento_id = isset($_POST['pedimento_id']) ? (int)$_POST['pedimento_id'] : 0;
|
||||
$factura_id = isset($_POST['factura_id']) ? (int)$_POST['factura_id'] : 0;
|
||||
$acepto = isset($_POST['acepto']) ? (int)$_POST['acepto'] : 0;
|
||||
$rfc_importador = isset($_POST['rfc_importador']) ? trim($_POST['rfc_importador']) : null;
|
||||
$firma_base64 = isset($_POST['firma_base64']) ? $_POST['firma_base64'] : null;
|
||||
$firmante = isset($_POST['firmante']) ? trim($_POST['firmante']) : null;
|
||||
$ip = $_SERVER['REMOTE_ADDR'] ?? null;
|
||||
|
||||
if ($pedimento_id <= 0 || $factura_id <= 0) { echo json_encode(['success' => false, 'message' => 'Parámetros inválidos']); return; }
|
||||
if ($acepto !== 1) { echo json_encode(['success' => false, 'message' => 'Debes aceptar la declaración']); return; }
|
||||
|
||||
$conn = getConnection();
|
||||
|
||||
// Verificar propiedad y relación factura-pedimento
|
||||
$chk = sqlsrv_query($conn, "SELECT 1 FROM pedimentos p JOIN pedimento_facturas f ON f.pedimento_id = p.id WHERE p.id = ? AND f.id = ? AND p.usuario_id = ?", [$pedimento_id, $factura_id, $usuario_id]);
|
||||
$ok = $chk && sqlsrv_fetch_array($chk) ? true : false; if ($chk) sqlsrv_free_stmt($chk);
|
||||
if (!$ok) { echo json_encode(['success' => false, 'message' => 'No autorizado o relación inválida']); return; }
|
||||
|
||||
// Asegurar tabla mve_solicitudes
|
||||
$sqlEnsure = "
|
||||
IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[mve_solicitudes]') AND type in (N'U'))
|
||||
BEGIN
|
||||
CREATE TABLE dbo.mve_solicitudes (
|
||||
id INT IDENTITY(1,1) PRIMARY KEY,
|
||||
pedimento_id INT NOT NULL,
|
||||
factura_id INT NOT NULL,
|
||||
usuario_id INT NOT NULL,
|
||||
acepto_declaracion BIT NOT NULL,
|
||||
rfc_importador NVARCHAR(20) NULL,
|
||||
ip NVARCHAR(64) NULL,
|
||||
fecha_solicitud DATETIME2 NOT NULL DEFAULT SYSDATETIME(),
|
||||
comentario NVARCHAR(400) NULL,
|
||||
firma_base64 NVARCHAR(MAX) NULL,
|
||||
firmante NVARCHAR(200) NULL
|
||||
);
|
||||
CREATE INDEX IX_mve_solicitudes_factura ON dbo.mve_solicitudes(factura_id);
|
||||
END;
|
||||
-- Ensure all expected columns exist on legacy tables
|
||||
IF COL_LENGTH('dbo.mve_solicitudes','pedimento_id') IS NULL ALTER TABLE dbo.mve_solicitudes ADD pedimento_id INT NULL;
|
||||
IF COL_LENGTH('dbo.mve_solicitudes','factura_id') IS NULL ALTER TABLE dbo.mve_solicitudes ADD factura_id INT NULL;
|
||||
IF COL_LENGTH('dbo.mve_solicitudes','usuario_id') IS NULL ALTER TABLE dbo.mve_solicitudes ADD usuario_id INT NULL;
|
||||
IF COL_LENGTH('dbo.mve_solicitudes','acepto_declaracion') IS NULL ALTER TABLE dbo.mve_solicitudes ADD acepto_declaracion BIT NULL;
|
||||
IF COL_LENGTH('dbo.mve_solicitudes','rfc_importador') IS NULL ALTER TABLE dbo.mve_solicitudes ADD rfc_importador NVARCHAR(20) NULL;
|
||||
IF COL_LENGTH('dbo.mve_solicitudes','ip') IS NULL ALTER TABLE dbo.mve_solicitudes ADD ip NVARCHAR(64) NULL;
|
||||
IF COL_LENGTH('dbo.mve_solicitudes','fecha_solicitud') IS NULL ALTER TABLE dbo.mve_solicitudes ADD fecha_solicitud DATETIME2 NULL;
|
||||
IF COL_LENGTH('dbo.mve_solicitudes','comentario') IS NULL ALTER TABLE dbo.mve_solicitudes ADD comentario NVARCHAR(400) NULL;
|
||||
IF COL_LENGTH('dbo.mve_solicitudes', 'firma_base64') IS NULL ALTER TABLE dbo.mve_solicitudes ADD firma_base64 NVARCHAR(MAX) NULL;
|
||||
IF COL_LENGTH('dbo.mve_solicitudes', 'firmante') IS NULL ALTER TABLE dbo.mve_solicitudes ADD firmante NVARCHAR(200) NULL;
|
||||
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_mve_solicitudes_factura' AND object_id = OBJECT_ID('dbo.mve_solicitudes'))
|
||||
CREATE INDEX IX_mve_solicitudes_factura ON dbo.mve_solicitudes(factura_id);
|
||||
";
|
||||
$ensureOk = sqlsrv_query($conn, $sqlEnsure);
|
||||
if ($ensureOk === false) {
|
||||
$err = sqlsrv_errors();
|
||||
echo json_encode(['success' => false, 'message' => 'Error al preparar tabla de solicitudes', 'detail' => $err]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Determinar columnas legacy (id_*) y nuevas (*_id) disponibles
|
||||
$has_id_ped = false; $has_id_fac = false; $has_id_usr = false;
|
||||
$chkCols = sqlsrv_query($conn, "SELECT name FROM sys.columns WHERE object_id = OBJECT_ID('dbo.mve_solicitudes') AND name IN ('id_pedimento','id_factura','id_usuario','pedimento_id','factura_id','usuario_id')");
|
||||
if ($chkCols) {
|
||||
while ($c = sqlsrv_fetch_array($chkCols, SQLSRV_FETCH_ASSOC)) {
|
||||
if ($c['name'] === 'id_pedimento') $has_id_ped = true;
|
||||
if ($c['name'] === 'id_factura') $has_id_fac = true;
|
||||
if ($c['name'] === 'id_usuario') $has_id_usr = true;
|
||||
}
|
||||
sqlsrv_free_stmt($chkCols);
|
||||
}
|
||||
|
||||
// Validar firma obligatoria
|
||||
if (!$firma_base64 || trim($firma_base64) === '') {
|
||||
echo json_encode(['success' => false, 'message' => 'La firma es obligatoria']);
|
||||
return;
|
||||
}
|
||||
|
||||
$db = getDB();
|
||||
$stmt = $db->prepare("SELECT * FROM mve_facturas_datos WHERE id_factura = ?");
|
||||
$stmt->execute([$id_factura]);
|
||||
$datos = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
// Construir INSERT dinámico para soportar ambos esquemas
|
||||
$cols = [];
|
||||
$vals = [];
|
||||
$paramsIns = [];
|
||||
// IDs
|
||||
$cols[] = 'pedimento_id'; $vals[] = '?'; $paramsIns[] = $pedimento_id;
|
||||
if ($has_id_ped) { $cols[] = 'id_pedimento'; $vals[] = '?'; $paramsIns[] = $pedimento_id; }
|
||||
$cols[] = 'factura_id'; $vals[] = '?'; $paramsIns[] = $factura_id;
|
||||
if ($has_id_fac) { $cols[] = 'id_factura'; $vals[] = '?'; $paramsIns[] = $factura_id; }
|
||||
$cols[] = 'usuario_id'; $vals[] = '?'; $paramsIns[] = $usuario_id;
|
||||
if ($has_id_usr) { $cols[] = 'id_usuario'; $vals[] = '?'; $paramsIns[] = $usuario_id; }
|
||||
// Resto de columnas
|
||||
$cols = array_merge($cols, ['acepto_declaracion','rfc_importador','ip','firma_base64','firmante']);
|
||||
$vals = array_merge($vals, array_fill(0, 5, '?'));
|
||||
$paramsIns = array_merge($paramsIns, [1, $rfc_importador, $ip, $firma_base64, $firmante]);
|
||||
|
||||
if ($datos) {
|
||||
// Estructurar datos para el frontend
|
||||
$datosEstructurados = [
|
||||
'art65' => [
|
||||
'fecha_transporte' => $datos['art65_fecha_transporte'],
|
||||
'importe_transporte' => $datos['art65_importe_transporte'],
|
||||
'fecha_descuentos' => $datos['art65_fecha_descuentos'],
|
||||
'importe_descuentos' => $datos['art65_importe_descuentos'],
|
||||
'fecha_posteriores' => $datos['art65_fecha_posteriores'],
|
||||
'importe_posteriores' => $datos['art65_importe_posteriores'],
|
||||
'fecha_contribuciones' => $datos['art65_fecha_contribuciones'],
|
||||
'importe_contribuciones' => $datos['art65_importe_contribuciones'],
|
||||
'fecha_pagos_vendedor' => $datos['art65_fecha_pagos_vendedor'],
|
||||
'importe_pagos_vendedor' => $datos['art65_importe_pagos_vendedor']
|
||||
],
|
||||
'art66' => [
|
||||
'fecha_comisiones' => $datos['art66_fecha_comisiones'],
|
||||
'importe_comisiones' => $datos['art66_importe_comisiones'],
|
||||
'cargo_comisiones' => $datos['art66_cargo_comisiones'],
|
||||
'fecha_envases' => $datos['art66_fecha_envases'],
|
||||
'importe_envases' => $datos['art66_importe_envases'],
|
||||
'cargo_envases' => $datos['art66_cargo_envases'],
|
||||
'fecha_embalaje' => $datos['art66_fecha_embalaje'],
|
||||
'importe_embalaje' => $datos['art66_importe_embalaje'],
|
||||
'cargo_embalaje' => $datos['art66_cargo_embalaje'],
|
||||
'fecha_transporte_dec' => $datos['art66_fecha_transporte_dec'],
|
||||
'importe_transporte_dec' => $datos['art66_importe_transporte_dec'],
|
||||
'cargo_transporte_dec' => $datos['art66_cargo_transporte_dec'],
|
||||
'fecha_ingenieria' => $datos['art66_fecha_ingenieria'],
|
||||
'importe_ingenieria' => $datos['art66_importe_ingenieria'],
|
||||
'cargo_ingenieria' => $datos['art66_cargo_ingenieria'],
|
||||
'fecha_regalias' => $datos['art66_fecha_regalias'],
|
||||
'importe_regalias' => $datos['art66_importe_regalias'],
|
||||
'cargo_regalias' => $datos['art66_cargo_regalias'],
|
||||
'fecha_producto' => $datos['art66_fecha_producto'],
|
||||
'importe_producto' => $datos['art66_importe_producto'],
|
||||
'cargo_producto' => $datos['art66_cargo_producto']
|
||||
]
|
||||
];
|
||||
|
||||
echo json_encode(['success' => true, 'datos' => $datosEstructurados]);
|
||||
} else {
|
||||
echo json_encode(['success' => true, 'datos' => null]);
|
||||
$sqlIns = 'INSERT INTO mve_solicitudes (' . implode(',', $cols) . ') VALUES (' . implode(',', $vals) . ')';
|
||||
$ins = sqlsrv_query($conn, $sqlIns, $paramsIns);
|
||||
if ($ins === false) {
|
||||
$err = sqlsrv_errors();
|
||||
$msg = 'No se pudo registrar la solicitud';
|
||||
if ($err && isset($err[0]['message'])) { $msg .= ': ' . $err[0]['message']; }
|
||||
echo json_encode(['success' => false, 'message' => $msg]);
|
||||
return;
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['success' => false, 'message' => 'Error interno: ' . $e->getMessage()]);
|
||||
}
|
||||
// Actualizar estado en cove_respuestas a 'solicitado'
|
||||
$sel = sqlsrv_query($conn, "SELECT id FROM cove_respuestas WHERE factura_id = ? AND usuario_id = ?", [$factura_id, $usuario_id]);
|
||||
$row = $sel ? sqlsrv_fetch_array($sel, SQLSRV_FETCH_ASSOC) : null; if ($sel) sqlsrv_free_stmt($sel);
|
||||
if ($row) {
|
||||
sqlsrv_query($conn, "UPDATE cove_respuestas SET estado = 'solicitado', fecha_actualizacion = SYSDATETIME() WHERE id = ?", [$row['id']]);
|
||||
} else {
|
||||
sqlsrv_query($conn, "INSERT INTO cove_respuestas (usuario_id, pedimento_id, factura_id, estado, fecha_actualizacion) VALUES (?, ?, ?, 'solicitado', SYSDATETIME())", [$usuario_id, $pedimento_id, $factura_id]);
|
||||
}
|
||||
|
||||
// Generar documentos de prueba (acuse y detalle) en el expediente del pedimento
|
||||
$usuario_nombre = $_SESSION['usuario_nombre'] ?? 'sistema';
|
||||
mve_generar_documentos_expediente($conn, $pedimento_id, $usuario_nombre);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
19
app/controllers/test_connection.php
Normal file
19
app/controllers/test_connection.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
session_start();
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
// Simple test endpoint
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Conexión exitosa',
|
||||
'timestamp' => date('Y-m-d H:i:s'),
|
||||
'usuario' => isset($_SESSION['usuario']) ? $_SESSION['usuario']['nombre'] ?? 'Usuario logueado' : 'No hay usuario',
|
||||
'post_data' => $_POST,
|
||||
'files_data' => isset($_FILES['archivo']) ? [
|
||||
'nombre' => $_FILES['archivo']['name'],
|
||||
'tamaño' => $_FILES['archivo']['size'],
|
||||
'tipo' => $_FILES['archivo']['type'],
|
||||
'error' => $_FILES['archivo']['error']
|
||||
] : 'No hay archivo'
|
||||
]);
|
||||
?>
|
||||
Reference in New Issue
Block a user