Tul xxx Tul
User / IP
:
216.73.217.87
Host / Server
:
45.84.207.204 / aircan.me
System
:
Linux lt-bnk-web1726.main-hosting.eu 5.14.0-611.36.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Mar 3 11:23:52 EST 2026 x86_64
Command
|
Upload
|
Create
Mass Deface
|
Jumping
|
Symlink
|
Reverse Shell
Ping
|
Port Scan
|
DNS Lookup
|
Whois
|
Header
|
cURL
:
/
home
/
u931257429
/
domains
/
aircan.me
/
public_html
/
vendefacil
/
models
/
Viewing: ReportesModel.php
<?php class ReportesModel extends Query { public function __construct() { parent::__construct(); } private function asegurarFechaVencimientoProducto() { $row = $this->select("SHOW COLUMNS FROM productos LIKE 'fecha_vencimiento'"); if (empty($row)) { $this->save("ALTER TABLE productos ADD COLUMN fecha_vencimiento DATE DEFAULT NULL AFTER garantia_tipo", []); } } // ========================================== // MÉTODOS PARA OBTENER DATOS DE FILTROS // ========================================== public function getCategorias() { return $this->selectAll("SELECT id, categoria FROM categorias WHERE estado = 1"); } public function getMarcas() { return $this->selectAll("SELECT id, marca FROM marcas WHERE estado = 1"); } public function getClientes($id_sucursal) { return $this->selectAll("SELECT id, nombre FROM clientes WHERE estado = 1 AND id_sucursal = $id_sucursal"); } public function getVendedores($id_sucursal) { return $this->selectAll("SELECT id, nombre FROM usuarios WHERE estado = 1 AND id_sucursal = $id_sucursal"); } public function getProveedores($id_sucursal) { return $this->selectAll("SELECT id, nombre FROM proveedor WHERE estado = 1 AND id_sucursal = $id_sucursal"); } public function getSucursales() { return $this->selectAll("SELECT id, nombre FROM sucursales WHERE estado = 1"); } public function getEmpresa($id_sucursal) { return $this->select("SELECT * FROM sucursales WHERE id = $id_sucursal"); } // ========================================== // MÉTODOS PARA CONSULTAS DE REPORTES // ========================================== public function getInventario($fecha_inicio, $fecha_fin, $categoria, $bodega, $vencimiento, $id_sucursal_actual) { $this->asegurarFechaVencimientoProducto(); // Aseguramos la existencia de la tabla de lotes $rowLotes = $this->select("SHOW TABLES LIKE 'producto_lotes_vencimiento'"); if (empty($rowLotes)) { $this->save("CREATE TABLE IF NOT EXISTS producto_lotes_vencimiento ( id int(11) NOT NULL AUTO_INCREMENT, id_producto int(11) NOT NULL, id_sucursal int(11) NOT NULL, fecha_vencimiento date NOT NULL, cantidad decimal(10,2) NOT NULL DEFAULT 0.00, estado int(11) NOT NULL DEFAULT 1, fecha timestamp NOT NULL DEFAULT current_timestamp(), PRIMARY KEY (id), UNIQUE KEY uq_producto_sucursal_vencimiento (id_producto, id_sucursal, fecha_vencimiento), KEY idx_producto_lotes_producto (id_producto), KEY idx_producto_lotes_sucursal (id_sucursal), KEY idx_producto_lotes_fecha (fecha_vencimiento) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci", []); } $sql = "SELECT p.*, c.categoria as nombre_categoria, s.nombre as bodega, pl.fecha_vencimiento as lote_fecha, pl.cantidad as lote_cantidad, pl.id as lote_id FROM productos p INNER JOIN categorias c ON p.id_categoria = c.id INNER JOIN sucursales s ON p.id_sucursal = s.id LEFT JOIN producto_lotes_vencimiento pl ON p.id = pl.id_producto AND pl.id_sucursal = p.id_sucursal AND pl.estado = 1 WHERE p.estado = 1"; // Filtro por fecha (usando la fecha de registro del producto) if (!empty($fecha_inicio) && !empty($fecha_fin)) { $sql .= " AND p.fecha BETWEEN '$fecha_inicio 00:00:00' AND '$fecha_fin 23:59:59'"; } // Filtro por bodega if ($bodega !== 'todos' && !empty($bodega)) { $sql .= " AND p.id_sucursal = " . intval($bodega); } else { // If they didn't specify a bodega, filter by current bodega // (or if we want 'todos' to show ALL bodegas, then we don't add the WHERE condition) // But they asked for 'todos' option, so 'todos' shows all. } if ($categoria !== 'todos' && !empty($categoria)) { $sql .= " AND p.id_categoria = " . intval($categoria); } if (!empty($vencimiento) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $vencimiento)) { $sql .= " AND ( (pl.id IS NOT NULL AND pl.fecha_vencimiento <= '$vencimiento') OR (pl.id IS NULL AND p.fecha_vencimiento IS NOT NULL AND p.fecha_vencimiento <= '$vencimiento') )"; } $sql .= " ORDER BY p.descripcion ASC, pl.fecha_vencimiento ASC"; return $this->selectAll($sql); } public function getVentas($fecha_inicio, $fecha_fin, $categoria, $cliente, $vendedor, $id_sucursal) { $sql = "SELECT v.id, v.fecha, v.serie, v.total as subtotal, v.iva_monto, v.total_final as total, v.productos, c.nombre as cliente FROM ventas v INNER JOIN clientes c ON v.id_cliente = c.id WHERE v.id_sucursal = $id_sucursal AND v.estado = 1"; if (!empty($fecha_inicio) && !empty($fecha_fin)) { $sql .= " AND v.fecha BETWEEN '$fecha_inicio 00:00:00' AND '$fecha_fin 23:59:59'"; } if ($cliente !== 'todos' && !empty($cliente)) { $sql .= " AND v.id_cliente = " . intval($cliente); } if ($vendedor !== 'todos' && !empty($vendedor)) { $sql .= " AND v.id_usuario = " . intval($vendedor); } $sql .= " ORDER BY v.fecha DESC"; $ventasRaw = $this->selectAll($sql); if (empty($ventasRaw)) { return []; } // Obtener IDs de productos para buscar sus costos y categorías $productIds = []; $decodedVentas = []; foreach ($ventasRaw as $venta) { $items = json_decode($venta['productos'], true); if (!is_array($items)) { $items = []; } foreach ($items as $item) { if (isset($item['id'])) { $pid = (int)$item['id']; if ($pid > 0) { $productIds[$pid] = true; } } } $venta['items'] = $items; $decodedVentas[] = $venta; } // Obtener costo y categoría de los productos $productInfo = []; if (!empty($productIds)) { $idsSql = implode(',', array_keys($productIds)); $sqlProd = "SELECT id, precio_compra, id_categoria FROM productos WHERE id IN ($idsSql)"; $prodResults = $this->selectAll($sqlProd); foreach ($prodResults as $p) { $productInfo[(int)$p['id']] = [ 'precio_compra' => (float)$p['precio_compra'], 'id_categoria' => (int)$p['id_categoria'] ]; } } $finalVentas = []; foreach ($decodedVentas as $venta) { $costoTotal = 0.0; $hasTargetCategory = ($categoria === 'todos' || empty($categoria)); foreach ($venta['items'] as $item) { $pid = isset($item['id']) ? (int)$item['id'] : 0; $qty = isset($item['cantidad']) ? (float)$item['cantidad'] : 0.0; $precioCompra = 0.0; $prodCategory = 0; if (isset($productInfo[$pid])) { $precioCompra = $productInfo[$pid]['precio_compra']; $prodCategory = $productInfo[$pid]['id_categoria']; } $costoTotal += $qty * $precioCompra; if ($categoria !== 'todos' && !empty($categoria) && $prodCategory === (int)$categoria) { $hasTargetCategory = true; } } if ($hasTargetCategory) { unset($venta['productos']); unset($venta['items']); $venta['costo'] = $costoTotal; $finalVentas[] = $venta; } } return $finalVentas; } public function getVentasDetalleReporte($fecha_inicio, $fecha_fin, $vendedor, $cajero, $cliente, $id_sucursal) { $sql = "SELECT v.id, v.fecha, v.serie as factura, v.metodo as forma_pago, v.productos, c.nombre as cliente FROM ventas v LEFT JOIN clientes c ON v.id_cliente = c.id WHERE v.id_sucursal = $id_sucursal AND v.estado = 1"; if (!empty($fecha_inicio) && !empty($fecha_fin)) { $sql .= " AND v.fecha BETWEEN '$fecha_inicio 00:00:00' AND '$fecha_fin 23:59:59'"; } if ($cliente !== 'todos' && !empty($cliente)) { $sql .= " AND v.id_cliente = " . intval($cliente); } if ($vendedor !== 'todos' && !empty($vendedor)) { $sql .= " AND v.id_vendedor = " . intval($vendedor); } if ($cajero !== 'todos' && !empty($cajero)) { $sql .= " AND v.id_usuario = " . intval($cajero); } $sql .= " ORDER BY v.fecha DESC"; $ventasRaw = $this->selectAll($sql); if (empty($ventasRaw)) { return []; } $productIds = []; $decodedVentas = []; foreach ($ventasRaw as $venta) { $items = json_decode($venta['productos'], true); if (!is_array($items)) { $items = []; } foreach ($items as $item) { if (isset($item['id'])) { $pid = (int)$item['id']; if ($pid > 0) { $productIds[$pid] = true; } } } $venta['items'] = $items; $decodedVentas[] = $venta; } $productInfo = []; if (!empty($productIds)) { $idsSql = implode(',', array_keys($productIds)); $sqlProd = "SELECT p.id, p.codigo, p.descripcion, p.precio_compra, p.servicio, cat.categoria FROM productos p LEFT JOIN categorias cat ON p.id_categoria = cat.id WHERE p.id IN ($idsSql)"; $prodResults = $this->selectAll($sqlProd); foreach ($prodResults as $p) { $productInfo[(int)$p['id']] = [ 'codigo' => $p['codigo'], 'descripcion' => $p['descripcion'], 'precio_compra' => (float)$p['precio_compra'], 'categoria' => $p['categoria'], 'servicio' => (int)$p['servicio'] ]; } } $finalItems = []; foreach ($decodedVentas as $venta) { foreach ($venta['items'] as $item) { $pid = isset($item['id']) ? (int)$item['id'] : 0; $qty = isset($item['cantidad']) ? (float)$item['cantidad'] : 0.0; $precio_venta_unitario = isset($item['precio']) ? (float)$item['precio'] : 0.0; $codigo = ''; $categoria = ''; $producto_desc = isset($item['nombre']) ? $item['nombre'] : ''; $precio_compra_unitario = 0.0; if (isset($productInfo[$pid])) { $codigo = $productInfo[$pid]['codigo']; $categoria = $productInfo[$pid]['categoria']; $producto_desc = $productInfo[$pid]['descripcion']; // Preferir la descripcion de BD if ($productInfo[$pid]['servicio'] !== 1) { $precio_compra_unitario = $productInfo[$pid]['precio_compra']; } } $precio_costo_total = $precio_compra_unitario * $qty; $precio_venta_total = $precio_venta_unitario * $qty; // Si la venta tiene descuento, deberiamos considerarlo. // Pero a nivel de item, el precio en json es el precio facturado (sin descuento global o con descuento?) // Usaremos los valores netos registrados. $utilidad = $precio_venta_total - $precio_costo_total; $porcentaje_utilidad = 0; if ($precio_costo_total > 0) { $porcentaje_utilidad = ($utilidad / $precio_costo_total) * 100; } else if ($precio_costo_total == 0 && $utilidad > 0) { $porcentaje_utilidad = 100; } $finalItems[] = [ 'codigo' => $codigo, 'categoria' => $categoria, 'producto' => $producto_desc, 'cliente' => $venta['cliente'], 'factura' => $venta['factura'], 'forma_pago' => $venta['forma_pago'], 'cantidad' => $qty, 'precio_costo' => $precio_costo_total, 'precio_venta' => $precio_venta_total, 'utilidad' => $utilidad, 'porcentaje_utilidad' => $porcentaje_utilidad, 'fecha' => $venta['fecha'] ]; } } return $finalItems; } public function getVentasTaller($fecha_inicio, $fecha_fin, $estado, $tecnico, $id_sucursal) { $sql = "SELECT r.fecha_ingreso as fecha, r.problema, r.estado, r.mano_obra as precio_venta, c.nombre as cliente, r.aparato as equipo, u.nombre as tecnico, (SELECT IFNULL(SUM(monto), 0) FROM abono_reparacion WHERE id_reparacion = r.id) as precio_pagado FROM reparaciones r INNER JOIN clientes c ON r.id_cliente = c.id INNER JOIN usuarios u ON r.id_usuario = u.id WHERE r.id_sucursal = $id_sucursal"; if (!empty($fecha_inicio) && !empty($fecha_fin)) { $sql .= " AND r.fecha_ingreso BETWEEN '$fecha_inicio' AND '$fecha_fin'"; } if ($estado !== 'todos' && !empty($estado)) { $sql .= " AND r.estado = '$estado'"; } if ($tecnico !== 'todos' && !empty($tecnico)) { $sql .= " AND r.id_usuario = '$tecnico'"; } $sql .= " ORDER BY r.fecha_ingreso DESC"; return $this->selectAll($sql); } public function getTrasladosDetalleReporte($fecha_inicio, $fecha_fin, $vendedor, $cajero, $cliente, $id_sucursal) { // En los traslados no existen vendedores, cajeros o clientes reales, pero los recibimos para cumplir la firma. $sql = "SELECT p.codigo, c.categoria, p.descripcion as producto, s1.nombre as origen, s2.nombre as destino, dt.cantidad, p.precio_compra as precio_costo, (dt.cantidad * p.precio_compra) as costo_total, t.fecha_envio as fecha, t.estado FROM traslados t INNER JOIN detalle_traslados dt ON t.id = dt.traslado_id INNER JOIN productos p ON dt.producto_id = p.id LEFT JOIN categorias c ON p.id_categoria = c.id INNER JOIN sucursales s1 ON t.sucursal_origen_id = s1.id INNER JOIN sucursales s2 ON t.sucursal_destino_id = s2.id WHERE t.sucursal_origen_id = $id_sucursal"; if (!empty($fecha_inicio) && !empty($fecha_fin)) { $sql .= " AND t.fecha_envio BETWEEN '$fecha_inicio 00:00:00' AND '$fecha_fin 23:59:59'"; } $sql .= " ORDER BY t.fecha_envio DESC"; return $this->selectAll($sql); } public function getApartados($fecha_inicio, $fecha_fin, $cliente, $estado, $id_sucursal) { $sql = "SELECT a.*, c.nombre as cliente, c.telefono FROM apartados a INNER JOIN clientes c ON a.id_cliente = c.id WHERE a.id_sucursal = $id_sucursal"; if (!empty($fecha_inicio) && !empty($fecha_fin)) { $sql .= " AND a.fecha_create BETWEEN '$fecha_inicio 00:00:00' AND '$fecha_fin 23:59:59'"; } if ($cliente !== 'todos' && !empty($cliente)) { $sql .= " AND a.id_cliente = " . intval($cliente); } if ($estado !== 'todos' && $estado !== '') { $sql .= " AND a.estado = " . intval($estado); // 0 = pendiente, 1 = completado } $sql .= " ORDER BY a.fecha_create DESC"; return $this->selectAll($sql); } public function getSalidasInventario($fecha_inicio, $fecha_fin, $motivo, $id_sucursal) { $sql = "SELECT i.*, p.descripcion as producto, p.codigo, u.nombre as usuario, i.movimiento as motivo FROM inventario i INNER JOIN productos p ON i.id_producto = p.id INNER JOIN usuarios u ON i.id_usuario = u.id WHERE i.id_sucursal = $id_sucursal AND LOWER(i.accion) = 'salida'"; if (!empty($fecha_inicio) && !empty($fecha_fin)) { $sql .= " AND i.fecha BETWEEN '$fecha_inicio 00:00:00' AND '$fecha_fin 23:59:59'"; } if ($motivo !== 'todos' && !empty($motivo)) { $sql .= " AND i.movimiento LIKE '%" . $motivo . "%'"; } $sql .= " ORDER BY i.fecha DESC"; return $this->selectAll($sql); } public function getCompras($fecha_inicio, $fecha_fin, $proveedor, $id_sucursal) { $sql = "SELECT c.*, p.nombre as proveedor, u.nombre as usuario FROM compras c INNER JOIN proveedor p ON c.id_proveedor = p.id INNER JOIN usuarios u ON c.id_usuario = u.id WHERE c.id_sucursal = $id_sucursal"; if (!empty($fecha_inicio) && !empty($fecha_fin)) { $sql .= " AND c.fecha BETWEEN '$fecha_inicio 00:00:00' AND '$fecha_fin 23:59:59'"; } if ($proveedor !== 'todos' && !empty($proveedor)) { $sql .= " AND c.id_proveedor = " . intval($proveedor); } $sql .= " ORDER BY c.fecha DESC"; return $this->selectAll($sql); } public function getGastos($fecha_inicio, $fecha_fin, $categoria, $subcategoria, $id_sucursal) { $sql = "SELECT g.*, g.categoria as categoria_nombre, u.nombre as usuario FROM gastos g INNER JOIN usuarios u ON g.id_usuario = u.id WHERE g.id_sucursal = $id_sucursal"; if (!empty($fecha_inicio) && !empty($fecha_fin)) { $sql .= " AND g.fecha BETWEEN '$fecha_inicio 00:00:00' AND '$fecha_fin 23:59:59'"; } if ($categoria !== 'todos' && !empty($categoria)) { $sql .= " AND g.categoria = '" . $categoria . "'"; } if ($subcategoria !== 'todos' && !empty($subcategoria)) { $sql .= " AND g.subcategoria = '" . $subcategoria . "'"; } $sql .= " ORDER BY g.fecha DESC"; return $this->selectAll($sql); } public function getCuentasCobrar($fecha_inicio, $fecha_fin, $cliente, $estado, $id_sucursal) { $sql = "SELECT c.*, v.serie, v.fecha as fecha_venta, cl.nombre as cliente, (SELECT SUM(abono) FROM abonos a WHERE a.id_credito = c.id) as abono, (c.monto - IFNULL((SELECT SUM(abono) FROM abonos a WHERE a.id_credito = c.id), 0)) as restante FROM creditos c INNER JOIN ventas v ON c.id_venta = v.id INNER JOIN clientes cl ON v.id_cliente = cl.id WHERE v.id_sucursal = $id_sucursal"; if (!empty($fecha_inicio) && !empty($fecha_fin)) { $sql .= " AND c.fecha BETWEEN '$fecha_inicio 00:00:00' AND '$fecha_fin 23:59:59'"; } if ($cliente !== 'todos' && !empty($cliente)) { $sql .= " AND v.id_cliente = " . intval($cliente); } if ($estado !== 'todos' && $estado !== '') { $sql .= " AND c.estado = " . intval($estado); // 1 = pendiente, 0 = pagado } $sql .= " ORDER BY c.fecha DESC"; return $this->selectAll($sql); } public function getCuentasPagar($fecha_inicio, $fecha_fin, $proveedor, $estado, $id_sucursal) { $sql = "SELECT cp.*, c.serie, c.fecha as fecha_compra, p.nombre as proveedor, (SELECT SUM(abono) FROM abonosporpagar a WHERE a.id_credito = cp.id) as abono, (cp.monto - IFNULL((SELECT SUM(abono) FROM abonosporpagar a WHERE a.id_credito = cp.id), 0)) as restante FROM porpagar cp INNER JOIN compras c ON cp.id_compra = c.id INNER JOIN proveedor p ON c.id_proveedor = p.id WHERE c.id_sucursal = $id_sucursal"; if (!empty($fecha_inicio) && !empty($fecha_fin)) { $sql .= " AND cp.fecha BETWEEN '$fecha_inicio 00:00:00' AND '$fecha_fin 23:59:59'"; } if ($proveedor !== 'todos' && !empty($proveedor)) { $sql .= " AND c.id_proveedor = " . intval($proveedor); } if ($estado !== 'todos' && $estado !== '') { $sql .= " AND cp.estado = " . intval($estado); } $sql .= " ORDER BY cp.fecha DESC"; return $this->selectAll($sql); } public function getActivosFijos($fecha_inicio, $fecha_fin, $estado, $id_sucursal) { $sql = "SELECT a.*, s.nombre as sucursal FROM activos_fijos a INNER JOIN sucursales s ON a.id_sucursal = s.id WHERE a.id_sucursal = $id_sucursal"; if (!empty($fecha_inicio) && !empty($fecha_fin)) { $sql .= " AND a.fecha_compra BETWEEN '$fecha_inicio 00:00:00' AND '$fecha_fin 23:59:59'"; } if ($estado !== 'todos' && $estado !== '') { $sql .= " AND a.estado = " . intval($estado); } return $this->selectAll($sql); } public function getProductosQRs($id_sucursal) { $sql = "SELECT p.id, p.codigo, p.descripcion, p.precio_venta, c.categoria FROM productos p INNER JOIN categorias c ON p.id_categoria = c.id WHERE p.id_sucursal = $id_sucursal AND p.estado = 1 ORDER BY p.descripcion ASC"; return $this->selectAll($sql); } public function getRentabilidadProductos($codigo, $nombre, $id_sucursal) { $sql = "SELECT p.codigo, p.descripcion as producto, c.categoria, p.precio_compra, p.precio_venta FROM productos p LEFT JOIN categorias c ON p.id_categoria = c.id WHERE p.id_sucursal = $id_sucursal AND p.estado = 1"; if (!empty($codigo)) { $sql .= " AND p.codigo = '$codigo'"; } if (!empty($nombre)) { $sql .= " AND p.descripcion LIKE '%" . $nombre . "%'"; } $sql .= " ORDER BY p.descripcion ASC"; return $this->selectAll($sql); } public function getProductoIndividualQR($id_producto, $id_sucursal) { $sql = "SELECT p.id, p.codigo, p.descripcion, p.precio_venta, c.categoria FROM productos p INNER JOIN categorias c ON p.id_categoria = c.id WHERE p.id = $id_producto AND p.id_sucursal = $id_sucursal AND p.estado = 1"; return $this->select($sql); } public function asegurarTablaHistorial() { $row = $this->select("SHOW TABLES LIKE 'historial_codigos'"); if (empty($row)) { $sql = "CREATE TABLE IF NOT EXISTS historial_codigos ( id INT AUTO_INCREMENT PRIMARY KEY, tipo VARCHAR(50) NOT NULL, valor VARCHAR(255) NOT NULL, estandar VARCHAR(50) DEFAULT 'N/A', cantidad INT NOT NULL DEFAULT 1, fecha TIMESTAMP DEFAULT CURRENT_TIMESTAMP, id_usuario INT NOT NULL, id_sucursal INT NOT NULL, KEY idx_historial_usuario (id_usuario), KEY idx_historial_sucursal (id_sucursal) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"; $this->save($sql, []); } } public function registrarHistorial($tipo, $valor, $estandar, $cantidad, $id_usuario, $id_sucursal) { $this->asegurarTablaHistorial(); $sql = "INSERT INTO historial_codigos (tipo, valor, estandar, cantidad, id_usuario, id_sucursal) VALUES (?, ?, ?, ?, ?, ?)"; return $this->insertar($sql, [$tipo, $valor, $estandar, $cantidad, $id_usuario, $id_sucursal]); } public function getHistorial($id_sucursal) { $this->asegurarTablaHistorial(); return $this->selectAll("SELECT h.*, u.nombre as usuario FROM historial_codigos h INNER JOIN usuarios u ON h.id_usuario = u.id WHERE h.id_sucursal = $id_sucursal ORDER BY h.fecha DESC"); } } ?>
Coded With 💗 by
0x6ick