diff --git a/backend/README.md b/backend/README.md index 8f412266..6c6554af 100644 --- a/backend/README.md +++ b/backend/README.md @@ -1,443 +1,30 @@ -# Four Points - Backend - -> API del Sistema de Gestión Hotelera (Express + MySQL) - ---- - -## Índice - -1. [Arquitectura](#1-arquitectura) -2. [Estructura del Proyecto](#2-estructura-del-proyecto) -3. [Tech Stack](#3-tech-stack) -4. [API Endpoints](#4-api-endpoints) -5. [Middlewares](#5-middlewares) -6. [Base de Datos](#6-base-de-datos) -7. [Configuración y Deployment](#7-configuración-y-deployment) -8. [Scripts y Comandos](#8-scripts-y-comandos) -9. [Completar en Más Detalle](#9-completar-en-más-detalle) - ---- - -## 1. Arquitectura - -``` -┌─────────────────────────────────────────────────────────────────────────────────┐ -│ ARQUITECTURA FOUR POINTS │ -├─────────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────────────────────┐ │ -│ │ FRONTEND (Next.js 16) │ │ -│ │ │ │ -│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │ │ -│ │ │ Dashboard │ │ Componentes │ │ Lib/ │ │ Stores │ │ │ -│ │ │ (pages) │ │ (React UI) │ │ Hooks │ │ (Zustand)│ │ │ -│ │ └─────────────┘ └─────────────┘ └─────────────┘ └───────────┘ │ │ -│ │ │ │ │ │ │ │ -│ │ └──────────────────┼──────────────────┼──────────────────┘ │ │ -│ │ │ │ │ │ -│ │ ┌────────▼────────┐ ┌────▼────────┐ │ │ -│ │ │ React Query │ │ API Client │ │ │ -│ │ │ (Server State) │ │ (auto-refresh) │ │ -│ │ └─────────────────┘ └─────────────┘ │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ │ HTTPS + Credentials │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────────────┐ │ -│ │ BACKEND (Express 5) │ │ -│ │ │ │ -│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ -│ │ │ Routes │ → │ Controllers │ → │ Repositories│ │ │ -│ │ │ (Express) │ │ (Lógica) │ │ (MySQL) │ │ │ -│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ -│ │ │ │ │ │ │ -│ │ ▼ ▼ ▼ │ │ -│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ -│ │ │ Middlewares │ │ Services │ │ Models │ │ │ -│ │ │ (auth, etc) │ │ (cron, etc) │ │ (Zod/TS) │ │ │ -│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ │ TCP/IP │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────────────┐ │ -│ │ BASE DE DATOS │ │ -│ │ │ │ -│ │ ┌─────────────────┐ ┌─────────────────────────────┐ │ │ -│ │ │ MySQL Local │ │ MySQL Aiven (Cloud) │ │ │ -│ │ │ (development) │ │ (production) │ │ │ -│ │ └─────────────────┘ └─────────────────────────────┘ │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────────────────────┘ -``` - -### Flujo de Datos - -``` -1. Usuario abre navegador → Next.js (Vercel) -2. Login → JWT tokens en HttpOnly cookies -3. Petición API → Express (Render) con credentials: 'include' -4. Express valida JWT → Ejecuta controller → Repository → MySQL -5. Respuesta → Cliente (React Query cache) -``` - ---- - -## 2. Estructura del Proyecto - -``` -backend/ -├── config/ -│ ├── config.ts # Variables de entorno -│ ├── db.ts # Conexión MySQL -│ ├── date-utils.ts # Utilidades de fecha -│ ├── error-codes.ts # Códigos de error -│ └── certs/ # Certificados SSL -├── controllers/ # Lógica de negocio -│ ├── auth/ -│ │ ├── auth-controllers.ts -│ │ └── user-controllers.ts -│ ├── activity/ -│ ├── backoffice/ -│ ├── blacklist/ -│ ├── cashier/ -│ ├── conciliation/ -│ ├── departments/ -│ ├── group/ -│ ├── logbook/ -│ ├── maintenance/ -│ ├── messages/ -│ ├── notifications/ -│ ├── parking/ -│ └── search/ -├── middlewares/ -│ ├── authenticateToken.ts # Verificar JWT (cookie o Bearer header) -│ ├── roleCheck.ts # Validar permisos -│ ├── rateLimiter.ts # Rate limiting (100 req/15min) -│ └── demoRestriction.ts # Bloquear writes en demo -├── models/ # Zod schemas + Types -├── repositories/ # Consultas SQL -├── routes/ # Express routers -├── services/ # Servicios externos -│ ├── auth/ -│ ├── blacklist/ -│ ├── conciliation/ -│ ├── cron/ -│ ├── group/ -│ ├── logbook/ -│ ├── notifications/ -│ ├── parking/ -│ └── scheduling/ # Sistema de horarios -├── validations/ # Zod schemas -├── types/ -│ └── express.d.ts -├── index.ts # Entry point -├── package.json -└── tsconfig.json -``` - ---- - -## 3. Tech Stack - -| Tecnología | Propósito | -| ---------------------- | ---------------------------------------- | -| **Node.js 20+** | Runtime environment | -| **Express 5** | Framework web (última versión major) | -| **TypeScript** | Desarrollo con tipos | -| **MySQL 8** | Base de datos relacional | -| **mysql2** | Driver MySQL con promesas | -| **jsonwebtoken** | Autenticación JWT (access 15 min + refresh 7 d) | -| **cookie-parser** | Lectura de HttpOnly cookies | -| **Zod 4** | Validación de requests | -| **Cloudinary** | Almacenamiento cloud de imágenes/PDFs | -| **Multer** | Upload de archivos (multipart/form-data) | -| **Archiver** | Generación de ZIPs | -| **node-cron** | Tareas programadas | -| **nodemailer** | Envío de emails | -| **bcrypt** | Hash de passwords (10 rounds) | -| **express-rate-limit** | Rate limiting | -| **dayjs** | Manipulación de fechas | -| **Axios** | Llamadas a APIs externas | - -### Dependencias - -```json -{ - "archiver": "^7.0.1", - "axios": "^1.12.2", - "bcrypt": "6.0.0", - "cloudinary": "^2.8.0", - "cookie-parser": "^1.4.7", - "cors": "^2.8.5", - "dayjs": "^1.11.18", - "express": "5.1.0", - "express-rate-limit": "^8.2.1", - "express-session": "^1.18.0", - "jsonwebtoken": "^9.0.2", - "multer": "^2.0.2", - "mysql2": "3.14.2", - "node-cron": "^4.2.1", - "nodemailer": "^7.0.10", - "passport": "^0.7.0", - "passport-jwt": "^4.0.1", - "zod": "^4.0.5" -} -``` - ---- - -## 4. API Endpoints - -### Autenticación - -``` -POST /api/auth/login # Login con credenciales -POST /api/auth/logout # Cerrar sesión -GET /api/auth/me # Usuario actual -POST /api/auth/refresh # Refresh token -POST /api/auth/register # Registro (opcional) -``` - -### Módulos Principales - -| Módulo | Base Route | Operaciones | -| ----------------- | -------------------- | ---------------------------------------------------- | -| **Users** | `/api/users` | CRUD, avatar upload, roles | -| **Groups** | `/api/groups` | Reservas, contactos, habitaciones, pagos, historial | -| **Parking** | `/api/parking` | Espacios, reservas, check-in/out, tarifas, analytics | -| **Logbooks** | `/api/logbooks` | Entradas, comentarios, seguimiento de lectura | -| **Cashier** | `/api/cashier` | Turnos, denominaciones, pagos, vouchers, reportes | -| **Maintenance** | `/api/maintenance` | Órdenes de trabajo, imágenes, estados | -| **Blacklist** | `/api/blacklist` | Incidentes, verificación docs | -| **Conciliation** | `/api/conciliations` | Conteo diario de habitaciones | -| **Backoffice** | `/api/backoffice` | Facturas, proveedores, PDFs | -| **Messages** | `/api/messages` | Conversaciones, mensajes directos | -| **Notifications** | `/api/notifications` | Alertas, entrega programada | -| **Activity** | `/api/activity` | Feed del dashboard, KPIs | -| **Departments** | `/api/departments` | Gestión de departamentos | -| **Search** | `/api/search` | Búsqueda global | -| **Scheduling** | `/api/scheduling` | Gestión de horarios de personal | - -### Sistema de Scheduling (Módulo Especial) {#scheduling} - -El módulo de scheduling incluye: - -- **CP-SAT Solver**: Optimizador de horarios con Google OR-Tools -- **Daemon Python**: Proceso persistente para solve requests -- **Validación**: Restricciones de negocio (descansos, días libres, bloques de noche) - -``` -POST /api/scheduling/months/:id/generate # Generar cronograma -POST /api/scheduling/months/:id/reset # Resetear asignaciones -POST /api/scheduling/constraints/:id/approve # Aprobar restricciones -``` - -> Para scripts de debug del scheduling, ver `docs/backend/scheduling/solver-setup.md`. - -### Formato de Respuestas - -```typescript -// Éxito -{ "success": true, "data": { ... } } - -// Error -{ "success": false, "error": "...", "code": "ERROR_CODE" } -``` - ---- - -## 5. Middlewares - -| Middleware | Propósito | -| ---------------------- | ------------------------------------- | -| `authenticateToken` | Verificar JWT (access token) | -| `roleCheck` | Validar permisos por rol | -| `rateLimiter` | Prevenir abuso (100 req/15min por IP) | -| `demoRestriction` | Bloquear writes para usuarios demo | - -### Servicios Cron - -```typescript -// CronService ejecuta: -- Notificaciones: Todos los días a las 7:00 AM -- Batch Payment: Día 10 de cada mes a las 23:59 - (facturas 'validated' → 'paid' del mes anterior) -``` - ---- - -## 6. Base de Datos - -### Esquema de Base de Datos - -El sistema usa **40+ tablas** organizadas por módulo: - -| Categoría | Tablas | -| ----------------- | -------------------------------------------------------------------------------------------------- | -| **Auth** | `users`, `roles` | -| **Groups** | `group_reservations`, `group_contacts`, `group_rooms`, `group_payments`, `group_history` | -| **Parking** | `parking_spaces`, `parking_bookings`, `parking_rates`, `parking_levels`, `parking_invoices` | -| **Logbooks** | `logbook_entries`, `logbook_comments`, `logbook_reads`, `logbook_history` | -| **Cashier** | `cashier_shifts`, `cashier_denominations`, `cashier_payments`, `cashier_vouchers`, `cashier_daily` | -| **Maintenance** | `maintenance_orders`, `maintenance_images`, `maintenance_history` | -| **Blacklist** | `blacklist_entries`, `blacklist_images` | -| **Conciliation** | `conciliations`, `conciliation_monthly` | -| **Backoffice** | `invoices`, `suppliers`, `invoice_images` | -| **Messages** | `conversations`, `messages`, `conversation_participants` | -| **Notifications** | `notifications`, `notification_reads`, `notification_schedule` | -| **Scheduling** | `scheduling_months`, `scheduling_assignments`, `scheduling_constraints`, `scheduling_config` | -| **Activity** | `activity_log`, `activity_types` | -| **System** | `departments`, `settings` | - -### Relaciones Clave - -``` -users (1) ─────────────< (n) logbook_entries -users (1) ─────────────< (n) maintenance_orders -users (1) ─────────────< (n) cashier_shifts -users (1) ─────────────< (n) group_history -users (1) ─────────────< (n) scheduling_assignments - -group_reservations (1) ─< (n) group_contacts -group_reservations (1) ─< (n) group_rooms -group_reservations (1) ─< (n) group_payments -group_reservations (1) ─< (n) group_history - -parking_spaces (1) ────< (n) parking_bookings -parking_levels (1) ────< (n) parking_spaces - -departments (1) ───────< (n) logbook_entries -departments (1) ───────< (n) users -``` - -### Configuración de Base de Datos - -| Entorno | Base de Datos | Host | -| --------- | ------------- | ---------------------- | -| **Local** | `hotel_db` | localhost:3306 | -| **Aiven** | `hotel_db` | Host cloud Aiven (SSL) | - -### Scripts SQL - -``` -db-mysql/ -├── MASTER_INSTALL.sql # Instalación completa -├── MASTER_INSTALL_LOCAL.sql # Para MySQL local -├── MASTER_INSTALL_AIVEN.sql # Para Aiven cloud -├── local/ -│ ├── 01_create_database.sql -│ ├── 02_core_tables.sql -│ ├── 03_logbook_tables.sql -│ ├── 04_parking_tables.sql -│ ├── 05_parking_functions_triggers.sql -│ ├── 06_parking_procedures.sql -│ ├── 07_parking_initial_data.sql -│ ├── 08_parking_sample_data.sql -│ ├── 09_conciliation.sql -│ ├── 10_group-tracking.sql -│ ├── 11_cashier.sql -│ ├── 12_blacklist.sql -│ ├── 13_maintenance.sql -│ ├── 14_messages.sql -│ ├── 15_demo_user.sql -│ ├── 16_backoffice.sql -│ ├── 17_notifications.sql -│ ├── 18_user_avatar.sql -│ ├── 19_scheduling.sql -│ └── 99_verification.sql -└── backup/ - ├── backup_hotel_db-local.sql - └── backup_hotel_db-aiven.sql -``` - ---- - -## 7. Configuración y Deployment - -### Variables de Entorno - -```env -DB_HOST=localhost -DB_USER=root -DB_PASSWORD=password -DB_NAME=hotel_db -PORT=4000 -SECRET_JWT_KEY=your-secret-key -SESSION_SECRET=your-session-secret -SALT_ROUNDS=10 -CLOUDINARY_CLOUD_NAME=... -CLOUDINARY_API_KEY=... -CLOUDINARY_API_SECRET=... -NODE_ENV=development -DB_ENVIRONMENT=local # o 'aiven' para cloud -``` - -### CORS Configuration - -El backend permite los siguientes orígenes: - -``` -- http://localhost:3000 (desarrollo) -- https://four-points.stackbp.es (producción) -- https://four-points.vercel.app (Vercel) -- https://*.vercel.app (todos los previews) -- https://four-points.onrender.com (fallback) -``` - -### Seguridad - -| Medida | Implementación | -| ---------------------- | ---------------------------------- | -| **XSS Protection** | HttpOnly cookies, sin localStorage | -| **CSRF Protection** | SameSite cookies, whitelist CORS | -| **SQL Injection** | Parameterized queries (mysql2) | -| **Rate Limiting** | 100 requests / 15 min por IP | -| **Password Hashing** | bcrypt (10 rounds) | -| **Input Validation** | Zod schemas en todos los endpoints | -| **Error Sanitization** | Errores genéricos en producción | - -### Deployment - -| Servicio | Proveedor | Propósito | -| ------------ | ------------------------ | ---------------------- | -| **Backend** | Render | Auto-deploy desde main | -| **Backend** | four-points.onrender.com | Fallback | -| **Database** | Aiven | MySQL 8 gestionado | -| **Media** | Cloudinary | Imágenes y PDFs | - ---- - -## 8. Scripts y Comandos - -```bash -pnpm dev # Desarrollo con tsx watch (puerto 4000) -pnpm dev:local # Usar MySQL local -pnpm dev:aiven # Usar MySQL Aiven -pnpm start # Start producción -pnpm typecheck # TypeScript check -pnpm test # Tests con Vitest -pnpm test:watch # Tests en modo watch -pnpm test:coverage # Tests con coverage -``` - ---- - -## 9. Documentación Relacionada - -Para documentación detallada consultar: - -- **Sistema de scheduling**: `docs/backend/scheduling/README.md` — arquitectura, endpoints, CP-SAT solver -- **Solver Python**: `docs/backend/scheduling/solver-setup.md` — daemon, OR-Tools, tests -- **Autenticación en producción**: `docs/backend/auth/productionAuthSetup.md` -- **CORS**: `docs/backend/config/cors-configuration.md` -- **Seguridad**: `docs/backend/security/security-implementation.md` -- **Checklist**: `docs/backend/checklist.md` -- **DB**: `backend/db-mysql/INDEX.md`, `MIGRATIONS_POLICY.md` -- **Testing**: `docs/backend/testing/README.md` -- **Restricciones de scheduling**: `docs/scheduling/constraints.md` -- **Variables de entorno**: `docs/backend/enviroments/environment-variables.md` \ No newline at end of file +# Four-Points — Backend + +REST API in Express 5 + TypeScript over MySQL 8, with the scheduling solver +(Python + OR-Tools) as a child process. To install and run the whole project, +see the [root README](../README.md). + +## Layout + +| Folder | What it holds | +| ------------------------------------------------------- | ---------------------------------------------------------------------- | +| `routes/`, `controllers/`, `services/`, `repositories/` | One folder per module | +| `middlewares/` | Auth, roles, demo restrictions, rate limits, uploads | +| `config/` | Database, CORS, logger, environment | +| `db-mysql/` | Schema, migrations and seeds ([policy](db-mysql/MIGRATIONS_POLICY.md)) | +| `scheduling-solver/` | Python CP-SAT solver | +| `scripts/` | `setup:local`, demo user, scheduling seed export | +| `tests/` | Vitest suites ([notes](tests/README.md)) | + +## Commands + +| Command | Does | +| ---------------------------------------------------- | ------------------------------------------------------------------ | +| `pnpm setup:local` | Builds a local `hotel_db` with fictitious data and the local admin | +| `pnpm dev:local` | API on :4000 against the local database | +| `pnpm test` | Unit and integration tests | +| `pnpm test:corpus` | Solver corpus (needs the Python venv) | +| `pnpm typecheck` · `pnpm lint` · `pnpm format:check` | What CI runs | + +Each module has an `AGENTS.md` under `services/` with its rules; the product +documentation lives in [`docs/`](../docs/general/README.md). diff --git a/backend/backend.md b/backend/backend.md deleted file mode 100644 index abb08eaf..00000000 --- a/backend/backend.md +++ /dev/null @@ -1,795 +0,0 @@ -# Four Points - Backend Architecture - -> Private REST API for the Hotel Property Management System - - - - - - -This document describes the backend architecture. The backend repository is **private**. - ---- - -## Table of Contents - -1. [Tech Stack](#1-tech-stack) -2. [Architecture](#2-architecture) -3. [Entry Point (index.ts)](#3-entry-point-indexts) -4. [Configuration](#4-configuration) -5. [API Structure](#5-api-structure) -6. [Controllers](#6-controllers) -7. [Repositories](#7-repositories) -8. [Services](#8-services) -9. [Authentication & Security](#9-authentication--security) -10. [Database Schema](#10-database-schema) -11. [Cron Jobs](#11-cron-jobs) -12. [File Handling](#12-file-handling) -13. [Error Handling](#13-error-handling) -14. [Middlewares](#14-middlewares) -15. [Demo Mode](#15-demo-mode) -16. [Deployment](#16-deployment) -17. [Scripts & Commands](#17-scripts--commands) - ---- - -## 1. Tech Stack - -| Technology | Version | Purpose | -| ---------- | ------- | ------- | -| **Node.js** | 20+ | Runtime environment | -| **Express** | 5.1.0 | Web framework (latest major) | -| **TypeScript** | 5.9.3 | Type-safe development | -| **MySQL** | 8 | Relational database | -| **mysql2** | 3.14.2 | MySQL driver with promises | -| **Passport.js** | 0.7.0 | Authentication middleware | -| **passport-jwt** | 4.0.1 | JWT strategy for Passport | -| **jsonwebtoken** | 9.0.2 | JWT token handling | -| **bcrypt** | 6.0.0 | Password hashing (10 rounds) | -| **Zod** | 4.0.5 | Request validation & schemas | -| **Cloudinary** | 2.8.0 | Image & PDF cloud storage | -| **Multer** | 2.0.2 | File upload (multipart/form-data) | -| **Archiver** | 7.0.1 | ZIP file generation | -| **node-cron** | 4.2.1 | Scheduled tasks | -| **nodemailer** | 7.0.10 | Email notifications | -| **express-rate-limit** | 8.2.1 | Rate limiting (100 req/15min) | -| **cors** | 2.8.5 | Cross-origin resource sharing | -| **cookie-parser** | 1.4.7 | Cookie parsing | -| **dayjs** | 1.11.18 | Date manipulation | -| **Axios** | 1.12.2 | External API calls | -| **dotenv** | 17.2.0 | Environment variables | -| **tsx** | 4.20.6 | TypeScript execution (dev) | - -### Package Manager - -```json -{ - "packageManager": "pnpm@10.13.1" -} -``` - -### Dev Dependencies - -| Tool | Purpose | -| ---- | ------- | -| cross-env | Environment variables cross-platform | -| standard | ESLint config | -| @types/* | TypeScript definitions | - ---- - -## 2. Architecture - -``` -┌─────────────────────────────────────────────────────────────┐ -│ EXPRESS SERVER │ -├─────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────┐ │ -│ │ index.ts │ │ -│ │ • CORS configuration (7 origins allowed) │ │ -│ │ • Security middleware (x-powered-by disabled) │ │ -│ │ • Global error handler │ │ -│ │ • 404 handler │ │ -│ └─────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────┐ │ -│ │ Middlewares │ │ -│ │ • express.json() - Body parsing │ │ -│ │ • cookie-parser() - Cookie parsing │ │ -│ │ • cors() - Cross-origin settings │ │ -│ │ • rateLimiter - 100 req/15min per IP │ │ -│ └─────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ -│ │ Routes │ → │ Controllers │ → │Repositories │ │ -│ │ (Express) │ │ (Lógica) │ │ (MySQL) │ │ -│ │ validation │ │ negocio │ │ queries │ │ -│ └─────────────┘ └─────────────┘ └─────────────┘ │ -│ │ │ │ │ -│ ▼ ▼ ▼ │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ -│ │ Zod Schemas │ │ Services │ │ Models │ │ -│ │ (validatio) │ │ (cron,ext) │ │ (Zod/TS) │ │ -│ └─────────────┘ └─────────────┘ └─────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────┐ │ -│ │ MySQL 8 │ │ -│ │ (40+ tables)│ │ -│ └─────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────┘ -``` - ---- - -## 3. Entry Point (index.ts) - -**File:** `backend/index.ts` (192 líneas) - -```typescript -// Main imports -import express, { Request, Response, NextFunction } from 'express' -import cookieParser from 'cookie-parser' -import cors from 'cors' -import { PORT } from './config/config.js' - -// Services -import { CronService } from './services/cron/cron-service.js' - -// Route imports (18 route files) -import authRoutes from './routes/auth/auth-routes.js' -import userRoutes from './routes/auth/user-routes.js' -import logbookRoutes from './routes/logbook/logbook-routes.js' -import parkingRoutes from './routes/parking/parking.routes.js' -import parkingStatsRoutes from './routes/parking/stats.routes.js' -import parkingBookingsRoutes from './routes/parking/bookings.routes.js' -import departmentsRoutes from './routes/departments/departments-routes.js' -import conciliationRoutes from './routes/conciliation/conciliation.routes.js' -import groupRoutes from './routes/group/group-routes.js' -import notificationRoutes from './routes/notifications/notifications-routes.js' -import cashierRoutes from './routes/cashier/cashier-routes.js' -import blacklistRoutes from './routes/blacklist/blacklist-routes.js' -import maintenanceRoutes from './routes/maintenance/maintenance-routes.js' -import activityRoutes from './routes/activity/activity-routes.js' -import messagesRoutes from './routes/messages/messages-routes.js' -import backofficeRoutes from './routes/backoffice/backoffice-routes.js' -import searchRoutes from './routes/search/search-routes.js' -import demoActivityRoutes from './routes/demo/demo-activity-routes.js' - -// App initialization -const app = express() - -// Security: Disable x-powered-by header -app.disable('x-powered-by') - -// CORS Configuration -const allowedOrigins = [ - 'http://localhost:3000', - 'https://four-points.stackbp.es', - 'https://four-points.vercel.app', - 'https://api.four-points.stackbp.es', - 'https://four-points.onrender.com', - process.env.FRONTEND_URL, -].filter(Boolean) as string[] - -const vercelPreviewPattern = /\.vercel\.app$/ - -app.use(cors({ - origin: (origin, callback) => { - if (!origin) { - callback(null, true) - return - } - if (allowedOrigins.includes(origin) || vercelPreviewPattern.test(origin)) { - callback(null, true) - } else { - console.warn(`[CORS] Blocked origin: ${origin}`) - callback(new Error('Not allowed by CORS')) - } - }, - credentials: true, - methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], - allowedHeaders: ['Content-Type', 'Authorization', 'Cookie'], - exposedHeaders: ['Set-Cookie'], -})) - -// Global middlewares -app.use(express.json()) -app.use(cookieParser()) - -// Health check endpoint -app.get('/', (_req: Request, res: Response) => { - res.json({ - status: 'online', - message: 'API funcionando correctamente', - timestamp: new Date().toISOString(), - }) -}) - -// Route registration (18 modules) -app.use('/api/auth', authRoutes) -app.use('/api/users', userRoutes) -app.use('/api/logbooks', logbookRoutes) -app.use('/api/parking', parkingRoutes) -app.use('/api/parking/stats', parkingStatsRoutes) -app.use('/api/parking/bookings', parkingBookingsRoutes) -app.use('/api/departments', departmentsRoutes) -app.use('/api/conciliations', conciliationRoutes) -app.use('/api/groups', groupRoutes) -app.use('/api/notifications', notificationRoutes) -app.use('/api/cashier', cashierRoutes) -app.use('/api/blacklist', blacklistRoutes) -app.use('/api/maintenance', maintenanceRoutes) -app.use('/api/activity', activityRoutes) -app.use('/api/messages', messagesRoutes) -app.use('/api/backoffice', backofficeRoutes) -app.use('/api/search', searchRoutes) -app.use('/api/demo-activity', demoActivityRoutes) - -// 404 Handler -app.use((req: Request, res: Response) => { - res.status(404).json({ - error: 'Ruta no encontrada', - path: req.path, - }) -}) - -// Global Error Handler -interface HttpError extends Error { - status?: number -} - -app.use((err: HttpError, _req: Request, res: Response, _next: NextFunction) => { - console.error('Error global:', err) - res.status(err.status || 500).json({ - error: process.env.NODE_ENV === 'production' ? 'Error interno del servidor' : err.message, - }) -}) - -// Start server -app.listen(PORT, () => { - console.log(`🚀 Server running at http://localhost:${PORT}`) - console.log(`📝 Environment: ${process.env.NODE_ENV || 'development'}`) - CronService.start() -}) -``` - ---- - -## 4. Configuration - -**File:** `backend/config/config.ts` (44 líneas) - -```typescript -import dotenv from 'dotenv' -dotenv.config() - -interface EnvConfig { - PORT: number - SECRET_JWT_KEY: string - SALT_ROUNDS: number -} - -// Critical: JWT secret must be defined -if (!process.env.SECRET_JWT_KEY) { - throw new Error('Falta la variable SECRET_JWT_KEY en el entorno') -} - -export const PORT: number = parseInt(process.env.PORT || '3000', 10) -export const SECRET_JWT_KEY: string = process.env.SECRET_JWT_KEY -export const SALT_ROUNDS: number = parseInt(process.env.SALT_ROUNDS || '10', 10) - -export default config -``` - -### Environment Variables (.env.example) - -```env -# Server -PORT=4000 -NODE_ENV=development - -# Database -DB_HOST=localhost -DB_USER=root -DB_PASSWORD=password -DB_NAME=hotel_db -DB_ENVIRONMENT=local - -# Authentication -SECRET_JWT_KEY=your-super-secret-key -SALT_ROUNDS=10 - -# Cloudinary (optional) -CLOUDINARY_CLOUD_NAME=your-cloud-name -CLOUDINARY_API_KEY=your-api-key -CLOUDINARY_API_SECRET=your-api-secret - -# Email (optional) -SMTP_HOST=smtp.example.com -SMTP_PORT=587 -SMTP_USER=your-email -SMTP_PASS=your-password -``` - -### Database Connection - -**File:** `backend/config/db.ts` - -Manages MySQL connection pool using mysql2 with promise support. - -### Error Codes - -**File:** `backend/config/error-codes.ts` - -Centralized error codes for i18n integration. - -### Date Utilities - -**File:** `backend/config/date-utils.ts` - -Helper functions for date manipulation using dayjs. - ---- - -## 5. API Structure - -### Authentication - -| Method | Endpoint | Description | -| ------ | -------- | ----------- | -| POST | `/api/auth/login` | Login with credentials | -| POST | `/api/auth/logout` | Clear session | -| GET | `/api/auth/me` | Get current user | -| POST | `/api/auth/refresh` | Refresh access token | -| POST | `/api/auth/register` | Register new user | - -### Core Modules - -| Module | Base Route | Controllers | -| ------ | ---------- | ----------- | -| **Users** | `/api/users` | user-controllers.ts | -| **Groups** | `/api/groups` | group-controller.ts, contact, payment, room, history | -| **Parking** | `/api/parking` | parking.controller.ts, bookings, stats | -| **Logbooks** | `/api/logbooks` | logbook-controllers.ts, comments, reads | -| **Cashier** | `/api/cashier` | shift, denomination, payment, daily, report, voucher | -| **Maintenance** | `/api/maintenance` | maintenance-controller.ts | -| **Blacklist** | `/api/blacklist` | blacklist-controller.ts | -| **Conciliation** | `/api/conciliations` | conciliation.controller.ts, monthly | -| **Backoffice** | `/api/backoffice` | backoffice-controller.ts | -| **Messages** | `/api/messages` | conversation-controller.ts, message-controller.ts | -| **Notifications** | `/api/notifications` | notification-controller.ts | -| **Activity** | `/api/activity` | activity-controller.ts | -| **Departments** | `/api/departments` | departments-controller.ts | -| **Scheduling** | `/api/scheduling` | scheduling-controller.ts | -| **Chat** | `/api/chat` | chat-controller.ts | -| **Search** | `/api/search` | search-controller.ts | -| **Demo** | `/api/demo-activity` | demo-activity-controller.ts | - ---- - -## 6. Controllers - -Located in `backend/controllers/` (20+ controller files) - -### Auth Controllers - -| File | Functions | -| ---- | --------- | -| `auth-controllers.ts` | login, logout, me, refresh | -| `user-controllers.ts` | CRUD, avatar upload, profile | - -### Module Controllers - -**Groups:** -- `group-controller.ts` - Main CRUD operations -- `group-contact-controller.ts` - Contact management -- `group-payment-controller.ts` - Payment tracking -- `group-room-controller.ts` - Room assignment -- `group-history-controller.ts` - Audit trail -- `group-status-controller.ts` - Status workflow - -**Parking:** -- `parking.controller.ts` - Spaces, rates, levels -- `bookings.controller.ts` - Booking CRUD, check-in/out -- `stats.controller.ts` - Dashboard statistics - -**Cashier:** -- `cashier-shift-controller.ts` - Shift management -- `cashier-denomination-controller.ts` - Currency counting -- `cashier-payment-controller.ts` - Payment processing -- `cashier-daily-controller.ts` - Daily summaries -- `cashier-report-controller.ts` - Report generation -- `cashier-history-controller.ts` - History tracking -- `cashier-voucher-controller.ts` - Voucher management - -**Logbooks:** -- `logbook-controllers.ts` - Entry CRUD -- `logbookComments-controllers.ts` - Comments -- `logbookReads-controllers.ts` - Read tracking - -**Others:** -- `activity-controller.ts` - Dashboard feed -- `backoffice-controller.ts` - Invoices, suppliers -- `blacklist-controller.ts` - Incident records -- `maintenance-controller.ts` - Work orders -- `conciliation.controller.ts` - Daily reconciliation -- `conciliation-monthly.controller.ts` - Monthly summaries -- `departments-controller.ts` - Department management -- `notification-controller.ts` - Alert management -- `conversation-controller.ts` - Chat conversations -- `message-controller.ts` - Individual messages -- `search-controller.ts` - Global search -- `demo-activity-controller.ts` - Demo logging - ---- - -## 7. Repositories - -Located in `backend/repositories/` (25+ repository files) - -### Structure Pattern - -Each module has dedicated repositories for data access: - -``` -repositories/ -├── auth/ -│ └── user-repository.ts -├── activity/ -│ └── activity-repository.ts -├── backoffice/ -│ └── backoffice-repository.ts -├── blacklist/ -│ └── blacklist-repository.ts -├── cashier/ -│ ├── cashier-daily-repository.ts -│ ├── cashier-denomination-repository.ts -│ ├── cashier-history-repository.ts -│ ├── cashier-payment-repository.ts -│ ├── cashier-shift-repository.ts -│ ├── cashier-shift-user-repository.ts -│ └── cashier-voucher-repository.ts -├── conciliation/ -│ ├── conciliation.repository.ts -│ └── conciliation-monthly.repository.ts -├── departments/ -│ └── departments-repository.ts -├── group/ -│ ├── group-contact-repository.ts -│ ├── group-history-repository.ts -│ ├── group-payment-repository.ts -│ ├── group-repository.ts -│ ├── group-room-repository.ts -│ └── group-status-repository.ts -├── logbook/ -│ ├── logbook-repository.ts -│ ├── logbookComments-repository.ts -│ ├── logbookCommentsHistory-repository.ts -│ ├── logbookHistory-repository.ts -│ └── logbookReads-repository.ts -├── maintenance/ -│ └── maintenance-repository.ts -├── messages/ -│ ├── conversation-repository.ts -│ └── message-repository.ts -├── notifications/ -│ └── notification-repository.ts -├── parking/ -│ ├── bookings.repository.ts -│ ├── parking.repository.ts -│ └── stats.repository.ts -└── search/ - └── search-repository.ts -``` - ---- - -## 8. Services - -Located in `backend/services/` (8 service files) - -| Service | File | Purpose | -| ------- | ---- | ------- | -| **Token Service** | `auth/tokenService.ts` | JWT generation and verification | -| **Cloudinary** | `blacklist/cloudinary-service.ts` | Image upload management | -| **Cron Service** | `cron/cron-service.ts` | Scheduled tasks | -| **Group History** | `group/group-history-service.ts` | Audit logging | -| **Payment Calculator** | `group/payment-calculator-service.ts` | Payment calculations | -| **Logbook History** | `logbook/logbookHistory-service.ts` | Read tracking | -| **Notification Generator** | `notifications/notification-generator-service.ts` | Auto notifications | -| **Schedule Validator** | `scheduling/schedule-validator.ts` | Real-time schedule validation | - ---- - -## 9. Authentication & Security - -### JWT Flow - -``` -Login → Validate credentials → Generate tokens → Set HttpOnly cookies - │ -Request with cookie → Verify JWT → Check role → Execute controller ─┘ - │ -401 → Auto-refresh via /api/auth/refresh → Retry request - │ -Refresh expired → Redirect to /login -``` - -### Token Configuration - -| Token | Duration | Storage | -| ----- | -------- | ------- | -| Access | 15 min | HttpOnly cookie | -| Refresh | 7 days | HttpOnly cookie | - -### Security Measures - -| Measure | Implementation | -| ------- | -------------- | -| **XSS Protection** | HttpOnly cookies, no localStorage | -| **CSRF Protection** | SameSite cookies, CORS whitelist | -| **SQL Injection** | Parameterized queries (mysql2) | -| **Rate Limiting** | 100 requests / 15 min per IP | -| **Password Hashing** | bcrypt (10 rounds) | -| **Input Validation** | Zod schemas on all endpoints | -| **Error Sanitization** | Generic errors in production | -| **Header Security** | x-powered-by disabled | - -### Middleware Functions - -```typescript -// authenticateToken.ts -export function authenticateToken(req, res, next) { - const token = req.cookies.access_token - if (!token) return res.status(401).json({ error: 'No token' }) - - jwt.verify(token, SECRET_JWT_KEY, (err, user) => { - if (err) return res.status(403).json({ error: 'Invalid token' }) - req.user = user - next() - }) -} - -// roleCheck.ts -export function roleCheck(...roles) { - return (req, res, next) => { - if (!roles.includes(req.user.role)) { - return res.status(403).json({ error: 'Insufficient permissions' }) - } - next() - } -} -``` - ---- - -## 10. Database Schema - -### Core Tables (40+) - -| Category | Tables | -| --------- | ------ | -| **Auth** | `users`, `refresh_tokens` | -| **Groups** | `group_reservations`, `group_contacts`, `group_rooms`, `group_payments`, `group_history` | -| **Parking** | `parking_spaces`, `parking_bookings`, `parking_rates`, `parking_levels`, `parking_invoices` | -| **Logbooks** | `logbook_entries`, `logbook_comments`, `logbook_reads`, `logbook_history` | -| **Cashier** | `cashier_shifts`, `cashier_denominations`, `cashier_payments`, `cashier_vouchers`, `cashier_daily`, `cashier_shift_users` | -| **Maintenance** | `maintenance_orders`, `maintenance_images`, `maintenance_history` | -| **Blacklist** | `blacklist_entries`, `blacklist_images` | -| **Conciliation** | `conciliations`, `conciliation_monthly` | -| **Backoffice** | `invoices`, `suppliers`, `invoice_images` | -| **Messages** | `conversations`, `messages`, `conversation_participants` | -| **Notifications** | `notifications`, `notification_reads`, `notification_schedule` | -| **Activity** | `activity_log`, `activity_types` | -| **Scheduling** | `scheduling_months`, `scheduling_days`, `scheduling_assignments`, `scheduling_constraints`, `scheduling_shifts`, `scheduling_employee_rules`, `scheduling_employees`, `scheduling_employee_contracts`, `scheduling_config`, `scheduling_history` | -| **System** | `departments`, `settings` | - -### Key Relationships - -``` -users (1) ─────────────< (n) logbook_entries -users (1) ─────────────< (n) maintenance_orders -users (1) ─────────────< (n) cashier_shifts -users (1) ─────────────< (n) group_history - -group_reservations (1) ─< (n) group_contacts -group_reservations (1) ─< (n) group_rooms -group_reservations (1) ─< (n) group_payments -group_reservations (1) ─< (n) group_history - -parking_spaces (1) ────< (n) parking_bookings -parking_levels (1) ────< (n) parking_spaces - -departments (1) ───────< (n) logbook_entries -departments (1) ───────< (n) users -``` - ---- - -## 11. Cron Jobs - -**File:** `backend/services/cron/cron-service.ts` (263 líneas) - -### Scheduled Tasks - -| Job | Schedule | Purpose | -| --- | -------- | ------- | -| **Notifications** | Daily at 7:00 AM (`0 7 * * *`) | Process pending notifications | -| **Batch Payment** | Day 10 at 23:59 (`59 23 10 * *`) | Mark validated invoices as paid | - -### Batch Payment Process - -```typescript -// Marks all 'validated' invoices from previous month as 'paid' -// Triggered automatically on day 10 at 23:59 -// Manual trigger available via CronService.runBatchPaymentNow() -``` - -### Cron Service Methods - -| Method | Purpose | -| ------- | ------- | -| `start()` | Initialize all cron jobs | -| `runNotificationsNow()` | Manual trigger for notifications | -| `runBatchPaymentNow()` | Manual trigger for batch payment | -| `previewBatchPayment()` | Preview invoices to be marked as paid | -| `getStatus()` | Get next run times | - ---- - -## 12. File Handling - -| Feature | Technology | Usage | -| ------- | ---------- | ----- | -| **Image Upload** | Multer + Cloudinary | Avatars, maintenance photos, blacklist evidence | -| **PDF Upload** | Multer + Cloudinary | Invoice documents, contracts | -| **ZIP Generation** | Archiver | Bulk export of images/documents | -| **Email Attachments** | Nodemailer | Reports, notifications with files | -| **PDF Generation** | pdf-lib (service) | Parking invoices, receipts | - ---- - -## 13. Error Handling - -### Response Format - -```typescript -// Success response -{ "success": true, "data": { ... } } - -// Error response -{ "success": false, "error": "Error message", "code": "ERROR_CODE" } - -// Validation error -{ "success": false, "error": "Validation failed", "details": [...] } -``` - -### HTTP Status Codes - -| Code | Meaning | -| ---- | ------- | -| 200 | OK | -| 201 | Created | -| 400 | Bad Request | -| 401 | Unauthorized | -| 403 | Forbidden | -| 404 | Not Found | -| 422 | Validation Error | -| 500 | Internal Server Error | - ---- - -## 14. Middlewares - -| Middleware | File | Purpose | -| --------- | ---- | ------- | -| `authenticateToken` | authenticateToken.ts | Verify JWT, attach user to request | -| `roleCheck` | roleCheck.ts | Validate user role permissions | -| `rateLimiter` | rateLimiter.ts | Prevent abuse (100 req/15min per IP) | -| `demoRestriction` | demoRestriction.ts | Block write operations for demo users | - ---- - -## 15. Demo Mode - -Demo users can read all data but write operations are restricted: - -| Route | Method | Allowed Action | -| ----- | ------ | -------------- | -| `/api/auth/logout` | POST | Session management | -| `/api/parking/bookings` | POST | Test booking flow | -| `/api/logbooks/*/comments` | POST | Test comments | -| `/api/maintenance` | POST | Test work orders | - -All other write operations return `403 Forbidden`. - ---- - -## 16. Deployment - -| Service | Provider | Configuration | -| ------- | -------- | ------------- | -| **Backend** | Render | Auto-deploy from main branch | -| **Backend** | Fallback | four-points.onrender.com:4000 | -| **Database** | Aiven | MySQL 8 with SSL | -| **Media Storage** | Cloudinary | Images and PDFs | - -### Build & Start - -```bash -# Development -pnpm dev # tsx watch -pnpm dev:local # DB_ENVIRONMENT=local -pnpm dev:aiven # DB_ENVIRONMENT=aiven - -# Production -pnpm start # tsx index.ts - -# TypeScript -pnpm typecheck # tsc --noEmit -``` - ---- - -## 17. Scripts & Commands - -### npm Scripts - -```bash -pnpm dev # Development with tsx watch -pnpm dev:local # Use local MySQL database -pnpm dev:aiven # Use Aiven cloud database -pnpm build # No build needed (tsx) -pnpm start # Production start -pnpm typecheck # TypeScript type checking -pnpm test # Run tests -pnpm test:watch # Watch mode -pnpm test:coverage # Coverage report -``` - -### Database Commands - -```bash -# MySQL connection -mysql -u root -p hotel_db - -# Aiven connection -mysql -u usuario -h host -p hotel_db -P 3306 --ssl-ca=certs/ca-certificate.pem - -# Dump local -mysqldump -u root -p hotel_db > backup.sql - -# Import -mysql -u root -p hotel_db < backup.sql -``` - ---- - -## Related Documentation - -| Document | Description | -| --------- | ----------- | -| `backend/README.md` | JWT to Sessions migration guide | -| `backend.md` | This file | -| `docs/backend/database/` | Database configuration guides | -| `docs/backend/security/` | Security implementation details | - ---- - -## Author - -**Salvador Perez** - -- GitHub: [@bpstack](https://github.com/bpstack) -- Email: contact.bpstack@gmail.com - ---- - -
- Built with Express 5, TypeScript, and MySQL -
diff --git a/backend/db-mysql/AGENTS.md b/backend/db-mysql/AGENTS.md index 2eda1fe0..47b3ac1c 100644 --- a/backend/db-mysql/AGENTS.md +++ b/backend/db-mysql/AGENTS.md @@ -24,7 +24,6 @@ backend/db-mysql/ ├── backup/ # DB dumps (local + Aiven) ├── MASTER_INSTALL.sql # Runs all aiven/ files in order. Empty DB only. ├── MIGRATIONS_POLICY.md -├── MIGRATION_GUIDE.md ├── INDEX.md # Full table index + incremental migration log └── mock-data.sql # Clears module data and loads fictitious data (keeps users and scheduling) ``` @@ -172,4 +171,4 @@ password. - `MIGRATIONS_POLICY.md` — full policy rationale and when to change the model. - `INDEX.md` — module-by-module table list + full incremental migration log. -- `MIGRATION_GUIDE.md` — initial install guide (scripts 01-19 walkthrough). +- Fresh install: `pnpm setup:local` (`scripts/setup-local.ts`), never `MASTER_INSTALL.sql` by hand. diff --git a/backend/db-mysql/INDEX.md b/backend/db-mysql/INDEX.md index e0de4188..30eef9bf 100644 --- a/backend/db-mysql/INDEX.md +++ b/backend/db-mysql/INDEX.md @@ -34,7 +34,6 @@ db-mysql/ ├── MASTER_INSTALL.sql # Instalación completa (apunta a aiven/) ├── INDEX.md ├── README.md -├── MIGRATION_GUIDE.md ├── cleanup-scheduling.sql └── mock-data.sql # Vacía los módulos y carga datos ficticios (no toca usuarios ni horarios) ``` diff --git a/backend/db-mysql/MIGRATIONS_POLICY.md b/backend/db-mysql/MIGRATIONS_POLICY.md index a020598f..6a805718 100644 --- a/backend/db-mysql/MIGRATIONS_POLICY.md +++ b/backend/db-mysql/MIGRATIONS_POLICY.md @@ -71,7 +71,7 @@ Esos cambios se han reconstruido a posteriori como scripts marcados `[RETROACTIV ## Archivos relacionados - `INDEX.md` — índice general, tabla "Migraciones incrementales" -- `MIGRATION_GUIDE.md` — guía de instalación inicial (scripts 01-20 congelados) +- `pnpm setup:local` — instalación local desde cero (`scripts/setup-local.ts`) - `README.md` — overview de la carpeta - `scripts/` — scripts incrementales, ordenados por fecha. Única fuente de verdad para cambios desde 2026-05-20. - `aiven/NN_*.sql` — snapshot congelado del install base. No editar. diff --git a/backend/db-mysql/MIGRATION_GUIDE.md b/backend/db-mysql/MIGRATION_GUIDE.md deleted file mode 100644 index 33cf7ae1..00000000 --- a/backend/db-mysql/MIGRATION_GUIDE.md +++ /dev/null @@ -1,216 +0,0 @@ -# 🚀 GUÍA DE MIGRACIÓN - HOTEL DB - -Esta guía te permite reconstruir completamente la base de datos en cualquier momento. - -## 📋 ORDEN DE EJECUCIÓN - -Ejecuta los scripts en orden usando `MASTER_INSTALL.sql` o manualmente desde el directorio `aiven/`: - -```bash -# Opción 1: Un solo comando (recomendado) -mysql -u root -p < MASTER_INSTALL.sql - -# Opción 2: Manual, script por script (desde directorio aiven/) -cd aiven/ -mysql -u root -p < 01_create_database.sql -mysql -u root -p < 02_core_tables.sql -# ... etc -``` - -### Scripts disponibles (01-19) - -| # | Archivo | Descripción | -| --- | ----------------------------------- | ---------------------------------------------------------------------------------- | -| 01 | `01_create_database.sql` | Crea BD con UTF-8 | -| 02 | `02_core_tables.sql` | Roles, departments, users | -| 03 | `03_logbook_tables.sql` | Sistema de bitácora | -| 04 | `04_parking_tables.sql` | Tablas de parking | -| 05 | `05_parking_functions_triggers.sql` | Funciones y triggers | -| 06 | `06_parking_procedures.sql` | Procedimientos almacenados | -| 07 | `07_parking_initial_data.sql` | Datos iniciales (plazas + tarifas) | -| 08 | `08_parking_sample_data.sql` | Datos de ejemplo (opcional) | -| 09 | `09_conciliation.sql` | Conciliación bancaria | -| 10 | `10_group-tracking.sql` | Seguimiento de grupos | -| 11 | `11_cashier.sql` | Sistema de caja | -| 12 | `12_blacklist.sql` | Lista negra | -| 13 | `13_maintenance.sql` | Mantenimiento | -| 14 | `14_messages.sql` | Mensajería | -| 15 | `15_demo_user.sql` | Usuario demo | -| 16 | `16_backoffice.sql` | Backoffice | -| 17 | `17_notifications.sql` | Notificaciones | -| 18 | `18_user_avatar.sql` | Avatares de usuario | -| 19 | `19_scheduling.sql` | Programación de turnos | -| 20 | `20_checklist.sql` | Checklists operativos (runs, step_state, event_log, config, comments, attachments) | -| 99 | `99_verification.sql` | Verificación de instalación | - -> **Política de migraciones (vigente desde 2026-05-20):** Los archivos `aiven/NN_*.sql` están **congelados** como snapshot del schema base. Todo cambio posterior vive únicamente en `scripts/AAAAMMDD_*.sql`. Para reconstruir la BD desde cero: `MASTER_INSTALL.sql` + todos los `scripts/*.sql` en orden cronológico. Ver `MIGRATIONS_POLICY.md`. - ---- - -## ✅ VERIFICACIÓN POST-MIGRACIÓN - -Después de ejecutar todos los scripts, verifica que todo esté correcto: - -```sql -USE hotel_db; - --- Verificar tablas -SHOW TABLES; - --- Verificar plazas -SELECT COUNT(*) AS total_plazas FROM parking_spots; --- Debe devolver: 20 - --- Verificar tarifas -SELECT COUNT(*) AS total_tarifas FROM parking_rates; --- Debe devolver: 30 - --- Verificar disponibilidad -SELECT COUNT(*) AS total_disponibilidad FROM parking_availability; --- Debe devolver: ~7300 (20 plazas × 365 días) - --- Verificar funciones -SELECT ROUTINE_NAME -FROM information_schema.ROUTINES -WHERE ROUTINE_SCHEMA = 'hotel_db' - AND ROUTINE_TYPE = 'FUNCTION'; - --- Verificar procedimientos -SELECT ROUTINE_NAME -FROM information_schema.ROUTINES -WHERE ROUTINE_SCHEMA = 'hotel_db' - AND ROUTINE_TYPE = 'PROCEDURE'; - --- Verificar triggers -SELECT TRIGGER_NAME -FROM information_schema.TRIGGERS -WHERE TRIGGER_SCHEMA = 'hotel_db'; -``` - ---- - -## 🔄 RESET COMPLETO - -Si necesitas empezar desde cero (⚠️ CUIDADO: Borra TODO): - -```bash -# 1. Hacer backup -mysqldump -u root -p hotel_db > backup_$(date +%Y%m%d).sql - -# 2. Ejecutar instalación completa -mysql -u root -p < MASTER_INSTALL.sql -``` - ---- - -## 🛠️ MANTENIMIENTO - -### Sincronización diaria automática (Parking) - -Añade a cron (Linux/Mac) o usa evento MySQL: - -```sql -USE hotel_db; - -SET GLOBAL event_scheduler = ON; - -CREATE EVENT daily_maintenance -ON SCHEDULE EVERY 1 DAY -STARTS (TIMESTAMP(CURRENT_DATE) + INTERVAL 1 DAY + INTERVAL 3 HOUR) -DO - CALL daily_parking_maintenance(); -``` - -### Sincronización manual (Parking) - -```sql -CALL sync_parking_availability(); -``` - ---- - -## 📦 ESTRUCTURA DE ARCHIVOS - -``` -db-mysql/ -├── aiven/ -│ ├── 01_create_database.sql -│ ├── 02_core_tables.sql -│ ├── 03_logbook_tables.sql -│ ├── 04_parking_tables.sql -│ ├── 05_parking_functions_triggers.sql -│ ├── 06_parking_procedures.sql -│ ├── 07_parking_initial_data.sql -│ ├── 08_parking_sample_data.sql -│ ├── 09_conciliation.sql -│ ├── 10_group-tracking.sql -│ ├── 11_cashier.sql -│ ├── 12_blacklist.sql -│ ├── 13_maintenance.sql -│ ├── 14_messages.sql -│ ├── 15_demo_user.sql -│ ├── 16_backoffice.sql -│ ├── 17_notifications.sql -│ ├── 18_user_avatar.sql -│ ├── 19_scheduling.sql -│ └── 99_verification.sql -├── MASTER_INSTALL.sql -├── INDEX.md -└── MIGRATION_GUIDE.md -``` - ---- - -## 🎯 CARACTERÍSTICAS DEL SISTEMA - -### Parking - -- **Generación automática de booking_code**: Formato `PK-YYYYMMDD-0001` -- **Control de disponibilidad**: Triggers mantienen sincronizada la tabla `parking_availability` -- **Integridad referencial flexible**: SET NULL para preservar historial - -### Scheduling - -- **Gestión de turnos mensuales**: Meses en estado `draft` o `published` -- **Bloqueo de celdas**: Assignments con `source_constraint_id` están bloqueados -- **Validación en tiempo real**: Validator evalúa constraints - ---- - -## 🆘 TROUBLESHOOTING - -### Error: "Foreign key constraint fails" - -- Asegúrate de ejecutar los scripts en orden -- Verifica que la tabla `users` existe antes de crear `parking_bookings` - -### Error: "Trigger already exists" - -- Los scripts incluyen `DROP TRIGGER IF EXISTS` - -### Error: "Function does not exist" - -- Verifica que ejecutaste `05_parking_functions_triggers.sql` - -### Disponibilidad no se actualiza (Parking) - -```sql -CALL sync_parking_availability(); -SHOW TRIGGERS LIKE 'parking_bookings'; -``` - ---- - -## 📞 NOTAS IMPORTANTES - -1. **Backup**: Siempre haz backup antes de cualquier migración -2. **Orden**: Los scripts DEBEN ejecutarse en orden -3. **UTF-8**: Todos los scripts usan `utf8mb4_0900_ai_ci` (MySQL 8.0+) -4. **Passwords**: Cambia las contraseñas por defecto -5. **Producción**: Revisa y ajusta las tarifas según tu negocio - ---- - -**Última actualización**: Febrero 2026 -**Versión**: 2.0 -**Estado**: ✅ Producción diff --git a/backend/db-mysql/README.md b/backend/db-mysql/README.md index c9c83c01..d13f342d 100644 --- a/backend/db-mysql/README.md +++ b/backend/db-mysql/README.md @@ -36,7 +36,6 @@ db-mysql/ ├── MASTER_INSTALL.sql # Snapshot 2026-05-20 (base congelada) ├── INDEX.md # Índice general + tabla de incrementales ├── MIGRATIONS_POLICY.md # Política vigente -├── MIGRATION_GUIDE.md # Guía de instalación └── README.md # Este archivo ``` @@ -45,15 +44,14 @@ db-mysql/ ### Instalación completa ```bash -# Un solo comando (recomendado) -mysql -u root -p < MASTER_INSTALL.sql - -# O desde el directorio aiven/ -cd aiven/ -mysql -u root -p < 01_create_database.sql -# ... ejecutar en orden +# Desde backend/: tablas, migraciones, admin local y datos ficticios +pnpm setup:local ``` +No ejecutes `MASTER_INSTALL.sql` a mano: borra `hotel_db`, no aplica las +migraciones de `scripts/` y tiene dos fallos del baseline que solo +`setup:local` corrige (ADR-039). + ### Verificación ```bash @@ -142,7 +140,7 @@ WHERE status = 'completed' ## 🆘 Troubleshooting -Ver [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md) para solución de problemas comunes. +Una instalación que falla: vuelve a lanzar `pnpm setup:local -- --force` (ver «Instalación completa»). --- @@ -156,7 +154,7 @@ Ver [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md) para solución de problemas comunes ## 🔗 Enlaces Útiles -- [Guía de Migración](MIGRATION_GUIDE.md) +- [Política de migraciones](MIGRATIONS_POLICY.md) - [Índice de Tablas](INDEX.md) - [Script de Verificación](aiven/99_verification.sql) diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index 0711f117..e3261d3a 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -842,3 +842,31 @@ cero, se corrigen en `setup:local` y con `20261005_complete_fresh_install.sql` sin tocar `aiven/` (ADR-021). - **Revisa:** ADR-015 en la BD local. + +## ADR-040 — La documentación obsoleta se archiva fuera del repositorio + +- **Estado:** ✅ aceptada (2026-10-05) +- **Fecha:** 2026-10-05 +- **Decisión:** un documento que ya no describe el proyecto se mueve a + `docs/_archive/- Made with Next.js, TypeScript, and TailwindCSS -
+The product documentation lives in [`docs/`](../docs/general/README.md). diff --git a/frontend/app/dashboard/conciliation/nota.md b/frontend/app/dashboard/conciliation/nota.md deleted file mode 100644 index e5f24e71..00000000 --- a/frontend/app/dashboard/conciliation/nota.md +++ /dev/null @@ -1,15 +0,0 @@ -### Tengo que implementar una descripción en cada entrada de la conciliación. - -Por ejemplo: Habitaciones que estaban OOO (restan) - -En este caso, las habitaciones marcadas como “OOO” (fuera de orden) deben llevar siempre una descripción, ya que su contabilización implica una resta en el sistema. - -Por ejemplo, una habitación puede no haberse limpiado el día anterior debido a un problema de mantenimiento. Sin embargo, dicho día se registró como “habitación limpiada pendiente” (LS), es decir, se consideró como si ya estuviera realizada. - -Por tanto, no puede incluirse nuevamente dentro del total de habitaciones facturadas de hoy, ya que su limpieza fue contabilizada previamente. - -En la sección “Total de habitaciones realmente limpiadas por Pisos” estas habitaciones sí aparecerán, ya que el departamento de Pisos registra todas las limpiezas efectivamente realizadas. - -Por este motivo, Recepción debe restar estas habitaciones del total indicado por Pisos, para reflejar correctamente la facturación del día actual y evitar duplicidades. - -### La descripción en este caso podría ser: Habitaciones que estaban fuera de orden (OOO) y fueron limpiadas posteriormente. Se restan porque su limpieza ya fue contabilizada en el día anterior. (LS pendientes) diff --git a/frontend/messages/cmd.md b/frontend/messages/cmd.md deleted file mode 100644 index 52ab98a8..00000000 --- a/frontend/messages/cmd.md +++ /dev/null @@ -1 +0,0 @@ -rg "electronic" frontend/messages/