Autosave: 20260609-225057
This commit is contained in:
parent
923ddb7b18
commit
3f9d04425f
397
dashboard.php
397
dashboard.php
@ -192,52 +192,106 @@ if ($user_role === 'Administrador' || $user_role === 'Control Logistico' || $use
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TABLA DE PEDIDOS POR DÍA Y ASESORA (TIPO EXCEL)
|
// TABLA DE PEDIDOS POR DÍA Y ASESORA (TIPO EXCEL) - PROVINCIA y CONTRAENTREGA
|
||||||
$pedidos_mensual_asesora = [];
|
$pedidos_mensual_provincia_asesora = [];
|
||||||
|
$pedidos_mensual_contraentrega_asesora = [];
|
||||||
$asesoras_mensual = [];
|
$asesoras_mensual = [];
|
||||||
|
$asesoras_mensual_provincia = [];
|
||||||
|
$asesoras_mensual_contraentrega = [];
|
||||||
|
|
||||||
if ($user_role === 'Administrador' || $user_role === 'Control Logistico' || $user_role === 'Logistica' || $user_role === 'Asesor') {
|
if ($user_role === 'Administrador' || $user_role === 'Control Logistico' || $user_role === 'Logistica' || $user_role === 'Asesor') {
|
||||||
// 1. Obtener todas las asesoras
|
// 1. Obtener todas las asesoras
|
||||||
$stmt_asesoras = $pdo->query("SELECT id, nombre_asesor FROM users WHERE role = 'Asesor' AND nombre_asesor IS NOT NULL AND nombre_asesor != ''");
|
$stmt_asesoras = $pdo->query("SELECT id, nombre_asesor FROM users WHERE role = 'Asesor' AND nombre_asesor IS NOT NULL AND nombre_asesor != ''");
|
||||||
$asesoras_mensual = $stmt_asesoras->fetchAll(PDO::FETCH_ASSOC);
|
$asesoras_mensual = $stmt_asesoras->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
// Por defecto, las dos tablas usan la misma lista (luego se ordena por cada tipo)
|
||||||
|
$asesoras_mensual_provincia = $asesoras_mensual;
|
||||||
|
$asesoras_mensual_contraentrega = $asesoras_mensual;
|
||||||
|
|
||||||
$asesora_ids = array_column($asesoras_mensual, 'id');
|
$asesora_ids = array_column($asesoras_mensual, 'id');
|
||||||
|
|
||||||
// 2. Obtener y procesar los datos de pedidos del mes
|
|
||||||
if (!empty($asesora_ids)) {
|
if (!empty($asesora_ids)) {
|
||||||
$placeholders = implode(',', array_fill(0, count($asesora_ids), '?'));
|
// PROVINCIA
|
||||||
$stmt_pedidos_mensual = $pdo->prepare("
|
$estados_provincia = ['ROTULADO 📦', 'EN TRANSITO 🚛', 'EN DESTINO 🏬', 'COMPLETADO ✅'];
|
||||||
|
$placeholders_estados_prov = implode(',', array_fill(0, count($estados_provincia), '?'));
|
||||||
|
$placeholders_asesores = implode(',', array_fill(0, count($asesora_ids), '?'));
|
||||||
|
|
||||||
|
$stmt_prov = $pdo->prepare("
|
||||||
SELECT DAY(created_at) as dia, asesor_id, COUNT(id) as total_pedidos
|
SELECT DAY(created_at) as dia, asesor_id, COUNT(id) as total_pedidos
|
||||||
FROM pedidos
|
FROM pedidos
|
||||||
WHERE MONTH(created_at) = ? AND YEAR(created_at) = ? AND asesor_id IN (" . $placeholders . ")
|
WHERE estado IN ($placeholders_estados_prov)
|
||||||
|
AND MONTH(created_at) = ? AND YEAR(created_at) = ?
|
||||||
|
AND asesor_id IN ($placeholders_asesores)
|
||||||
GROUP BY dia, asesor_id
|
GROUP BY dia, asesor_id
|
||||||
");
|
");
|
||||||
$params = array_merge([$selected_month, $selected_year], $asesora_ids);
|
$params_prov = array_merge($estados_provincia, [$selected_month, $selected_year], $asesora_ids);
|
||||||
$stmt_pedidos_mensual->execute($params);
|
$stmt_prov->execute($params_prov);
|
||||||
$pedidos_data = $stmt_pedidos_mensual->fetchAll(PDO::FETCH_ASSOC);
|
$pedidos_prov_data = $stmt_prov->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
foreach ($pedidos_data as $row) {
|
foreach ($pedidos_prov_data as $row) {
|
||||||
$pedidos_mensual_asesora[$row['dia']][$row['asesor_id']] = $row['total_pedidos'];
|
$dia = (int)$row['dia'];
|
||||||
|
$asesor_id = (int)$row['asesor_id'];
|
||||||
|
$pedidos_mensual_provincia_asesora[$dia][$asesor_id] = (int)$row['total_pedidos'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Calcular totales por asesora para el mes
|
// Totales por asesora (Provincia) para ordenar columnas
|
||||||
$totales_por_asesora_para_orden = array_fill_keys($asesora_ids, 0);
|
$totales_prov_para_orden = array_fill_keys($asesora_ids, 0);
|
||||||
foreach ($pedidos_mensual_asesora as $dia_data) {
|
foreach ($pedidos_mensual_provincia_asesora as $dia_data) {
|
||||||
foreach ($dia_data as $asesor_id => $cantidad) {
|
foreach ($dia_data as $asesor_id => $cantidad) {
|
||||||
if (isset($totales_por_asesora_para_orden[$asesor_id])) {
|
if (isset($totales_prov_para_orden[$asesor_id])) {
|
||||||
$totales_por_asesora_para_orden[$asesor_id] += $cantidad;
|
$totales_prov_para_orden[$asesor_id] += (int)$cantidad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Ordenar el array de asesoras basado en el total de pedidos (de menor a mayor)
|
usort($asesoras_mensual_provincia, function ($a, $b) use ($totales_prov_para_orden) {
|
||||||
usort($asesoras_mensual, function ($a, $b) use ($totales_por_asesora_para_orden) {
|
$total_a = $totales_prov_para_orden[$a['id']] ?? 0;
|
||||||
$total_a = $totales_por_asesora_para_orden[$a['id']] ?? 0;
|
$total_b = $totales_prov_para_orden[$b['id']] ?? 0;
|
||||||
$total_b = $totales_por_asesora_para_orden[$b['id']] ?? 0;
|
return $total_a <=> $total_b; // de menor a mayor
|
||||||
return $total_a <=> $total_b;
|
});
|
||||||
|
|
||||||
|
// CONTRAENTREGA
|
||||||
|
$estados_contraentrega = ['RUTA_CONTRAENTREGA', 'RETORNADO', 'ENTREGA EXITOSA'];
|
||||||
|
$placeholders_estados_contra = implode(',', array_fill(0, count($estados_contraentrega), '?'));
|
||||||
|
|
||||||
|
$stmt_contra = $pdo->prepare("
|
||||||
|
SELECT DAY(created_at) as dia, asesor_id, COUNT(id) as total_pedidos
|
||||||
|
FROM pedidos
|
||||||
|
WHERE estado IN ($placeholders_estados_contra)
|
||||||
|
AND MONTH(created_at) = ? AND YEAR(created_at) = ?
|
||||||
|
AND asesor_id IN ($placeholders_asesores)
|
||||||
|
GROUP BY dia, asesor_id
|
||||||
|
");
|
||||||
|
$params_contra = array_merge($estados_contraentrega, [$selected_month, $selected_year], $asesora_ids);
|
||||||
|
$stmt_contra->execute($params_contra);
|
||||||
|
$pedidos_contra_data = $stmt_contra->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
foreach ($pedidos_contra_data as $row) {
|
||||||
|
$dia = (int)$row['dia'];
|
||||||
|
$asesor_id = (int)$row['asesor_id'];
|
||||||
|
$pedidos_mensual_contraentrega_asesora[$dia][$asesor_id] = (int)$row['total_pedidos'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Totales por asesora (Contraentrega) para ordenar columnas
|
||||||
|
$totales_contra_para_orden = array_fill_keys($asesora_ids, 0);
|
||||||
|
foreach ($pedidos_mensual_contraentrega_asesora as $dia_data) {
|
||||||
|
foreach ($dia_data as $asesor_id => $cantidad) {
|
||||||
|
if (isset($totales_contra_para_orden[$asesor_id])) {
|
||||||
|
$totales_contra_para_orden[$asesor_id] += (int)$cantidad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usort($asesoras_mensual_contraentrega, function ($a, $b) use ($totales_contra_para_orden) {
|
||||||
|
$total_a = $totales_contra_para_orden[$a['id']] ?? 0;
|
||||||
|
$total_b = $totales_contra_para_orden[$b['id']] ?? 0;
|
||||||
|
return $total_a <=> $total_b; // de menor a mayor
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<h1 class="h3 mb-4 text-gray-800">Dashboard</h1>
|
<h1 class="h3 mb-4 text-gray-800">Dashboard</h1>
|
||||||
<p class="mb-4">Bienvenido, <?php echo htmlspecialchars($user_name); ?>!</p>
|
<p class="mb-4">Bienvenido, <?php echo htmlspecialchars($user_name); ?>!</p>
|
||||||
@ -474,13 +528,13 @@ if ($user_role === 'Administrador' || $user_role === 'Control Logistico' || $use
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if (($user_role === 'Administrador' || $user_role === 'Control Logistico' || $user_role === 'Logistica' || $user_role === 'Asesor')): ?>
|
<?php if (($user_role === 'Administrador' || $user_role === 'Control Logistico' || $user_role === 'Logistica' || $user_role === 'Asesor')): ?>
|
||||||
<!-- Reporte Mensual de Pedidos por Asesora -->
|
<!-- Reporte Mensual de Pedidos por Asesora - Provincia -->
|
||||||
<div class="card shadow mb-4">
|
<div class="card shadow mb-4">
|
||||||
<div class="card-header py-3">
|
<div class="card-header py-3">
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Reporte Mensual de Pedidos por Asesora (<?php echo $meses[$selected_month] . ' ' . $selected_year; ?>)</h6>
|
<h6 class="m-0 font-weight-bold text-primary">Reporte Mensual de Pedidos por Asesora - Provincia (<?php echo $meses[$selected_month] . ' ' . $selected_year; ?>)</h6>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<?php if (empty($asesoras_mensual)): ?>
|
<?php if (empty($asesoras_mensual_provincia)): ?>
|
||||||
<div class="alert alert-warning">No hay asesoras configuradas para mostrar en este reporte.</div>
|
<div class="alert alert-warning">No hay asesoras configuradas para mostrar en este reporte.</div>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
@ -488,7 +542,7 @@ if ($user_role === 'Administrador' || $user_role === 'Control Logistico' || $use
|
|||||||
<thead class="thead-dark">
|
<thead class="thead-dark">
|
||||||
<tr class="text-center">
|
<tr class="text-center">
|
||||||
<th style="width: 80px; vertical-align: middle;">Día</th>
|
<th style="width: 80px; vertical-align: middle;">Día</th>
|
||||||
<?php foreach ($asesoras_mensual as $asesora): ?>
|
<?php foreach ($asesoras_mensual_provincia as $asesora): ?>
|
||||||
<th><?php echo htmlspecialchars($asesora['nombre_asesor']); ?></th>
|
<th><?php echo htmlspecialchars($asesora['nombre_asesor']); ?></th>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<th style="vertical-align: middle;">Total Día</th>
|
<th style="vertical-align: middle;">Total Día</th>
|
||||||
@ -497,7 +551,7 @@ if ($user_role === 'Administrador' || $user_role === 'Control Logistico' || $use
|
|||||||
<tbody>
|
<tbody>
|
||||||
<?php
|
<?php
|
||||||
$dias_en_mes = cal_days_in_month(CAL_GREGORIAN, $selected_month, $selected_year);
|
$dias_en_mes = cal_days_in_month(CAL_GREGORIAN, $selected_month, $selected_year);
|
||||||
$totales_por_asesora = array_fill_keys(array_column($asesoras_mensual, 'id'), 0);
|
$totales_por_asesora = array_fill_keys(array_column($asesoras_mensual_provincia, 'id'), 0);
|
||||||
$gran_total_mes = 0;
|
$gran_total_mes = 0;
|
||||||
|
|
||||||
for ($dia = 1; $dia <= $dias_en_mes; $dia++):
|
for ($dia = 1; $dia <= $dias_en_mes; $dia++):
|
||||||
@ -505,9 +559,9 @@ if ($user_role === 'Administrador' || $user_role === 'Control Logistico' || $use
|
|||||||
?>
|
?>
|
||||||
<tr class="text-center">
|
<tr class="text-center">
|
||||||
<td class="font-weight-bold"><?php echo str_pad($dia, 2, '0', STR_PAD_LEFT) . '/' . str_pad($selected_month, 2, '0', STR_PAD_LEFT); ?></td>
|
<td class="font-weight-bold"><?php echo str_pad($dia, 2, '0', STR_PAD_LEFT) . '/' . str_pad($selected_month, 2, '0', STR_PAD_LEFT); ?></td>
|
||||||
<?php foreach ($asesoras_mensual as $asesora):
|
<?php foreach ($asesoras_mensual_provincia as $asesora):
|
||||||
$asesora_id = $asesora['id'];
|
$asesora_id = $asesora['id'];
|
||||||
$cantidad = $pedidos_mensual_asesora[$dia][$asesora_id] ?? 0;
|
$cantidad = $pedidos_mensual_provincia_asesora[$dia][$asesora_id] ?? 0;
|
||||||
$total_dia += $cantidad;
|
$total_dia += $cantidad;
|
||||||
$totales_por_asesora[$asesora_id] += $cantidad;
|
$totales_por_asesora[$asesora_id] += $cantidad;
|
||||||
echo '<td>' . ($cantidad > 0 ? $cantidad : '<span class="text-muted">-</span>') . '</td>';
|
echo '<td>' . ($cantidad > 0 ? $cantidad : '<span class="text-muted">-</span>') . '</td>';
|
||||||
@ -522,7 +576,7 @@ if ($user_role === 'Administrador' || $user_role === 'Control Logistico' || $use
|
|||||||
<tfoot class="thead-dark">
|
<tfoot class="thead-dark">
|
||||||
<tr class="text-center">
|
<tr class="text-center">
|
||||||
<th>Total Mes</th>
|
<th>Total Mes</th>
|
||||||
<?php foreach ($asesoras_mensual as $asesora): ?>
|
<?php foreach ($asesoras_mensual_provincia as $asesora): ?>
|
||||||
<th class="text-center"><?php echo $totales_por_asesora[$asesora['id']]; ?></th>
|
<th class="text-center"><?php echo $totales_por_asesora[$asesora['id']]; ?></th>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<th class="text-center"><?php echo $gran_total_mes; ?></th>
|
<th class="text-center"><?php echo $gran_total_mes; ?></th>
|
||||||
@ -533,6 +587,7 @@ if ($user_role === 'Administrador' || $user_role === 'Control Logistico' || $use
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if ($user_role === 'Administrador' || $user_role === 'Control Logistico' || $user_role === 'Logistica' || $user_role === 'Asesor'): ?>
|
<?php if ($user_role === 'Administrador' || $user_role === 'Control Logistico' || $user_role === 'Logistica' || $user_role === 'Asesor'): ?>
|
||||||
@ -549,93 +604,224 @@ $selected_month] . ' ' . $selected_year; ?>)</h6>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Tabla de Resumen por Asesora -->
|
<!-- Resumen Provincia por Asesora (cuadro 1) -->
|
||||||
<div class="card shadow mb-4">
|
<div class="card shadow mb-4">
|
||||||
<div class="card-header py-3">
|
<div class="card-header py-3">
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Resumen Detallado por Asesora (<?php echo $meses[$selected_month] . ' ' . $selected_year; ?>)</h6>
|
<h6 class="m-0 font-weight-bold text-primary">Resumen Provincia por Asesora (<?php echo $meses[$selected_month] . ' ' . $selected_year; ?>)</h6>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
|
<?php $estados_provincia = ['ROTULADO 📦', 'EN TRANSITO 🚛', 'EN DESTINO 🏬', 'COMPLETADO ✅']; ?>
|
||||||
|
<table class="table table-bordered" id="dataTableProvincia" width="100%" cellspacing="0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Asesora</th>
|
<th>Asesora</th>
|
||||||
<?php
|
<?php foreach ($estados_provincia as $estado): ?>
|
||||||
$estado_display_map = ['RUTA_CONTRAENTREGA' => 'Ruta Contraentrega', 'RETORNADO' => 'Retornado', 'ENTREGA EXITOSA' => 'Entrega Exitosa'];
|
<th><?php echo htmlspecialchars($estado); ?></th>
|
||||||
foreach ($estados as $estado):
|
<?php endforeach; ?>
|
||||||
$display_name = $estado_display_map[$estado] ?? $estado;
|
|
||||||
echo "<th>" . htmlspecialchars($display_name) . "</th>";
|
|
||||||
endforeach; ?>
|
|
||||||
<th>Total</th>
|
<th>Total</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php if (empty($asesor_data)):
|
<?php if (empty($asesor_data)): ?>
|
||||||
echo "<tr><td colspan=\"" . (count($estados) + 2) . "\" class=\"text-center\">No hay datos para el período seleccionado.</td></tr>";
|
<tr><td colspan="<?php echo count($estados_provincia) + 2; ?>" class="text-center">No hay datos para el período seleccionado.</td></tr>
|
||||||
else:
|
<?php else: ?>
|
||||||
// Initialize totals
|
<?php
|
||||||
$totals = array_fill_keys($estados, 0);
|
$totals_provincia = array_fill_keys($estados_provincia, 0);
|
||||||
$grand_total = 0;
|
$grand_total_provincia = 0;
|
||||||
|
|
||||||
// Definir los grupos de estados para los cálculos de porcentaje
|
foreach ($asesor_data as $data):
|
||||||
$estados_efectividad = ['RUTA_CONTRAENTREGA', 'RETORNADO', 'ENTREGA EXITOSA'];
|
echo "<tr>";
|
||||||
|
echo "<td>" . htmlspecialchars($data['nombre']) . "</td>";
|
||||||
|
|
||||||
foreach ($asesor_data as $data):
|
$total_provincia = 0;
|
||||||
echo "<tr>";
|
foreach ($estados_provincia as $e) {
|
||||||
echo "<td>" . htmlspecialchars($data['nombre']) . "</td>";
|
$total_provincia += $data['pedidos'][$e];
|
||||||
|
|
||||||
// Calcular los totales para cada grupo
|
|
||||||
$total_efectividad = 0;
|
|
||||||
$total_general_grupo = 0;
|
|
||||||
foreach ($estados_efectividad as $e) {
|
|
||||||
$total_efectividad += $data['pedidos'][$e];
|
|
||||||
}
|
|
||||||
foreach ($estados as $estado) {
|
|
||||||
if (!in_array($estado, $estados_efectividad)) {
|
|
||||||
$total_general_grupo += $data['pedidos'][$estado];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($estados as $estado):
|
|
||||||
$cantidad = $data['pedidos'][$estado];
|
|
||||||
$totals[$estado] += $cantidad;
|
|
||||||
echo "<td>";
|
|
||||||
echo $cantidad;
|
|
||||||
|
|
||||||
// Calcular porcentaje basado en el grupo
|
|
||||||
if (in_array($estado, $estados_efectividad)) {
|
|
||||||
if ($total_efectividad > 0) {
|
|
||||||
$porcentaje = round(($cantidad / $total_efectividad) * 100, 1);
|
|
||||||
echo " <span class=\"text-muted\">({" . $porcentaje . "}%)</span>";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ($total_general_grupo > 0) {
|
|
||||||
$porcentaje = round(($cantidad / $total_general_grupo) * 100, 1);
|
|
||||||
echo " <span class=\"text-muted\">({" . $porcentaje . "}%)</span>";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "</td>";
|
foreach ($estados_provincia as $estado):
|
||||||
|
$cantidad = (int)($data['pedidos'][$estado] ?? 0);
|
||||||
|
$totals_provincia[$estado] += $cantidad;
|
||||||
|
echo "<td>";
|
||||||
|
echo $cantidad;
|
||||||
|
|
||||||
|
if ($total_provincia > 0) {
|
||||||
|
$porcentaje = round(($cantidad / $total_provincia) * 100, 1);
|
||||||
|
echo " <span class=\"text-muted\">({" . $porcentaje . "}%)</span>";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "</td>";
|
||||||
|
endforeach;
|
||||||
|
|
||||||
|
echo "<td><strong>" . $total_provincia . "</strong></td>";
|
||||||
|
$grand_total_provincia += $total_provincia;
|
||||||
|
echo "</tr>";
|
||||||
endforeach;
|
endforeach;
|
||||||
echo "<td><strong>" . $data['total'] . "</strong></td>";
|
|
||||||
$grand_total += $data['total'];
|
|
||||||
echo "</tr>";
|
|
||||||
endforeach;
|
|
||||||
endif;
|
|
||||||
?>
|
|
||||||
</tbody>
|
|
||||||
<?php if (!empty($asesor_data)):
|
|
||||||
?>
|
|
||||||
<tfoot>
|
|
||||||
<tr style="background-color: #f8f9fc; font-weight: bold;">
|
|
||||||
<td>Total General</td>
|
|
||||||
<?php foreach ($totals as $total_estado):
|
|
||||||
echo "<td>" . $total_estado . "</td>";
|
|
||||||
endforeach;
|
|
||||||
echo "<td>" . $grand_total . "</td>";
|
|
||||||
?>
|
?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
<?php if (!empty($asesor_data)): ?>
|
||||||
|
<tfoot>
|
||||||
|
<tr style="background-color: #f8f9fc; font-weight: bold;">
|
||||||
|
<td>Total Provincia</td>
|
||||||
|
<?php foreach ($totals_provincia as $total_estado): ?>
|
||||||
|
<td><?php echo $total_estado; ?></td>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<td><?php echo $grand_total_provincia; ?></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
<?php endif; ?>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ($user_role === 'Administrador'): ?>
|
||||||
|
|
||||||
|
<!-- Reporte Mensual de Pedidos por Asesora - Contraentrega -->
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
<div class="card-header py-3 d-flex align-items-center justify-content-between">
|
||||||
|
<h6 class="m-0 font-weight-bold text-primary">Reporte Mensual de Pedidos por Asesora - Contraentrega (<?php echo $meses[$selected_month] . ' ' . $selected_year; ?>)</h6>
|
||||||
|
<button class="btn btn-sm btn-outline-primary"
|
||||||
|
type="button"
|
||||||
|
id="btnContraentregaMensualToggle"
|
||||||
|
data-bs-toggle="collapse"
|
||||||
|
data-bs-target="#contraentregaMensualCollapse"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-controls="contraentregaMensualCollapse">
|
||||||
|
Ver reporte
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="contraentregaMensualCollapse" class="card-body collapse">
|
||||||
|
<?php if (empty($asesoras_mensual_contraentrega)): ?>
|
||||||
|
<div class="alert alert-warning">No hay asesoras configuradas para mostrar en este reporte.</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered table-striped" width="100%" cellspacing="0" style="font-size: 0.8rem;">
|
||||||
|
<thead class="thead-dark">
|
||||||
|
<tr class="text-center">
|
||||||
|
<th style="width: 80px; vertical-align: middle;">Día</th>
|
||||||
|
<?php foreach ($asesoras_mensual_contraentrega as $asesora): ?>
|
||||||
|
<th><?php echo htmlspecialchars($asesora['nombre_asesor']); ?></th>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<th style="vertical-align: middle;">Total Día</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php
|
||||||
|
$dias_en_mes = cal_days_in_month(CAL_GREGORIAN, $selected_month, $selected_year);
|
||||||
|
$totales_por_asesora = array_fill_keys(array_column($asesoras_mensual_contraentrega, 'id'), 0);
|
||||||
|
$gran_total_mes = 0;
|
||||||
|
|
||||||
|
for ($dia = 1; $dia <= $dias_en_mes; $dia++):
|
||||||
|
$total_dia = 0;
|
||||||
|
?>
|
||||||
|
<tr class="text-center">
|
||||||
|
<td class="font-weight-bold"><?php echo str_pad($dia, 2, '0', STR_PAD_LEFT) . '/' . str_pad($selected_month, 2, '0', STR_PAD_LEFT); ?></td>
|
||||||
|
<?php foreach ($asesoras_mensual_contraentrega as $asesora):
|
||||||
|
$asesora_id = $asesora['id'];
|
||||||
|
$cantidad = $pedidos_mensual_contraentrega_asesora[$dia][$asesora_id] ?? 0;
|
||||||
|
$total_dia += $cantidad;
|
||||||
|
$totales_por_asesora[$asesora_id] += $cantidad;
|
||||||
|
echo '<td>' . ($cantidad > 0 ? $cantidad : '<span class="text-muted">-</span>') . '</td>';
|
||||||
|
endforeach; ?>
|
||||||
|
<td class="font-weight-bold"><?php echo $total_dia; ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php
|
||||||
|
$gran_total_mes += $total_dia;
|
||||||
|
endfor;
|
||||||
|
?>
|
||||||
|
</tbody>
|
||||||
|
<tfoot class="thead-dark">
|
||||||
|
<tr class="text-center">
|
||||||
|
<th>Total Mes</th>
|
||||||
|
<?php foreach ($asesoras_mensual_contraentrega as $asesora): ?>
|
||||||
|
<th class="text-center"><?php echo $totales_por_asesora[$asesora['id']]; ?></th>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<th class="text-center"><?php echo $gran_total_mes; ?></th>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- Resumen Contraentrega por Asesora (cuadro 2) -->
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
<div class="card-header py-3">
|
||||||
|
<h6 class="m-0 font-weight-bold text-warning">Resumen Contraentrega por Asesora (<?php echo $meses[$selected_month] . ' ' . $selected_year; ?>)</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<?php
|
||||||
|
$estados_contraentrega = ['RUTA_CONTRAENTREGA', 'RETORNADO', 'ENTREGA EXITOSA'];
|
||||||
|
$estado_display_map_contra = [
|
||||||
|
'RUTA_CONTRAENTREGA' => 'Ruta Contraentrega',
|
||||||
|
'RETORNADO' => 'Retornado',
|
||||||
|
'ENTREGA EXITOSA' => 'Entrega Exitosa'
|
||||||
|
];
|
||||||
|
?>
|
||||||
|
<table class="table table-bordered" id="dataTableContraentrega" width="100%" cellspacing="0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Asesora</th>
|
||||||
|
<?php foreach ($estados_contraentrega as $estado): ?>
|
||||||
|
<th><?php echo htmlspecialchars($estado_display_map_contra[$estado] ?? $estado); ?></th>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<th>Total</th>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php if (empty($asesor_data)): ?>
|
||||||
|
<tr><td colspan="<?php echo count($estados_contraentrega) + 2; ?>" class="text-center">No hay datos para el período seleccionado.</td></tr>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php
|
||||||
|
$totals_contraentrega = array_fill_keys($estados_contraentrega, 0);
|
||||||
|
$grand_total_contraentrega = 0;
|
||||||
|
|
||||||
|
foreach ($asesor_data as $data):
|
||||||
|
echo "<tr>";
|
||||||
|
echo "<td>" . htmlspecialchars($data['nombre']) . "</td>";
|
||||||
|
|
||||||
|
$total_contraentrega = 0;
|
||||||
|
foreach ($estados_contraentrega as $e) {
|
||||||
|
$total_contraentrega += $data['pedidos'][$e];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($estados_contraentrega as $estado):
|
||||||
|
$cantidad = (int)($data['pedidos'][$estado] ?? 0);
|
||||||
|
$totals_contraentrega[$estado] += $cantidad;
|
||||||
|
echo "<td>";
|
||||||
|
echo $cantidad;
|
||||||
|
|
||||||
|
if ($total_contraentrega > 0) {
|
||||||
|
$porcentaje = round(($cantidad / $total_contraentrega) * 100, 1);
|
||||||
|
echo " <span class=\"text-muted\">({" . $porcentaje . "}%)</span>";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "</td>";
|
||||||
|
endforeach;
|
||||||
|
|
||||||
|
echo "<td><strong>" . $total_contraentrega . "</strong></td>";
|
||||||
|
$grand_total_contraentrega += $total_contraentrega;
|
||||||
|
echo "</tr>";
|
||||||
|
endforeach;
|
||||||
|
?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
<?php if (!empty($asesor_data)): ?>
|
||||||
|
<tfoot>
|
||||||
|
<tr style="background-color: #f8f9fc; font-weight: bold;">
|
||||||
|
<td>Total Contraentrega</td>
|
||||||
|
<?php foreach ($totals_contraentrega as $total_estado): ?>
|
||||||
|
<td><?php echo $total_estado; ?></td>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<td><?php echo $grand_total_contraentrega; ?></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@ -682,4 +868,21 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
const collapseEl = document.getElementById('contraentregaMensualCollapse');
|
||||||
|
const btn = document.getElementById('btnContraentregaMensualToggle');
|
||||||
|
|
||||||
|
if (!collapseEl || !btn) return;
|
||||||
|
|
||||||
|
collapseEl.addEventListener('shown.bs.collapse', function () {
|
||||||
|
btn.textContent = 'Minimizar';
|
||||||
|
});
|
||||||
|
|
||||||
|
collapseEl.addEventListener('hidden.bs.collapse', function () {
|
||||||
|
btn.textContent = 'Ver reporte';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<?php include 'layout_footer.php'; ?>
|
<?php include 'layout_footer.php'; ?>
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
-- Add EMPAQUETADO as valid option to tipo_paquete ENUM in pedidos table
|
||||||
|
ALTER TABLE pedidos MODIFY COLUMN tipo_paquete ENUM('RUTA', 'CONTRAENTREGA', 'NO CONTESTA, VOLVER A LLAMAR', 'PENDIENTE A RETORNO', 'COMPLETADO', 'EMPAQUETADO', 'RETORNADO', 'ANULADO') DEFAULT NULL;
|
||||||
@ -297,12 +297,19 @@ try {
|
|||||||
'Codigo EAN',
|
'Codigo EAN',
|
||||||
'Cantidad',
|
'Cantidad',
|
||||||
'Precio',
|
'Precio',
|
||||||
'Total'
|
'Total',
|
||||||
|
'DE DEDICATORIA / OBS.'
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($pedidos as $pedido) {
|
foreach ($pedidos as $pedido) {
|
||||||
[$provincia, $distrito] = splitProvinciaDistrito($pedido['codigo_rastreo'] ?? '');
|
[$provincia, $distrito] = splitProvinciaDistrito($pedido['codigo_rastreo'] ?? '');
|
||||||
|
|
||||||
|
$nota_adicional = trim((string)($pedido['nota_adicional'] ?? ''));
|
||||||
|
if ($nota_adicional === '') {
|
||||||
|
$nota_adicional = trim((string)($pedido['descargo'] ?? ''));
|
||||||
|
}
|
||||||
|
$nota_adicional_display = $nota_adicional !== '' ? $nota_adicional : '';
|
||||||
|
|
||||||
$cantidad_total = parseTotalQuantity($pedido['cantidad'] ?? 0);
|
$cantidad_total = parseTotalQuantity($pedido['cantidad'] ?? 0);
|
||||||
$total = (float)($pedido['monto_total'] ?? 0);
|
$total = (float)($pedido['monto_total'] ?? 0);
|
||||||
$unit_price_rounded = $cantidad_total > 0 ? round($total / $cantidad_total, 2) : 0;
|
$unit_price_rounded = $cantidad_total > 0 ? round($total / $cantidad_total, 2) : 0;
|
||||||
@ -378,7 +385,8 @@ try {
|
|||||||
(string)$eanOut,
|
(string)$eanOut,
|
||||||
$cantidadOut,
|
$cantidadOut,
|
||||||
$precioOut,
|
$precioOut,
|
||||||
$total
|
$total,
|
||||||
|
$nota_adicional_display
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -248,7 +248,7 @@ include 'layout_header.php';
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 mb-3">
|
<div class="col-md-6 mb-3">
|
||||||
<label for="fecha_entrega" class="form-label">Fecha de Entrega</label>
|
<label for="fecha_entrega" class="form-label">Fecha de Entrega</label>
|
||||||
<input type="date" class="form-control" id="fecha_entrega" name="fecha_entrega" value="<?php echo htmlspecialchars($pedido['fecha_entrega'] ?? ''); ?>">
|
<input type="date" class="form-control" id="fecha_entrega" name="fecha_entrega" value="<?php echo htmlspecialchars($pedido['fecha_entrega'] ?? ''); ?>" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -320,7 +320,7 @@ include 'layout_header.php';
|
|||||||
<option value="">Seleccionar</option>
|
<option value="">Seleccionar</option>
|
||||||
<?php
|
<?php
|
||||||
$current_paquete = $pedido['tipo_paquete'] ?? '';
|
$current_paquete = $pedido['tipo_paquete'] ?? '';
|
||||||
$paquetes = ['RUTA', 'ANULADO', 'PENDIENTE A RETORNO', 'RETORNADO'];
|
$paquetes = ['RUTA', 'EMPAQUETADO', 'ANULADO', 'PENDIENTE A RETORNO', 'RETORNADO'];
|
||||||
foreach ($paquetes as $paquete) {
|
foreach ($paquetes as $paquete) {
|
||||||
$selected = ($current_paquete == $paquete) ? 'selected' : '';
|
$selected = ($current_paquete == $paquete) ? 'selected' : '';
|
||||||
echo "<option value='{$paquete}' {$selected}>" . htmlspecialchars($paquete) . "</option>";
|
echo "<option value='{$paquete}' {$selected}>" . htmlspecialchars($paquete) . "</option>";
|
||||||
|
|||||||
@ -64,6 +64,7 @@ function getPaqueteStyle($paquete) {
|
|||||||
if ($paquete === 'NO CONTESTA, VOLVER A LLAMAR') return 'background-color: #fd7e14; color: white;'; // Orange
|
if ($paquete === 'NO CONTESTA, VOLVER A LLAMAR') return 'background-color: #fd7e14; color: white;'; // Orange
|
||||||
if ($paquete === 'PENDIENTE A RETORNO') return 'background-color: #dc3545; color: white;'; // Red
|
if ($paquete === 'PENDIENTE A RETORNO') return 'background-color: #dc3545; color: white;'; // Red
|
||||||
if ($paquete === 'COMPLETADO') return 'background-color: #198754; color: white;'; // Success green
|
if ($paquete === 'COMPLETADO') return 'background-color: #198754; color: white;'; // Success green
|
||||||
|
if ($paquete === "EMPAQUETADO") return "background-color: #20c997; color: white;"; // Empaquetado
|
||||||
if ($paquete === 'RETORNADO') return 'background-color: #dc3545; color: white;'; // Same red as PENDIENTE A RETORNO
|
if ($paquete === 'RETORNADO') return 'background-color: #dc3545; color: white;'; // Same red as PENDIENTE A RETORNO
|
||||||
if ($paquete === 'ANULADO') return 'background-color: #212529; color: white;'; // Dark
|
if ($paquete === 'ANULADO') return 'background-color: #212529; color: white;'; // Dark
|
||||||
return 'background-color: #6c757d; color: white;'; // Secondary grey
|
return 'background-color: #6c757d; color: white;'; // Secondary grey
|
||||||
@ -505,6 +506,7 @@ function getPaqueteStyleJS(paquete) {
|
|||||||
if (paquete === 'PENDIENTE A RETORNO') return 'background-color: #dc3545; color: white;';
|
if (paquete === 'PENDIENTE A RETORNO') return 'background-color: #dc3545; color: white;';
|
||||||
if (paquete === 'RETORNADO') return 'background-color: #dc3545; color: white;';
|
if (paquete === 'RETORNADO') return 'background-color: #dc3545; color: white;';
|
||||||
if (paquete === 'COMPLETADO') return 'background-color: #198754; color: white;';
|
if (paquete === 'COMPLETADO') return 'background-color: #198754; color: white;';
|
||||||
|
if (paquete === "EMPAQUETADO") return "background-color: #20c997; color: white;";
|
||||||
return 'background-color: #6c757d; color: white;';
|
return 'background-color: #6c757d; color: white;';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,6 +582,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
{val: 'ANULADO', text: 'ANULADO'},
|
{val: 'ANULADO', text: 'ANULADO'},
|
||||||
{val: 'PENDIENTE A RETORNO', text: 'PENDIENTE A RETORNO'},
|
{val: 'PENDIENTE A RETORNO', text: 'PENDIENTE A RETORNO'},
|
||||||
{val: 'RETORNADO', text: 'RETORNADO'},
|
{val: 'RETORNADO', text: 'RETORNADO'},
|
||||||
|
{val: "EMPAQUETADO", text: "EMPAQUETADO"},
|
||||||
{val: 'COMPLETADO', text: 'COMPLETADO'}
|
{val: 'COMPLETADO', text: 'COMPLETADO'}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -69,7 +69,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$referencia_domicilio = trim($_POST['referencia_domicilio'] ?? '');
|
$referencia_domicilio = trim($_POST['referencia_domicilio'] ?? '');
|
||||||
$coordenadas = trim($_POST['coordenadas'] ?? '');
|
$coordenadas = trim($_POST['coordenadas'] ?? '');
|
||||||
$seguimiento = trim($_POST['seguimiento'] ?? '');
|
$seguimiento = trim($_POST['seguimiento'] ?? '');
|
||||||
$fecha_entrega = !empty($_POST['fecha_entrega']) ? trim($_POST['fecha_entrega']) : null;
|
$fecha_entrega_raw = trim((string)($_POST['fecha_entrega'] ?? ''));
|
||||||
|
$fecha_entrega = null;
|
||||||
|
if ($fecha_entrega_raw !== '' && $fecha_entrega_raw !== '0000-00-00') {
|
||||||
|
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $fecha_entrega_raw)) {
|
||||||
|
redirectPedidoContraentregaWithError('La Fecha de Entrega no tiene un formato válido (YYYY-MM-DD).', $id, $embed_mode);
|
||||||
|
}
|
||||||
|
$fecha_entrega = $fecha_entrega_raw;
|
||||||
|
}
|
||||||
|
|
||||||
// --- Manejo de multiples productos ---
|
// --- Manejo de multiples productos ---
|
||||||
$productos_post = $_POST['productos'] ?? [];
|
$productos_post = $_POST['productos'] ?? [];
|
||||||
@ -112,7 +119,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
if ($tipo_paquete === '') {
|
if ($tipo_paquete === '') {
|
||||||
$tipo_paquete = null;
|
$tipo_paquete = null;
|
||||||
}
|
}
|
||||||
$tipos_paquete_validos = ['RUTA', 'CONTRAENTREGA', 'NO CONTESTA, VOLVER A LLAMAR', 'PENDIENTE A RETORNO', 'COMPLETADO', 'RETORNADO', 'ANULADO'];
|
$tipos_paquete_validos = ['RUTA', 'CONTRAENTREGA', 'NO CONTESTA, VOLVER A LLAMAR', 'PENDIENTE A RETORNO', 'COMPLETADO', 'EMPAQUETADO', 'RETORNADO', 'ANULADO'];
|
||||||
if ($tipo_paquete !== null && !in_array($tipo_paquete, $tipos_paquete_validos, true)) {
|
if ($tipo_paquete !== null && !in_array($tipo_paquete, $tipos_paquete_validos, true)) {
|
||||||
redirectPedidoContraentregaWithError('El paquete seleccionado no es válido. Seleccione una opción de la lista.', $id, $embed_mode);
|
redirectPedidoContraentregaWithError('El paquete seleccionado no es válido. Seleccione una opción de la lista.', $id, $embed_mode);
|
||||||
}
|
}
|
||||||
@ -133,8 +140,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
redirectPedidoContraentregaWithError('Seleccione un distrito válido para la provincia elegida.', $id, $embed_mode);
|
redirectPedidoContraentregaWithError('Seleccione un distrito válido para la provincia elegida.', $id, $embed_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($nombre_completo) || empty($celular) || empty($sede_envio) || empty($provincia) || empty($distrito) || empty($producto) || $cantidad === false || $monto_total === false || empty($coordenadas)) {
|
if (empty($nombre_completo) || empty($celular) || empty($sede_envio) || empty($provincia) || empty($distrito) || empty($producto) || $cantidad === false || $monto_total === false || empty($fecha_entrega) || empty($coordenadas)) {
|
||||||
redirectPedidoContraentregaWithError('Por favor, complete todos los campos obligatorios: departamento, provincia, distrito y coordenadas.', $id, $embed_mode);
|
redirectPedidoContraentregaWithError('Por favor, complete todos los campos obligatorios: fecha de entrega, departamento, provincia, distrito y coordenadas.', $id, $embed_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
$coordenadasNormalizadas = normalizeContraentregaCoordinates($coordenadas);
|
$coordenadasNormalizadas = normalizeContraentregaCoordinates($coordenadas);
|
||||||
|
|||||||
@ -26,7 +26,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$stmt = $pdo->prepare("UPDATE pedidos SET tipo_paquete = NULL WHERE id = ?");
|
$stmt = $pdo->prepare("UPDATE pedidos SET tipo_paquete = NULL WHERE id = ?");
|
||||||
$result = $stmt->execute([$pedido_id]);
|
$result = $stmt->execute([$pedido_id]);
|
||||||
} else {
|
} else {
|
||||||
$valid_types = ['RUTA', 'ANULADO', 'PENDIENTE A RETORNO', 'RETORNADO', 'CONTRAENTREGA', 'NO CONTESTA, VOLVER A LLAMAR', 'COMPLETADO'];
|
$valid_types = ['RUTA', 'ANULADO', 'PENDIENTE A RETORNO', 'RETORNADO', 'CONTRAENTREGA', 'NO CONTESTA, VOLVER A LLAMAR', 'COMPLETADO', 'EMPAQUETADO'];
|
||||||
if (!in_array($tipo_paquete, $valid_types)) {
|
if (!in_array($tipo_paquete, $valid_types)) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Tipo inválido']);
|
echo json_encode(['success' => false, 'message' => 'Tipo inválido']);
|
||||||
exit;
|
exit;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user