Files
hotel-hacienda/docs/DATABASE.md
Consultoria AS 411d517ba4 docs: documentación extensiva del proyecto
- README.md con guía completa de instalación y arquitectura
- docs/BACKEND.md — guía detallada del API
- docs/FRONTEND.md — guía del SPA React
- docs/DATABASE.md — funciones SQL y patrones de datos
- docs/API.md — referencia completa de endpoints REST
- docs/DEPLOYMENT.md — guía de despliegue en producción
- docs/TROUBLESHOOTING.md — solución de problemas comunes
- CHANGELOG.md — historial de cambios
- CONTRIBUTING.md — guía de contribución
2026-06-09 16:26:09 -07:00

14 KiB

🗄️ Documentación de Base de Datos — PostgreSQL

Índice

  1. Filosofía de Diseño
  2. Conexión
  3. Funciones SQL por Dominio
  4. Tablas Principales (Inferidas)
  5. Patrones de Datos
  6. JSONB como Patrón de Intercambio
  7. Integraciones que Escriben en JSONB
  8. Guía para Modificar Funciones SQL

Filosofía de Diseño

Este sistema sigue un patrón "Database-First" donde la lógica de negocio reside principalmente en funciones SQL almacenadas de PostgreSQL. Los controllers de Node.js actúan como una capa de presentación HTTP liviana que solo orquesta llamadas a estas funciones.

Implicaciones:

  • Para modificar lógica de negocio, debes modificar las funciones SQL, no solo el JavaScript.
  • Los controllers pasan parámetros posicionales ($1, $2) y reciben resultados directamente.
  • No hay ORM ni capa de abstracción de base de datos.

Conexión

El backend usa pg (node-postgres) con un Pool:

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
});

Variables de entorno requeridas: DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME.


Funciones SQL por Dominio

🔐 Autenticación

Función Parámetros Retorno Descripción
validarusuario(name_mail_user, user_pass) text, text {status, rol, user_id, user_name} Valida credenciales
createuser(name_user, id_rol, email, user_pass) text, int, text, text status Crea usuario
reppassuser(user_mail, new_pass) text, text status Reemplaza contraseña

👥 Empleados

Función Parámetros Retorno Descripción
getemployees() setof record Lista paginada de empleados
activeemployeesnumber() int Total de empleados activos
getoneemployee(rfcEmployee) text setof record Un empleado por RFC
newemployee(...) 12 parámetros status Inserta empleado
updateemployee(...) 12 parámetros status Actualiza empleado
getattendance() setof record Registros de asistencia

📄 Contratos

Función Parámetros Retorno Descripción
getcontracts() setof record Lista de contratos
getinfocontract(id) int setof record Info de un contrato
neartoend() setof record Contratos próximos a vencer
newcontract(...) varios status Crea contrato
updatecontract(...) varios status Actualiza contrato
positions() setof record Catálogo de puestos
areas() setof record Catálogo de áreas
bosses() setof record Catálogo de jefes

📦 Productos / Inventario

Función Parámetros Retorno Descripción
getproducts() setof record Lista de productos
getoneproduct(id) int setof record Un producto
newproduct(..., jsonb, ...) 11 parámetros status Crea producto
updateproduct(..., jsonb, ...) 12 parámetros status Actualiza producto
discardproductsstock(id, quantity, reasons) int, numeric, text status Descarta stock
getdiscardproduct() setof record Productos descartados
report_inventoryv2() setof record Reporte de inventario
stockadjusment() setof record Ajustes pendientes
setstockadjusmentsv2(jsonb) jsonb stockadjus Aplica ajustes
consumptionstock(product_id, quantity, date, rfc) varios status Registra consumo
getconsumptionreport() setof record Reporte de consumos
newsupplier(name, rfc, mail, phone) 4 parámetros status Crea proveedor
updatesupplier(id, name, rfc, mail, phone) 5 parámetros status Actualiza proveedor
disableSuppliers(id) int status Deshabilita proveedor
newsuplier(...) varios status (posible duplicado ortográfico)

💰 Gastos (Expenses)

