186 lines
7.7 KiB
PHP
186 lines
7.7 KiB
PHP
<?php
|
|
date_default_timezone_set('America/Lima');
|
|
require_once 'includes/header.php';
|
|
require_once 'db/config.php'; // Conexión a la base de datos
|
|
|
|
// Obtener todas las ciudades para el filtro
|
|
try {
|
|
$stmt_ciudades = db()->query("SELECT id, nombre FROM ciudades ORDER BY nombre");
|
|
$ciudades = $stmt_ciudades->fetchAll(PDO::FETCH_ASSOC);
|
|
} catch (PDOException $e) {
|
|
die("Error al obtener las ciudades: " . $e->getMessage());
|
|
}
|
|
|
|
// Obtener todos los productos para el filtro
|
|
try {
|
|
$stmt_productos = db()->query("SELECT id, nombre FROM productos ORDER BY nombre");
|
|
$productos = $stmt_productos->fetchAll(PDO::FETCH_ASSOC);
|
|
} catch (PDOException $e) {
|
|
die("Error al obtener los productos: " . $e->getMessage());
|
|
}
|
|
|
|
// Filtrar por ciudad y/o producto si se han seleccionado
|
|
$ciudad_seleccionada_id = isset($_GET['ciudad_id']) ? (int)$_GET['ciudad_id'] : 0;
|
|
$producto_seleccionado_id = isset($_GET['producto_id']) ? (int)$_GET['producto_id'] : 0;
|
|
|
|
// Consulta para obtener el historial de movimientos
|
|
try {
|
|
$sql = "
|
|
SELECT
|
|
m.id,
|
|
p.nombre AS producto_nombre,
|
|
m.tipo AS tipo_movimiento,
|
|
m.cantidad,
|
|
COALESCE(c_origen.nombre, c_destino.nombre) AS ciudad_nombre,
|
|
u.nombre AS usuario_nombre,
|
|
m.fecha AS fecha_movimiento,
|
|
m.fecha_registro,
|
|
m.observacion
|
|
FROM
|
|
movimientos m
|
|
JOIN
|
|
productos p ON m.producto_id = p.id
|
|
LEFT JOIN
|
|
ciudades c_origen ON m.ciudad_origen_id = c_origen.id
|
|
LEFT JOIN
|
|
ciudades c_destino ON m.ciudad_destino_id = c_destino.id
|
|
JOIN
|
|
usuarios u ON m.usuario_id = u.id
|
|
";
|
|
|
|
$conditions = [];
|
|
$params = [];
|
|
|
|
if ($ciudad_seleccionada_id > 0) {
|
|
$conditions[] = "(c_origen.id = :ciudad_id OR c_destino.id = :ciudad_id)";
|
|
$params[':ciudad_id'] = $ciudad_seleccionada_id;
|
|
}
|
|
|
|
if ($producto_seleccionado_id > 0) {
|
|
$conditions[] = "m.producto_id = :producto_id";
|
|
$params[':producto_id'] = $producto_seleccionado_id;
|
|
}
|
|
|
|
if (!empty($conditions)) {
|
|
$sql .= " WHERE " . implode(" AND ", $conditions);
|
|
}
|
|
|
|
$sql .= " ORDER BY m.fecha_registro DESC";
|
|
|
|
$stmt = db()->prepare($sql);
|
|
$stmt->execute($params);
|
|
$movimientos = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} catch (PDOException $e) {
|
|
// En caso de un error de base de datos, muestra un mensaje en lugar de una página en blanco
|
|
die("Error al obtener el historial de movimientos: " . $e->getMessage());
|
|
}
|
|
?>
|
|
|
|
<div class="container mt-5">
|
|
<h2>Historial de Movimientos de Stock</h2>
|
|
<hr>
|
|
|
|
<!-- Filtros -->
|
|
<form action="historial.php" method="get" class="mb-4">
|
|
<div class="form-row align-items-end">
|
|
<div class="col-md-4">
|
|
<label for="ciudad_id">Filtrar por Ciudad:</label>
|
|
<select name="ciudad_id" id="ciudad_id" class="form-control">
|
|
<option value="0">Todas las ciudades</option>
|
|
<?php foreach ($ciudades as $ciudad): ?>
|
|
<option value="<?php echo $ciudad['id']; ?>" <?php echo ($ciudad_seleccionada_id == $ciudad['id']) ? 'selected' : ''; ?>>
|
|
<?php echo htmlspecialchars($ciudad['nombre']); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label for="producto_id">Filtrar por Producto:</label>
|
|
<select name="producto_id" id="producto_id" class="form-control">
|
|
<option value="0">Todos los productos</option>
|
|
<?php foreach ($productos as $producto): ?>
|
|
<option value="<?php echo $producto['id']; ?>" <?php echo ($producto_seleccionado_id == $producto['id']) ? 'selected' : ''; ?>>
|
|
<?php echo htmlspecialchars($producto['nombre']); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<button type="submit" class="btn btn-primary mt-4">Filtrar</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-bordered table-hover">
|
|
<thead class="thead-dark">
|
|
<tr>
|
|
<th>Producto</th>
|
|
<th>Tipo</th>
|
|
<th>Cantidad</th>
|
|
<th>Ciudad</th>
|
|
<th>Usuario</th>
|
|
<th>Fecha Movimiento</th>
|
|
<th>Fecha Registro</th>
|
|
<th>Observación</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (!empty($movimientos)): ?>
|
|
<?php foreach ($movimientos as $movimiento): ?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars($movimiento['producto_nombre']); ?></td>
|
|
<td>
|
|
<?php
|
|
$tipo = $movimiento['tipo_movimiento'];
|
|
$clase_color = '';
|
|
if ($tipo == 'Entrada') {
|
|
$clase_color = 'bg-success';
|
|
} elseif ($tipo == 'Salida') {
|
|
$clase_color = 'bg-danger';
|
|
} else {
|
|
$clase_color = 'bg-secondary';
|
|
}
|
|
echo '<span class="badge ' . $clase_color . '">' . htmlspecialchars($tipo) . '</span>';
|
|
?>
|
|
</td>
|
|
<td><?php echo htmlspecialchars($movimiento['cantidad']); ?></td>
|
|
<td><?php echo htmlspecialchars($movimiento['ciudad_nombre']); ?></td>
|
|
<td><?php echo htmlspecialchars($movimiento['usuario_nombre']); ?></td>
|
|
<td>
|
|
<?php
|
|
try {
|
|
$fecha = new DateTime($movimiento['fecha_movimiento']);
|
|
echo htmlspecialchars($fecha->format('d/m/Y'));
|
|
} catch (Exception $e) {
|
|
echo htmlspecialchars($movimiento['fecha_movimiento']);
|
|
}
|
|
?>
|
|
</td>
|
|
<td>
|
|
<?php
|
|
try {
|
|
$fecha = new DateTime($movimiento['fecha_registro'], new DateTimeZone('UTC'));
|
|
$fecha->setTimezone(new DateTimeZone('America/Lima'));
|
|
echo htmlspecialchars($fecha->format('d/m/Y H:i'));
|
|
} catch (Exception $e) {
|
|
echo htmlspecialchars($movimiento['fecha_registro']);
|
|
}
|
|
?>
|
|
</td>
|
|
<td><?php echo htmlspecialchars($movimiento['observacion']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php else: ?>
|
|
<tr>
|
|
<td colspan="8" class="text-center">No hay movimientos registrados para los filtros seleccionados.</td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<?php
|
|
require_once 'includes/footer.php';
|
|
?>
|