234 lines
13 KiB
PHP
234 lines
13 KiB
PHP
<?php
|
|
require_once 'db/config.php';
|
|
require_once 'layout_header.php';
|
|
|
|
$db = db();
|
|
|
|
// Fetch all products for the modal
|
|
$stmt_products = $db->query("SELECT id, nombre FROM products ORDER BY nombre ASC");
|
|
$products = $stmt_products->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// Fetch all draft entries with their real inventory progress
|
|
$stmt = $db->query("SELECT ib.*, u.nombre_asesor as registrador, v.nombre_asesor as verificador,
|
|
(SELECT SUM(quantity) FROM stock_movements WHERE borrador_id = ib.id AND type = 'entrada') as cantidad_en_sistema
|
|
FROM ingreso_borrador ib
|
|
LEFT JOIN users u ON ib.usuario_registro_id = u.id
|
|
LEFT JOIN users v ON ib.usuario_verifico_id = v.id
|
|
ORDER BY ib.fecha_registro DESC");
|
|
$ingresos = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
?>
|
|
|
|
<div class="container-fluid mt-4">
|
|
<div class="row mb-4">
|
|
<div class="col-md-12 d-flex justify-content-between align-items-center">
|
|
<h2><i class="fas fa-clipboard-check me-2"></i> Auditoría de Ingreso de Mercadería (Borrador)</h2>
|
|
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#nuevoIngresoModal">
|
|
<i class="fas fa-plus me-1"></i> Nuevo Registro de Carga
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card shadow-sm border-0">
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle" id="tablaIngresos">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>Fecha Registro</th>
|
|
<th>Producto</th>
|
|
<th>Cant. Esperada</th>
|
|
<th>Cant. Real (Visto Bueno)</th>
|
|
<th>Estado Físico</th>
|
|
<th>Progreso en Sistema</th>
|
|
<th>Acciones</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($ingresos as $ingreso): ?>
|
|
<?php
|
|
$statusClass = 'bg-warning text-dark';
|
|
$statusIcon = 'fa-clock';
|
|
if ($ingreso['estado'] == 'Conforme') {
|
|
$statusClass = 'bg-success text-white';
|
|
$statusIcon = 'fa-check-circle';
|
|
} elseif ($ingreso['estado'] == 'Discrepancia') {
|
|
$statusClass = 'bg-danger text-white';
|
|
$statusIcon = 'fa-exclamation-triangle';
|
|
}
|
|
|
|
// Calculate progress bar
|
|
$totalAprobado = $ingreso['cantidad_recibida'] ?? $ingreso['cantidad_esperada'];
|
|
$totalEnSistema = $ingreso['cantidad_en_sistema'] ?? 0;
|
|
$porcentaje = ($totalAprobado > 0) ? min(100, round(($totalEnSistema / $totalAprobado) * 100)) : 0;
|
|
$barColor = 'bg-info';
|
|
if ($porcentaje >= 100) $barColor = 'bg-success';
|
|
elseif ($porcentaje > 0) $barColor = 'bg-primary';
|
|
?>
|
|
<tr>
|
|
<td><?php echo date('d/m/Y H:i', strtotime($ingreso['fecha_registro'])); ?></td>
|
|
<td>
|
|
<strong><?php echo htmlspecialchars($ingreso['nombre_producto']); ?></strong>
|
|
<?php if ($ingreso['product_id']): ?>
|
|
<br><small class="text-muted">ID: <?php echo $ingreso['product_id']; ?></small>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><span class="badge bg-info text-dark fs-6"><?php echo $ingreso['cantidad_esperada']; ?></span></td>
|
|
<td>
|
|
<?php if ($ingreso['cantidad_recibida'] !== null): ?>
|
|
<span class="badge bg-secondary fs-6"><?php echo $ingreso['cantidad_recibida']; ?></span>
|
|
<?php else: ?>
|
|
<span class="text-muted">---</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<span class="badge <?php echo $statusClass; ?> px-3 py-2">
|
|
<i class="fas <?php echo $statusIcon; ?> me-1"></i> <?php echo $ingreso['estado']; ?>
|
|
</span>
|
|
</td>
|
|
<td style="min-width: 150px;">
|
|
<div class="d-flex align-items-center">
|
|
<div class="progress flex-grow-1 me-2" style="height: 10px;">
|
|
<div class="progress-bar <?php echo $barColor; ?> progress-bar-striped progress-bar-animated"
|
|
role="progressbar"
|
|
style="width: <?php echo $porcentaje; ?>%"
|
|
aria-valuenow="<?php echo $porcentaje; ?>"
|
|
aria-valuemin="0"
|
|
aria-valuemax="100"></div>
|
|
</div>
|
|
<small class="fw-bold"><?php echo $porcentaje; ?>%</small>
|
|
</div>
|
|
<small class="text-muted"><?php echo $totalEnSistema; ?> de <?php echo $totalAprobado; ?> en sistema</small>
|
|
</td>
|
|
<td>
|
|
<div class="btn-group">
|
|
<?php if ($ingreso['estado'] == 'Pendiente'): ?>
|
|
<button class="btn btn-sm btn-primary btn-verificar"
|
|
data-id="<?php echo $ingreso['id']; ?>"
|
|
data-producto="<?php echo htmlspecialchars($ingreso['nombre_producto']); ?>"
|
|
data-esperada="<?php echo $ingreso['cantidad_esperada']; ?>">
|
|
<i class="fas fa-user-check"></i> Visto Bueno
|
|
</button>
|
|
<?php elseif ($porcentaje < 100): ?>
|
|
<a href="registro_entrada.php?borrador_id=<?php echo $ingreso['id']; ?>" class="btn btn-sm btn-success">
|
|
<i class="fas fa-sign-in-alt"></i> Registrar Entrada
|
|
</a>
|
|
<?php else: ?>
|
|
<button class="btn btn-sm btn-outline-secondary" disabled>
|
|
<i class="fas fa-check-double"></i> Completado
|
|
</button>
|
|
<?php endif; ?>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Nuevo Ingreso -->
|
|
<div class="modal fade" id="nuevoIngresoModal" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content border-0 shadow">
|
|
<div class="modal-header bg-primary text-white">
|
|
<h5 class="modal-title"><i class="fas fa-truck-loading me-2"></i> Registrar Carga Esperada</h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<form action="save_ingreso_borrador.php" method="POST">
|
|
<input type="hidden" name="action" value="create">
|
|
<div class="modal-body">
|
|
<div class="mb-3">
|
|
<label class="form-label">Vincular a Producto del Sistema (Opcional)</label>
|
|
<select name="product_id" class="form-select select2-modal">
|
|
<option value="">-- Seleccionar Producto --</option>
|
|
<?php foreach ($products as $product): ?>
|
|
<option value="<?php echo $product['id']; ?>"><?php echo htmlspecialchars($product['nombre']); ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<div class="form-text">Si el producto ya existe, selecciónelo para habilitar el seguimiento.</div>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Nombre del Producto / Descripción (Si no está en la lista)</label>
|
|
<input type="text" name="nombre_producto" class="form-control" placeholder="Ej: Caja de Rosas Rojas x 100">
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Cantidad que el Proveedor indica (Esperada)</label>
|
|
<input type="number" name="cantidad_esperada" class="form-control" min="1" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Observaciones (Opcional)</label>
|
|
<textarea name="observaciones" class="form-control" rows="2"></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer bg-light">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
|
<button type="submit" class="btn btn-primary">Guardar Borrador</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Verificar -->
|
|
<div class="modal fade" id="verificarModal" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content border-0 shadow">
|
|
<div class="modal-header bg-info text-dark">
|
|
<h5 class="modal-title"><i class="fas fa-user-check me-2"></i> Verificación de Mercadería</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<form action="save_ingreso_borrador.php" method="POST">
|
|
<input type="hidden" name="action" value="verify">
|
|
<input type="hidden" name="id" id="verify_id">
|
|
<div class="modal-body">
|
|
<div class="alert alert-info">
|
|
<p class="mb-1"><strong>Producto:</strong> <span id="verify_producto"></span></p>
|
|
<p class="mb-0"><strong>Cantidad Esperada:</strong> <span id="verify_esperada"></span></p>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Cantidad Contabilizada Real</label>
|
|
<input type="number" name="cantidad_recibida" id="cantidad_recibida" class="form-control form-control-lg text-center" min="0" required>
|
|
<div class="form-text">Ingrese la cantidad exacta que ha contado físicamente.</div>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Notas de Verificación</label>
|
|
<textarea name="observaciones" class="form-control" rows="2" placeholder="Ej: Llegaron 2 dañadas, o todo conforme."></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer bg-light">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
|
|
<button type="submit" class="btn btn-success">Confirmar Visto Bueno</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
$(document).ready(function() {
|
|
$('#tablaIngresos').DataTable({
|
|
language: {
|
|
url: '//cdn.datatables.net/plug-ins/1.13.6/i18n/es-ES.json'
|
|
},
|
|
order: [[0, 'desc']]
|
|
});
|
|
|
|
$('.btn-verificar').on('click', function() {
|
|
const id = $(this).data('id');
|
|
const producto = $(this).data('producto');
|
|
const esperada = $(this).data('esperada');
|
|
|
|
$('#verify_id').val(id);
|
|
$('#verify_producto').text(producto);
|
|
$('#verify_esperada').text(esperada);
|
|
$('#cantidad_recibida').val('');
|
|
|
|
$('#verificarModal').modal('show');
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<?php require_once 'layout_footer.php'; ?>
|