Skip to main content

Installation Guide

This guide provides comprehensive instructions for installing Pro Stock Tool in both development and production environments.

System Requirements

Minimum Requirements

  • PHP: 7.4 or higher
  • MySQL: 5.7 or higher (or MariaDB 10.2+)
  • Web Server: Apache 2.4+ or Nginx 1.18+
  • RAM: 512 MB minimum (1 GB recommended)
  • Disk Space: 100 MB for application files
  • Browser: Modern browser with JavaScript enabled

Required PHP Extensions

php -m | grep -E "mysqli|json|mbstring"
Required extensions:
  • mysqli - MySQL database connectivity
  • json - JSON encoding/decoding
  • mbstring - Multibyte string handling
Ensure all required PHP extensions are enabled before proceeding with installation.

Installation Methods

Development Environment Setup

1

Install XAMPP/WAMP/MAMP (Optional)

For an all-in-one solution, install a pre-packaged stack:XAMPP (Windows/Mac/Linux):
# Download from https://www.apachefriends.org/
# Install and start Apache and MySQL services
Or install components separately:
# Ubuntu/Debian
sudo apt update
sudo apt install php php-mysqli mysql-server apache2

# macOS (using Homebrew)
brew install php mysql

# Windows
# Download PHP from https://windows.php.net/
# Download MySQL from https://dev.mysql.com/downloads/
2

Clone the Project

# Clone to your web server directory
cd /var/www/html  # or C:\xampp\htdocs on Windows
git clone <repository-url> Pro-Stock-Tool
cd Pro-Stock-Tool
Or download the ZIP and extract:
unzip Pro-Stock-Tool.zip -d /var/www/html/
cd /var/www/html/Pro-Stock-Tool
3

Set File Permissions

# Linux/macOS
chmod -R 755 .
chown -R www-data:www-data .

# Ensure PHP can read all files
find . -type f -exec chmod 644 {} \;
find . -type d -exec chmod 755 {} \;
4

Create Database

Access MySQL:
mysql -u root -p
Create the database:
CREATE DATABASE prostocktool CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
5

Import Database Schema

Create the complete database schema:
USE prostocktool;

-- Warehouses 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,
  INDEX idx_nombre (nombre)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Categories 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 VARCHAR(20) DEFAULT 'ACTIVO',
  fecha_creacion DATETIME DEFAULT CURRENT_TIMESTAMP,
  fecha_actualizacion DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  INDEX idx_nombre (nombre),
  INDEX idx_estado (estado)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Subcategories table
