Files
hotel-hacienda/DOCUMENTACION_TECNICA.md
Consultoria AS f284a5ca27 feat: consolidación completa del proyecto + documentación técnica inicial
- Incluye backend API (Node.js + Express + PostgreSQL)
- Incluye frontend SPA (React 19 + Vite)
- Documentación técnica completa del sistema
- Configuración de entornos y variables de ejemplo
2026-06-09 16:13:11 -07:00

28 KiB

📘 DOCUMENTACIÓN TÉCNICA — Sistema Hotel Hacienda San Angel

Versión: 1.0
Fecha: 2026-06-09
Proyecto: /home/Hotel
Autor: Análisis automático del codebase


1. RESUMEN EJECUTIVO

Este es un sistema administrativo financiero y operativo para un hotel ("Hacienda San Angel"). Gestiona:

  • Ingresos (Little Hotelier, Stripe, facturas electrónicas, Horux)
  • Gastos (aprovisionamiento, pagos mensuales, aprobaciones)
  • Nómina (empleados, contratos, asistencia)
  • Inventario (productos, ajustes, salidas, descartes)
  • P&L (Hotel y Restaurante)
  • Configuraciones (habitaciones, propiedades, catálogos)

Arquitectura: Monolito clásico. Backend liviano en Express que delega casi toda la lógica de negocio a PostgreSQL mediante funciones SQL. Frontend SPA en React con Vite.

⚠️ Advertencia crítica: No hay ORM. Los controllers solo orquestan llamadas a funciones SQL. Si modificas algo en el backend sin conocer la función PostgreSQL correspondiente, romperás el sistema.


2. STACK TECNOLÓGICO

Backend (/home/Hotel/backend/hotel_hacienda/)

Capa Tecnología Versión
Runtime Node.js
Framework Express.js ^5.1.0
Base de datos PostgreSQL
Driver DB pg (node-postgres) ^8.16.3
ORM NINGUNO
HTTP client Axios ^1.13.2
Email Nodemailer ^7.0.12
Pagos Stripe SDK ^20.1.0
Excel/CSV xlsx, csv-parser ^0.18.5, ^3.2.0
Validación express-validator ^7.2.1
Dev Nodemon ^3.1.10

Frontend (/home/Hotel/frontend/Frontend-Hotel/)

Capa Tecnología Versión
Framework React ^19.1.1
Build tool Vite ^7.1.2
Router react-router-dom ^7.8.2
Estilos Tailwind CSS + Bootstrap 5 + CSS puro ^4.1.13, ^5.3.8
Forms react-hook-form + Yup ^7.66.1, ^1.7.1
HTTP Axios + fetch nativo ^1.11.0
Estado global React Context API
Excel export xlsx ^0.18.5
Íconos react-icons ^5.5.0

3. ESTRUCTURA DE CARPETAS

Backend

hotel_hacienda/
├── index.js                 # Solo requiere src/server.js
├── src/
│   ├── server.js            # Levanta servidor en PORT
│   ├── app.js               # Config Express, CORS, monta rutas /api/*
│   ├── db/
│   │   └── connection.js    # Pool de PostgreSQL (pg)
│   ├── middlewares/
│   │   ├── handleValidation.js
│   │   └── validators.js    # Solo valida login por ahora
│   ├── routes/              # 16 archivos de rutas
│   ├── controllers/         # 18 archivos de controllers
│   └── services/
│       └── mailService.js   # Transporte Nodemailer

Frontend

