Autosave: 20260516-005835
This commit is contained in:
parent
16e55cb151
commit
40389434b1
254
dashboard_principal.php
Normal file
254
dashboard_principal.php
Normal file
@ -0,0 +1,254 @@
|
||||
<?php
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
require_once 'db/config.php';
|
||||
|
||||
// Verificar si es admin
|
||||
if (!isset($_SESSION['user_id']) || !in_array($_SESSION['user_role'], ['Administrador', 'admin'])) {
|
||||
header("Location: index.php");
|
||||
exit();
|
||||
}
|
||||
|
||||
$db = db();
|
||||
|
||||
// 1. Estadísticas de hoy
|
||||
$hoy = date('Y-m-d');
|
||||
$stmtHoy = $db->prepare("SELECT COUNT(*) as total_pedidos, SUM(monto_total) as total_dinero FROM pedidos WHERE DATE(created_at) = ? AND estado != 'RETORNADO'");
|
||||
$stmtHoy->execute([$hoy]);
|
||||
$statsHoy = $stmtHoy->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// 2. Pedidos Pendientes (ROTULADO ?)
|
||||
$stmtPendientes = $db->query("SELECT COUNT(*) FROM pedidos WHERE estado = 'ROTULADO ?'");
|
||||
$pendientes = $stmtPendientes->fetchColumn();
|
||||
|
||||
// 3. Recaudo Esperado (En tránsito, En destino, Ruta contraentrega)
|
||||
$stmtRecaudo = $db->query("SELECT SUM(monto_debe) FROM pedidos WHERE estado IN ('EN TRANSITO ?', 'EN DESTINO ?', 'RUTA_CONTRAENTREGA') AND (estado_pago != 'Pagado' OR estado_pago IS NULL)");
|
||||
$recaudoEsperado = $stmtRecaudo->fetchColumn() ?: 0;
|
||||
|
||||
// 4. Stock Crítico (menos de 5 unidades en total entre todas las sedes)
|
||||
$stmtStock = $db->query("SELECT COUNT(*) FROM (SELECT product_id, SUM(quantity) as total_stock FROM stock_sedes GROUP BY product_id HAVING total_stock <= 5) as critico");
|
||||
$stockCritico = $stmtStock->fetchColumn() ?: 0;
|
||||
|
||||
// 5. Datos para Gráfico de Ventas (Últimos 7 días)
|
||||
$ventas7dias = [];
|
||||
for ($i = 6; $i >= 0; $i--) {
|
||||
$fecha = date('Y-m-d', strtotime("-$i days"));
|
||||
$stmt = $db->prepare("SELECT COUNT(*) as cant, SUM(monto_total) as monto FROM pedidos WHERE DATE(created_at) = ? AND estado != 'RETORNADO'");
|
||||
$stmt->execute([$fecha]);
|
||||
$res = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$ventas7dias[] = [
|
||||
'fecha' => date('d/m', strtotime($fecha)),
|
||||
'cantidad' => $res['cant'] ?: 0,
|
||||
'monto' => $res['monto'] ?: 0
|
||||
];
|
||||
}
|
||||
|
||||
// 6. Estados de Pedidos
|
||||
$stmtEstados = $db->query("SELECT estado, COUNT(*) as total FROM pedidos GROUP BY estado");
|
||||
$estadosData = $stmtEstados->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// 7. Top Productos
|
||||
$stmtTopProd = $db->query("SELECT producto, COUNT(*) as ventas FROM pedidos GROUP BY producto ORDER BY ventas DESC LIMIT 5");
|
||||
$topProductos = $stmtTopProd->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// 8. Ventas por Asesor
|
||||
$stmtAsesores = $db->query("SELECT u.nombre_asesor, COUNT(p.id) as total_pedidos, COALESCE(SUM(p.monto_total), 0) as total_monto
|
||||
FROM users u
|
||||
LEFT JOIN pedidos p ON u.id = p.asesor_id AND p.estado != 'RETORNADO'
|
||||
WHERE u.role = 'Asesor'
|
||||
GROUP BY u.id
|
||||
ORDER BY total_monto DESC");
|
||||
$ventasAsesores = $stmtAsesores->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$pageTitle = "Dashboard Principal";
|
||||
include 'layout_header.php';
|
||||
?>
|
||||
|
||||
<div class="container-fluid mt-4">
|
||||
<!-- Tarjetas de Resumen -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="card bg-primary text-white shadow h-100">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Ventas Hoy</h6>
|
||||
<h3>S/ <?php echo number_format($statsHoy['total_dinero'] ?: 0, 2); ?></h3>
|
||||
<p class="mb-0"><?php echo $statsHoy['total_pedidos']; ?> pedidos</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card bg-warning text-dark shadow h-100">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Pedidos Pendientes</h6>
|
||||
<h3><?php echo $pendientes; ?></h3>
|
||||
<p class="mb-0">Por procesar</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card bg-success text-white shadow h-100">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Recaudo Esperado</h6>
|
||||
<h3>S/ <?php echo number_format($recaudoEsperado, 2); ?></h3>
|
||||
<p class="mb-0">En ruta / Contraentrega</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card bg-danger text-white shadow h-100">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Stock Crítico</h6>
|
||||
<h3><?php echo $stockCritico; ?></h3>
|
||||
<p class="mb-0">Productos < 5 unidades</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- Gráfico de Ventas -->
|
||||
<div class="col-md-8 mb-4">
|
||||
<div class="card shadow">
|
||||
<div class="card-header bg-white">
|
||||
<h5 class="mb-0">Tendencia de Ventas (Últimos 7 días)</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<canvas id="ventasChart" height="100"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Gráfico de Estados -->
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card shadow">
|
||||
<div class="card-header bg-white">
|
||||
<h5 class="mb-0">Distribución de Estados</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<canvas id="estadosChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- Top Productos -->
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card shadow">
|
||||
<div class="card-header bg-white">
|
||||
<h5 class="mb-0">Top 5 Productos más Vendidos</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<canvas id="productosChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Ventas por Asesor -->
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card shadow">
|
||||
<div class="card-header bg-white">
|
||||
<h5 class="mb-0">Rendimiento por Asesor</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Asesor</th>
|
||||
<th>Pedidos</th>
|
||||
<th>Total Ventas</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($ventasAsesores as $asesor): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($asesor['nombre_asesor']); ?></td>
|
||||
<td><?php echo $asesor['total_pedidos']; ?></td>
|
||||
<td>S/ <?php echo number_format($asesor['total_monto'], 2); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script>
|
||||
// Gráfico de Ventas
|
||||
const ctxVentas = document.getElementById('ventasChart').getContext('2d');
|
||||
new Chart(ctxVentas, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: <?php echo json_encode(array_column($ventas7dias, 'fecha')); ?>,
|
||||
datasets: [{
|
||||
label: 'Monto (S/)',
|
||||
data: <?php echo json_encode(array_column($ventas7dias, 'monto')); ?>,
|
||||
borderColor: '#0d6efd',
|
||||
backgroundColor: 'rgba(13, 110, 253, 0.1)',
|
||||
fill: true,
|
||||
yAxisID: 'y',
|
||||
}, {
|
||||
label: 'Cantidad Pedidos',
|
||||
data: <?php echo json_encode(array_column($ventas7dias, 'cantidad')); ?>,
|
||||
borderColor: '#198754',
|
||||
borderDash: [5, 5],
|
||||
yAxisID: 'y1',
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
scales: {
|
||||
y: {
|
||||
type: 'linear',
|
||||
display: true,
|
||||
position: 'left',
|
||||
title: { display: true, text: 'Soles' }
|
||||
},
|
||||
y1: {
|
||||
type: 'linear',
|
||||
display: true,
|
||||
position: 'right',
|
||||
grid: { drawOnChartArea: false },
|
||||
title: { display: true, text: 'Pedidos' }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Gráfico de Estados
|
||||
const ctxEstados = document.getElementById('estadosChart').getContext('2d');
|
||||
new Chart(ctxEstados, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: <?php echo json_encode(array_column($estadosData, 'estado')); ?>,
|
||||
datasets: [{
|
||||
data: <?php echo json_encode(array_column($estadosData, 'total')); ?>,
|
||||
backgroundColor: ['#ffc107', '#0dcaf0', '#198754', '#dc3545', '#6c757d', '#0d6efd']
|
||||
}]
|
||||
}
|
||||
});
|
||||
|
||||
// Gráfico de Productos
|
||||
const ctxProductos = document.getElementById('productosChart').getContext('2d');
|
||||
new Chart(ctxProductos, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: <?php echo json_encode(array_column($topProductos, 'producto')); ?>,
|
||||
datasets: [{
|
||||
label: 'Unidades Vendidas',
|
||||
data: <?php echo json_encode(array_column($topProductos, 'ventas')); ?>,
|
||||
backgroundColor: '#0d6efd'
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
indexAxis: 'y',
|
||||
responsive: true
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php include 'layout_footer.php'; ?>
|
||||
@ -14,6 +14,12 @@ $userRole = $_SESSION['user_role'] ?? '';
|
||||
|
||||
// Define navigation items for each role
|
||||
$navItems = [
|
||||
'dashboard_principal' => [
|
||||
'url' => 'dashboard_principal.php',
|
||||
'icon' => 'fa-chart-line',
|
||||
'text' => 'Dashboard Principal',
|
||||
'roles' => ['Administrador', 'admin']
|
||||
],
|
||||
'dashboard' => [
|
||||
'url' => 'dashboard.php',
|
||||
'icon' => 'fa-tachometer-alt',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user