Skip to main content

Overview

This guide covers common problems you may encounter when developing or deploying Pro Stock Tool, along with step-by-step solutions.

Database Connection Issues

Symptom: API returns 500 error with “Error de conexión a la base de datos”Possible Causes:
  • MySQL server is not running
  • Incorrect database credentials
  • Database does not exist
Solutions:
1

Verify MySQL is running

Windows (XAMPP)
# Check if MySQL service is running
# Open XAMPP Control Panel and start MySQL
Linux/Mac
sudo systemctl status mysql
# or
sudo service mysql status
2

Check database credentials

Edit database/conexion.php:
database/conexion.php
$host = "localhost";  // Usually localhost
$user = "root";       // Default XAMPP user
$pass = "";           // Default XAMPP password (empty)
$db = "prostocktool"; // Your database name
3

Create database if missing

CREATE DATABASE prostocktool CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
4

Verify connection

Create a test file:
test-connection.php
<?php
require 'database/conexion.php';
echo json_encode(['status' => 'connected', 'db' => $db]);
$conn->close();
?>
Visit: http://localhost/Pro-Stock-Tool/test-connection.php
Symptom: SQL error “Table ‘prostocktool.bodegas’ doesn’t exist”Solution: Run the database migration scripts to create required tables.
Create bodegas table
CREATE TABLE `bodegas` (
  `id` INT AUTO_INCREMENT PRIMARY KEY,
  `nombre` VARCHAR(100) NOT NULL UNIQUE,
  `descripcion` TEXT,
  `fecha_creacion` DATETIME DEFAULT CURRENT_TIMESTAMP,
  `fecha_actualizacion` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Create categorias table
CREATE TABLE `categorias` (
  `id` INT AUTO_INCREMENT PRIMARY KEY,
  `nombre` VARCHAR(50) NOT NULL UNIQUE,
  `descripcion` VARCHAR(200),
  `color` VARCHAR(7) DEFAULT '#2e6df6',
  `estado` ENUM('ACTIVO', 'INACTIVO') DEFAULT 'ACTIVO',
  `fecha_creacion` DATETIME DEFAULT CURRENT_TIMESTAMP,
  `fecha_actualizacion` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Create proveedores table
CREATE TABLE `proveedores` (
  `id` INT AUTO_INCREMENT PRIMARY KEY,
  `nombre` VARCHAR(100) NOT NULL,
  `contacto` VARCHAR(100),
  `telefono` VARCHAR(20),
  `email` VARCHAR(100),
  `direccion` TEXT,
  `fecha_creacion` DATETIME DEFAULT CURRENT_TIMESTAMP,
  `fecha_actualizacion` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Create usuarios table
CREATE TABLE `usuarios` (
  `id` INT AUTO_INCREMENT PRIMARY KEY,
  `email` VARCHAR(100) NOT NULL UNIQUE,
  `nombre` VARCHAR(100) NOT NULL,
  `identidad` VARCHAR(20) NOT NULL UNIQUE,
  `password` VARCHAR(255) NOT NULL,
  `creado_en` DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Symptom: Cannot delete record due to foreign key referencesExample Error: “No se puede eliminar. Tiene 5 producto(s) asociado(s)”This is expected behavior - the application prevents deletion of records that have related data.Solutions:
  1. Delete or reassign related records first
  2. If testing, use CASCADE delete (not recommended for production):
For testing only
ALTER TABLE productos 
DROP FOREIGN KEY fk_bodega,
ADD CONSTRAINT fk_bodega 
  FOREIGN KEY (bodega_id) 
  REFERENCES bodegas(id) 
  ON DELETE CASCADE;
Cascading deletes will permanently remove all related records. Only use in development.

CORS and API Issues

Symptom: Console shows “Access-Control-Allow-Origin” errorCause: Missing or incorrect CORS headers in PHP endpointsSolution: Verify all PHP files have proper CORS headers:
Required headers
<?php
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

// Handle preflight OPTIONS request
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}
?>
In production, replace * with your specific domain:
header('Access-Control-Allow-Origin: https://yourdomain.com');
Symptom: JavaScript console shows “Unexpected token < in JSON”Causes:
  • PHP syntax error
  • Incorrect file path
  • PHP not parsing (served as plain text)
Solutions:
1

Check PHP error logs

XAMPP logs location
# Windows
C:\xampp\apache\logs\error.log

# Linux/Mac
/opt/lampp/logs/error_log
2

Enable error display (development only)

Add to top of PHP file:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
3

Verify PHP is processing files

Create test file:
test.php
<?php
phpinfo();
?>
If you see PHP code instead of info page, PHP is not configured.
4

Check API URL path

Verify path in controller
const API_URL = 'http://localhost/Pro-Stock-Tool/database/bodega.php';
//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//                Must match your actual project location
Symptom: No data loads, no error messagesSolution: Add comprehensive error handling:
Proper error handling
async function cargarBodegas() {
    try {
        console.log('Fetching from:', API_URL); // Debug log
        
        const response = await fetch(API_URL, { cache: 'no-store' });
        
        console.log('Response status:', response.status); // Debug log
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        const data = await response.json();
        
        console.log('Received data:', data); // Debug log
        
        if (data.success) {
            bodegas = data.data;
            renderizarBodegas(bodegas);
        } else {
            mostrarAlerta('Error: ' + data.error, 'error');
        }
    } catch (error) {
        console.error('Fetch error:', error);
        mostrarAlerta('Error de conexión: ' + error.message, 'error');
    }
}

Frontend Issues

Issue: Form submits without validationCause: Missing preventDefault() or validation logicSolution:
Proper form handling
formBodega.addEventListener('submit', function(e) {
    e.preventDefault(); // CRITICAL - prevents default form submission
    
    // Get values
    const nombre = bodegaNombre.value.trim();
    const descripcion = bodegaDescripcion.value.trim();
    
    // Validate
    if (!nombre) {
        mostrarAlerta('El nombre es obligatorio', 'error');
        bodegaNombre.focus();
        return; // Stop execution
    }
    
    if (nombre.length > 100) {
        mostrarAlerta('El nombre no puede superar 100 caracteres', 'error');
        bodegaNombre.focus();
        return;
    }
    
    // If validation passes, submit
    const datos = { nombre, descripcion };
    
    if (bodegaEditando) {
        actualizarBodega(bodegaEditando.id, datos);
    } else {
        crearBodega(datos);
    }
});
Issue: Typing in search box doesn’t filter resultsSolutions:
Check event listener
const searchInput = document.getElementById('buscarBodega');

if (!searchInput) {
    console.error('Search input not found!');
    return;
}

searchInput.addEventListener('input', filtrarBodegas);
// Use 'input' event (fires on every keystroke)
// NOT 'change' (only fires on blur)
Verify filter logic
function filtrarBodegas() {
    const busqueda = searchInput.value.toLowerCase().trim();
    
    console.log('Searching for:', busqueda); // Debug
    
    if (busqueda === '') {
        renderizarBodegas(bodegas); // Show all
        return;
    }
    
    const filtradas = bodegas.filter(bodega => {
        return bodega.nombre.toLowerCase().includes(busqueda) ||
               (bodega.descripcion && bodega.descripcion.toLowerCase().includes(busqueda));
    });
    
    console.log('Found:', filtradas.length); // Debug
    renderizarBodegas(filtradas);
}
Issue: Click edit, modal opens but form is emptySolution:
Check data retrieval
function editarBodega(id) {
    console.log('Editing ID:', id);
    
    // Convert both to same type for comparison
    const bodega = bodegas.find(b => Number(b.id) === Number(id));
    
    if (!bodega) {
        console.error('Bodega not found with ID:', id);
        mostrarAlerta('No se encontró la bodega', 'error');
        return;
    }
    
    console.log('Found bodega:', bodega);
    
    bodegaEditando = bodega;
    modalTitle.textContent = 'Editar Bodega';
    
    // Populate form fields
    bodegaNombre.value = bodega.nombre || '';
    bodegaDescripcion.value = bodega.descripcion || '';
    
    modalOverlay.classList.add('active');
    bodegaNombre.focus();
}

Styling Issues

Symptoms:
  • Page shows unstyled HTML
  • Browser console shows 404 for CSS files
Solutions:
1

Check file path

For pages in view/ directory
<link rel="stylesheet" href="../styles/bodega.css">
<!--                         ^^ go up one directory -->
For pages in root directory
<link rel="stylesheet" href="styles/bodega.css">
<!--                         no ../ prefix -->
2

Verify file exists

ls -la styles/
# Should show bodega.css, header-footer.css, etc.
3

Check browser network tab

Open DevTools > Network tab
  • Look for CSS files in red (404 errors)
  • Click on failed request to see full path attempted
4

Clear browser cache

Ctrl+Shift+Delete (Windows/Linux)
Cmd+Shift+Delete (Mac)

Or hard refresh:
Ctrl+F5 (Windows/Linux)
Cmd+Shift+R (Mac)
Issue: Page doesn’t adapt to smaller screensSolution: Verify viewport meta tag:
Required in <head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Add media queries:
/* Mobile breakpoint */
@media (max-width: 768px) {
    .header-actions {
        flex-direction: column;
        gap: 10px;
    }
    
    .search-input {
        width: 100%;
    }
    
    .grid-bodegas {
        grid-template-columns: 1fr; /* Single column on mobile */
    }
}

Performance Issues

Causes:
  • Large number of database records
  • Unoptimized queries
  • Missing indexes
Solutions:
-- Index frequently searched columns
CREATE INDEX idx_nombre ON bodegas(nombre);
CREATE INDEX idx_estado ON categorias(estado);
Symptom: Browser tab slows down over timeCause: Event listeners not removedSolution:
Clean up when needed
// Store reference to listener
let searchHandler = null;

function initializeSearch() {
    // Remove old listener if exists
    if (searchHandler) {
        searchInput.removeEventListener('input', searchHandler);
    }
    
    // Create new listener
    searchHandler = () => filtrarBodegas();
    searchInput.addEventListener('input', searchHandler);
}

// For dynamically created elements, use event delegation
// (already implemented in Pro Stock Tool pattern)

Deployment Issues

Common causes:
1

Update database credentials

Production database/conexion.php
$host = "mysql.yourhost.com"; // Not localhost
$user = "prod_user";
$pass = "secure_password";
$db = "prod_prostocktool";
2

Fix absolute URLs

Change from localhost
// BEFORE
const API_URL = 'http://localhost/Pro-Stock-Tool/database/bodega.php';

// AFTER
const API_URL = '/database/bodega.php'; // Relative path
// or
const API_URL = 'https://yourdomain.com/api/bodega.php';
3

Check file permissions

# PHP files need execute permission
chmod 644 database/*.php
chmod 755 database/
4

Enable error logging

Don't display errors in production
<?php
error_reporting(E_ALL);
ini_set('display_errors', 0); // Don't show to users
ini_set('log_errors', 1);
ini_set('error_log', '/path/to/error.log');
Symptom: Spanish characters display as �� or strange symbolsSolution: Ensure UTF-8 everywhere:
ALTER DATABASE prostocktool 
CHARACTER SET utf8mb4 
COLLATE utf8mb4_unicode_ci;

ALTER TABLE bodegas 
CONVERT TO CHARACTER SET utf8mb4 
COLLATE utf8mb4_unicode_ci;

Debugging Tools

Browser DevTools

Console: View JavaScript errorsNetwork: Monitor API requestsElements: Inspect HTML/CSSShortcut: F12

PHP Error Logs

XAMPP Windows:
C:\xampp\apache\logs\error.log
XAMPP Linux/Mac:
/opt/lampp/logs/error_log

console.log() Debugging

console.log('Variable:', variable);
console.table(arrayOfObjects);
console.error('Error:', error);

Network Testing

Test API directly:
curl -X GET http://localhost/Pro-Stock-Tool/database/bodega.php
Or use Postman/Insomnia

Getting Help

When reporting issues, include:
  • Browser and version (Chrome 120, Firefox 115, etc.)
  • Operating system (Windows 11, macOS 14, Ubuntu 22.04)
  • PHP version (php -v)
  • MySQL version (mysql --version)
  • Error messages (exact text)
  • Steps to reproduce

Project Structure

Review the folder organization

Coding Standards

Check code conventions and patterns

Build docs developers (and LLMs) love