Autosave: 20260217-024246

This commit is contained in:
Flatlogic Bot 2026-02-17 02:42:46 +00:00
parent 05af420873
commit 520d1acb1b
3 changed files with 94 additions and 87 deletions

View File

@ -1,40 +1,33 @@
<?php <?php
// get_barcodes_by_product_and_sede.php
header('Content-Type: application/json');
require_once 'db/config.php'; require_once 'db/config.php';
$response = ['success' => false, 'barcodes' => []]; header('Content-Type: application/json');
if (isset($_GET['product_id']) && isset($_GET['sede_id'])) { $productId = isset($_GET['product_id']) ? (int)$_GET['product_id'] : 0;
$productId = (int)$_GET['product_id']; $sedeId = isset($_GET['sede_id']) ? (int)$_GET['sede_id'] : 0;
$sedeId = (int)$_GET['sede_id'];
try { if ($productId <= 0 || $sedeId <= 0) {
$db = db(); echo json_encode([]);
$stmt = $db->prepare(" exit;
SELECT codigo_unico, estado
FROM unidades_inventario
WHERE producto_id = :product_id AND sede_id = :sede_id AND estado != 'Vendido'
ORDER BY id DESC
");
$stmt->bindParam(':product_id', $productId, PDO::PARAM_INT);
$stmt->bindParam(':sede_id', $sedeId, PDO::PARAM_INT);
$stmt->execute();
// Usamos FETCH_ASSOC para obtener un array asociativo por cada fila
$barcodes = $stmt->fetchAll(PDO::FETCH_ASSOC);
$response['success'] = true;
$response['barcodes'] = $barcodes;
} catch (PDOException $e) {
// En un entorno de producción, registrarías este error en lugar de mostrarlo
$response['message'] = 'Error de base de datos: ' . $e->getMessage();
}
} else {
$response['message'] = 'ID de producto o sede no proporcionado.';
} }
echo json_encode($response); try {
?> $db = db();
$stmt = $db->prepare(
"SELECT codigo_unico, estado
FROM unidades_inventario
WHERE producto_id = :product_id AND sede_id = :sede_id"
);
$stmt->bindParam(':product_id', $productId, PDO::PARAM_INT);
$stmt->bindParam(':sede_id', $sedeId, PDO::PARAM_INT);
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($results);
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
}
?>

View File

@ -16,10 +16,12 @@ if ($selected_sede_id) {
// Se añade p.id para poder usarlo en el botón // Se añade p.id para poder usarlo en el botón
$stmt = $db->prepare(" $stmt = $db->prepare("
SELECT p.id, p.nombre, p.sku, ss.quantity SELECT p.id, p.nombre, p.sku, COUNT(ui.id) as quantity
FROM products p FROM products p
JOIN stock_sedes ss ON p.id = ss.product_id JOIN unidades_inventario ui ON p.id = ui.producto_id
WHERE ss.sede_id = ? AND ss.quantity > 0 WHERE ui.sede_id = ? AND ui.estado = 'En Almacén'
GROUP BY p.id, p.nombre, p.sku
HAVING quantity > 0
ORDER BY p.nombre ASC ORDER BY p.nombre ASC
"); ");
$stmt->execute([$selected_sede_id]); $stmt->execute([$selected_sede_id]);
@ -64,8 +66,7 @@ if ($selected_sede_id) {
<tr> <tr>
<th>Producto</th> <th>Producto</th>
<th>SKU</th> <th>SKU</th>
<th class="text-end">Cantidad en Stock</th> <th class="text-center">Cantidad en Stock</th>
<th class="text-center">Acciones</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -73,14 +74,14 @@ if ($selected_sede_id) {
<tr> <tr>
<td><?php echo htmlspecialchars($item['nombre']); ?></td> <td><?php echo htmlspecialchars($item['nombre']); ?></td>
<td><?php echo htmlspecialchars($item['sku']); ?></td> <td><?php echo htmlspecialchars($item['sku']); ?></td>
<td class="text-end"><?php echo htmlspecialchars($item['quantity']); ?></td>
<td class="text-center"> <td class="text-center">
<button class="btn btn-info btn-sm view-codes-btn" <?php if ($item['quantity'] > 0): ?>
data-product-id="<?php echo $item['id']; ?>" <a href="#" class="ver-codigos" data-product-id="<?php echo $item['id']; ?>" data-sede-id="<?php echo $selected_sede_id; ?>">
data-sede-id="<?php echo $selected_sede_id; ?>" <?php echo $item['quantity']; ?>
data-product-name="<?php echo htmlspecialchars($item['nombre']); ?>"> </a>
Ver Códigos <?php else: ?>
</button> 0
<?php endif; ?>
</td> </td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
@ -112,9 +113,7 @@ if ($selected_sede_id) {
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p><strong>Producto:</strong> <span id="modalProductName"></span></p> <p><strong>Producto:</strong> <span id="modalProductName"></span></p>
<ul id="codesList" class="list-group"> <div id="codesTableContainer"></div>
<!-- Los códigos se cargarán aquí dinámicamente -->
</ul>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
@ -123,28 +122,21 @@ if ($selected_sede_id) {
</div> </div>
</div> </div>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
console.log("El documento está listo y jQuery está funcionando."); $(".table").on('click', '.ver-codigos', function(e) {
e.preventDefault();
$('.view-codes-btn').on('click', function() {
console.log("Botón 'Ver Códigos' presionado.");
var productId = $(this).data('product-id'); var productId = $(this).data('product-id');
var sedeId = $(this).data('sede-id'); var sedeId = $(this).data('sede-id');
var productName = $(this).data('product-name'); var productName = $(this).closest('tr').find('td:first').text();
console.log("ID de Producto:", productId, "ID de Sede:", sedeId);
$('#modalProductName').text(productName); $('#modalProductName').text(productName);
$('#codesList').html('<li class="list-group-item">Cargando...</li>'); $('#codesTableContainer').html('<p>Cargando...</p>');
var myModal = new bootstrap.Modal(document.getElementById('codesModal')); var myModal = new bootstrap.Modal(document.getElementById('codesModal'));
myModal.show(); myModal.show();
console.log("Iniciando llamada AJAX a get_barcodes_by_product_and_sede.php");
$.ajax({ $.ajax({
url: 'get_barcodes_by_product_and_sede.php', url: 'get_barcodes_by_product_and_sede.php',
type: 'GET', type: 'GET',
@ -153,24 +145,29 @@ $(document).ready(function() {
product_id: productId, product_id: productId,
sede_id: sedeId sede_id: sedeId
}, },
success: function(response) { success: function(data) {
console.log("Respuesta AJAX exitosa:", response);
var codesListHtml = ''; function getBadgeClass(estado) {
if (response && response.success && response.barcodes && response.barcodes.length > 0) { if (estado === 'En Almacén') return 'bg-success';
response.barcodes.forEach(function(barcode) { if (estado === 'Vendido') return 'bg-danger';
codesListHtml += '<li class="list-group-item">' + barcode + '</li>'; if (estado === 'Generado') return 'bg-info';
return 'bg-secondary';
}
let tableHtml = '<table class="table table-bordered table-striped"><thead><tr><th>Código</th><th>Estado</th></tr></thead><tbody>';
if (data.length > 0) {
data.forEach(item => {
const badgeClass = getBadgeClass(item.estado);
tableHtml += '<tr><td>' + item.codigo_unico + '</td><td><span class="badge ' + badgeClass + '">' + item.estado + '</span></td></tr>';
}); });
} else { } else {
codesListHtml = '<li class="list-group-item">' + (response.message || 'No se encontraron códigos para este producto en esta sede.') + '</li>'; tableHtml += '<tr><td colspan="2" class="text-center">No se encontraron unidades.</td></tr>';
} }
$('#codesList').html(codesListHtml); tableHtml += '</tbody></table>';
$('#codesTableContainer').html(tableHtml);
}, },
error: function(jqXHR, textStatus, errorThrown) { error: function() {
console.error("Error en la llamada AJAX:"); $('#codesTableContainer').html('<p class="text-danger">Error al cargar los códigos.</p>');
console.error("Estado:", textStatus);
console.error("Error:", errorThrown);
console.error("Respuesta del servidor:", jqXHR.responseText);
$('#codesList').html('<li class="list-group-item text-danger">Error al cargar los códigos. Revise la consola para más detalles.</li>');
} }
}); });
}); });

View File

@ -21,7 +21,7 @@ try {
// 1. Datos para las tarjetas de resumen // 1. Datos para las tarjetas de resumen
$total_productos = $pdo->query("SELECT COUNT(*) FROM products")->fetchColumn(); $total_productos = $pdo->query("SELECT COUNT(*) FROM products")->fetchColumn();
$total_sedes = $pdo->query("SELECT COUNT(*) FROM sedes")->fetchColumn(); $total_sedes = $pdo->query("SELECT COUNT(*) FROM sedes")->fetchColumn();
$total_stock = $pdo->query("SELECT SUM(quantity) FROM stock_sedes")->fetchColumn(); $total_stock = $pdo->query("SELECT COUNT(*) FROM unidades_inventario WHERE estado = 'En Almacén'")->fetchColumn();
// 2. Datos para la tabla de inventario // 2. Datos para la tabla de inventario
$sedes_stmt = $pdo->query("SELECT id, nombre FROM sedes ORDER BY nombre"); $sedes_stmt = $pdo->query("SELECT id, nombre FROM sedes ORDER BY nombre");
@ -30,7 +30,7 @@ try {
$products_stmt = $pdo->query("SELECT id, nombre, sku FROM products ORDER BY nombre"); $products_stmt = $pdo->query("SELECT id, nombre, sku FROM products ORDER BY nombre");
$products = $products_stmt->fetchAll(PDO::FETCH_ASSOC); $products = $products_stmt->fetchAll(PDO::FETCH_ASSOC);
$stock_stmt = $pdo->query("SELECT product_id, sede_id, quantity FROM stock_sedes"); $stock_stmt = $pdo->query("SELECT producto_id, sede_id, COUNT(*) as quantity FROM unidades_inventario WHERE estado = 'En Almacén' GROUP BY producto_id, sede_id");
$stock_data = $stock_stmt->fetchAll(PDO::FETCH_ASSOC); $stock_data = $stock_stmt->fetchAll(PDO::FETCH_ASSOC);
$inventario = []; $inventario = [];
@ -44,9 +44,9 @@ try {
} }
foreach ($stock_data as $stock_item) { foreach ($stock_data as $stock_item) {
if (isset($inventario[$stock_item['product_id']])) { if (isset($inventario[$stock_item['producto_id']])) {
$inventario[$stock_item['product_id']]['sedes'][$stock_item['sede_id']] = $stock_item['quantity']; $inventario[$stock_item['producto_id']]['sedes'][$stock_item['sede_id']] = $stock_item['quantity'];
$inventario[$stock_item['product_id']]['total'] += $stock_item['quantity']; $inventario[$stock_item['producto_id']]['total'] += $stock_item['quantity'];
} }
} }
@ -192,13 +192,21 @@ try {
<?php if (empty($inventario)): ?> <?php if (empty($inventario)): ?>
<tr><td colspan="<?php echo count($sedes) + 3; ?>" class="text-center">No hay productos.</td></tr> <tr><td colspan="<?php echo count($sedes) + 3; ?>" class="text-center">No hay productos.</td></tr>
<?php else: ?> <?php else: ?>
<?php foreach ($inventario as $datos_producto): ?> <?php foreach ($inventario as $product_id => $datos_producto): ?>
<tr> <tr>
<td><?php echo htmlspecialchars($datos_producto['nombre']); ?></td> <td><?php echo htmlspecialchars($datos_producto['nombre']); ?></td>
<td><?php echo htmlspecialchars($datos_producto['sku']); ?></td> <td><?php echo htmlspecialchars($datos_producto['sku']); ?></td>
<td class="text-center fw-bold"><?php echo $datos_producto['total']; ?></td> <td class="text-center fw-bold"><?php echo $datos_producto['total']; ?></td>
<?php foreach ($datos_producto['sedes'] as $cantidad): ?> <?php foreach ($datos_producto['sedes'] as $sede_id => $cantidad): ?>
<td class="text-center"><?php echo $cantidad; ?></td> <td class="text-center">
<?php if ($cantidad > 0): ?>
<a href="#" class="ver-codigos" data-product-id="<?php echo $product_id; ?>" data-sede-id="<?php echo $sede_id; ?>">
<?php echo $cantidad; ?>
</a>
<?php else: ?>
0
<?php endif; ?>
</td>
<?php endforeach; ?> <?php endforeach; ?>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
@ -326,14 +334,23 @@ $(document).ready(function() {
product_id: productId, product_id: productId,
sede_id: sedeId sede_id: sedeId
}, },
success: function(response) { success: function(data) {
var tableHtml = '<table class="table table-bordered"><thead><tr><th>Código</th><th>Estado</th></tr></thead><tbody>';
if (response && response.success && response.barcodes && response.barcodes.length > 0) { function getBadgeClass(estado) {
response.barcodes.forEach(function(item) { if (estado === 'En Almacén') return 'bg-success';
tableHtml += '<tr><td>' + item.codigo_unico + '</td><td>' + item.estado + '</td></tr>'; if (estado === 'Vendido') return 'bg-danger';
if (estado === 'Generado') return 'bg-info';
return 'bg-secondary';
}
let tableHtml = '<table class="table table-bordered table-striped"><thead><tr><th>Código</th><th>Estado</th></tr></thead><tbody>';
if (data.length > 0) {
data.forEach(item => {
const badgeClass = getBadgeClass(item.estado);
tableHtml += '<tr><td>' + item.codigo_unico + '</td><td><span class="badge ' + badgeClass + '">' + item.estado + '</span></td></tr>';
}); });
} else { } else {
tableHtml += '<tr><td colspan="2">' + (response.message || 'No se encontraron códigos.') + '</td></tr>'; tableHtml += '<tr><td colspan="2" class="text-center">No se encontraron unidades.</td></tr>';
} }
tableHtml += '</tbody></table>'; tableHtml += '</tbody></table>';
$('#codesTableContainer').html(tableHtml); $('#codesTableContainer').html(tableHtml);