Autosave: 20260203-060838
This commit is contained in:
parent
2caed5f3df
commit
96d2546dba
@ -25,18 +25,51 @@ try {
|
|||||||
$columns = [
|
$columns = [
|
||||||
'bcp_yape', 'b_nacion', 'interbank', 'bbva', 'otros_ingresos',
|
'bcp_yape', 'b_nacion', 'interbank', 'bbva', 'otros_ingresos',
|
||||||
'tu1', 'tu2', 'tu3', 'fl1', 'fl2', 'fl3',
|
'tu1', 'tu2', 'tu3', 'fl1', 'fl2', 'fl3',
|
||||||
'rc_envio', 'rc_contraent', 'total_inversion_publicitaria'
|
'rc_envio', 'rc_contraent'
|
||||||
];
|
];
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.table thead th {
|
||||||
|
background-color: #e9ecef; /* Un gris claro y profesional */
|
||||||
|
color: #495057;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.table td[contenteditable="true"]:focus {
|
||||||
|
background-color: #fff3cd; /* Un amarillo suave para resaltar la celda activa */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<div class="container-fluid mt-4">
|
<div class="container-fluid mt-4">
|
||||||
<h2>Flujo de Caja</h2>
|
<h2>Flujo de Caja</h2>
|
||||||
<p>Registro y control de los movimientos de ingresos y gastos.</p>
|
<p>Registro y control de los movimientos de ingresos y gastos.</p>
|
||||||
|
|
||||||
|
<form method="GET" action="flujo_de_caja.php" class="form-inline mb-4">
|
||||||
|
<div class="form-group mr-2">
|
||||||
|
<label for="month" class="mr-2">Mes:</label>
|
||||||
|
<select name="month" id="month" class="form-control">
|
||||||
|
<?php for ($m = 1; $m <= 12; $m++): ?>
|
||||||
|
<option value="<?php echo str_pad($m, 2, '0', STR_PAD_LEFT); ?>" <?php echo $m == $month ? 'selected' : ''; ?>>
|
||||||
|
<?php echo DateTime::createFromFormat('!m', $m)->format('F'); ?>
|
||||||
|
</option>
|
||||||
|
<?php endfor; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group mr-2">
|
||||||
|
<label for="year" class="mr-2">Año:</label>
|
||||||
|
<select name="year" id="year" class="form-control">
|
||||||
|
<?php for ($y = date('Y'); $y >= date('Y') - 5; $y--): ?>
|
||||||
|
<option value="<?php echo $y; ?>" <?php echo $y == $year ? 'selected' : ''; ?>><?php echo $y; ?></option>
|
||||||
|
<?php endfor; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Filtrar</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-bordered table-striped table-hover" style="width: 100%;">
|
<table class="table table-bordered table-striped table-hover" style="width: 100%;">
|
||||||
<thead class="thead-dark">
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th rowspan="2" style="vertical-align: middle; text-align: center;">Fecha</th>
|
<th rowspan="2" style="vertical-align: middle; text-align: center;">Fecha</th>
|
||||||
<th colspan="5" style="text-align: center;">Ingresos</th>
|
<th colspan="5" style="text-align: center;">Ingresos</th>
|
||||||
@ -93,9 +126,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ingresos = getVal('bcp_yape') + getVal('b_nacion') + getVal('interbank') + getVal('bbva') + getVal('otros_ingresos') + getVal('rc_envio') + getVal('rc_contraent');
|
const ingresos = getVal('bcp_yape') + getVal('b_nacion') + getVal('interbank') + getVal('bbva') + getVal('otros_ingresos') + getVal('rc_envio') + getVal('rc_contraent');
|
||||||
const inversionManual = getVal('total_inversion_publicitaria');
|
|
||||||
const inversionAuto = getVal('tu1') + getVal('tu2') + getVal('tu3') + getVal('fl1') + getVal('fl2') + getVal('fl3');
|
const totalInversion = getVal('tu1') + getVal('tu2') + getVal('tu3') + getVal('fl1') + getVal('fl2') + getVal('fl3');
|
||||||
const totalInversion = inversionManual > 0 ? inversionManual : inversionAuto;
|
|
||||||
|
|
||||||
const recaudoFinal = ingresos - totalInversion;
|
const recaudoFinal = ingresos - totalInversion;
|
||||||
|
|
||||||
@ -107,6 +139,17 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
// Initial calculation for all rows
|
// Initial calculation for all rows
|
||||||
table.querySelectorAll('tbody tr').forEach(updateTotals);
|
table.querySelectorAll('tbody tr').forEach(updateTotals);
|
||||||
|
|
||||||
|
// Event listener for cell focus to select all content
|
||||||
|
table.addEventListener('focus', function(e) {
|
||||||
|
if (e.target.hasAttribute('contenteditable')) {
|
||||||
|
const range = document.createRange();
|
||||||
|
range.selectNodeContents(e.target);
|
||||||
|
const sel = window.getSelection();
|
||||||
|
sel.removeAllRanges();
|
||||||
|
sel.addRange(range);
|
||||||
|
}
|
||||||
|
}, true); // Use capturing for focus
|
||||||
|
|
||||||
// Event listener for cell edits
|
// Event listener for cell edits
|
||||||
table.addEventListener('blur', function(e) {
|
table.addEventListener('blur', function(e) {
|
||||||
if (e.target.hasAttribute('contenteditable')) {
|
if (e.target.hasAttribute('contenteditable')) {
|
||||||
@ -143,9 +186,17 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
updateTotals(row);
|
updateTotals(row);
|
||||||
}
|
}
|
||||||
}, true); // Use capturing to ensure blur event is handled properly
|
}, true); // Use capturing to ensure blur event is handled properly
|
||||||
|
|
||||||
|
// Event listener for Enter key to save and not expand
|
||||||
|
table.addEventListener('keydown', function(e) {
|
||||||
|
if (e.key === 'Enter' && e.target.hasAttribute('contenteditable')) {
|
||||||
|
e.preventDefault(); // Prevent new line
|
||||||
|
e.target.blur(); // Trigger blur to save
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
require_once 'layout_footer.php';
|
require_once 'layout_footer.php';
|
||||||
?>
|
?>
|
||||||
|
|||||||
@ -80,6 +80,37 @@ $navItems = [
|
|||||||
'text' => 'Gestionar Productos',
|
'text' => 'Gestionar Productos',
|
||||||
'roles' => ['Administrador', 'admin']
|
'roles' => ['Administrador', 'admin']
|
||||||
],
|
],
|
||||||
|
'panel_inventario' => [
|
||||||
|
'icon' => 'fa-warehouse',
|
||||||
|
'text' => 'Panel de Inventario',
|
||||||
|
'roles' => ['Administrador', 'admin', 'Control Logistico'],
|
||||||
|
'submenu' => [
|
||||||
|
'dashboard' => [
|
||||||
|
'url' => 'panel_inventario.php?seccion=dashboard',
|
||||||
|
'icon' => 'fa-tachometer-alt',
|
||||||
|
'text' => 'Dashboard',
|
||||||
|
'roles' => ['Administrador', 'admin', 'Control Logistico']
|
||||||
|
],
|
||||||
|
'entrada' => [
|
||||||
|
'url' => 'panel_inventario.php?seccion=entrada',
|
||||||
|
'icon' => 'fa-arrow-circle-down',
|
||||||
|
'text' => 'Registro de Entrada',
|
||||||
|
'roles' => ['Administrador', 'admin', 'Control Logistico']
|
||||||
|
],
|
||||||
|
'salida' => [
|
||||||
|
'url' => 'panel_inventario.php?seccion=salida',
|
||||||
|
'icon' => 'fa-arrow-circle-up',
|
||||||
|
'text' => 'Registro de Salida',
|
||||||
|
'roles' => ['Administrador', 'admin', 'Control Logistico']
|
||||||
|
],
|
||||||
|
'registro_producto' => [
|
||||||
|
'url' => 'panel_inventario.php?seccion=registro_producto',
|
||||||
|
'icon' => 'fa-plus-circle',
|
||||||
|
'text' => 'Registro de Producto',
|
||||||
|
'roles' => ['Administrador', 'admin', 'Control Logistico']
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
'finanzas_group' => [
|
'finanzas_group' => [
|
||||||
'icon' => 'fa-dollar-sign',
|
'icon' => 'fa-dollar-sign',
|
||||||
'text' => 'Finanzas',
|
'text' => 'Finanzas',
|
||||||
|
|||||||
180
panel_inventario.php
Normal file
180
panel_inventario.php
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
<?php
|
||||||
|
$pageTitle = "Panel de Inventario";
|
||||||
|
require_once 'layout_header.php';
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
// Determine the current section from the URL, default to 'dashboard'
|
||||||
|
$seccion = isset($_GET['seccion']) ? $_GET['seccion'] : 'dashboard';
|
||||||
|
|
||||||
|
$message = '';
|
||||||
|
$message_type = '';
|
||||||
|
|
||||||
|
// Handle product registration form submission
|
||||||
|
if ($seccion === 'registro_producto' && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['nombre_producto'])) {
|
||||||
|
$nombre_producto = trim($_POST['nombre_producto']);
|
||||||
|
|
||||||
|
if (!empty($nombre_producto)) {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
// Check if product already exists
|
||||||
|
$stmt = $pdo->prepare("SELECT COUNT(*) FROM products WHERE nombre = ?");
|
||||||
|
$stmt->execute([$nombre_producto]);
|
||||||
|
if ($stmt->fetchColumn() > 0) {
|
||||||
|
$message = "Error: El producto '{$nombre_producto}' ya existe.";
|
||||||
|
$message_type = "danger";
|
||||||
|
} else {
|
||||||
|
// Insert new product with default values
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO products (nombre, unidades_disponibles, cobertura, show_on_panel, order_position) VALUES (?, 0, '[]', 1, 0)");
|
||||||
|
if ($stmt->execute([$nombre_producto])) {
|
||||||
|
$message = "Producto '{$nombre_producto}' registrado con éxito.";
|
||||||
|
$message_type = "success";
|
||||||
|
} else {
|
||||||
|
$message = "Error al registrar el producto.";
|
||||||
|
$message_type = "danger";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message = "Error de base de datos: " . $e->getMessage();
|
||||||
|
$message_type = "danger";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$message = "El nombre del producto no puede estar vacío.";
|
||||||
|
$message_type = "warning";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Set the title based on the section
|
||||||
|
switch ($seccion) {
|
||||||
|
case 'entrada':
|
||||||
|
$pageTitle = "Registro de Entrada";
|
||||||
|
break;
|
||||||
|
case 'salida':
|
||||||
|
$pageTitle = "Registro de Salida";
|
||||||
|
break;
|
||||||
|
case 'registro_producto':
|
||||||
|
$pageTitle = "Registro de Nuevo Producto";
|
||||||
|
break;
|
||||||
|
case 'dashboard':
|
||||||
|
default:
|
||||||
|
$pageTitle = "Dashboard de Inventario";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="container mt-4">
|
||||||
|
<?php if ($message): ?>
|
||||||
|
<div class="alert alert-<?php echo $message_type; ?> alert-dismissible fade show" role="alert">
|
||||||
|
<?php echo htmlspecialchars($message); ?>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// Display content based on the selected section
|
||||||
|
if ($seccion === 'entrada'):
|
||||||
|
?>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5 class="card-title mb-0">Registro de Entrada de Inventario</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p>Esta sección está en construcción. Aquí podrás registrar la entrada de nuevo stock.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
elseif ($seccion === 'salida'):
|
||||||
|
?>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5 class="card-title mb-0">Registro de Salida de Inventario</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p>Esta sección está en construcción. Aquí podrás registrar la salida de stock por ventas u otros motivos.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
elseif ($seccion === 'registro_producto'):
|
||||||
|
?>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5 class="card-title mb-0">Registrar Nuevo Producto</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form method="POST" action="panel_inventario.php?seccion=registro_producto">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="nombre_producto" class="form-label">Nombre del Producto</label>
|
||||||
|
<input type="text" class="form-control" id="nombre_producto" name="nombre_producto" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Guardar Producto</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
else: // Default to dashboard
|
||||||
|
// Fetch product data from the database
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->query("SELECT nombre, unidades_disponibles, cobertura FROM products ORDER BY nombre ASC");
|
||||||
|
$products = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo "<div class='alert alert-danger'>Error al conectar con la base de datos: " . $e->getMessage() . "</div>";
|
||||||
|
$products = [];
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5 class="card-title mb-0">Stock de Productos por Ciudad</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Producto</th>
|
||||||
|
<th scope="col" class="text-center">Stock Total</th>
|
||||||
|
<th scope="col">Ciudades de Cobertura</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php if (empty($products)): ?>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3" class="text-center">No hay productos para mostrar.</td>
|
||||||
|
</tr>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php foreach ($products as $product): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo htmlspecialchars($product['nombre']); ?></td>
|
||||||
|
<td class="text-center"><?php echo htmlspecialchars($product['unidades_disponibles']); ?></td>
|
||||||
|
<td>
|
||||||
|
<?php
|
||||||
|
$cobertura_list = json_decode($product['cobertura'], true);
|
||||||
|
if (json_last_error() === JSON_ERROR_NONE && is_array($cobertura_list)) {
|
||||||
|
echo htmlspecialchars(implode(', ', $cobertura_list));
|
||||||
|
} else {
|
||||||
|
echo htmlspecialchars($product['cobertura']);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
endif;
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// We need to re-include the header to update the title dynamically
|
||||||
|
if (isset($pageTitle)) {
|
||||||
|
echo "<script>document.title = '" . htmlspecialchars($pageTitle) . "';</script>";
|
||||||
|
echo "<script>document.querySelector('.content h1').textContent = '" . htmlspecialchars($pageTitle) . "';</script>";
|
||||||
|
}
|
||||||
|
require_once 'layout_footer.php';
|
||||||
|
?>
|
||||||
Loading…
x
Reference in New Issue
Block a user