Arquitectura de backoffice: gestión de facturas de proveedor
Cómo diseñamos el módulo de backoffice: cuatro entidades, flujo de validación de facturas, editor de PDFs con sellos digitales, pagos automáticos y exportación.
El módulo de backoffice gestiona el flujo completo de facturas de proveedor: desde que llega la factura hasta que se paga, se archiva y se exporta para contabilidad. Este artículo describe las decisiones de arquitectura que convierten un simple CRUD de facturas en una herramienta de gestión financiera real.
→ Contexto de negocio: el backoffice es uno de los módulos administrativos del sistema HotelCode.
Cuatro entidades, un flujo coordinado
El modelo de datos gira en torno a cuatro entidades principales:
Categorías de coste — el primer nivel de clasificación. Cada factura se asigna a un centro de coste (Food & Beverage, Maintenance, Rooms, Admin…) y un departamento dentro de ese centro. Las categorías son datos de referencia: se crean una vez y se usan como filtro en todos los listados y reportes.
Proveedores — el maestro de vendors. Cada proveedor tiene sus datos fiscales (CIF), cuenta bancaria, método de pago habitual (transferencia o domiciliación), periodicidad de facturación (mensual, bimestral, trimestral, anual, bajo demanda) y una categoría por defecto que las facturas nuevas heredan automáticamente. Los proveedores se pueden activar o desactivar sin perder el historial de facturas asociadas.
Facturas — la entidad central. Cada factura tiene su número, importe sin IVA, importe con IVA, porcentaje de IVA, fechas clave (emisión, recepción, periodo de facturación, vencimiento, pago) y un estado que evoluciona a lo largo de un flujo de trabajo: pending → validated → paid. Además, cada factura almacena dos PDFs en Cloudinary: el PDF original del proveedor y el PDF validado (estampado y firmado por el hotel).
Activos (sellos y firmas) — imágenes PNG/WebP que se usan para validar facturas. Hay dos tipos: sellos (el sello oficial del hotel) y firmas (la firma del responsable). Se suben una vez, se marcan como predeterminados y quedan disponibles para el editor de PDFs.
El flujo de trabajo de una factura
El ciclo de vida de una factura sigue un flujo estricto con transiciones controladas:
1. Creación
El administrador crea la factura con los datos básicos: número, proveedor, importes, fechas. La categoría y el método de pago se heredan del proveedor si no se especifican. Se escribe una fila en el log de historial (bo_invoice_history) con la acción created.
2. Carga del PDF
El administrador sube el PDF original del proveedor. El fichero se recibe con multer, se valida (máximo 10MB, solo PDFs) y se sube a Cloudinary en la carpeta backoffice/invoices/. La URL firmada de Cloudinary nunca llega al navegador: el backend la almacena y sirve el fichero a través de un proxy (GET /api/backoffice/invoices/:id/pdf-download).
3. Validación (el paso clave)
Cuando el administrador valida una factura, ocurre algo interesante: si la factura tiene un PDF original, se abre el editor de PDFs. Este editor, implementado en el frontend con pdfjs-dist para renderizar y pdf-lib para modificar, permite:
- Arrastrar y soltar sellos y firmas desde los activos del hotel
- Redimensionar y rotar los elementos con handles visuales
- Añadir anotaciones de texto y resaltados
- Navegar por páginas múltiples con zoom
- Deshacer hasta 5 estados atrás
Cuando el administrador guarda, los elementos se “hornean” en el PDF (se convierten en parte permanente del documento), el PDF modificado se sube a Cloudinary como type=validated, y la factura pasa a estado validated. Si la factura no tiene PDF, un diálogo de confirmación advierte y valida directamente.
4. Desvalidar
Si hay un error, el administrador puede revertir la validación (validated → pending) y corregir los datos o el PDF.
5. Pago individual
Una factura validada se puede marcar como pagada con la fecha de pago. Solo las facturas en estado validated pueden pagarse.
6. Pago por lotes (batch pay)
El administrador puede seleccionar todas las facturas validadas de un mes y marcarlas como pagadas en una sola operación. El sistema escribe una fila de historial por cada factura y registra quién ejecutó el pago por lotes.
7. Pago automático por cron
Hay un cron job que se dispara el día 10 de cada mes a las 23:59 (hora de Madrid) y ejecuta automáticamente el pago por lotes de todas las facturas validadas del mes anterior. Esto coincide con el ciclo de pago típico en la hostelería española: las facturas del mes de enero se validan durante febrero y se pagan el 10 de marzo. Si el administrador quiere cambiar la fecha o revisar antes de que el cron se dispare, puede hacerlo manualmente; el cron es una red de seguridad, no una obligación.
8. Revertir pagos
Tanto el pago individual como el pago por lotes se pueden revertir. Si una factura se pagó por error, el administrador la revierte a estado validated y puede corregir o anular el pago real en el banco.
El PDF Editor: validación legal con sello digital
El editor de PDFs merece una mención aparte porque es lo que convierte el módulo en una herramienta de validación legal, no solo de seguimiento financiero. En España, las facturas de proveedores deben estamparse con el sello del hotel y firmarse por el responsable antes de archivarse como documento oficial. El PDF Editor replica este proceso en digital:
- Los sellos y firmas se gestionan como activos (se suben una vez, se usan muchas veces)
- El administrador arrastra el sello a la posición correcta en el PDF
- Añade la firma junto al sello
- Puede añadir anotaciones (número de autorización, fecha de validación, observaciones)
- El PDF resultante es el documento oficial validado
El PDF original del proveedor y el PDF validado se almacenan por separado en Cloudinary. Ambos son accesibles desde la interfaz, pero el que cuenta para contabilidad y auditorías es el validado.
Seguridad: los PDFs son privados
Un detalle arquitectónico importante: las URLs de Cloudinary son firmadas y nunca se exponen al navegador. El backend actúa como proxy:
- El cliente pide
GET /api/backoffice/invoices/:id/pdf-download?type=validated - El backend valida que el usuario está autenticado
- El backend descarga el PDF de Cloudinary usando la URL firmada (que solo el servidor conoce)
- El backend transmite el PDF al cliente como stream
Esto previene que alguien con acceso a la base de datos pueda descargar PDFs directamente de Cloudinary sin pasar por la autenticación. Además, hay validaciones de seguridad adicionales:
isOwnCloudinaryUrl()verifica que la URL almacenada pertenece al proyecto de Cloudinary del hotel (previene ataques SSRF donde alguien inyecta una URL externa)isPublicIdInFolder()asegura que solo se pueden eliminar/reemplazar ficheros en la carpetabackoffice/invoices/(previene que un bug o un ataque borre ficheros de otras partes del sistema)
Reporting y exportación
El módulo incluye varias capas de visibilidad financiera:
Dashboard de KPIs — seis tarjetas en la parte superior de la página muestran: facturas pendientes (cantidad y importe total), facturas vencidas, facturas pagadas este mes, total pagado histórico, y número de proveedores activos. Es la foto rápida del estado financiero.
Resumen mensual — una vista agregada por mes que muestra cuántas facturas se crearon, validaron y pagaron cada mes, con totales por estado. Útil para detectar tendencias o para preparar informes para la dirección.
Exportación a Excel — genera un workbook con dos hojas: “Facturas” (todos los datos de cada factura) y “Resumen” (totales agregados). El fichero se genera en el navegador con la librería xlsx, sin necesidad de round-trip al servidor.
Exportación a PDF — genera un PDF A4 apaisado con una tabla de facturas, cabecera con logo del hotel, filas alternas para legibilidad, y totales al pie. Útil para imprimir y llevar a reuniones o para archivar físicamente.
Exportación a CSV — la pestaña de facturas pagadas permite exportar hasta 50 facturas en formato CSV (separador punto y coma, compatible con Excel en español). Es el formato que piden muchos gestores externos para importar datos en sus sistemas de contabilidad.
Descarga ZIP de PDFs validados — el administrador puede seleccionar hasta 100 facturas validadas y descargarlas todas en un único ZIP. El backend descarga los PDFs de Cloudinary, los empaqueta con archiver (streaming, sin cargar todo en memoria) y devuelve el ZIP. El nombre de cada fichero sigue el formato {Proveedor}_{NumeroFactura}_{Mes}_validado.pdf, listo para archivar o enviar a contabilidad.
Auditoría: quién hizo qué y cuándo
Cada cambio de estado en una factura escribe una fila en bo_invoice_history:
created— quién creó la factura y cuándoupdated— qué campo se cambió, valor antiguo, valor nuevo, quién lo hizovalidated— quién validó la factura, cuándo, y notas de validaciónrejected— quién rechazó la factura y por qué (notas obligatorias)paid— quién marcó como pagada y en qué fechadeleted— quién eliminó la factura
El log de historial es append-only: no se puede modificar ni eliminar. Es la fuente de verdad para auditorías internas, reclamaciones de proveedores o revisiones de contabilidad.
Roles y permisos
El módulo está restringido al rol admin. No hay acceso para recepcionistas ni mantenimiento, porque el backoffice maneja datos financieros sensibles (importes, cuentas bancarias, pagos). El usuario demo puede explorar el módulo en modo lectura, pero no puede crear categorías ni subir ficheros (el middleware denyDemo bloquea esas operaciones).
En resumen
Para el director de hotel o el responsable de administración, lo importante es esto:
Antes: las facturas de proveedores llegaban por email, se imprimían, se sellaban a mano, se firmaban, se escaneaban, se guardaban en una carpeta física y se anotaban en un Excel de control.
Ahora: las facturas llegan y se registran en el sistema. El PDF del proveedor se sube directamente. Cuando se valida, el administrador abre el editor de PDFs, arrastra el sello del hotel y la firma, y guarda. El PDF validado queda archivado en el sistema, accesible en cualquier momento. No hay que imprimir, sellar, firmar, escanear ni archivar físicamente.
El día 10 de cada mes, el sistema paga automáticamente todas las facturas validadas del mes anterior. Si hay que revisar antes, el administrador puede hacerlo manualmente. Si hay que revertir un pago, se revierte con un clic.
Cuando el gestor externo pide un reporte, el administrador exporta a Excel, PDF o CSV con un clic. Cuando hay una auditoría, descarga un ZIP con todas las facturas validadas del periodo, con los sellos y firmas ya puestos, listo para entregar.
Y todo queda registrado: quién creó la factura, quién la validó, quién la pagó, cuándo, con qué notas.
Otros artículos técnicos
Arquitectura de checklists operativos: el procedimiento que vive en el sistema
Cómo diseñamos el módulo de checklists operativos: tres listas diarias, registro de ejecución, log de eventos, reinicio automático y procedimientos enlazados.
Arquitectura de seguridad: autenticación JWT y prevención de vulnerabilidades
Cómo implementamos la seguridad en Four-Points PMS: autenticación JWT con cookies HttpOnly, prevención de XSS/CSRF/SQL injection, rate limiting y protección contra ataques comunes.
Generación automática de turnos con Google OR-Tools (CP-SAT)
Cómo utilizamos Google OR-Tools con CP-SAT para generar cuadrantes completos de turnos en segundos, respetando decenas de restricciones laborales simultáneas.