Autosave: 20260203-060838
This commit is contained in:
parent
2caed5f3df
commit
96d2546dba
@ -25,18 +25,51 @@ try {
|
||||
$columns = [
|
||||
'bcp_yape', 'b_nacion', 'interbank', 'bbva', 'otros_ingresos',
|
||||
'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">
|
||||
<h2>Flujo de Caja</h2>
|
||||
<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">
|
||||
<table class="table table-bordered table-striped table-hover" style="width: 100%;">
|
||||
<thead class="thead-dark">
|
||||
<thead>
|
||||
<tr>
|
||||
<th rowspan="2" style="vertical-align: middle; text-align: center;">Fecha</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 inversionManual = getVal('total_inversion_publicitaria');
|
||||
const inversionAuto = getVal('tu1') + getVal('tu2') + getVal('tu3') + getVal('fl1') + getVal('fl2') + getVal('fl3');
|
||||
const totalInversion = inversionManual > 0 ? inversionManual : inversionAuto;
|
||||
|
||||
const totalInversion = getVal('tu1') + getVal('tu2') + getVal('tu3') + getVal('fl1') + getVal('fl2') + getVal('fl3');
|
||||
|
||||
const recaudoFinal = ingresos - totalInversion;
|
||||
|
||||
@ -107,6 +139,17 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
// Initial calculation for all rows
|
||||
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
|
||||
table.addEventListener('blur', function(e) {
|
||||
if (e.target.hasAttribute('contenteditable')) {
|
||||
@ -143,9 +186,17 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
updateTotals(row);
|
||||
}
|
||||
}, 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>
|
||||
|
||||
<?php
|
||||
require_once 'layout_footer.php';
|
||||
?>
|
||||
?>
|
||||
|
||||
@ -80,6 +80,37 @@ $navItems = [
|
||||
'text' => 'Gestionar Productos',
|
||||
'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' => [
|
||||
'icon' => 'fa-dollar-sign',
|
||||
'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