Función Parámetros Retorno Descripción
newexpensev2(..., jsonb, ...) 14 parámetros status Crea gasto
updateexpensev4(..., jsonb) 15 parámetros status Actualiza gasto
getexpense(id) int setof record Obtiene un gasto
getpendingappexpenses() setof record Gastos pendientes de aprobación
getapprovedappexpenses() setof record Gastos aprobados
getrejectedappexpenses() setof record Gastos rechazados
setapprovalstatus(id, status, approved_by) 3 parámetros status Actualiza estado de aprobación
setpaymentstatusv2(id, status) 2 parámetros status Actualiza estado de pago
pendingapppayments() setof record Pagos pendientes
countdelaypayments() int Pagos con retraso
totalspent() numeric Total gastado
totalapproved() numeric Total aprobado
totalrejected() numeric Total rechazado
report_expenses() setof record Reporte de gastos
paymentsreport() setof record Reporte de pagos
mainsupplier() setof record Proveedor principal
gettaxes() setof record Catálogo de impuestos

🛒 Compras / Purchase Entries

Función Parámetros Retorno Descripción
getpurchases() setof record Detalles de compras pendientes
purchaseentry(id, checking) int, int status Registra recepción física

💳 Pagos Mensuales

Función Parámetros Retorno Descripción
newmonthlyexpensev2(...) 10 parámetros status Crea gasto mensual
updatemonthlyexpensev2(...) 11 parámetros status Actualiza gasto mensual
setpaymentstatusmonthlyv2(id, status) 2 parámetros status Actualiza estado de pago
setpaymentstatusmonthlyv2(id, status, tax_id, total) 4 parámetros status Actualiza estado y monto
refresh_monthly_expenses() status Refresca gastos mensuales
getmonthlypayments() setof record Lista de pagos mensuales
getONEmonthlypayment(id) int setof record Un pago mensual
needToRefresh(id, boolean) 2 parámetros rows Controla actualización automática

📧 Emails Programáticos

Función Parámetros Retorno Descripción
validateendpoint(endpoint_name) text boolean Verifica si se puede ejecutar (1x/mes)
nearexpiring() setof record Contratos por vencer
paymentdelay() setof record Pagos atrasados
expensesneartodeadline() setof record Gastos próximos a fecha límite
expensesspecial() setof record Gastos especiales
birthdays() setof record Cumpleaños
contractexpired() setof record Contratos vencidos
expiredcontractsmonth() setof record Contratos vencidos del mes

📊 Ingresos (Little Hotelier)

Función Parámetros Retorno Descripción
getincomes(...) varios (filtros) setof record Lista de ingresos
totalincomes(...) varios numeric Total de ingresos
channelscards(...) varios setof record Canales de ingreso
loadincomes(jsonb) jsonb status Carga masiva de ingresos
loadproductsales(jsonb) jsonb status Carga masiva de ventas de productos
loadchequesdetalle(jsonb) jsonb status Carga masiva de cheques
reportincomes(...) varios setof record Reporte de ingresos
countticket(...) varios int Conteo de tickets
efectivo(...), otros(...), propinas(...), tarjeta(...), vales(...) varios numeric Desglose por tipo de pago
sumatotal(...) varios numeric Suma total
ticketpromedio(...) varios numeric Ticket promedio

🏨 Horux / Facturas / Stripe

Función Parámetros Retorno Descripción
addhoruxdata(jsonb) jsonb int (total insertados) Inserta facturas masivamente
getcategoryincome() setof record Categorías de ingreso
getinvoiceincome() setof record Facturas de ingreso
getaccountincome() setof record Cuentas de ingreso
getincomehorux() setof record Ingresos Horux
gettotalincome() numeric Total de ingresos Horux
getoneincome(id) int setof record Un ingreso Horux
newincome(account_id, amount, date, invoice, area_id, categories::jsonb) 6 parámetros status Crea ingreso Horux
updateincome(id, account_id, amount, date, invoice, area_id, categories::jsonb) 7 parámetros status Actualiza ingreso Horux
addstripedatav2(jsonb) jsonb int (inserted) Inserta datos de Stripe

📈 Hotel P&L / Restaurant P&L

Función Parámetros Retorno Descripción
cogs(...) varios (fechas) setof record Cost of Goods Sold
ebitda(...) varios setof record EBITDA
employeeshare(...) varios setof record Participación de empleados
grossprofit(...) varios setof record Ganancia bruta
tips(...) varios setof record Propinas
totalrevenue(...) varios setof record Ingresos totales
weightedCategoriesCost(...) varios setof record Costos ponderados por categoría

