diff --git a/assets/uploads/vouchers/6a0c95b513412-Captura de pantalla 2026-05-19 115218.png b/assets/uploads/vouchers/6a0c95b513412-Captura de pantalla 2026-05-19 115218.png new file mode 100644 index 00000000..d783608d Binary files /dev/null and b/assets/uploads/vouchers/6a0c95b513412-Captura de pantalla 2026-05-19 115218.png differ diff --git a/dashboard_principal.php b/dashboard_principal.php index 229becd6..b45ebeae 100644 --- a/dashboard_principal.php +++ b/dashboard_principal.php @@ -118,15 +118,15 @@ $stmtEstados = $db->query("SELECT estado, COUNT(*) as total FROM pedidos p WHERE $estadosData = $stmtEstados->fetchAll(PDO::FETCH_ASSOC); // 7. Top Productos (Ajustado al periodo) - TOTAL -$stmtTopProd = $db->query("SELECT producto, SUM(cantidad) as ventas FROM pedidos p WHERE $date_condition AND estado NOT IN ('RETORNADO', 'GESTIONES') GROUP BY producto ORDER BY ventas DESC LIMIT 10"); +$stmtTopProd = $db->query("SELECT producto, SUM(cantidad) as ventas FROM pedidos p WHERE $date_condition AND estado NOT IN ('RETORNADO', 'GESTIONES') GROUP BY producto ORDER BY ventas DESC"); $topProductos = $stmtTopProd->fetchAll(PDO::FETCH_ASSOC); // 7b. Top Productos Contraentrega (Ajustado al periodo) -$stmtTopProdCE = $db->query("SELECT producto, SUM(cantidad) as ventas FROM pedidos p WHERE $date_condition AND estado IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA') GROUP BY producto ORDER BY ventas DESC LIMIT 10"); +$stmtTopProdCE = $db->query("SELECT producto, SUM(cantidad) as ventas FROM pedidos p WHERE $date_condition AND estado IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA') GROUP BY producto ORDER BY ventas DESC"); $topProductosCE = $stmtTopProdCE->fetchAll(PDO::FETCH_ASSOC); // 7c. Top Productos Provincia (Ajustado al periodo) -$stmtTopProdProv = $db->query("SELECT producto, SUM(cantidad) as ventas FROM pedidos p WHERE $date_condition AND estado NOT IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA', 'RETORNADO', 'GESTIONES') GROUP BY producto ORDER BY ventas DESC LIMIT 10"); +$stmtTopProdProv = $db->query("SELECT producto, SUM(cantidad) as ventas FROM pedidos p WHERE $date_condition AND estado NOT IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA', 'RETORNADO', 'GESTIONES') GROUP BY producto ORDER BY ventas DESC"); $topProductosProv = $stmtTopProdProv->fetchAll(PDO::FETCH_ASSOC); // 8. Ventas por Asesor (Ajustado al periodo) @@ -194,7 +194,6 @@ $stmtTopDetalle = $db->query(" WHERE $date_condition AND p.estado NOT IN ('RETORNADO', 'GESTIONES') GROUP BY p.producto ORDER BY total_cantidad DESC - LIMIT 10 "); $topProductosDetalle = $stmtTopDetalle->fetchAll(PDO::FETCH_ASSOC); @@ -206,7 +205,6 @@ $stmtTopDetalleCE = $db->query(" WHERE $date_condition AND p.estado IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA') GROUP BY p.producto ORDER BY total_cantidad DESC - LIMIT 10 "); $topProductosDetalleCE = $stmtTopDetalleCE->fetchAll(PDO::FETCH_ASSOC); @@ -218,7 +216,6 @@ $stmtTopDetalleProv = $db->query(" WHERE $date_condition AND p.estado NOT IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA', 'RETORNADO', 'GESTIONES') GROUP BY p.producto ORDER BY total_cantidad DESC - LIMIT 10 "); $topProductosDetalleProv = $stmtTopDetalleProv->fetchAll(PDO::FETCH_ASSOC); @@ -235,7 +232,6 @@ $stmtProdRendimientoCE = $db->query(" AND estado IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA', 'RETORNADO') GROUP BY producto ORDER BY total DESC - LIMIT 10 "); $prodRendimientoCE = $stmtProdRendimientoCE->fetchAll(PDO::FETCH_ASSOC); @@ -252,10 +248,21 @@ $stmtProdRendimientoProv = $db->query(" AND estado NOT IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA', 'RETORNADO') GROUP BY producto ORDER BY total DESC - LIMIT 10 "); $prodRendimientoProv = $stmtProdRendimientoProv->fetchAll(PDO::FETCH_ASSOC); +// 16. Top Upsells (Combinaciones de productos distintos) +$stmtTopUpsell = $db->query(" + SELECT producto, COUNT(*) as total_pedidos, SUM(monto_total) as recaudo + FROM pedidos p + WHERE $date_condition + AND producto LIKE '%,%' + AND estado NOT IN ('RETORNADO', 'GESTIONES') + GROUP BY producto + ORDER BY total_pedidos DESC +"); +$topUpsells = $stmtTopUpsell->fetchAll(PDO::FETCH_ASSOC); + $canalesResumen = [ 'Provincia' => ['pedidos' => 0, 'monto' => 0, 'estados' => []], 'Contraentrega' => ['pedidos' => 0, 'monto' => 0, 'estados' => []] @@ -447,8 +454,8 @@ include 'layout_header.php';
Estados Provincia
Distribución Interna -
-
+
+
@@ -466,8 +473,8 @@ include 'layout_header.php';
Estados Contraentrega
Distribución Interna
-
-
+
+
@@ -599,18 +606,20 @@ include 'layout_header.php';
-
Top 10 Productos Más Vendidos (Total)
+
Productos Más Vendidos (Total)
Rendimiento Global
- +
+ +
-
+
- + @@ -620,7 +629,7 @@ include 'layout_header.php'; - +
Producto Cant.
35 ? substr($prod['producto'], 0, 35) . '...' : $prod['producto']); ?> @@ -641,20 +650,83 @@ include 'layout_header.php'; + +
+
+
+
+
Top Upsell: Combinaciones de Productos Distintos
+ Estrategia de Venta Cruzada +
+
+ +
+ +

