listarProductos(); if (isset($_SESSION['venta']['cliente'])) { $cliente = $_SESSION['venta']['cliente']; } else { $cliente = ''; } // Obtengo cálculos preliminares $subtotal = $cajamodel->calcularSubtotal() ?? 0; $descuento = $cajamodel->calcularDescuentoTotal() ?? 0; $total = $cajamodel->calcularPrecioTotal() ?? 0; ob_start(); require __DIR__ . '/../views/ventas/crearVentaView.php'; return ob_get_clean(); } // AGREGAR PRODUCTO A LA VENTA (el post es atendido por CAJA) case 'agregar_producto': // Requiero el productoModel require_once __DIR__ . '/../models/productoModel.php'; $productomodel = new productoModel(); $productos = $productomodel->listarProductosVenta(); foreach ($productos as $i => $p) { if (!isset($p['id'])) { unset($productos[$i]); continue; } if ($p['stock'] === null || $p['stock'] === 0) { $productos[$i]['stock'] = '-'; } $productos[$i]['descuento_total'] = number_format($p['descuento_total'], 2, '.', '') . ' %'; } ob_start(); require __DIR__ . '/../views/ventas/agregarProductoView.php'; return ob_get_clean(); // SELECCIONAR CLIENTE PARA LA VENTA case 'seleccionar_cliente': // Requiero el modelo de cliente require_once __DIR__ . '/../models/clienteModel.php'; $clientemodel = new clienteModel(); // Se muestra la vista de selección de cliente if ($_SERVER['REQUEST_METHOD'] === 'GET') { $clientes = $clientemodel->listarClientes(); ob_start(); require __DIR__ . '/../views/ventas/seleccionarClienteView.php'; return ob_get_clean(); } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $idCliente = (int) ($_POST['id_cliente'] ?? 0); if ($idCliente <= 0) { $_SESSION['flash_error'] = "No se seleccionó ningún cliente."; header("Location: index.php?opt=seleccionar_cliente"); exit; } $cliente = $clientemodel->obtenerPorId($idCliente); if (!$cliente) { $_SESSION['flash_error'] = "Cliente inválido."; header("Location: index.php?opt=seleccionar_cliente"); exit; } $_SESSION['venta']['cliente'] = [ 'id' => $cliente['id'], 'nombre' => $cliente['nombre'], 'apellido' => $cliente['apellido'], 'telefono' => $cliente['telefono'], 'email' => $cliente['email'], 'cuit' => $cliente['cuit'], 'cond_iva' => $cliente['cond_iva'] ]; $_SESSION['venta_extra']['cond_iva'] = $cliente['cond_iva']; $_SESSION['venta_extra']['cuit'] = $cliente['cuit']; $_SESSION['flash_success'] = "Cliente agregado correctamente."; header("Location: index.php?opt=crear_venta"); exit; } // ELIMINAR CLIENTE YA SELECCIONADO case 'eliminar_cliente': if (isset($_SESSION['venta']['cliente'])) { unset($_SESSION['venta']['cliente']); // También se eliminan datos de la venta guardados desde vista resumen if (isset($_SESSION['venta_extra'])) { unset($_SESSION['venta_extra']); unset($_SESSION['venta_final']); } $_SESSION['flash_success'] = "Cliente eliminado correctamente."; } else { $_SESSION['flash_error'] = "No había cliente seleccionado."; } header("Location: index.php?opt=crear_venta"); exit; // GENERAR VISTA RESUMEN DE VENTA case 'resumen_venta': $cliente = ($_SESSION['venta']['cliente'] ?? null); $_SESSION['venta_extra']['cond_iva'] = $_SESSION['venta_extra']['cond_iva'] ?? $cliente['cond_iva'] ?? 'consumidor_final'; $_SESSION['venta_extra']['cuit'] = $_SESSION['venta_extra']['cuit'] ?? $cliente['cuit'] ?? '00000000000'; // Requiero el modelo de caja require_once __DIR__ . '/../models/cajaModel.php'; $cajamodel = new cajaModel(); $productos = $cajamodel->listarProductos(); $descuento = $cajamodel->calcularDescuentoTotal(); if (!$cliente || empty($productos)) { $_SESSION['flash_error'] = "Debe seleccionar el cliente y al menos un producto."; header("Location: index.php?opt=crear_venta"); exit; } if ($_SERVER['REQUEST_METHOD'] === 'GET') { require_once __DIR__ . '/../models/ventaModel.php'; $ventamodel = new ventaModel(); // 1. Subtotal SIEMPRE se recalcula (pueden haber cambiado productos/cantidades) $subtotal = $cajamodel->calcularSubtotal() ?? 0; // 2. Datos extra guardados en sesión (si existen) $descuentoIngresado = isset($_SESSION['venta_extra']['descuento']) ? (float) $_SESSION['venta_extra']['descuento'] : 0; $recargoIngresado = isset($_SESSION['venta_extra']['recargo']) ? (float) $_SESSION['venta_extra']['recargo'] : 0; // 3. Recalculo siempre con subtotal actual $datosProvisorios = $ventamodel->actualizarDatosProvisorio($descuentoIngresado, $recargoIngresado, $subtotal, $descuento); $descuento = $datosProvisorios['descuento'] ?? 0; $recargo = $datosProvisorios['recargo'] ?? 0; $total = $datosProvisorios['total'] ?? 0; // Guardo en SESSION $_SESSION['venta_final'] = [ 'descuento' => $descuento, 'recargo' => $recargo, 'total' => $total ]; ob_start(); require __DIR__ . '/../views/ventas/resumenVentaView.php'; return ob_get_clean(); } // GUARDAR DATOS DE VENTA (permite volver hacia atrás en el proceso y no perder datos) case 'guardar_datos_venta': // Validaciones de reglas de negocio // Condición IVA $condIvaPermitidas = [ 'consumidor_final', 'responsable_inscripto', 'monotributo' ]; $condIva = $_POST['cond_iva'] ?? 'consumidor_final'; if (!in_array($condIva, $condIvaPermitidas, true)) { $_SESSION['flash_error'] = 'Condición de IVA inválida.'; header('Location: index.php?opt=resumen_venta'); exit; } // CUIT $cuit = ($_POST['cuit_1'] ?? '') . ($_POST['cuit_2'] ?? '') . ($_POST['cuit_3'] ?? ''); $cuit = trim($cuit); if ($cuit === '') { $_SESSION['flash_error'] = 'Debe ingresar un CUIT.'; header('Location: index.php?opt=resumen_venta'); exit; } if (!preg_match('/^\d{11}$/', $cuit)) { $_SESSION['flash_error'] = 'El CUIT debe contener 11 dígitos.'; header('Location: index.php?opt=resumen_venta'); exit; } // Forma de pago + tipo de pago $reglasPago = [ 'efectivo' => ['pago_unico'], 'transferencia' => ['pago_unico'], 'echeq' => ['pago_unico'], 'debito' => ['pago_unico'], 'credito' => ['pago_unico', '3_cuotas', '6_cuotas', '12_cuotas'], ]; $formaPago = $_POST['forma_pago'] ?? 'efectivo'; $tipoPago = $_POST['tipo_pago'] ?? 'pago_unico'; if (!isset($reglasPago[$formaPago]) || !in_array($tipoPago, $reglasPago[$formaPago], true)) { $_SESSION['flash_error'] = 'Combinación de forma y tipo de pago inválida.'; header('Location: index.php?opt=resumen_venta'); exit; } // Validación de descuento y recargo $descuentoVenta = isset($_POST['descuento']) ? (float) $_POST['descuento'] : 0; $recargoVenta = isset($_POST['recargo']) ? (float) $_POST['recargo'] : 0; if ($descuentoVenta < 0 || $recargoVenta > 100) { $_SESSION['flash_error'] = 'El descuento debe estar entre 0 y 100%.'; header('Location: index.php?opt=resumen_venta'); exit; } if ($descuentoVenta < 0 || $recargoVenta > 100) { $_SESSION['flash_error'] = 'El recargo debe estar entre 0 y 100%.'; header('Location: index.php?opt=resumen_venta'); exit; } // Guardado de datos // Guardo datos extra de la venta para ser reutilizados en la vista $datosExtraVenta = [ 'cond_iva' => $condIva, 'cuit' => $cuit, 'forma_pago' => $formaPago, 'tipo_pago' => $tipoPago, 'descuento' => $descuentoVenta, 'recargo' => $recargoVenta ]; // También los persisto en sesión para mantener estado $_SESSION['venta_extra'] = $datosExtraVenta; // Datos para la vista require_once __DIR__ . '/../models/cajaModel.php'; $cajamodel = new cajaModel(); $cliente = ($_SESSION['venta']['cliente'] ?? null); $productos = $cajamodel->listarProductos(); $vendedor = $_SESSION['user'] ?? null; // VALIDACIONES BASE if (!$cliente || empty($productos)) { $_SESSION['flash_error'] = 'Datos incompletos para generar la venta.'; header('Location: index.php?opt=crear_pedido'); exit; } if (!$vendedor) { $_SESSION['flash_error'] = 'No se pudo identificar el usuario.'; header('Location: index.php?opt=crear_pedido'); exit; } /* Subtotal que no contiene descuentos. (Al ingresar descuento o recargo, lo guardo en un array separado, para no sobreescribir datos) */ $subtotal = $cajamodel->calcularSubtotal() ?? 0; $descuento = $cajamodel->calcularDescuentoTotal() ?? 0; // Validación del subtotal if ($subtotal <= 0) { $_SESSION['flash_error'] = 'La venta no contiene productos válidos.'; header('Location: index.php?opt=crear_venta'); exit; } // Llamamos a la función que devuelve los datos actualizados en un array nuevo require_once __DIR__ . '/../models/ventaModel.php'; $ventamodel = new ventaModel(); $datosProvisorios = $ventamodel->actualizarDatosProvisorio($descuentoVenta, $recargoVenta, $subtotal, $descuento); $recargo = $datosProvisorios['recargo'] ?? 0; $descuento = $datosProvisorios['descuento'] ?? 0; $total = $datosProvisorios['total'] ?? 0; $_SESSION['venta_final'] = [ 'recargo' => $recargo, 'descuento' => $descuento, 'total' => $total ]; $_SESSION['flash_success'] = "Datos guardados de manera provisoria."; header("Location: index.php?opt=resumen_venta"); exit; // GENERACION DE VENTA PDF MEDIANTE USO DE LIBRERIA DOMPDF case 'generar_venta_pdf': // OBTENEMOS LA VISTA if ($_SERVER['REQUEST_METHOD'] === 'GET') { $numeroVenta = $_SESSION['ultima_venta_id']; ob_start(); require __DIR__ . '/../views/ventas/descargarComprobante.php'; return ob_get_clean(); } // GENERACIÓN DEL PDF if ($_SERVER['REQUEST_METHOD'] === 'POST') { // Requiero datos de empresa y configuración require __DIR__ . '/../models/configuracionModel.php'; $configuracionmodel = new configuracionModel(); $datosEmpresa = $configuracionmodel->obtenerConfiguracion(); $mapCondIVA = [ 'consumidor_final' => 'Consumidor Final', 'responsable_inscripto' => 'Responsable Inscripto', 'monotributo' => 'Monotributo', ]; $datosEmpresa['cond_iva'] = $mapCondIVA[$datosEmpresa['cond_iva']]; // Obtenemos array con datos necesarios, que fueron guardados durante la confirmación de venta en $_SESSION $datosVenta = $_SESSION['venta_pdf'] ?? null; if (!$datosVenta) { $_SESSION['flash_error'] = 'No existen datos para generar el comprobante.'; header('Location: index.php?opt=crear_venta'); exit; } // Asignamos datos a variables y validamos $cliente = $datosVenta['cliente']; $vendedor = $datosVenta['vendedor']; $productos = $datosVenta['productos']; // VALIDACIONES BASE if (!$cliente || empty($productos)) { $_SESSION['flash_error'] = 'Datos incompletos para generar la venta.'; header('Location: index.php?opt=crear_pedido'); exit; } if (!$vendedor) { $_SESSION['flash_error'] = 'No se pudo identificar el usuario.'; header('Location: index.php?opt=crear_pedido'); exit; } // Asignamos datos a variables y validamos $condIVA = $datosVenta['cond_iva']; $cuit = $datosVenta['cuit']; $formaPago = $datosVenta['forma_pago']; $tipoPago = $datosVenta['tipo_pago']; $descuentoVenta = $datosVenta['descuentoVenta']; $recargoVenta = $datosVenta['recargoVenta']; // VALIDACIÓN CONDICIÓN IVA $condIvaPermitidas = [ 'consumidor_final', 'responsable_inscripto', 'monotributo' ]; if (!in_array($condIVA, $condIvaPermitidas, true)) { $_SESSION['flash_error'] = 'Condición de IVA inválida.'; header('Location: index.php?opt=resumen_venta'); exit; } // Validación de CUIT $cuit = trim($cuit); if (!preg_match('/^\d{10,11}$/', $cuit)) { $_SESSION['flash_error'] = 'CUIT inválido.'; header('Location: index.php?opt=resumen_venta'); exit; } // VALIDACIÓN FORMA + TIPO DE PAGO $reglasPago = [ 'efectivo' => ['pago_unico'], 'transferencia' => ['pago_unico'], 'echeq' => ['pago_unico'], 'debito' => ['pago_unico'], 'credito' => ['pago_unico', '3_cuotas', '6_cuotas', '12_cuotas'], ]; if (!isset($reglasPago[$formaPago]) || !in_array($tipoPago, $reglasPago[$formaPago], true)) { $_SESSION['flash_error'] = 'Combinación de forma y tipo de pago inválida.'; header('Location: index.php?opt=resumen_venta'); exit; } // VALIDACIÓN DESCUENTO / RECARGO if ($descuentoVenta < 0 || $descuentoVenta > 100) { $_SESSION['flash_error'] = 'El descuento debe estar entre 0 y 100%.'; header('Location: index.php?opt=resumen_venta'); exit; } if ($recargoVenta < 0 || $recargoVenta > 100) { $_SESSION['flash_error'] = 'El recargo debe estar entre 0 y 100%.'; header('Location: index.php?opt=resumen_venta'); exit; } $subtotal = $datosVenta['subtotal']; if ($subtotal <= 0) { $_SESSION['flash_error'] = 'La venta no contiene productos válidos.'; header('Location: index.php?opt=resumen_venta'); exit; } // Asignamos datos a variables y validamos $descuento = $datosVenta['descuento']; $recargo = $datosVenta['recargo']; $total = $datosVenta['total']; if ($total <= 0) { $_SESSION['flash_error'] = 'Total inválido.'; header('Location: index.php?opt=resumen_venta'); exit; } // MAPEOS PARA PDF $mapCondIVA = [ 'consumidor_final' => 'Consumidor Final', 'responsable_inscripto' => 'Responsable Inscripto', 'monotributo' => 'Monotributo', ]; $mapFormaPago = [ 'efectivo'=> 'Efectivo', 'transferencia' => 'Transferencia', 'debito' => 'Débito', 'credito' => 'Crédito', 'echeq' => 'Echeq', ]; $mapTipoPago = [ 'pago_unico' => 'Pago Único', '3_cuotas' => '3 Cuotas', '6_cuotas' => '6 Cuotas', '12_cuotas' => '12 Cuotas', ]; $condIVALabel = $mapCondIVA[$condIVA]; $formaPagoLabel = $mapFormaPago[$formaPago]; $tipoPagoLabel = $mapTipoPago[$tipoPago]; // CÁLCULO DE CUOTAS if ($tipoPago !== 'pago_unico') { $cuota = (int) explode('_', $tipoPago)[0]; $valorCuota = $total / $cuota; } // Obtenemos el número de venta que se obtuvo desde la base de datos al momento de guardar la venta $numero = $_SESSION['ultima_venta_id'] ?? null; if (!$numero) { $_SESSION['flash_error'] = 'No se encontró el número de venta.'; header('Location: index.php?opt=crear_venta'); exit; } // Variable para mostrar el código en la vista $numeroVenta = '0001-' . str_pad($numero, 8, '0', STR_PAD_LEFT); // RENDER PDF ob_start(); require __DIR__ . '/../pdf/ventas/ventaPDF.php'; $html = ob_get_clean(); $cssPath = '/var/www/html/css/stylesPDF.css'; $css = file_get_contents($cssPath); // Configuración de opciones $options = new Options(); $options->set('isRemoteEnabled', true); // Permite cargar recursos externos (CSS, imágenes, etc.) $options->set('chroot', '/var/www/html'); // Define directorios base para recursos locales $options->set('defaultFont', 'DejaVu Sans'); // Creación de instancia Dompdf con las opciones seteadas $dompdf = new Dompdf($options); // Cargar el HTML que se va a convertir en PDF $dompdf->loadHtml(" $html "); $dompdf->setPaper('A4', 'portrait'); // Define el tamanio de hoja y la orientación $dompdf->render(); // Renderiza el PDF (procesa el HTML) // Enviar el PDF al browser $dompdf->stream( 'Venta N° ' . $numeroVenta . '.pdf', ['Attachment' => true] // false = se muestra en el navegador | true = descarga directa ); exit; } // CONTINUAR SIN DESCARGAR EL COMPROBANTE PDF case 'continuar_sin_comprobante': // Liberamos $_SESSION unset($_SESSION['venta_pdf']); unset($_SESSION['ultima_venta_id']); $_SESSION['flash_success'] = 'Venta finalizada correctamente.'; header('Location: index.php?opt=crear_venta'); exit; // CONFIRMAR VENTA case 'confirmar_venta': // Validaciones de regla de negocio // Condición IVA $condIvaPermitidas = [ 'consumidor_final', 'responsable_inscripto', 'monotributo' ]; $condIva = $_POST['cond_iva'] ?? 'consumidor_final'; if (!in_array($condIva, $condIvaPermitidas, true)) { $_SESSION['flash_error'] = 'Condición de IVA inválida.'; header('Location: index.php?opt=resumen_venta'); exit; } // CUIT $cuit = ($_POST['cuit_1'] ?? '') . ($_POST['cuit_2'] ?? '') . ($_POST['cuit_3'] ?? ''); $cuit = trim($cuit); if ($cuit === '') { $_SESSION['flash_error'] = 'Debe ingresar un CUIT.'; header('Location: index.php?opt=resumen_venta'); exit; } if (!preg_match('/^\d{11}$/', $cuit)) { $_SESSION['flash_error'] = 'El CUIT debe contener 11 dígitos.'; header('Location: index.php?opt=resumen_venta'); exit; } // Forma de pago + tipo de pago $reglasPago = [ 'efectivo' => ['pago_unico'], 'transferencia' => ['pago_unico'], 'echeq' => ['pago_unico'], 'debito' => ['pago_unico'], 'credito' => ['pago_unico', '3_cuotas', '6_cuotas', '12_cuotas'], ]; $formaPago = $_POST['forma_pago'] ?? 'efectivo'; $tipoPago = $_POST['tipo_pago'] ?? 'pago_unico'; if (!isset($reglasPago[$formaPago]) || !in_array($tipoPago, $reglasPago[$formaPago], true)) { $_SESSION['flash_error'] = 'Combinación de forma y tipo de pago inválida.'; header('Location: index.php?opt=resumen_venta'); exit; } // Validación de descuento y recargo $descuentoVenta = isset($_POST['descuento']) ? (float) $_POST['descuento'] : 0; $recargoVenta = isset($_POST['recargo']) ? (float) $_POST['recargo'] : 0; if ($descuentoVenta < 0 || $descuentoVenta > 100) { $_SESSION['flash_error'] = 'El descuento debe estar entre 0 y 100%.'; header('Location: index.php?opt=resumen_venta'); exit; } if ($recargoVenta < 0 || $recargoVenta > 100) { $_SESSION['flash_error'] = 'El recargo debe estar entre 0 y 100%.'; header('Location: index.php?opt=resumen_venta'); exit; } // Guardado de datos de la venta $datosExtraVenta = [ 'forma_pago' => $formaPago, 'tipo_pago' => $tipoPago, 'descuento' => $descuentoVenta, 'recargo' => $recargoVenta, ]; // Requiero los modelos necesarios require_once __DIR__ . '/../models/cajaModel.php'; $cajamodel = new cajaModel(); require_once __DIR__ . '/../models/clienteModel.php'; $clientemodel = new clienteModel(); require_once __DIR__ . '/../models/ventaModel.php'; $ventamodel = new ventaModel(); $idCliente = $_SESSION['venta']['cliente']['id'] ?? null; if ($idCliente === null) { $_SESSION['flash_error'] = 'No seleccionó un cliente.'; header('Location: index.php?opt=resumen_venta'); exit; } $vendedor = $_SESSION['user'] ?? null; $cliente = $clientemodel->obtenerPorId($idCliente); if (!$cliente) { $_SESSION['flash_error'] = 'No se pudo identificar el cliente.'; header('Location: index.php?opt=resumen_venta'); exit; } if (!$vendedor) { $_SESSION['flash_error'] = 'No se pudo identificar el usuario.'; header('Location: index.php?opt=resumen_venta'); exit; } $productosFinales = $cajamodel->listarProductos(); if (empty($productosFinales)) { $_SESSION['flash_error'] = 'No hay productos en la venta.'; header('Location: index.php?opt=resumen_venta'); exit; } foreach ($productosFinales as $p) { if (empty($p['id_producto']) || empty($p['cantidad']) || $p['cantidad'] <= 0) { $_SESSION['flash_error'] = 'Venta con productos inválidos.'; header('Location: index.php?opt=resumen_venta'); exit; } } /* Subtotal que no contiene descuentos. (Al ingresar descuento o recargo, lo guardo en un array separado, para no sobreescribir datos) */ $subtotal = $cajamodel->calcularSubtotal() ?? 0; $descuento = $cajamodel->calcularDescuentoTotal() ?? 0; // Validación del subtotal if ($subtotal <= 0) { $_SESSION['flash_error'] = 'La venta no contiene productos válidos.'; header('Location: index.php?opt=crear_venta'); exit; } // Llamamos a la función que devuelve los datos actualizados en un array nuevo $datosProvisorios = $ventamodel->actualizarDatosProvisorio($descuentoVenta, $recargoVenta, $subtotal, $descuento); if ($datosProvisorios['total'] <= 0) { $_SESSION['flash_error'] = 'El total de la venta es inválido.'; header('Location: index.php?opt=resumen_venta'); exit; } // Obtenemos el ID de venta desde la base de datos $idVenta = $ventamodel->guardarVenta($productosFinales, $vendedor, $cliente, $datosExtraVenta, $datosProvisorios); // Verificamos si se obtuvo el ID desde la base o si ocurrió un error if ($idVenta !== false) { // Guardamos en $_SESSION los datos necesarios para la generación del PDF $_SESSION['ultima_venta_id'] = $idVenta; $_SESSION['venta_pdf'] = [ 'cliente' => $cliente, 'vendedor' => $vendedor, 'productos' => $productosFinales, 'cond_iva' => $condIva, 'cuit' => $cuit, 'forma_pago' => $formaPago, 'tipo_pago' => $tipoPago, 'descuentoVenta' => $descuentoVenta, 'recargoVenta' => $recargoVenta, 'descuento' => $datosProvisorios['descuento'], 'recargo' => $datosProvisorios['recargo'], 'subtotal' => $subtotal, 'total' => $datosProvisorios['total'] ]; // Liberamos $cajamodel->vaciarCajaVenta(); unset($_SESSION['venta']['cliente']); unset($_SESSION['venta_extra']); unset($_SESSION['venta_final']); unset($_SESSION['prov_venta']); $_SESSION['flash_success'] = "Venta guardada correctamente."; } else { $_SESSION['flash_error'] = $ventamodel->getError() ?? 'No se pudo guardar la venta.'; } header("Location: index.php?opt=generar_venta_pdf"); exit; // LISTAR VENTAS case 'listar_ventas': // Requiero el modelo de venta require_once __DIR__ . '/../models/ventaModel.php'; $ventamodel = new ventaModel(); $anioActual = date('Y'); $anioSeleccionado = $_GET['anio'] ?? $anioActual; $ventas = $ventamodel->listarVentas($anioSeleccionado); foreach ($ventas as $i => $v) { // Saneamiento de fecha (para poder ordenar correctamente el campo con dataTables) if (!empty($v['fecha'])) { $dt = new DateTime($v['fecha']); // Para ordenar $ventas[$i]['fecha'] = $dt->format('Y-m-d'); // Para mostrar $ventas[$i]['fecha_formateada'] = $dt->format('d/m/Y'); } else { $ventas[$i]['fecha'] = '-'; $ventas[$i]['fecha_formateada'] = '-'; } // Mapeos de forma y tipo de pago $mapFormaPago = [ 'efectivo'=> 'Efectivo', 'transferencia' => 'Transferencia', 'debito' => 'Débito', 'credito' => 'Crédito', 'echeq' => 'Echeq', ]; $mapTipoPago = [ 'pago_unico' => 'Pago Único', '3_cuotas' => '3 Cuotas', '6_cuotas' => '6 Cuotas', '12_cuotas' => '12 Cuotas', ]; // Saneamiento de forma de pago $ventas[$i]['forma_pago'] = $mapFormaPago[$ventas[$i]['forma_pago']]; // Saneamiento de tipo de pago $ventas[$i]['tipo_pago'] = $mapTipoPago[$ventas[$i]['tipo_pago']]; } ob_start(); require __DIR__ . '/../views/ventas/listaVentasView.php'; return ob_get_clean(); // MOSTRAR DETALLE DE PRODUCTOS DE UNA VENTA case 'detalle_venta': $idVenta = (int) ($_GET['id'] ?? 0); if ($idVenta <= 0) { $_SESSION['flash_error'] = 'Datos inválidos.'; header('Location: index.php?opt=listar_ventas'); exit; } require_once __DIR__ . '/../models/ventaModel.php'; $ventamodel = new ventaModel(); $venta_detalle = $ventamodel->getDetalleVenta($idVenta); ob_start(); require __DIR__ . '/../views/ventas/ventaDetalleView.php'; return ob_get_clean(); // DEFAULT (404) default: ob_start(); header("Location: index.php?opt=404View.php"); return ob_get_clean(); }