Autosave: 20260523-020012
BIN
assets/uploads/vouchers/6a109ee11f3a8-681.png
Normal file
|
After Width: | Height: | Size: 414 KiB |
BIN
assets/uploads/vouchers/6a10b27643e04-Screenshot_360.png
Normal file
|
After Width: | Height: | Size: 233 KiB |
BIN
assets/uploads/vouchers/6a10bd6b64b32-Screenshot_361.png
Normal file
|
After Width: | Height: | Size: 296 KiB |
BIN
assets/uploads/vouchers/6a10c03da0bd2-Screenshot_362.png
Normal file
|
After Width: | Height: | Size: 301 KiB |
|
After Width: | Height: | Size: 172 KiB |
|
After Width: | Height: | Size: 183 KiB |
|
After Width: | Height: | Size: 192 KiB |
|
After Width: | Height: | Size: 170 KiB |
|
After Width: | Height: | Size: 215 KiB |
@ -184,14 +184,42 @@ $stmtRetorno = $db->query("SELECT (COUNT(CASE WHEN estado = 'RETORNADO' THEN 1 E
|
||||
FROM pedidos p WHERE $date_condition");
|
||||
$tasaRetorno = $stmtRetorno->fetchColumn() ?: 0;
|
||||
|
||||
// --- NUEVO: Obtener configuración de costos para utilidad neta ---
|
||||
$stmtConfig = $db->query("SELECT clave, valor FROM configuracion_costos");
|
||||
$configCosts = $stmtConfig->fetchAll(PDO::FETCH_KEY_PAIR);
|
||||
$costoEnvioAgencia = $configCosts['envio_agencia'] ?? 0;
|
||||
$costoEnvioCE = $configCosts['envio_contraentrega'] ?? 0;
|
||||
$comisionVentaFija = $configCosts['comision_venta'] ?? 0;
|
||||
$publicidadDiaria = $configCosts['publicidad_diaria'] ?? 0;
|
||||
|
||||
// 11. Utilidad Total Estimada (Ajustado al periodo)
|
||||
// Calculamos ingresos, costo de productos, comisiones y envíos diferenciados
|
||||
$stmtUtilidad = $db->query("
|
||||
SELECT SUM(p.monto_total - (COALESCE(pr.costo, 0) * p.cantidad)) as utilidad_total
|
||||
SELECT
|
||||
SUM(p.monto_total) as ingresos_brutos,
|
||||
SUM(COALESCE(pr.costo, 0) * p.cantidad) as costo_productos_total,
|
||||
SUM(CASE
|
||||
WHEN p.agencia IN ('SHALOM', 'OLVA') THEN $costoEnvioAgencia
|
||||
ELSE $costoEnvioCE
|
||||
END) as costo_envio_total,
|
||||
COUNT(p.id) * $comisionVentaFija as comision_total
|
||||
FROM pedidos p
|
||||
LEFT JOIN products pr ON p.producto = pr.nombre
|
||||
WHERE $date_condition AND p.estado != 'RETORNADO'
|
||||
");
|
||||
$utilidadTotal = $stmtUtilidad->fetchColumn() ?: 0;
|
||||
$resUtilidad = $stmtUtilidad->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// Calcular cuántos días hay en el periodo para restar la publicidad diaria
|
||||
$stmtDias = $db->query("SELECT COUNT(DISTINCT DATE(created_at)) FROM pedidos p WHERE $date_condition");
|
||||
$numDias = $stmtDias->fetchColumn() ?: 1;
|
||||
$gastoPublicidadTotal = $numDias * $publicidadDiaria;
|
||||
|
||||
$ingresosBrutos = $resUtilidad['ingresos_brutos'] ?: 0;
|
||||
$costoProductos = $resUtilidad['costo_productos_total'] ?: 0;
|
||||
$costoEnvioTotal = $resUtilidad['costo_envio_total'] ?: 0;
|
||||
$comisionTotal = $resUtilidad['comision_total'] ?: 0;
|
||||
|
||||
$utilidadTotal = $ingresosBrutos - $costoProductos - $costoEnvioTotal - $comisionTotal - $gastoPublicidadTotal;
|
||||
|
||||
// 12. Datos Detallados por Canal (Provincia vs Contraentrega)
|
||||
$stmtDetalleCanal = $db->query("SELECT
|
||||
@ -385,9 +413,34 @@ include 'layout_header.php';
|
||||
<div class="col-xl-3 col-md-6 mb-3">
|
||||
<div class="card bg-success text-white shadow h-100">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Utilidad Estimada</h6>
|
||||
<h3>S/ <?php echo number_format($utilidadTotal, 2); ?></h3>
|
||||
<p class="mb-0">Margen bruto del periodo</p>
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<h6 class="card-title mb-1">Utilidad Neta Estimada</h6>
|
||||
<h3 class="mb-0">S/ <?php echo number_format($utilidadTotal, 2); ?></h3>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<i class="fas fa-wallet fa-2x opacity-50"></i>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-2 bg-white opacity-25">
|
||||
<div class="small">
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>Costo Prod:</span>
|
||||
<span>- S/ <?php echo number_format($costoProductos, 2); ?></span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>Envío:</span>
|
||||
<span>- S/ <?php echo number_format($costoEnvioTotal, 2); ?></span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>Comisión:</span>
|
||||
<span>- S/ <?php echo number_format($comisionTotal, 2); ?></span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>Publicidad:</span>
|
||||
<span>- S/ <?php echo number_format($gastoPublicidadTotal, 2); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -62,7 +62,7 @@ $pedidos = $stmt->fetchAll();
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Rótulos del Día</title>
|
||||
<title>Imprimir Rótulos</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
|
||||
@ -346,21 +346,6 @@ include 'layout_header.php';
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label for="comision_vendedora" class="form-label">Comisión Vendedora (S/)</label>
|
||||
<input type="number" step="0.01" class="form-control" id="comision_vendedora" name="comision_vendedora" value="<?php echo htmlspecialchars($pedido['comision_vendedora'] ?? '0.00'); ?>">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label for="costo_envio_real" class="form-label">Costo Envío Real (S/)</label>
|
||||
<input type="number" step="0.01" class="form-control" id="costo_envio_real" name="costo_envio_real" value="<?php echo htmlspecialchars($pedido['costo_envio_real'] ?? '0.00'); ?>">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label for="gasto_publicidad_unitario" class="form-label">Gasto Publicidad Unit. (S/)</label>
|
||||
<input type="number" step="0.01" class="form-control" id="gasto_publicidad_unitario" name="gasto_publicidad_unitario" value="<?php echo htmlspecialchars($pedido['gasto_publicidad_unitario'] ?? '0.00'); ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="notas" class="form-label">Notas</label>
|
||||
<textarea class="form-control" id="notas" name="notas" rows="3"><?php echo htmlspecialchars($pedido['notas']); ?></textarea>
|
||||
|
||||
@ -136,7 +136,7 @@ include 'layout_header.php';
|
||||
<button type="submit" class="btn btn-info">Filtrar</button>
|
||||
<a href="pedidos.php" class="btn btn-secondary">Limpiar</a>
|
||||
<?php if ($user_role === 'Administrador' || $user_role === 'Logistica'): ?>
|
||||
<a href="imprimir_rotulos_grandes.php?<?php echo http_build_query(array_merge($_GET, ['today' => 1])); ?>" class="btn btn-dark" target="_blank">Generar Rótulos del Día</a>
|
||||
<a href="imprimir_rotulos_grandes.php?<?php echo http_build_query($_GET); ?>" class="btn btn-dark" target="_blank">Generar Todos los Rótulos</a>
|
||||
<a href="download_report.php" class="btn btn-success">Descargar Todos los Rotulados</a>
|
||||
<a href="download_shalom.php?type=terrestre" class="btn btn-primary">Descargar Shalom Terrestre</a>
|
||||
<a href="download_shalom.php?type=aereo" class="btn btn-warning" style="background-color: #fd7e14; border-color: #fd7e14; color: white;">Descargar Shalom Aéreo</a>
|
||||
|
||||
@ -187,6 +187,7 @@ include 'layout_header.php';
|
||||
<th>ID</th>
|
||||
<th>Seguimiento</th>
|
||||
<th>Paquete</th>
|
||||
<th>Estado</th>
|
||||
<th>Cliente</th>
|
||||
|
||||
<th>Celular</th>
|
||||
@ -201,7 +202,6 @@ include 'layout_header.php';
|
||||
<th>Monto Total</th>
|
||||
<th>Monto Debe</th>
|
||||
<?php endif; ?>
|
||||
<th>Estado</th>
|
||||
<th>Fecha de Entrega</th>
|
||||
<?php if ($user_role !== 'Asesor'): ?><th>Asesor</th><?php endif; ?>
|
||||
<th>Fecha Creación</th>
|
||||
@ -218,6 +218,11 @@ include 'layout_header.php';
|
||||
<?php echo htmlspecialchars(!empty($pedido['tipo_paquete']) ? $pedido['tipo_paquete'] : 'Seleccionar'); ?>
|
||||
</span>
|
||||
</td>
|
||||
<td class="editable-estado" data-id="<?php echo $pedido['id']; ?>" data-value="<?php echo htmlspecialchars($pedido['estado']); ?>" style="cursor: pointer;">
|
||||
<span class="badge" style="<?php echo getStatusStyle($pedido['estado']); ?>">
|
||||
<?php echo htmlspecialchars($pedido['estado']); ?>
|
||||
</span>
|
||||
</td>
|
||||
<td><?php echo htmlspecialchars($pedido['nombre_completo']); ?></td>
|
||||
|
||||
<td>
|
||||
@ -266,11 +271,6 @@ include 'layout_header.php';
|
||||
<td><?php echo htmlspecialchars($pedido['monto_total']); ?></td>
|
||||
<td><?php echo htmlspecialchars($pedido['monto_debe']); ?></td>
|
||||
<?php endif; ?>
|
||||
<td class="editable-estado" data-id="<?php echo $pedido['id']; ?>" data-value="<?php echo htmlspecialchars($pedido['estado']); ?>" style="cursor: pointer;">
|
||||
<span class="badge" style="<?php echo getStatusStyle($pedido['estado']); ?>">
|
||||
<?php echo htmlspecialchars($pedido['estado']); ?>
|
||||
</span>
|
||||
</td>
|
||||
<td><span class="badge" style="<?php echo getFechaEntregaStyle($pedido['fecha_entrega']); ?>"><?php echo htmlspecialchars(!empty($pedido['fecha_entrega']) && $pedido['fecha_entrega'] != '0000-00-00' ? date('d/m/Y', strtotime($pedido['fecha_entrega'])) : 'N/A'); ?></span></td>
|
||||
<?php if ($user_role !== 'Asesor'): ?><td><?php echo htmlspecialchars($pedido['asesor_nombre'] ?? 'N/A'); ?></td><?php endif; ?>
|
||||
<td><?php echo htmlspecialchars($pedido['created_at']); ?></td>
|
||||
|
||||
@ -85,9 +85,22 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$nota_adicional = trim($_POST['nota_adicional'] ?? '');
|
||||
$observacion = trim($_POST['observacion'] ?? '');
|
||||
$descargo = trim($_POST['descargo'] ?? '');
|
||||
$comision_vendedora = filter_var($_POST['comision_vendedora'] ?? 0, FILTER_VALIDATE_FLOAT) ?: 0;
|
||||
$costo_envio_real = filter_var($_POST['costo_envio_real'] ?? 0, FILTER_VALIDATE_FLOAT) ?: 0;
|
||||
$gasto_publicidad_unitario = filter_var($_POST['gasto_publicidad_unitario'] ?? 0, FILTER_VALIDATE_FLOAT) ?: 0;
|
||||
|
||||
// Obtener costos predeterminados de la configuración
|
||||
$stmt_config = $pdo->query("SELECT clave, valor FROM configuracion_costos");
|
||||
$config = $stmt_config->fetchAll(PDO::FETCH_KEY_PAIR);
|
||||
|
||||
// Solo asignamos valores de config si es un pedido nuevo y no vienen en el POST
|
||||
if (!$id) {
|
||||
$comision_vendedora = $config['comision_venta'] ?? 0;
|
||||
$costo_envio_real = ($agencia === 'SHALOM' || $agencia === 'OLVA') ? ($config['envio_agencia'] ?? 0) : ($config['envio_contraentrega'] ?? 0);
|
||||
$gasto_publicidad_unitario = 0; // Opcional: podrías calcular publicidad_diaria / pedidos_del_dia
|
||||
} else {
|
||||
// Si es edición, intentamos capturar del POST por si acaso, si no, se manejará en el SQL dinámico
|
||||
$comision_vendedora = isset($_POST['comision_vendedora']) ? filter_var($_POST['comision_vendedora'], FILTER_VALIDATE_FLOAT) : null;
|
||||
$costo_envio_real = isset($_POST['costo_envio_real']) ? filter_var($_POST['costo_envio_real'], FILTER_VALIDATE_FLOAT) : null;
|
||||
$gasto_publicidad_unitario = isset($_POST['gasto_publicidad_unitario']) ? filter_var($_POST['gasto_publicidad_unitario'], FILTER_VALIDATE_FLOAT) : null;
|
||||
}
|
||||
|
||||
if (!empty($productos_detalle)) {
|
||||
$notas .= "\n\n" . $notas_adicionales;
|
||||
@ -194,13 +207,26 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
"nota_adicional = :nota_adicional",
|
||||
"observacion = :observacion",
|
||||
"descargo = :descargo",
|
||||
"comision_vendedora = :comision_vendedora",
|
||||
"costo_envio_real = :costo_envio_real",
|
||||
"gasto_publicidad_unitario = :gasto_publicidad_unitario",
|
||||
"voucher_adelanto_path = :voucher_adelanto_path",
|
||||
"voucher_restante_path = :voucher_restante_path"
|
||||
];
|
||||
|
||||
if ($comision_vendedora !== null) {
|
||||
$sql_parts[] = "comision_vendedora = :comision_vendedora";
|
||||
} else {
|
||||
unset($params['comision_vendedora']);
|
||||
}
|
||||
if ($costo_envio_real !== null) {
|
||||
$sql_parts[] = "costo_envio_real = :costo_envio_real";
|
||||
} else {
|
||||
unset($params['costo_envio_real']);
|
||||
}
|
||||
if ($gasto_publicidad_unitario !== null) {
|
||||
$sql_parts[] = "gasto_publicidad_unitario = :gasto_publicidad_unitario";
|
||||
} else {
|
||||
unset($params['gasto_publicidad_unitario']);
|
||||
}
|
||||
|
||||
// Conditionally add fecha_completado
|
||||
$completed_states = ['Completado', 'COMPLETADO ✅'];
|
||||
if (in_array($estado, $completed_states)) {
|
||||
|
||||