Frontend-Hotel/
├── index.html
├── vite.config.js
├── src/
│   ├── main.jsx             # Entry point (AuthProvider > LangProvider > BrowserRouter)
│   ├── App.jsx              # Definición de todas las rutas
│   ├── index.css            # Tailwind directives + estilos base
│   ├── constants/
│   │   └── menuconfig.js    # Menú de navegación con permisos
│   ├── context/
│   │   ├── AuthContext.jsx  # Estado de usuario (rol en localStorage)
│   │   └── LenguageContext.jsx  # Idioma EN/ES
│   ├── components/
│   │   ├── Layout2.jsx      # Layout activo (Sidebar + Topbar + Outlet)
│   │   ├── Sidebar.jsx
│   │   ├── Table/
│   │   │   └── HotelTable.jsx
│   │   ├── ExcelExportButton.jsx
│   │   ├── SummaryCard.jsx
│   │   ├── Modals/          # Confirmaciones genéricas
│   │   └── ...
│   ├── pages/               # ~50+ páginas por dominio
│   │   ├── Login.jsx
│   │   ├── Dashboard/
│   │   ├── Expenses/
│   │   ├── Inventory/
│   │   ├── Payroll/
│   │   ├── Income/
│   │   ├── Settings/
│   │   └── ...
│   ├── services/
│   │   ├── api.js           # Instancia axios (infrautilizada)
│   │   └── ...Service.js    # Algunos con URLs hardcodeadas a localhost
│   └── styles/              # CSS puro por página

4. BASE DE DATOS — EL CORAZÓN DEL SISTEMA

⚠️ ESTO ES LO MÁS IMPORTANTE: El backend NO tiene lógica de negocio en JavaScript. Los controllers llaman directamente a funciones SQL de PostgreSQL.

Patrón general de un controller

const pool = require('../db/connection');

const algunaFuncion = async (req, res) => {
  try {
    const { param1, param2 } = req.body;
    const result = await pool.query(
      'SELECT nombrefuncionsql($1, $2) AS status',
      [param1, param2]
    );
    const status = result.rows[0].status;
    res.json({ message: 'OK', status });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Error' });
  }
};

Conexión a PostgreSQL

// src/db/connection.js
const { Pool } = require('pg');
const pool = new Pool({
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME
});

Funciones SQL conocidas (mapeo por dominio)

Nota: Esta lista se deriva de las llamadas en controllers. Si necesitas modificar lógica de negocio, DEBES revisar primero la función en PostgreSQL.

Auth

  • validarusuario(name_mail_user, user_pass) → Devuelve {status, rol, user_id, user_name}
  • createuser(name_user, id_rol, email, user_pass) → Devuelve status
  • reppassuser(user_mail, new_pass) → Devuelve status

Empleados

  • getemployees() → Lista con paginación manual (LIMIT/OFFSET)
  • activeemployeesnumber() → Total de activos
  • getoneemployee(rfcEmployee) → Un empleado
  • newemployee(...12 params...) → Inserta empleado
  • updateemployee(...12 params...) → Actualiza empleado
  • getattendance() → Registros de asistencia

Contratos

  • getcontracts(), getinfocontract(id), neartoend()
  • newcontract(...), updatecontract(...)
  • positions(), areas(), bosses()
  • reportempcontract(), disabledcontract()

Productos / Inventario

  • getproducts(), newproduct(...), update_product(...)
  • productcategory(), producttype(), suppliers()
  • stockadjusment(), stockadjusmentset(...)
  • discardproduct(...), gdiscardproducts()
  • newconsumptionstock(...), getconsumptionstockreport()
  • newsuplier(...), updatesupplier(...)

Gastos

  • pendingapproval(), approvedexpenses(), rejectedexpenses()
  • newexpense(...), updateexpense(...)
  • mainsupplier(), getexpense(id), gettaxes()
  • reportexpenses(), reportpayments(), monthlypayments()
  • countpending(), totalapproved()

Status / Aprobaciones

  • approveupdate(id), paymentupdate(id)
  • penapppayments(), countdelaypay(), totalspent()

Pagos Mensuales

  • newexpmonthly(...), refreshmonthly()
  • paymentstatusmonthly(id), updateexpmonthly(...)
  • onemothlyexpense(id), needtorefresh(id)

Configuraciones

  • newroom(...), newproperty(...)
  • reportrooms(), reportproperties()
  • approveby(), requestby(), categoryexpense()
  • currency(), units(), recurrence()

Emails (envío limitado por tabla endpoint_logs)

  • validateendpoint(endpoint_name) → Controla ejecución 1 vez por mes
  • nearexpiring(), paymentdelay(), expensesneartodeadline()
  • expensesspecial(), birthdays(), contractexpired()
  • expiredcontractsmonth()