💱 Tipo de Cambio

Función Parámetros Retorno Descripción
consultexchange(...) varios setof record Consulta tipo de cambio
getexchanges() setof record Historial de tipos de cambio

⚙️ Configuraciones

Función Parámetros Retorno Descripción
newroom(...) varios status Crea habitación
newproperty(...) varios status Crea propiedad
reportrooms() setof record Reporte de habitaciones
reportproperties() setof record Reporte de propiedades
approveby() setof record Usuarios que pueden aprobar
requestby() setof record Usuarios que pueden solicitar
categoryexpense() setof record Categorías de gasto
currency() setof record Monedas
units() setof record Unidades de medida
recurrence() setof record Recurrencias (mensual, etc.)

Tablas Principales (Inferidas)

Basado en las funciones SQL y los controllers, las tablas principales son:

Tabla Propósito
employees Datos de empleados
contracts Contratos laborales
products Catálogo de productos
suppliers Proveedores
expenses Gastos/egresos
purchase_details Líneas de compra asociadas a gastos
inventory_entries / stock_movements Movimientos de inventario
incomes Ingresos de Little Hotelier
income_hrx Ingresos de Horux
invoice_income Facturas descargadas
stripe_data Datos de transfers de Stripe
users Usuarios del sistema
roles Roles de usuario
areas Áreas del hotel
positions Puestos de trabajo
endpoint_logs Control de ejecución de emails (1x/mes)
settings_rooms Habitaciones
settings_properties Propiedades

Patrones de Datos

Paginación Manual

-- En los controllers
SELECT * FROM getemployees() LIMIT $1 OFFSET $2;
SELECT COUNT(*) FROM employees;

Estados Numéricos

Muchas funciones retornan un status numérico:

  • 1 = Éxito
  • 0 = Error/No permitido
  • -3 = Condición no cumplida (ej. "gasto no aprobado")
  • Otros negativos = Errores específicos

JSONB como Patrón de Intercambio

El sistema usa extensivamente jsonb para pasar datos complejos:

Ejemplo: Productos en un Gasto

// Controller
const products = [
  { id_product: 1, quantity: 10 },
  { id_product: 2, quantity: 5 }
];
const productJson = JSON.stringify(products);

await pool.query(
  'SELECT newexpensev2($1,$2,$3,$4,$5,$6,$7,$8,$9,$10::jsonb,$11,$12,$13,$14)',
  [..., productJson, ...]
);

Ejemplo: Ajustes de Stock

const stockproductadjusment = [
  { id_product: 1, new_stock: 50 },
  { id_product: 2, new_stock: 30 }
];

await pool.query(
  'SELECT * FROM setstockadjusmentsv2($1::jsonb)',
  [JSON.stringify(stockproductadjusment)]
);

Ejemplo: Facturas Masivas

const facturas = await getFacturas(desde, hasta);
await pool.query(
  'SELECT addhoruxdata($1::jsonb)',
  [JSON.stringify(facturas)]
);

Integraciones que Escriben en JSONB

Integración Función SQL Tabla Destino
Little Hotelier (CSV/XLSX) loadincomes(jsonb) incomes
Facturas API (México) addhoruxdata(jsonb) income_hrx / invoice_income
Stripe addstripedatav2(jsonb) stripe_data

Guía para Modificar Funciones SQL

Paso 1: Verificar Dependencias

Busca TODOS los controllers que llaman a la función:

grep -r "nombrefuncion(" backend/hotel_hacienda/src/

Paso 2: Probar en PostgreSQL Directamente

SELECT * FROM nombrefuncion('param1', 'param2');
-- o
SELECT nombrefuncion('param1') AS status;

Paso 3: Considerar Idempotencia

Si la función modifica datos (INSERT/UPDATE), considera:

  • ¿Qué pasa si se llama dos veces con los mismos parámetros?
  • ¿Debería usar ON CONFLICT o verificar IF EXISTS?

Paso 4: Actualizar Controllers si Cambia la Firma

Si agregas/quitas parámetros, actualiza TODOS los pool.query(...) que la llaman.

Paso 5: Documentar el Cambio

Actualiza este archivo (docs/DATABASE.md) y DOCUMENTACION_TECNICA.md.