Servidor de Reporting
1. Introducción i objetivos
El sistema sirve para gestionar plantillas de reporte y generar documentos como facturas, albaranes, pedidos...
Objetivos principales:
- Agilizar la edición de plantillas.
- Agilizar la generación de documentos.
- Generar diferentes tipos de archivo con una misma plantilla.
2. Requisitos y convenciones
2.1. Requisitos funcionales
| ID | Requisito |
|---|---|
| RF1 | Tiene que haber un endpoint que dada un nombre de plantilla y un conjunto de datos genere un report. |
| RF2 | Las plantillas deben de guardarse en una carpeta en el servidor |
| RF3 | Debe generar como mínimo en formato PDF. |
| RF4 | La respuesta del endpoint que genera el report debe er la ruta al archivo generado. |
| RF5 | Se tiene que poder insertarle un código de barras. |
| RF6 | Se deben de poder imprimir reports de forma individual. (1 documento -> 1 pdf). |
| RF7 | Se ha de establecer el numero de días que los documentos quedan en el servidor. |
| RF8 | Formatos soportados: A4, A5. Vertical u horizontal. |
| RF9 | Los documentos tienen que poder tener número de página en formato: "Pág n de m". |
| RF10 | Los documentos deben de poder tener sumatorios al inicio y fin de las tablas de datos para saber el valor acumulado. |
| RF11 | Las plantillas que se pueden guardar deben de ser en formato ODT, DOCX y XLSX. |
2.2. Requisitos no funcionales
| ID | Requisito |
|---|---|
| RNF1 | El servidor debe funcionar en Linux, Windows y Mac. |
| RNF2 | El servicio debe ejecutarse en un contenedor de Docker. |
| RNF3 | Las plantillas y los reportes generados deben estar en un volumen de Docker. |
| RNF4 | Rendimiento objetivo: menos de 5 segundos por report. |
| RNF5 | Medida de los archivos generados: menos de 200 Kb. |
2.3. Convenciones
| ID | Restricción | Trasfondo y motivación |
|---|---|---|
| C1 | Documentación de arquitectura | Estructura basada en la plantilla arc42 |
| C2 | Código | El proyecto usa las guías de estilo de JavaScript de Google (https://google.github.io/styleguide/jsguide.html) |
| C3 | Idioma | La documentación está en Español y el código en inglés. |
| C4 | Plantillas | Usamos Carbone.io para guiarnos en la construcción de las plantillas Style guide to design a report(https://help.carbone.io/en-us/article/style-guide-to-design-a-report-z8lv57/). Documentation(https://carbone.io/documentation.html). |
| C5 | Códigos de barras | Los tipos de código de barras que usamos són el ean13 y el code128. Si se quiere usar un código de barras se debe poner en el body como "barcode" y en el "barcodeType" el tipo de código de barras. Sólo se pueden añadir en pdf. |
3. Estrategia de soluciones
- Tencologias del servicio
- Visual Studio Code: IDE.
- Node.js 16.x: entorno del servicio.
- Express.js: framweork de node.js para hacer APIs.
- Carbone.js: generador de reportes.
- Multer 1.4.5: middleware para gestionar archivos en node.
- uuidv4 6.2.13: creador de UUIDs.
- pdf-lib 1.3.1: crear y modificar documentos pdf en javascript.
- node-schedule 2.1.1: programador de tareas para node.js.
- Docker: Automatiza el despliegue de apps y servicios dentro de contenedores para que se puedan ejecutar en distintos sistemas operativos.
4. Vista de bloques
4.1. Nivel 1 - Vista General
El sistema se compone de:
- API de generación de reportes: Servicio de Node.js que maneja solicitudes para gestionar plantillas y para generar reportes.
- Sistema de almacenamiento: Volumen de Docker donde se almacenan las plantillas y reportes en la máquina host.
- Servicio de plantillas: Módulo que maneja la carga y gestión de plantillas.
4.2. Nivel 2 - Vista Detallada
- API:
POST /template: Guarda una plantilla. Se debe pasar el nombre de la plantilla por headers y por el body el archivo a pasar. Admite archivos con formato ODT, DOCX, PDF y XLSX. Se almacena en el volumen de Docker dentro de /reports/out/.POST /report?plantilla=nombrePlantilla&formato=formatoDeSalida: Genera un reporte basado en una plantilla y datos proporcionados.
- Sistema de alamcenamiento:
- Volumen docker montado en '/...'
5. Vista de despliegue
5.1 Cómo ejecutar y desplegar el servicio?
Sin docker:
- Si lo usas sin docker necesitareis instalar el LibreOffice para la conversión de pdfs. Lo podéis hacer desde aquí
- La versión de node que se ha usado es la 18, por lo tanto para que funcione todo correctamente deberias usar esta versión.
- Ejecutar:
- npm install
- npm start
- Ya estará escuchando en el puerto 3000. Los ficheros se guardaran en la carpeta del proyecto /reports y /logs.
Con Dockerfile:
- Si no existen las carpetas, se deben crear con permisos de lectura y escritura. Debes crear varias carpetas:
- /reports
- /reports/out
- /reports/barcode
- /reports/plantillas
- /logs
- /reports
- Añadir parámetros en el Dockerfile si no están:
ENV TEMPLATE_PATH=./reports/plantillas/
ENV OUT_PATH=./reports/out/
ENV BARCODE_PATH=./reports/barcode/
- Construir imagen de Docker:
docker build -t report-server .
- Ejecutar el contenedor (en el source del mount deben ir las variables de entorno que has definido antes en el Dockerfile pero en los reports sin el /out):
docker run --platform linux/amd64 -d --name report-server --mount type=bind,source="$HOME/reports",target=/app/reports --mount type=bind,source="$HOME/logs",target=/app/logs -p 3000:3000 report-server
Dónde $HOME/reports y $HOME/logs son las carpetas del host que se enlazarán con el volumen del contenedor para guardar reports y logs. Si no se añade "--platform linux/amd64" dará un warning en ordenadores con procesador arm64. El mount sirve para mapear la ruta del host a la ruta del contenedor para poder añadir y quitar plantillas manualmente.
- Para detener:
docker stop report-server
Con Docker Compose:
- Debes hacer el paso 1 del despliegue del servicio con el Dockerfile.
- Ahora debes añadir los parámetros en el docker-compose.yml. Por ejemplo:
vincoteam-reporting-api:
image: girosystem.azurecr.io/vincoteam-reporting-api:alpha
restart: unless-stopped
container_name: vincoteam-reporting-api
ports:
- "3000:3000"
volumes:
- /ruta/host/a/reports:/app/reports
- /ruta/host/a/logs:/app/logs
environment:
- REPORTS_HOST_FOLDER=/ruta/host/a/reports/out
- LOGS_HOST_FOLDER=/ruta/host/a/logs
- Para iniciar, ejecutar los comandos:
docker compose -f docker-compose-alpha.yml pull
docker compose -f docker-compose-alpha.yml up -d --remove-orphans
- Para detener, ejecutar el comando:
docker-compose down
5.2. Entornos
- Desarrollo: Docker en local.
- Producción: Servidor de producción con Docker.
5.3. Flujo de despliegue de nuevas versiones
- Realizar cambios en el código.
- Construir una nueva imagen de Docker.
- Detener y eliminar el contenedor antiguo.
- Ejecutar un nuevo contenedor con la nueva imagen.
6. Conceptos transversales (Cross-cutting)
6.1. Persistència
Los reportes y las plantillas se almacenan en un volumen de Docker.
6.2. Interfície de usuàrio
No aplicable para este servicio.
6.3. Transacciones
Cada generación de reporte es una transacción única.
6.4. Seguridad
Asegurar que el servicio esté detrás de un firewall y utilizar HTTPS.
6.5. Gestión de errores
Registrar todos los errores y manejar adecuadamente las excepciones.
6.6. Logging
Implementar un sisdema de logging para las solicitudes y los errores.
6.7. Configuraciones
Se usan variables de entorno para definir el puerto en el que escucha el servicio y las rutas de las carpetas dónde se guardan las plantillas y los reportes. Se guardan en el environment.env.
6.8. Localización
El idioma de los reportes dependen de los datos que le pasamos por el body y de las plantillas en si.
Lo que se puede editar es pasándole un campo "lang" en el json del body dónde si por ejemplo en la plantilla pones un formateador para que te lo detecte como valor de moneda, entonces si le pasas "en-us" te dará $, si le pasas "es-es" té pondrá €.
6.9. Testing
El test se ha hecho con jest.
Para ejecutarlo se hace así:
npm test