Ingresos (Little Hotelier + Horux)

  • getincomes(...), totalincomes(...), channelscards(...)
  • loadincomes(...), loadproductsales(...), loadchequesdetalle(...)
  • reportincomes(...), countticket(...), efectivo(...), otros(...)
  • propinas(...), tarjeta(...), vales(...), sumatotal(...), ticketpromedio(...)

Horux / Facturas / Stripe

  • addhoruxdata(jsonb) → Inserta facturas masivamente
  • getcategoryincome(), getinvoiceincome(), getaccountincome()
  • getincomehorux(), gettotalincome(), getoneincome(id)
  • newincome(...), updateincome(...)
  • addstripedatav2(jsonb) → Inserta datos de Stripe

Hotel P&L / Restaurant P&L

  • cogs(...), ebitda(...), employeeshare(...)
  • grossprofit(...), tips(...), totalrevenue(...)
  • weightedCategoriesCost(...)

Tipo de cambio

  • consultexchange(...), getexchanges()

Compras

  • getpurchases(), entry(id)

5. MAPA COMPLETO DE ENDPOINTS (Backend)

Prefijo base: /api

Auth → /api/auth

Método Ruta Controller Función SQL
POST /login auth.controller.js validarusuario($1,$2)
POST /createuser auth.controller.js createuser($1,$2,$3,$4)
POST /recoverpass auth.controller.js reppassuser($1,$2)

Empleados → /api/employees

Método Ruta Notas
GET / Paginación manual (?page=&limit=)
GET /activeEmployees
GET /getattendance
GET /gradeofstudy Tabla directa degreeofstudy
GET /relationship Tabla directa relationship_employee
POST /employee Obtiene un empleado por RFC
POST /newemployee 12 parámetros
POST /updateemployee 12 parámetros

Contratos → /api/contracts

Método Ruta Notas
GET /
GET /getinfocontract/:id
GET /neartoend
GET /positions
GET /areas
GET /bosses
GET /reportempcontract
GET /disabledcontract
POST /newcontract
PUT /updatecontract/:id

Reporte Contratos → /api/reportcontracts

Método Ruta
GET /

Productos → /api/products

Método Ruta Notas
GET /
GET /productcategory
GET /producttype
GET /suppliers
GET /gdiscardproducts
GET /reportinventory
GET /stockadjusment
GET /gethousekeeper
GET /getproducts
GET /getconsumptionstockreport
POST /newsupplier
POST /newproduct
POST /stockadjusmentset
POST /newconsumptionstock
POST /disableSupplier
PUT /update_product/:id
PUT /discardproduct/:id
PUT /product/:id
PUT updatesupplier/:id ⚠️ Falta / inicial en la ruta

Gastos → /api/expenses

Método Ruta Notas
GET /pendingapproval
GET /approvedexpenses
GET /rejectedexpenses
GET /mainsupplier
PUT /getexpense/:id ⚠️ Es PUT pero debería ser GET
GET /getinfo
GET /reportexpenses
POST /countpending
GET /reportpayments
GET /monthlypayments
POST /newexpense
POST /totalapproved
PUT /updateexpense/:id
GET /gettaxes

Status → /api/status

Método Ruta
PUT /approveupdate/:id
PUT /paymentupdate/:id
GET /penapppayments
GET /countdelaypay
GET /totalspent

Pagos Mensuales → /api/payment

Método Ruta
POST /newexpmonthly
GET /refreshmonthly
PUT /paymentstatusmonthly/:id
PUT /updateexpmonthly/:id
GET /onemothlyexpense/:id
PUT /needtorefresh/:id

Settings → /api/settings

Método Ruta
POST /newroom
POST /newproperty
GET /reportrooms
GET /reportproperties
GET /approveby
GET /requestby
GET /categoryexpense
GET /currency
GET /units
GET /recurrence

Emails → /api/emails

Método Ruta Notas
POST /nearexpiring Validado 1x/mes por endpoint_logs
POST /paymentdelay Validado 1x/mes
POST /expensesneartodeadline Validado 1x/mes
POST /expensesspecial Validado 1x/mes
POST /birthdays Validado 1x/mes
POST /contractexpired Validado 1x/mes
POST /expiredcontractsmonth Validado 1x/mes

Ingresos (Little Hotelier) → /api/incomes

