Files
MVE/app/controllers/mve.php

678 lines
38 KiB
PHP

<?php
require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/session.php';
// 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';
}
// 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;
}
$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 <= 0 || $id_pedimento <= 0) {
echo json_encode(['success' => false, 'message' => 'Parámetros inválidos']);
return;
}
$conn = getConnection();
// 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 = ?,
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 = ?,
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,
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,
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 (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
// 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 = [
$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,
]
];
echo json_encode(['success' => true, 'datos' => $datosEstructurados]);
} else {
echo json_encode(['success' => true, 'datos' => 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']);
}
}
// 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;
}
// 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]);
$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;
}
// 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]);
}