CREATE TABLE subcategorias (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nombre VARCHAR(50) NOT NULL,
  descripcion VARCHAR(200),
  categoria_id INT NOT NULL,
  fecha_creacion DATETIME DEFAULT CURRENT_TIMESTAMP,
  fecha_actualizacion DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (categoria_id) REFERENCES categorias(id) ON DELETE CASCADE,
  INDEX idx_categoria (categoria_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Parameters table (for product states/attributes)
CREATE TABLE parametros (
  id INT AUTO_INCREMENT PRIMARY KEY,
  codigo VARCHAR(10) NOT NULL UNIQUE,
  nombre VARCHAR(50) NOT NULL UNIQUE,
  descripcion TEXT,
  color VARCHAR(7) DEFAULT '#4a90e2',
  fecha_creacion DATETIME DEFAULT CURRENT_TIMESTAMP,
  fecha_actualizacion DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  INDEX idx_codigo (codigo)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Suppliers table
CREATE TABLE proveedores (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nif VARCHAR(20),
  nombre VARCHAR(100) NOT NULL,
  contacto VARCHAR(100),
  email VARCHAR(100),
  telefono VARCHAR(20),
  direccion TEXT,
  ciudad VARCHAR(100),
  web VARCHAR(200),
  terminos INT COMMENT 'Payment terms in days',
  parametro_id INT,
  fecha_creacion DATETIME DEFAULT CURRENT_TIMESTAMP,
  fecha_actualizacion DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (parametro_id) REFERENCES parametros(id) ON DELETE SET NULL,
  INDEX idx_nombre (nombre),
  INDEX idx_email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Users 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 COMMENT 'National ID or similar',
  password VARCHAR(255) NOT NULL COMMENT 'Bcrypt hashed password',
  creado_en DATETIME DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_email (email),
  INDEX idx_identidad (identidad)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Products table
CREATE TABLE productos (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nombre VARCHAR(100) NOT NULL,
  descripcion TEXT,
  codigo_barras VARCHAR(50),
  bodega_id INT,
  categoria_id INT,
  subcategoria_id INT,
  proveedor_id INT,
  parametro_id INT COMMENT 'Current state/status',
  cantidad_actual DECIMAL(10,2) DEFAULT 0,
  cantidad_minima DECIMAL(10,2) DEFAULT 0,
  cantidad_maxima DECIMAL(10,2) DEFAULT 0,
  precio_compra DECIMAL(10,2),
  precio_venta DECIMAL(10,2),
  fecha_vencimiento DATE,
  fecha_creacion DATETIME DEFAULT CURRENT_TIMESTAMP,
  fecha_actualizacion DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (bodega_id) REFERENCES bodegas(id) ON DELETE SET NULL,
  FOREIGN KEY (categoria_id) REFERENCES categorias(id) ON DELETE SET NULL,
  FOREIGN KEY (subcategoria_id) REFERENCES subcategorias(id) ON DELETE SET NULL,
  FOREIGN KEY (proveedor_id) REFERENCES proveedores(id) ON DELETE SET NULL,
  FOREIGN KEY (parametro_id) REFERENCES parametros(id) ON DELETE SET NULL,
  INDEX idx_nombre (nombre),
  INDEX idx_codigo_barras (codigo_barras),
  INDEX idx_bodega (bodega_id),
  INDEX idx_categoria (categoria_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
The schema uses InnoDB for transaction support and includes indexes for improved query performance.
6

Configure Database Connection

Edit database/conexion.php:
database/conexion.php
<?php

$host = "localhost";
$user = "root";
$pass = "";
$db = "prostocktool";

$conn = new mysqli($host, $user, $pass, $db);
if ($conn->connect_errno) {
    http_response_code(500);
    echo json_encode(["error" => "Error de conexión a la base de datos"]);
    exit;
}
?>
7

Start Development Server

# Using PHP built-in server
php -S localhost:8000

# Or start Apache/Nginx if already installed
sudo service apache2 start
sudo service mysql start
Access at: http://localhost:8000/login.html

Post-Installation Configuration

Update API URLs

Update API endpoints in JavaScript controller files to match your installation:
controllers/bodega.js
// Update this URL to match your installation
const API_URL = 'http://your-domain.com/database/bodega.php';
// Or for relative paths:
const API_URL = '/database/bodega.php';
Files to update:
  • controllers/bodega.js
  • controllers/categorias.js
  • controllers/proveedores.js
  • controllers/parametros.js
  • controllers/registro.js

Enable Error Logging

Create a custom error handler:
database/error_handler.php
<?php
// Log errors to file
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/../logs/php_errors.log');

// Don't display errors to users (production)
ini_set('display_errors', 0);

// Error handler function
function customErrorHandler($errno, $errstr, $errfile, $errline) {
    $log = sprintf(
        "[%s] Error %d: %s in %s on line %d\n",
        date('Y-m-d H:i:s'),
        $errno,
        $errstr,
        $errfile,
        $errline
    );
    error_log($log, 3, __DIR__ . '/../logs/app_errors.log');
    return true;
}

set_error_handler('customErrorHandler');
?>
Include in conexion.php:
require_once 'error_handler.php';

Create .htaccess for Security

Add .htaccess in the root directory:
.htaccess
# Prevent directory listing
Options -Indexes

# Protect sensitive files
<FilesMatch "\.(env|ini|log|sh|sql)$">
    Order allow,deny
    Deny from all
</FilesMatch>

# Enable CORS (if needed)
<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
    Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
    Header set Access-Control-Allow-Headers "Content-Type"
</IfModule>

# Enable compression
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/css text/javascript application/javascript application/json
</IfModule>

# Set caching for static assets
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType image/jpg "access plus 1 year"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
</IfModule>

Verification

Test Database Connection

Create a test file test_connection.php:
test_connection.php
<?php
require 'database/conexion.php';

if ($conn->ping()) {
    echo "Database connection successful!\n";
    echo "MySQL server version: " . $conn->server_info . "\n";
    
    // Test query
    $result = $conn->query("SELECT COUNT(*) as count FROM bodegas");
    $row = $result->fetch_assoc();
    echo "Warehouses in database: " . $row['count'] . "\n";
} else {
    echo "Database connection failed!\n";
}

$conn->close();
?>
Run it:
php test_connection.php
Delete test_connection.php after testing to avoid exposing database information.

Test API Endpoints

# Test warehouse endpoint
curl http://localhost/Pro-Stock-Tool/database/bodega.php

# Expected output:
# {"success":true,"data":[]}

Access the Application

Navigate to:
  • Development: http://localhost:8000/login.html
  • Production: https://your-domain.com/login.html

Troubleshooting

Causes:
  1. PHP syntax errors
  2. Database connection failure
  3. Missing file permissions
Solutions:
# Check Apache error log
sudo tail -f /var/log/apache2/error.log

# Check PHP error log
sudo tail -f /var/log/php_errors.log

# Verify file permissions
ls -la database/

# Test PHP syntax
php -l database/conexion.php
Solutions:
# Check if MySQL is running
sudo systemctl status mysql

# Start MySQL if stopped
sudo systemctl start mysql

# Test connection manually
mysql -u prostockuser -p prostocktool

# Check MySQL error log
sudo tail -f /var/log/mysql/error.log
For Apache, ensure headers module is enabled:
sudo a2enmod headers
sudo systemctl restart apache2
For Nginx, add to server block:
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type";
Check:
  1. Content-Type header is set: Content-Type: application/json
  2. No PHP warnings/notices before JSON output
  3. UTF-8 encoding is correct
Solution:
// At the top of each API file, before any output:
header('Content-Type: application/json; charset=utf-8');
Check PHP configuration:
php -i | grep upload_max_filesize
php -i | grep post_max_size
Update in php.ini:
upload_max_filesize = 20M
post_max_size = 20M
Restart web server:
sudo systemctl restart apache2

Security Best Practices

Database Security

  • Use dedicated database users with minimal privileges
  • Never use root in production
  • Enable SSL for database connections
  • Regular backups with encryption

Application Security

  • Keep PHP and MySQL updated
  • Disable PHP error display in production
  • Use HTTPS for all connections
  • Implement rate limiting on API endpoints

File Security

  • Set restrictive file permissions (644 for files, 755 for directories)
  • Protect database/conexion.php (chmod 600)
  • Use .htaccess to deny access to sensitive files
  • Keep configuration files outside web root when possible

Password Security

  • Enforce strong password policies
  • Passwords are hashed with bcrypt
  • Never log or display passwords
  • Implement password reset functionality securely

Backup and Maintenance

Database Backup

# Backup database
mysqldump -u prostockuser -p prostocktool > backup_$(date +%Y%m%d).sql

# Backup with compression
mysqldump -u prostockuser -p prostocktool | gzip > backup_$(date +%Y%m%d).sql.gz

# Restore from backup
mysql -u prostockuser -p prostocktool < backup_20260303.sql

Automated Backup Script

backup.sh
#!/bin/bash
BACKUP_DIR="/var/backups/prostocktool"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR

# Backup database
mysqldump -u prostockuser -pYourPassword prostocktool | gzip > $BACKUP_DIR/db_$DATE.sql.gz

# Backup files
tar -czf $BACKUP_DIR/files_$DATE.tar.gz /var/www/html/prostocktool

# Keep only last 7 days
find $BACKUP_DIR -type f -mtime +7 -delete

echo "Backup completed: $DATE"
Schedule with cron:
crontab -e
# Add: Daily backup at 2 AM
0 2 * * * /usr/local/bin/backup.sh

Next Steps

Configuration

Configure advanced settings and customize the application

API Reference

Explore the complete API documentation

Features

Learn about all available features

Server Setup

Configure your web server and deploy to production

Build docs developers (and LLMs) love