Método Ruta Notas
POST /getincomes Recibe filtros de fecha en body
POST /totalincomes
POST /channelscards
POST /loadincomes Carga masiva desde CSV/XLSX
POST /loadproductsales
POST /loadchequesdetalle
POST /reportincomes
POST /countticket
POST /efectivo
POST /otros
POST /propinas
POST /tarjeta
POST /vales
POST /sumatotal
POST /ticketpromedio
GET /getproductsales
GET /getdetallecheque

Compras → /api/purchases

Método Ruta
GET /getpurchases
PUT /entry/:id

Tipo de Cambio → /api/exchange

Método Ruta Notas
POST /consultexchange Llama API Banxico
GET /getexchanges

Hotel P&L → /api/hotelpl

Método Ruta
POST /cogs
POST /ebitda
POST /employeeshare
POST /grossprofit
POST /tips
POST /totalrevenue
POST /weightedCategoriesCost

Restaurant P&L → /api/restaurantpl

Método Ruta
POST /cogs
POST /ebitda
POST /grossprofit
POST /totalrevenue
POST /weightedCategoriesCost

Ingresos Horux → /api/incomeshrx

Método Ruta Notas
GET /accountincome
GET /categoryincome
GET /invoiceIncome
GET /totalIncome
GET /incomehorux
GET /oneincomehorux/:id
GET /stripedata/ Obtiene transfers de Stripe y las guarda
POST /stripedatademo/ Crea transfer demo en Stripe
POST /insertinvoice Descarga facturas de API externa y las inserta
POST /newincome
PUT /updateincome/:id

6. INTEGRACIONES EXTERNAS

6.1 Banxico (Tipo de cambio USD/MXN)

  • Endpoint: https://www.banxico.org.mx/SieAPIRest/service/v1/series/SF43718/datos/...
  • Token: process.env.BANXICO_TOKEN
  • Uso: exchange.controller.js

6.2 Stripe

  • Secret Key: process.env.STRIPE_SECRET_KEY
  • Operaciones:
    • Listar transfers (stripe.transfers.list())
    • Insertar en DB mediante addstripedatav2(jsonb)
    • Crear transfers demo (stripe.transfers.create())
  • Uso: incomehrx.controller.js

6.3 API de Facturas (México)

  • URL: process.env.FACTURAS_API_URL
  • Parámetros: issuerRfc, type, initialDate, finalDate
  • Auth: Bearer token (FACTURAS_API_TOKEN)
  • Uso: Descarga facturas del año actual y las inserta vía addhoruxdata(jsonb)

6.4 Nodemailer

  • Host: Configurable por env (EMAIL_HOST, EMAIL_PORT, EMAIL_USER, EMAIL_PASS)
  • From: soporte@horuxfin.com
  • Uso: Recuperación de contraseña, emails programáticos (cumpleaños, contratos por vencer, etc.)

7. SISTEMA DE AUTENTICACIÓN Y ROLES

Backend

  • NO usa JWT. El login devuelve {rol, user_id, user_name, message}.
  • NO hay middleware de autorización en las rutas. Cualquiera puede llamar a cualquier endpoint si conoce la URL.
  • La función validarusuario(name_mail_user, user_pass) valida contra PostgreSQL.

Frontend

  • El rol se guarda en localStorage bajo la clave "rol".
  • Los permisos son numéricos y hardcodeados en Layout2.jsx:
Rol Nombre implícito Acceso
1 Admin Todo
2 Supervisor limitado Dashboards, Expenses (solo Report/Monthly Report), Payroll (Report/Attendance/Employees/Contracts), Expenses to be approved
3 Similar a supervisor (según rangos)
4 Payroll, Income
5 Compras/Proveedores Solo: New Expense, Purchase Entries, New Suppliers (en Expenses)
6 Housekeeper Forzado a español. Solo sección "Housekeeper" → Outcomes

Lógica de permisos en Layout2.jsx

