- 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
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 |
| 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)→ Devuelvestatusreppassuser(user_mail, new_pass)→ Devuelvestatus
Empleados
getemployees()→ Lista con paginación manual (LIMIT/OFFSET)activeemployeesnumber()→ Total de activosgetoneemployee(rfcEmployee)→ Un empleadonewemployee(...12 params...)→ Inserta empleadoupdateemployee(...12 params...)→ Actualiza empleadogetattendance()→ 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 mesnearexpiring(),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 masivamentegetcategoryincome(),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())
- Listar transfers (
- 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
localStoragebajo 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
- Se sube archivo CSV o XLSX a
src/resources/littleHotelier/ - Endpoints
POST /api/incomes/loadincomes,/loadproductsales,/loadchequesdetalle - Los controllers leen el archivo, lo parsean y llaman funciones SQL que reciben
jsonb - PostgreSQL procesa e inserta los datos masivamente
8.2 Sincronización de Facturas (Horux)
- Endpoint
POST /api/incomeshrx/insertinvoice - Controller calcula fechas: inicio de año → hoy
- Llama API externa de facturas con esas fechas
- Recibe JSON y lo pasa a
addhoruxdata($1::jsonb) - PostgreSQL inserta/actualiza facturas
8.3 Sincronización de Stripe
- Endpoint
GET /api/incomeshrx/stripedata/ - Llama
stripe.transfers.list() - Serializa a JSON y pasa a
addstripedatav2($1::jsonb) - PostgreSQL inserta transacciones
8.4 Emails Programáticos
- Los endpoints en
/api/emails/*tienen lógica de "una ejecución por mes" - Usan la función
validateendpoint(endpoint_name)en PostgreSQL - Esta consulta una tabla
endpoint_logspara ver si ya se ejecutó - 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 envite.config.js) - Hosts permitidos:
hacienda.consultoria-as.com,hotel.consultoria-as.com
10. BUGS Y DEUDA TÉCNICA CONOCIDA
🔴 Críticos
-
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.
-
useAuthno existe pero se intenta importarAuthContext.jsxNO exportauseAuth.ProtectedRoute.jsxyNavbar.jsxintentan importarlo.- Impacto: Crash si se renderizan esos componentes.
-
Ruta malformada en backend
product.routes.js:router.put('updatesupplier/:id', ...)le falta/inicial.- Impacto: Ese endpoint nunca funcionará correctamente.
-
URLs hardcodeadas en services del frontend
incomeService.js,contractService.js,userService.js,employeeService.jsapuntan ahttp://localhost:3000ohttp://localhost:4000.- Impacto: Rompen en producción.
-
Método HTTP incorrecto
expense.routes.js:PUT /getexpense/:iddebería serGET.
🟡 Medios
-
No hay
ProtectedRouteactivo enApp.jsx- Todas las rutas internas son accesibles sin login.
-
Mezcla de
fetchyaxios- No hay estándar. Algunas páginas usan
fetch, otrasaxios, otras la instanciaapi.js.
- No hay estándar. Algunas páginas usan
-
Código comentado masivo
Layout.jsxtiene ~300 líneas comentadas.- Varios controllers y páginas tienen versiones antiguas comentadas.
- Impacto: Dificulta lectura y aumenta bundle size innecesariamente.
-
multeren frontend- Es un middleware de Node.js, no tiene sentido en React. Debería estar solo en backend.
-
Paginación manual en controllers
- Se hace
COUNT(*)+LIMIT/OFFSETmanual en cada controller. - Riesgo: Si dos personas agregan paginación de forma distinta, la API se vuelve inconsistente.
- Se hace
🟢 Leves
- No hay tests (ni unitarios ni e2e).
- No hay TypeScript — riesgo de errores de tipo en runtime.
- Tailwind instalado pero poco usado — la mayoría de estilos son CSS puro o Bootstrap.
- 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:
-
¿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.
-
¿Es un nuevo endpoint?
- Sigue el patrón existente:
route→controller→pool.query('SELECT funcion_sql($1)'). - Usa queries parametrizadas (
$1,$2) para evitar SQL Injection. - AGREGA la ruta en
app.jscon el prefijo/api/.
- Sigue el patrón existente:
-
¿Es un cambio en el frontend que consume datos?
- Verifica si la página usa
fetch,axioso la instanciaapi.js. - Si usas
fetch, usaimport.meta.env.VITE_API_BASE_URL. - NO hardcodees
localhost.
- Verifica si la página usa
-
¿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 enactiveSectiondeLayout2.jsx.
- Hay DOS lugares donde tocar:
-
¿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ámetrosjsonb.
-
¿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_logso modificar la función SQL.
- Los endpoints de email tienen validación de frecuencia (
-
¿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.jsconapp.use('/api/...', ...)? - ¿Usé
pool.querycon 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.jssi es una nueva sección? - ¿Actualicé
Layout2.jsxpara detectar la nueva ruta enactiveSection? - ¿Usé
import.meta.env.VITE_API_BASE_URLen vez delocalhost? - ¿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"
- Frontend: Modifica la página JSX donde está el formulario.
- Backend: Modifica el controller para recibir el nuevo campo en
req.body. - Base de datos: Modifica la función SQL para aceptar el nuevo parámetro.
- Verificación: Busca con
greptodos los lugares donde se llama esa función SQL.
"Quiero agregar una nueva página"
- Crea el componente en
src/pages/[dominio]/Nombre.jsx. - Agrégalo en
src/App.jsxdentro de<Route path="/app" element={<Layout />}>. - Si va en el menú:
- Agrégalo en
menuconfig.jsen la sección correspondiente. - Verifica permisos en
Layout2.jsx. - Agrega detección de ruta en
activeSectiondeLayout2.jsx.
- Agrégalo en
- Crea el endpoint backend si es necesario.
"Quiero modificar la lógica de un reporte"
- NO modifiques el controller para cambiar lógica de filtrado/agrupación.
- Modifica la función SQL que genera el reporte.
- El controller solo pasa parámetros (fechas, filtros) y devuelve lo que PostgreSQL responda.
"Quiero cambiar quién ve qué"
- Edita
Layout2.jsx, líneas ~18-36. - Los permisos usan números de rol. Asegúrate de entender qué número corresponde a qué usuario.
- 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_CORSincluya 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:
- Unificar HTTP client: Estandarizar todo en
api.js(axios) con interceptores para errores. - Eliminar código comentado: Especialmente
Layout.jsxy páginas grandes. - Arreglar
useAuth: Exportar un hookuseAuthdesdeAuthContext.jsx. - Arreglar ruta malformada:
updatesupplier/:id→/updatesupplier/:id. - Eliminar
multerdel frontend y mover lógica de upload al backend si es necesario. - Agregar middleware de autenticación mínimo (API key o JWT) en rutas sensibles.
- 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.