No se encontraron pedidos con combinaciones de productos distintos en este periodo.

+
+ +
+
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + +
Combinación de ProductosPedidosRecaudo
+ $part) { + echo '' . htmlspecialchars($part) . '' . ($index < count($parts)-1 ? ' ' : ''); + } + ?> + + + + S/ +
+
+
+
+ +
+
+
+
+
-
Top 10 Contraentrega
+
Productos Contraentrega
Motorizado
- +
+ +
-
+
- + @@ -664,7 +736,7 @@ include 'layout_header.php'; - +
Producto Cant.
25 ? substr($prod['producto'], 0, 25) . '...' : $prod['producto']); ?> @@ -686,15 +758,17 @@ include 'layout_header.php';
-
Top 10 Provincia
+
Productos Provincia
Agencias
- +
+ +
-
+
- + @@ -704,7 +778,7 @@ include 'layout_header.php'; - +
Producto Cant.
25 ? substr($prod['producto'], 0, 25) . '...' : $prod['producto']); ?> @@ -729,10 +803,10 @@ include 'layout_header.php';
Rendimiento Producto (Provincia)
- Top 10 + Todos los productos
-
+
@@ -747,10 +821,10 @@ include 'layout_header.php';
Rendimiento Producto (Contraentrega)
- Top 10 + Todos los productos
-
+
@@ -979,7 +1053,7 @@ include 'layout_header.php'; new Chart(ctxProductos, { type: 'bar', data: { - labels: 30 ? substr($p['producto'], 0, 30) . '...' : $p['producto']; }, $topProductos)); ?>, + labels: , datasets: [{ label: 'Unidades', data: , @@ -1028,7 +1102,7 @@ include 'layout_header.php'; new Chart(ctxProductosCE, { type: 'bar', data: { - labels: 15 ? substr($p['producto'], 0, 15) . '...' : $p['producto']; }, $topProductosCE)); ?>, + labels: , datasets: [{ label: 'Unidades', data: , @@ -1072,7 +1146,7 @@ include 'layout_header.php'; new Chart(ctxProductosProv, { type: 'bar', data: { - labels: 15 ? substr($p['producto'], 0, 15) . '...' : $p['producto']; }, $topProductosProv)); ?>, + labels: , datasets: [{ label: 'Unidades', data: , @@ -1116,9 +1190,7 @@ include 'layout_header.php'; new Chart(ctxRendimientoCE, { type: 'bar', data: { - labels: 15 ? substr($p['producto'], 0, 15) . '...' : $p['producto']; - }, $prodRendimientoCE)); ?>, + labels: , datasets: [ { label: 'Exitosa ✅', @@ -1175,9 +1247,7 @@ include 'layout_header.php'; new Chart(ctxRendimientoProv, { type: 'bar', data: { - labels: 15 ? substr($p['producto'], 0, 15) . '...' : $p['producto']; - }, $prodRendimientoProv)); ?>, + labels: , datasets: [ { label: 'Completado ✅', @@ -1269,6 +1339,41 @@ include 'layout_header.php'; } } }); + + // Gráfico de Upsell + + const ctxUpsell = document.getElementById('upsellChart').getContext('2d'); + new Chart(ctxUpsell, { + type: 'bar', + data: { + labels: , + datasets: [{ + label: 'Número de Pedidos', + data: , + backgroundColor: '#198754', + borderRadius: 5, + }] + }, + options: { + indexAxis: 'y', + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { display: false }, + datalabels: { + anchor: 'end', + align: 'right', + color: '#000', + font: { weight: 'bold' } + } + }, + scales: { + x: { beginAtZero: true, title: { display: true, text: 'Cantidad de Pedidos' } }, + y: { ticks: { font: { size: 10 } } } + } + } + }); + \ No newline at end of file