section.label === "Dashboards" ? (user >= 1 && user <= 2 ? false : true) :
section.label === "Expenses to be approved" ? (user === 1 || user === 2 ? false : true) :
section.label === "Expenses" ? (user >= 1 && user <= 5 ? false : true) :
section.label === "Inventory" ? (user >= 1 && user <= 5 ? false : true) :
section.label === "Payroll" ? (user >= 1 && user <= 4 ? false : true) :
section.label === "Hotel" ? (user === 1 ? false : true) :
section.label === "Income" ? (user >= 1 && user <= 4 ? false : true) :
section.label === "Housekeeper" ? (user === 6 ? false : true) :
false

8. FLUJOS DE DATOS CRÍTICOS

8.1 Carga de Ingresos desde Little Hotelier

  1. Se sube archivo CSV o XLSX a src/resources/littleHotelier/
  2. Endpoints POST /api/incomes/loadincomes, /loadproductsales, /loadchequesdetalle
  3. Los controllers leen el archivo, lo parsean y llaman funciones SQL que reciben jsonb
  4. PostgreSQL procesa e inserta los datos masivamente

8.2 Sincronización de Facturas (Horux)

  1. Endpoint POST /api/incomeshrx/insertinvoice
  2. Controller calcula fechas: inicio de año → hoy
  3. Llama API externa de facturas con esas fechas
  4. Recibe JSON y lo pasa a addhoruxdata($1::jsonb)
  5. PostgreSQL inserta/actualiza facturas

8.3 Sincronización de Stripe

  1. Endpoint GET /api/incomeshrx/stripedata/
  2. Llama stripe.transfers.list()
  3. Serializa a JSON y pasa a addstripedatav2($1::jsonb)
  4. PostgreSQL inserta transacciones

