feat: project scaffolding, database schema, config

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Gestoría LP
2026-03-01 23:25:55 +00:00
commit 10bc97e8b9
6 changed files with 166 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
# Uploaded files
uploads/*
!uploads/.htaccess
# IDE
.idea/
.vscode/
*.swp

14
.htaccess Normal file
View File

@@ -0,0 +1,14 @@
# Security headers
<IfModule mod_headers.c>
Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "SAMEORIGIN"
Header set X-XSS-Protection "1; mode=block"
</IfModule>
# Block access to sensitive directories
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^includes/ - [F,L]
RewriteRule ^sql/ - [F,L]
RewriteRule ^vendor/ - [F,L]
</IfModule>

28
includes/config.php Normal file
View File

@@ -0,0 +1,28 @@
<?php
// Database
define('DB_HOST', 'localhost');
define('DB_NAME', 'gestoria_lp');
define('DB_USER', 'root');
define('DB_PASS', '');
// SMTP (Hostinger)
define('SMTP_HOST', 'smtp.hostinger.com');
define('SMTP_PORT', 465);
define('SMTP_USER', 'contacto@gestorialp.com');
define('SMTP_PASS', '');
define('SMTP_FROM_NAME', 'Gestoría LP');
// WhatsApp
define('WHATSAPP_NUMBER', '521XXXXXXXXXX');
// Encryption key for client credentials (32 bytes for AES-256)
define('ENCRYPTION_KEY', 'CHANGE_THIS_TO_A_RANDOM_32_CHAR_KEY!');
// Upload settings
define('UPLOAD_DIR', __DIR__ . '/../uploads/');
define('MAX_FILE_SIZE', 5 * 1024 * 1024); // 5MB
define('ALLOWED_EXTENSIONS', ['pdf', 'jpg', 'jpeg', 'png', 'doc', 'docx']);
// Site
define('SITE_URL', 'https://gestorialp.com');
define('SITE_NAME', 'Gestoría LP');

15
includes/db.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
require_once __DIR__ . '/config.php';
function getDB(): PDO {
static $pdo = null;
if ($pdo === null) {
$dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8mb4';
$pdo = new PDO($dsn, DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
}
return $pdo;
}

94
sql/schema.sql Normal file
View File

@@ -0,0 +1,94 @@
CREATE DATABASE IF NOT EXISTS gestoria_lp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE gestoria_lp;
CREATE TABLE usuarios (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
email VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
CREATE TABLE clientes (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(150) NOT NULL,
telefono VARCHAR(20),
email VARCHAR(100),
direccion TEXT,
notas TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB;
CREATE TABLE credenciales (
id INT AUTO_INCREMENT PRIMARY KEY,
cliente_id INT NOT NULL,
portal VARCHAR(100) NOT NULL,
usuario VARCHAR(150) NOT NULL,
password_enc TEXT NOT NULL,
notas TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (cliente_id) REFERENCES clientes(id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE tramites (
id INT AUTO_INCREMENT PRIMARY KEY,
cliente_id INT NOT NULL,
tipo ENUM('visa','sentri','pasaporte','adelanto_cita','doble_nacionalidad') NOT NULL,
estado ENUM('nuevo','en_proceso','en_revision','completado','cancelado') DEFAULT 'nuevo',
fecha_solicitud DATE,
fecha_cita DATE,
fecha_resolucion DATE,
precio DECIMAL(10,2),
notas TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (cliente_id) REFERENCES clientes(id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE documentos (
id INT AUTO_INCREMENT PRIMARY KEY,
cliente_id INT NOT NULL,
tramite_id INT,
nombre VARCHAR(255) NOT NULL,
ruta_archivo VARCHAR(500) NOT NULL,
tipo VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (cliente_id) REFERENCES clientes(id) ON DELETE CASCADE,
FOREIGN KEY (tramite_id) REFERENCES tramites(id) ON DELETE SET NULL
) ENGINE=InnoDB;
CREATE TABLE solicitudes (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(150) NOT NULL,
telefono VARCHAR(20),
email VARCHAR(100),
servicio VARCHAR(50) NOT NULL,
datos_formulario JSON,
estado ENUM('nueva','contactada','convertida','descartada') DEFAULT 'nueva',
cliente_id INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (cliente_id) REFERENCES clientes(id) ON DELETE SET NULL
) ENGINE=InnoDB;
CREATE TABLE recordatorios (
id INT AUTO_INCREMENT PRIMARY KEY,
cliente_id INT,
tramite_id INT,
titulo VARCHAR(200) NOT NULL,
descripcion TEXT,
fecha DATE NOT NULL,
completado TINYINT(1) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (cliente_id) REFERENCES clientes(id) ON DELETE CASCADE,
FOREIGN KEY (tramite_id) REFERENCES tramites(id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE testimonios (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre_cliente VARCHAR(150) NOT NULL,
texto TEXT NOT NULL,
calificacion TINYINT CHECK (calificacion BETWEEN 1 AND 5),
activo TINYINT(1) DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

7
uploads/.htaccess Normal file
View File

@@ -0,0 +1,7 @@
# Deny all direct access to uploads
Order deny,allow
Deny from all
<FilesMatch "\.(?:pdf|jpe?g|png|doc|docx)$">
Allow from all
</FilesMatch>