Autosave: 20260519-165135

This commit is contained in:
Flatlogic Bot 2026-05-19 16:51:35 +00:00
parent 26b4617b8a
commit 8d1b45365f
17 changed files with 245 additions and 84 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

View File

@ -49,6 +49,18 @@ if ($period === 'custom' && !empty($start_date) && !empty($end_date)) {
$date_condition = "MONTH(p.created_at) = MONTH(CURDATE()) AND YEAR(p.created_at) = YEAR(CURDATE())";
$label_period = "Este Mes";
break;
case 'last_month':
$date_condition = "MONTH(p.created_at) = MONTH(DATE_SUB(CURDATE(), INTERVAL 1 MONTH)) AND YEAR(p.created_at) = YEAR(DATE_SUB(CURDATE(), INTERVAL 1 MONTH))";
$label_period = "Mes Anterior";
break;
case '3_months':
$date_condition = "DATE(p.created_at) >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)";
$label_period = "Últimos 3 Meses";
break;
case '6_months':
$date_condition = "DATE(p.created_at) >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)";
$label_period = "Últimos 6 Meses";
break;
case 'year':
$date_condition = "DATE(p.created_at) >= DATE_SUB(CURDATE(), INTERVAL 1 YEAR)";
$label_period = "Último Año";
@ -105,14 +117,18 @@ if ($period === 'today' || $period === 'yesterday') {
$stmtEstados = $db->query("SELECT estado, COUNT(*) as total FROM pedidos p WHERE $date_condition GROUP BY estado");
$estadosData = $stmtEstados->fetchAll(PDO::FETCH_ASSOC);
// 7. Top Productos (Ajustado al periodo)
$stmtTopProd = $db->query("SELECT producto, SUM(cantidad) as ventas FROM pedidos p WHERE $date_condition AND estado != 'RETORNADO' GROUP BY producto ORDER BY ventas DESC LIMIT 5");
// 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");
$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 5");
$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");
$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");
$topProductosProv = $stmtTopProdProv->fetchAll(PDO::FETCH_ASSOC);
// 8. Ventas por Asesor (Ajustado al periodo)
$stmtAsesores = $db->query("SELECT u.nombre_asesor,
COUNT(p.id) as total_pedidos,
@ -159,8 +175,7 @@ $utilidadTotal = $stmtUtilidad->fetchColumn() ?: 0;
// 12. Datos Detallados por Canal (Provincia vs Contraentrega)
$stmtDetalleCanal = $db->query("SELECT
CASE
WHEN estado IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA') THEN 'Contraentrega'
WHEN estado = 'RETORNADO' AND agencia = 'CONTRAENTREGA' THEN 'Contraentrega'
WHEN estado IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA', 'RETORNADO') THEN 'Contraentrega'
ELSE 'Provincia'
END as canal,
estado,
@ -171,15 +186,15 @@ $stmtDetalleCanal = $db->query("SELECT
GROUP BY canal, estado");
$detalleCanalRaw = $stmtDetalleCanal->fetchAll(PDO::FETCH_ASSOC);
// 13. Top Productos Detallado (Para la tabla)
// 13. Top Productos Detallado (Para la tabla) - TOTAL
$stmtTopDetalle = $db->query("
SELECT p.producto, SUM(p.cantidad) as total_cantidad, SUM(p.monto_total) as monto_total, AVG(pr.costo) as costo_promedio
FROM pedidos p
LEFT JOIN products pr ON p.producto = pr.nombre
WHERE $date_condition AND p.estado != 'RETORNADO'
WHERE $date_condition AND p.estado NOT IN ('RETORNADO', 'GESTIONES')
GROUP BY p.producto
ORDER BY total_cantidad DESC
LIMIT 5
LIMIT 10
");
$topProductosDetalle = $stmtTopDetalle->fetchAll(PDO::FETCH_ASSOC);
@ -191,10 +206,22 @@ $stmtTopDetalleCE = $db->query("
WHERE $date_condition AND p.estado IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA')
GROUP BY p.producto
ORDER BY total_cantidad DESC
LIMIT 5
LIMIT 10
");
$topProductosDetalleCE = $stmtTopDetalleCE->fetchAll(PDO::FETCH_ASSOC);
// 13c. Top Productos Detallado Provincia
$stmtTopDetalleProv = $db->query("
SELECT p.producto, SUM(p.cantidad) as total_cantidad, SUM(p.monto_total) as monto_total, AVG(pr.costo) as costo_promedio
FROM pedidos p
LEFT JOIN products pr ON p.producto = pr.nombre
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);
// 14. Rendimiento de Productos en Contraentrega (Para Gráfica de Barras Apiladas)
$stmtProdRendimientoCE = $db->query("
SELECT
@ -205,7 +232,7 @@ $stmtProdRendimientoCE = $db->query("
COUNT(*) as total
FROM pedidos p
WHERE $date_condition
AND (estado IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA') OR (estado = 'RETORNADO' AND agencia = 'CONTRAENTREGA'))
AND estado IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA', 'RETORNADO')
GROUP BY producto
ORDER BY total DESC
LIMIT 10
@ -222,7 +249,7 @@ $stmtProdRendimientoProv = $db->query("
COUNT(*) as total
FROM pedidos p
WHERE $date_condition
AND NOT (estado IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA') OR (estado = 'RETORNADO' AND agencia = 'CONTRAENTREGA'))
AND estado NOT IN ('RUTA_CONTRAENTREGA', 'ENTREGA EXITOSA', 'RETORNADO')
GROUP BY producto
ORDER BY total DESC
LIMIT 10
@ -271,6 +298,9 @@ include 'layout_header.php';
<a href="?period=15" class="btn btn-outline-primary btn-sm <?php echo $period == '15' ? 'active' : ''; ?>">15 Días</a>
<a href="?period=30" class="btn btn-outline-primary btn-sm <?php echo $period == '30' ? 'active' : ''; ?>">30 Días</a>
<a href="?period=month" class="btn btn-outline-primary btn-sm <?php echo $period == 'month' ? 'active' : ''; ?>">Este Mes</a>
<a href="?period=last_month" class="btn btn-outline-primary btn-sm <?php echo $period == 'last_month' ? 'active' : ''; ?>">Mes Anterior</a>
<a href="?period=3_months" class="btn btn-outline-primary btn-sm <?php echo $period == '3_months' ? 'active' : ''; ?>">3 Meses</a>
<a href="?period=6_months" class="btn btn-outline-primary btn-sm <?php echo $period == '6_months' ? 'active' : ''; ?>">6 Meses</a>
<a href="?period=year" class="btn btn-outline-primary btn-sm <?php echo $period == 'year' ? 'active' : ''; ?>">1 Año</a>
</div>
</form>
@ -565,53 +595,86 @@ include 'layout_header.php';
</div>
<div class="row">
<!-- Top Productos -->
<div class="col-md-6 mb-4">
<div class="card shadow">
<!-- Top Productos Total -->
<div class="col-12 mb-4">
<div class="card shadow h-100">
<div class="card-header bg-white d-flex justify-content-between align-items-center">
<h5 class="mb-0">Top 5 Productos más Vendidos</h5>
<span class="badge bg-primary">Por Unidades</span>
<h5 class="mb-0 text-primary"><i class="fas fa-trophy me-2"></i> Top 10 Productos Más Vendidos (Total)</h5>
<span class="badge bg-primary">Rendimiento Global</span>
</div>
<div class="card-body">
<canvas id="productosChart" class="mb-4"></canvas>
<div class="row">
<div class="col-12 mb-4">
<canvas id="productosChart" style="height: 550px;"></canvas>
</div>
<div class="col-12">
<div class="table-responsive">
<table class="table table-hover table-sm align-middle">
<thead class="table-light">
<tr>
<th>Producto</th>
<th class="text-center">Cant.</th>
<th class="text-end">Monto Total</th>
</tr>
</thead>
<tbody>
<?php foreach ($topProductosDetalle as $prod): ?>
<tr>
<td class="fw-bold text-dark small" style="font-size: 0.85rem;"><?php echo htmlspecialchars(strlen($prod['producto']) > 35 ? substr($prod['producto'], 0, 35) . '...' : $prod['producto']); ?></td>
<td class="text-center">
<span class="badge bg-light text-primary border border-primary px-3">
<?php echo number_format($prod['total_cantidad']); ?>
</span>
</td>
<td class="text-end fw-bold text-success" style="font-size: 0.85rem;">
S/ <?php echo number_format($prod['monto_total'], 2); ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<!-- Top Productos Contraentrega -->
<div class="col-md-6 mb-4">
<div class="card shadow h-100 border-left-warning">
<div class="card-header bg-white d-flex justify-content-between align-items-center">
<h5 class="mb-0 text-warning">Top 10 Contraentrega</h5>
<span class="badge bg-warning text-dark">Motorizado</span>
</div>
<div class="card-body">
<canvas id="productosCEChart" class="mb-4" style="height: 450px;"></canvas>
<div class="table-responsive">
<table class="table table-hover align-middle">
<table class="table table-hover table-sm align-middle">
<thead class="table-light">
<tr>
<th>Producto</th>
<th class="text-center">Cant.</th>
<th class="text-end">Monto Total</th>
<th class="text-end">Rent. %</th>
<th class="text-end">Monto</th>
</tr>
</thead>
<tbody>
<?php foreach ($topProductosDetalle as $prod):
$costoTotal = $prod['costo_promedio'] * $prod['total_cantidad'];
$utilidad = $prod['monto_total'] - $costoTotal;
$rentabilidad = ($prod['monto_total'] > 0) ? ($utilidad / $prod['monto_total']) * 100 : 0;
$rentClass = $rentabilidad > 30 ? 'text-success' : ($rentabilidad > 15 ? 'text-warning' : 'text-danger');
?>
<?php foreach ($topProductosDetalleCE as $prod): ?>
<tr>
<td class="fw-bold text-dark small"><?php echo htmlspecialchars($prod['producto']); ?></td>
<td class="fw-bold text-dark small" style="font-size: 0.75rem;"><?php echo htmlspecialchars(strlen($prod['producto']) > 25 ? substr($prod['producto'], 0, 25) . '...' : $prod['producto']); ?></td>
<td class="text-center">
<span class="badge bg-light text-primary border border-primary px-2">
<span class="badge bg-light text-warning border border-warning">
<?php echo number_format($prod['total_cantidad']); ?>
</span>
</td>
<td class="text-end fw-bold text-success small">
<td class="text-end fw-bold text-success small" style="font-size: 0.75rem;">
S/ <?php echo number_format($prod['monto_total'], 2); ?>
</td>
<td class="text-end fw-bold <?php echo $rentClass; ?> small">
<?php echo number_format($rentabilidad, 1); ?>%
</td>
</tr>
<?php endforeach; ?>
<?php if (empty($topProductosDetalle)): ?>
<tr>
<td colspan="4" class="text-center text-muted py-3">No hay datos en este periodo</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
@ -619,53 +682,39 @@ include 'layout_header.php';
</div>
</div>
<!-- Top Productos Contraentrega -->
<!-- Top Productos Provincia -->
<div class="col-md-6 mb-4">
<div class="card shadow border-left-warning">
<div class="card shadow h-100 border-left-info">
<div class="card-header bg-white d-flex justify-content-between align-items-center">
<h5 class="mb-0 text-warning"><i class="fas fa-motorcycle me-2"></i> Top 5 Contraentrega</h5>
<span class="badge bg-warning text-dark">Solo Contraentrega</span>
<h5 class="mb-0 text-info">Top 10 Provincia</h5>
<span class="badge bg-info text-white">Agencias</span>
</div>
<div class="card-body">
<canvas id="productosCEChart" class="mb-4"></canvas>
<canvas id="productosProvChart" class="mb-4" style="height: 450px;"></canvas>
<div class="table-responsive">
<table class="table table-hover align-middle">
<table class="table table-hover table-sm align-middle">
<thead class="table-light">
<tr>
<th>Producto</th>
<th class="text-center">Cant.</th>
<th class="text-end">Monto Total</th>
<th class="text-end">Rent. %</th>
<th class="text-end">Monto</th>
</tr>
</thead>
<tbody>
<?php foreach ($topProductosDetalleCE as $prod):
$costoTotal = $prod['costo_promedio'] * $prod['total_cantidad'];
$utilidad = $prod['monto_total'] - $costoTotal;
$rentabilidad = ($prod['monto_total'] > 0) ? ($utilidad / $prod['monto_total']) * 100 : 0;
$rentClass = $rentabilidad > 30 ? 'text-success' : ($rentabilidad > 15 ? 'text-warning' : 'text-danger');
?>
<?php foreach ($topProductosDetalleProv as $prod): ?>
<tr>
<td class="fw-bold text-dark small"><?php echo htmlspecialchars($prod['producto']); ?></td>
<td class="fw-bold text-dark small" style="font-size: 0.75rem;"><?php echo htmlspecialchars(strlen($prod['producto']) > 25 ? substr($prod['producto'], 0, 25) . '...' : $prod['producto']); ?></td>
<td class="text-center">
<span class="badge bg-light text-warning border border-warning px-2">
<span class="badge bg-light text-info border border-info">
<?php echo number_format($prod['total_cantidad']); ?>
</span>
</td>
<td class="text-end fw-bold text-success small">
<td class="text-end fw-bold text-success small" style="font-size: 0.75rem;">
S/ <?php echo number_format($prod['monto_total'], 2); ?>
</td>
<td class="text-end fw-bold <?php echo $rentClass; ?> small">
<?php echo number_format($rentabilidad, 1); ?>%
</td>
</tr>
<?php endforeach; ?>
<?php if (empty($topProductosDetalleCE)): ?>
<tr>
<td colspan="4" class="text-center text-muted py-3">No hay datos en este periodo</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
@ -930,16 +979,47 @@ include 'layout_header.php';
new Chart(ctxProductos, {
type: 'bar',
data: {
labels: <?php echo json_encode(array_map(function($p) { return strlen($p['producto']) > 20 ? substr($p['producto'], 0, 20) . '...' : $p['producto']; }, $topProductos)); ?>,
labels: <?php echo json_encode(array_map(function($p) { return strlen($p['producto']) > 30 ? substr($p['producto'], 0, 30) . '...' : $p['producto']; }, $topProductos)); ?>,
datasets: [{
label: 'Unidades Vendidas',
label: 'Unidades',
data: <?php echo json_encode(array_column($topProductos, 'ventas')); ?>,
backgroundColor: '#0d6efd'
backgroundColor: '#0d6efd',
borderRadius: 5,
barPercentage: 0.7
}]
},
options: {
indexAxis: 'y',
responsive: true
indexAxis: 'x',
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
datalabels: {
anchor: 'end',
align: 'top',
color: '#000',
offset: 5,
font: { size: 13, weight: 'bold' }
}
},
scales: {
y: {
beginAtZero: true,
grid: {
drawBorder: false,
color: 'rgba(0,0,0,0.05)'
},
title: { display: true, text: 'Unidades Vendidas', font: { weight: 'bold' } }
},
x: {
grid: { display: false },
ticks: {
maxRotation: 45,
minRotation: 45,
font: { size: 11, weight: 'bold' }
}
}
}
}
});
@ -948,16 +1028,86 @@ include 'layout_header.php';
new Chart(ctxProductosCE, {
type: 'bar',
data: {
labels: <?php echo json_encode(array_map(function($p) { return strlen($p['producto']) > 20 ? substr($p['producto'], 0, 20) . '...' : $p['producto']; }, $topProductosCE)); ?>,
labels: <?php echo json_encode(array_map(function($p) { return strlen($p['producto']) > 15 ? substr($p['producto'], 0, 15) . '...' : $p['producto']; }, $topProductosCE)); ?>,
datasets: [{
label: 'Unidades Vendidas (CE)',
label: 'Unidades',
data: <?php echo json_encode(array_column($topProductosCE, 'ventas')); ?>,
backgroundColor: '#ffc107'
backgroundColor: '#ffc107',
borderRadius: 5,
barPercentage: 0.7
}]
},
options: {
indexAxis: 'y',
responsive: true
indexAxis: 'x',
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
datalabels: {
anchor: 'end',
align: 'top',
color: '#000',
font: { size: 11, weight: 'bold' }
}
},
scales: {
y: {
beginAtZero: true,
grid: { color: 'rgba(0,0,0,0.05)' }
},
x: {
grid: { display: false },
ticks: {
maxRotation: 45,
minRotation: 45,
font: { size: 10, weight: 'bold' }
}
}
}
}
});
// Gráfico de Productos Provincia
const ctxProductosProv = document.getElementById('productosProvChart').getContext('2d');
new Chart(ctxProductosProv, {
type: 'bar',
data: {
labels: <?php echo json_encode(array_map(function($p) { return strlen($p['producto']) > 15 ? substr($p['producto'], 0, 15) . '...' : $p['producto']; }, $topProductosProv)); ?>,
datasets: [{
label: 'Unidades',
data: <?php echo json_encode(array_column($topProductosProv, 'ventas')); ?>,
backgroundColor: '#0dcaf0',
borderRadius: 5,
barPercentage: 0.7
}]
},
options: {
indexAxis: 'x',
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
datalabels: {
anchor: 'end',
align: 'top',
color: '#000',
font: { size: 11, weight: 'bold' }
}
},
scales: {
y: {
beginAtZero: true,
grid: { color: 'rgba(0,0,0,0.05)' }
},
x: {
grid: { display: false },
ticks: {
maxRotation: 45,
minRotation: 45,
font: { size: 10, weight: 'bold' }
}
}
}
}
});

View File

@ -0,0 +1,3 @@
-- Add cp_t and cp_f columns to flujo_caja table
ALTER TABLE flujo_caja ADD COLUMN cp_t INT DEFAULT 0;
ALTER TABLE flujo_caja ADD COLUMN cp_f INT DEFAULT 0;

View File

@ -13,7 +13,7 @@ $end_date = "$year-$month-$days_in_month";
$db_columns = [
'bcp_yape', 'b_nacion', 'interbank', 'bbva', 'otros_ingresos',
'tu1', 'tu2', 'tu3', 'fl1', 'fl2', 'fl3',
'rc_contraent', 'sc', 'c_pedidos'
'rc_contraent', 'sc', 'cp_t', 'cp_f'
];
// Columns to display in the table body in order
@ -53,7 +53,8 @@ for ($day = 1; $day <= $days_in_month; $day++) {
// Calculate totals
$totals = array_fill_keys($display_columns, 0);
$totals['sc'] = 0;
$totals['c_pedidos'] = 0;
$totals['cp_t'] = 0;
$totals['cp_f'] = 0;
$totals['total_ingresos'] = 0;
$totals['total_inversion'] = 0;
$totals['recaudo_final'] = 0;
@ -69,7 +70,8 @@ foreach ($all_days_data as $date => &$day_data) {
$totals[$col] += (float)($day_data[$col] ?? 0);
}
$totals['sc'] += (float)($day_data['sc'] ?? 0);
$totals['c_pedidos'] += (int)($day_data['c_pedidos'] ?? 0);
$totals['cp_t'] += (int)($day_data['cp_t'] ?? 0);
$totals['cp_f'] += (int)($day_data['cp_f'] ?? 0);
$totals['total_ingresos'] += $ingresos_dia;
$totals['total_inversion'] += $inversion_dia;
$totals['recaudo_final'] += ($ingresos_dia - $inversion_dia);
@ -130,7 +132,7 @@ unset($day_data);
<thead>
<tr>
<th rowspan="2" style="vertical-align: middle; text-align: center;">Fecha</th>
<th rowspan="2" style="vertical-align: middle; text-align: center;">C.pedidos</th>
<th colspan="2" style="text-align: center;">C.pedidos</th>
<th colspan="5" style="text-align: center;">Ingresos</th>
<th colspan="6" style="text-align: center;">Inversion Publicitaria</th>
<th rowspan="2" style="vertical-align: middle; text-align: center;">RC ENVIO</th>
@ -141,6 +143,8 @@ unset($day_data);
<th rowspan="2" style="vertical-align: middle; text-align: center;">Sc</th>
</tr>
<tr>
<th>CP. T</th>
<th>CP. F</th>
<th>BCP/YAPE</th>
<th>B. NACION</th>
<th>INTERBANK</th>
@ -158,7 +162,8 @@ unset($day_data);
<?php foreach ($all_days_data as $date => $day_data): ?>
<tr data-date="<?php echo $date; ?>">
<td><?php echo $date; ?></td>
<td contenteditable="true" data-column="c_pedidos"><?php echo htmlspecialchars(number_format((int)($day_data['c_pedidos'] ?? 0), 0, '', '')); ?></td>
<td contenteditable="true" data-column="cp_t"><?php echo htmlspecialchars(number_format((int)($day_data['cp_t'] ?? 0), 0, '', '')); ?></td>
<td contenteditable="true" data-column="cp_f"><?php echo htmlspecialchars(number_format((int)($day_data['cp_f'] ?? 0), 0, '', '')); ?></td>
<?php foreach ($display_columns as $col): ?>
<?php if ($col === 'rc_envio'): ?>
<td data-column="rc_envio"><?php echo htmlspecialchars(number_format((float)($day_data[$col] ?? 0), 2, '.', '')); ?></td>
@ -176,7 +181,8 @@ unset($day_data);
<tfoot>
<tr>
<th>TOTAL</th>
<th data-total-column="c_pedidos"><?php echo number_format($totals['c_pedidos'], 0); ?></th>
<th data-total-column="cp_t"><?php echo number_format($totals['cp_t'], 0); ?></th>
<th data-total-column="cp_f"><?php echo number_format($totals['cp_f'], 0); ?></th>
<?php foreach ($display_columns as $col): ?>
<th data-total-column="<?php echo $col; ?>"><?php echo number_format($totals[$col], 2); ?></th>
<?php endforeach; ?>
@ -218,7 +224,8 @@ document.addEventListener('DOMContentLoaded', function() {
function updateGrandTotals() {
const grandTotals = {
<?php foreach ($display_columns as $col) echo "'$col': 0,"; ?>
'c_pedidos': 0,
'cp_t': 0,
'cp_f': 0,
'sc': 0,
'total-ingresos': 0,
'total-inversion': 0,
@ -229,7 +236,8 @@ document.addEventListener('DOMContentLoaded', function() {
<?php foreach ($display_columns as $col): ?>
grandTotals['<?php echo $col; ?>'] += parseFloat(row.querySelector(`[data-column="<?php echo $col; ?>"]`).textContent.replace(/,/g, '')) || 0;
<?php endforeach; ?>
grandTotals['c_pedidos'] += parseInt(row.querySelector(`[data-column="c_pedidos"]`).textContent.replace(/,/g, '')) || 0;
grandTotals['cp_t'] += parseInt(row.querySelector(`[data-column="cp_t"]`).textContent.replace(/,/g, '')) || 0;
grandTotals['cp_f'] += parseInt(row.querySelector(`[data-column="cp_f"]`).textContent.replace(/,/g, '')) || 0;
grandTotals['sc'] += parseFloat(row.querySelector(`[data-column="sc"]`).textContent.replace(/,/g, '')) || 0;
grandTotals['total-ingresos'] += parseFloat(row.querySelector('.total-ingresos').textContent.replace(/,/g, '')) || 0;
grandTotals['total-inversion'] += parseFloat(row.querySelector('.total-inversion').textContent.replace(/,/g, '')) || 0;
@ -239,7 +247,7 @@ document.addEventListener('DOMContentLoaded', function() {
for (const key in grandTotals) {
const th = table.querySelector(`tfoot [data-total-column="${key}"]`);
if (th) {
if (key === 'c_pedidos') {
if (key === 'cp_t' || key === 'cp_f') {
th.textContent = grandTotals[key];
} else {
th.textContent = grandTotals[key].toFixed(2);
@ -269,7 +277,7 @@ document.addEventListener('DOMContentLoaded', function() {
const column = cell.dataset.column;
let value;
if (column === 'c_pedidos') {
if (column === 'cp_t' || column === 'cp_f') {
value = parseInt(cell.textContent.replace(/,/g, ''));
} else {
value = parseFloat(cell.textContent.replace(/,/g, ''));
@ -279,7 +287,7 @@ document.addEventListener('DOMContentLoaded', function() {
value = 0;
}
if (column === 'c_pedidos') {
if (column === 'cp_t' || column === 'cp_f') {
cell.textContent = value;
} else {
cell.textContent = value.toFixed(2);

View File

@ -10,7 +10,7 @@ if ($data) {
// Column name validation to prevent SQL injection
$allowed_columns = [
'c_pedidos', 'bcp_yape', 'b_nacion', 'interbank', 'bbva', 'otros_ingresos',
'c_pedidos', 'cp_t', 'cp_f', 'bcp_yape', 'b_nacion', 'interbank', 'bbva', 'otros_ingresos',
'tu1', 'tu2', 'tu3', 'fl1', 'fl2', 'fl3',
'rc_contraent', 'sc', 'total_inversion_publicitaria'
];