8.4 Emails Programáticos

  1. Los endpoints en /api/emails/* tienen lógica de "una ejecución por mes"
  2. Usan la función validateendpoint(endpoint_name) en PostgreSQL
  3. Esta consulta una tabla endpoint_logs para ver si ya se ejecutó
  4. Si es válido, genera el email (consultando otras funciones SQL) y envía vía Nodemailer

9. VARIABLES DE ENTORNO

Backend (/home/Hotel/backend/hotel_hacienda/.env)

PORT=3000
URL_CORS=https://tudominio.com  # Sin slash al final

DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=******
DB_NAME=hotel_hacienda

EMAIL_HOST=smtp.tudominio.com
EMAIL_PORT=587
EMAIL_USER=soporte@horuxfin.com
EMAIL_PASS=******

STRIPE_SECRET_KEY=sk_******

FACTURAS_API_URL=https://api.facturas.com/...
FACTURAS_ISSUER_RFC=RFC_EMISOR
FACTURAS_TYPE=I  # o E
FACTURAS_API_TOKEN=token_aqui

BANXICO_TOKEN=token_banxico

Frontend (/home/Hotel/frontend/Frontend-Hotel/.env)

VITE_API_BASE_URL=http://localhost:4000/api

Frontend dev server

  • Puerto: 5172 (hardcodeado en vite.config.js)
  • Hosts permitidos: hacienda.consultoria-as.com, hotel.consultoria-as.com

10. BUGS Y DEUDA TÉCNICA CONOCIDA

🔴 Críticos

  1. Sin autenticación en endpoints backend

    • Cualquiera puede llamar a cualquier API si conoce la URL.
    • Impacto: Seguridad. No modifiques datos sensibles sin agregar al menos un middleware de API key o JWT.
  2. useAuth no existe pero se intenta importar

    • AuthContext.jsx NO exporta useAuth.
    • ProtectedRoute.jsx y Navbar.jsx intentan importarlo.
    • Impacto: Crash si se renderizan esos componentes.
  3. Ruta malformada en backend

    • product.routes.js: router.put('updatesupplier/:id', ...) le falta / inicial.
    • Impacto: Ese endpoint nunca funcionará correctamente.
  4. URLs hardcodeadas en services del frontend

    • incomeService.js, contractService.js, userService.js, employeeService.js apuntan a http://localhost:3000 o http://localhost:4000.
    • Impacto: Rompen en producción.
  5. Método HTTP incorrecto

    • expense.routes.js: PUT /getexpense/:id debería ser GET.

🟡 Medios

  1. No hay ProtectedRoute activo en App.jsx

    • Todas las rutas internas son accesibles sin login.
  2. Mezcla de fetch y axios

    • No hay estándar. Algunas páginas usan fetch, otras axios, otras la instancia api.js.
  3. Código comentado masivo

    • Layout.jsx tiene ~300 líneas comentadas.
    • Varios controllers y páginas tienen versiones antiguas comentadas.
    • Impacto: Dificulta lectura y aumenta bundle size innecesariamente.
  4. multer en frontend

    • Es un middleware de Node.js, no tiene sentido en React. Debería estar solo en backend.
  5. Paginación manual en controllers

    • Se hace COUNT(*) + LIMIT/OFFSET manual en cada controller.
    • Riesgo: Si dos personas agregan paginación de forma distinta, la API se vuelve inconsistente.

🟢 Leves

  1. No hay tests (ni unitarios ni e2e).
  2. No hay TypeScript — riesgo de errores de tipo en runtime.
  3. Tailwind instalado pero poco usado — la mayoría de estilos son CSS puro o Bootstrap.
  4. No hay manejo de estado de servidor (TanStack Query, SWR) — cada componente maneja su propio useEffect + fetch.

11. REGLAS DE ORO PARA NO ROMPER INTEGRIDAD

Antes de tocar cualquier archivo, pregúntate:

  1. ¿Es un cambio de lógica de negocio?

    • Si SÍ → Revisa la función SQL correspondiente en PostgreSQL ANTES de tocar el controller.
    • Los controllers solo orquestan. La lógica vive en la base de datos.
  2. ¿Es un nuevo endpoint?

    • Sigue el patrón existente: routecontrollerpool.query('SELECT funcion_sql($1)').
    • Usa queries parametrizadas ($1, $2) para evitar SQL Injection.
    • AGREGA la ruta en app.js con el prefijo /api/.
  3. ¿Es un cambio en el frontend que consume datos?

    • Verifica si la página usa fetch, axios o la instancia api.js.
    • Si usas fetch, usa import.meta.env.VITE_API_BASE_URL.
    • NO hardcodees localhost.
  4. ¿Es un cambio en roles/permisos?

    • Hay DOS lugares donde tocar:
      • frontend/src/components/Layout2.jsx (permisos del menú sidebar)
      • frontend/src/constants/menuconfig.js (estructura del menú)
    • Si agregas una nueva ruta en App.jsx, agrega su lógica de detección en activeSection de Layout2.jsx.
  5. ¿Es un cambio en la base de datos?

    • Si modificas una función SQL, verifica TODOS los controllers que la llaman.
    • Si cambias la firma de una función (nuevos parámetros), debes actualizar TODOS los pool.query(...) que la usan.
    • Los controllers pasan arrays/objetos como JSON.stringify() para parámetros jsonb.
  6. ¿Es un cambio en emails?

    • Los endpoints de email tienen validación de frecuencia (validateendpoint).
    • Si quieres probar un email múltiples veces, necesitas limpiar la tabla endpoint_logs o modificar la función SQL.
  7. ¿Es un cambio en integraciones externas (Stripe, Facturas, Banxico)?

    • Verifica las variables de entorno.
    • Los endpoints de Stripe y Facturas son destructivos (insertan masivamente).
    • Prueba en ambiente de desarrollo primero.

12. CHECKLIST ANTES DE HACER UN CAMBIO

Backend

  • ¿Agregué la ruta en src/app.js con app.use('/api/...', ...)?
  • ¿Usé pool.query con parámetros $1, $2?
  • ¿Si creé una función SQL nueva, la probé directamente en PostgreSQL?
  • ¿No rompí la firma de una función SQL existente?
  • ¿El método HTTP es coherente? (GET para leer, POST para crear, PUT para actualizar)
  • ¿El response mantiene la estructura esperada por el frontend?

Frontend

  • ¿Agregué la ruta en src/App.jsx?
  • ¿Agregué la entrada en menuconfig.js si es una nueva sección?
  • ¿Actualicé Layout2.jsx para detectar la nueva ruta en activeSection?
  • ¿Usé import.meta.env.VITE_API_BASE_URL en vez de localhost?
  • ¿Agregué la traducción EN/ES si es texto visible?
  • ¿Verifiqué que el rol apropiado pueda ver la nueva página?

Base de datos

  • ¿La función SQL compila y ejecuta correctamente?
  • ¿Los tipos de parámetros coinciden con lo que envía el controller?
  • ¿Si modifico una tabla, revisé las funciones que dependen de ella?

13. GUÍA DE CAMBIOS POR ÁREA

"Quiero agregar un nuevo campo a un formulario existente"

  1. Frontend: Modifica la página JSX donde está el formulario.
  2. Backend: Modifica el controller para recibir el nuevo campo en req.body.
  3. Base de datos: Modifica la función SQL para aceptar el nuevo parámetro.
  4. Verificación: Busca con grep todos los lugares donde se llama esa función SQL.

"Quiero agregar una nueva página"

  1. Crea el componente en src/pages/[dominio]/Nombre.jsx.
  2. Agrégalo en src/App.jsx dentro de <Route path="/app" element={<Layout />}>.
  3. Si va en el menú:
    • Agrégalo en menuconfig.js en la sección correspondiente.
    • Verifica permisos en Layout2.jsx.
    • Agrega detección de ruta en activeSection de Layout2.jsx.
  4. Crea el endpoint backend si es necesario.

"Quiero modificar la lógica de un reporte"

  1. NO modifiques el controller para cambiar lógica de filtrado/agrupación.
  2. Modifica la función SQL que genera el reporte.
  3. El controller solo pasa parámetros (fechas, filtros) y devuelve lo que PostgreSQL responda.

"Quiero cambiar quién ve qué"

  1. Edita Layout2.jsx, líneas ~18-36.
  2. Los permisos usan números de rol. Asegúrate de entender qué número corresponde a qué usuario.
  3. Si quieres ocultar un submenú específico, usa la lógica de submenu.map(...).

14. NOTAS DE DESPLIEGUE

Backend

cd /home/Hotel/backend/hotel_hacienda
npm install
node src/server.js   # o nodemon para dev

Frontend

cd /home/Hotel/frontend/Frontend-Hotel
npm install
npm run dev          # Puerto 5172
npm run build        # Genera dist/

Proxy / CORS

  • El backend permite CORS desde URL_CORS (definido en .env).
  • Si el frontend y backend están en dominios distintos, asegúrate de que URL_CORS incluya el dominio del frontend.

15. HALLAZGOS ESPECIALES

JSONB como patrón de intercambio

Muchos endpoints que manejan datos complejos (facturas, Stripe, productos con categorías) usan JSON.stringify() en el controller y funciones SQL que aceptan jsonb:

const categoriesJson = categories ? JSON.stringify(categories) : '[]';
await pool.query('SELECT newincome($1,$2,$3,$4,$5,$6::jsonb)', [...params, categoriesJson]);

Consecuencia: Si cambias la estructura del JSON en el frontend, DEBES actualizar la función PostgreSQL para parsearla correctamente.

Paginación manual consistente

El patrón usado es:

const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 500;
const offset = (page - 1) * limit;
// Query principal con LIMIT $1 OFFSET $2
// Query COUNT(*) para total
// Respuesta: { page, limit, total, totalPages, data }

Si agregas paginación a un endpoint nuevo, sigue EXACTAMENTE esta estructura de respuesta para que HotelTable.jsx u otros componentes la entiendan.


16. PRÓXIMOS PASOS RECOMENDADOS (NO URGENTES)

Si el usuario quiere mejorar la salud del proyecto, priorizaría:

  1. Unificar HTTP client: Estandarizar todo en api.js (axios) con interceptores para errores.
  2. Eliminar código comentado: Especialmente Layout.jsx y páginas grandes.
  3. Arreglar useAuth: Exportar un hook useAuth desde AuthContext.jsx.
  4. Arreglar ruta malformada: updatesupplier/:id/updatesupplier/:id.
  5. Eliminar multer del frontend y mover lógica de upload al backend si es necesario.
  6. Agregar middleware de autenticación mínimo (API key o JWT) en rutas sensibles.
  7. Documentar funciones SQL: Este documento lista las funciones conocidas, pero no sus firmas exactas en PostgreSQL.

Fin del documento. Si realizas cambios significativos en el sistema, actualiza este archivo para mantenerlo vivo.