# Caso Leaderbrock: app comercial con agenda, rutas y tickets | Alher Tech

> Cómo construimos la app comercial de Leaderbrock: Spring WebFlux, app con Expo, tickets que la IA deja en borrador, multimoneda, mapa GPS y datos cifrados.

- Canonical page: https://alhertech.com/es/blog/caso-estudio-leaderbrock/
- Site: Alher Tech (custom software, AI agents and SEO engineering, https://alhertech.com/)
- Contact: https://alhertech.com/es/contacto/

---

Casos de estudio · 26 oct 2026 · 11 min de lectura

Leaderbrock Sports es una agencia de marketing deportivo de Valencia con un equipo comercial repartido por Europa y América. Hemos construido la app con la que trabaja ese equipo: la agenda, la ruta del día y los gastos con la foto del ticket, y el panel web desde el que la oficina planifica, supervisa y aprueba. Lo hemos hecho entero, el backend, la web y la app, desde una demo navegable en mayo de 2026 hasta la versión del 26 de octubre de 2026.

## Tres procesos que vivían en una hoja de cálculo y un sobre

Antes de la app, el equipo planificaba la semana en una hoja de cálculo compartida, guardaba los tickets en un sobre y los apuntaba a mano, y en la oficina nadie sabía dónde estaba cada comercial durante un viaje. La app sustituye esos tres procesos, y cada perfil ve su parte.

- Los comerciales llevan la app del móvil: su agenda, sus tickets y su ruta.
- Finanzas revisa y aprueba los gastos, los exporta para la contabilidad y recibe los informes.
- Los managers ven su parte del organigrama, con su agenda, sus gastos y su gente en el mapa, pero no aprueban gastos.
- Los administradores lo ven todo, dan los roles y aprueban las solicitudes de acceso. Nadie se da de alta solo.

pantallas en la app del móvil55roles: admin, manager, finanzas y comercial4bases de código: el backend y un monorepo con la web y la app2commits desde mayo de 2026+1.200
## La arquitectura

Como en [Boathous](https://alhertech.com/es/blog/caso-estudio-boathous/), el backend es Java reactivo. La web y la app comparten un mismo cliente de la API y un mismo paquete de dominio, así que una regla como el formato de un importe o qué rol puede abrir qué pantalla se escribe una vez y vale en las dos.

La app de campo y el panel de oficina hablan con un único backend en Spring Boot, que guarda los datos en PostgreSQL, cifra los tickets en un almacenamiento compatible con S3, manda los tickets a la IA para leerlos y envía avisos por push y email.
Cómo encajan la app, el panel de oficina y el backend
| Pieza | Tecnología | Por qué |
| --- | --- | --- |
| Backend | Java 25, Spring Boot 4.1 con WebFlux, PostgreSQL con R2DBC, Flyway | Reactivo de punta a punta: el mapa en directo, los avisos y la lectura de tickets comparten un servicio |
| Panel de oficina | React 19, Vite 8, Tailwind 4, FullCalendar, MapLibre | Planificación, revisión de gastos y el mapa del equipo en pantalla grande |
| App | Expo SDK 57, React Native 0.85, Expo Router | Una sola base de código para iPhone y Android, con cámara, GPS en segundo plano, Face ID y notificaciones |
| Código compartido | Un monorepo con Bun: cliente de la API, dominio, stores y tokens de diseño | La lógica de las dos apps vive en un solo sitio y se prueba una vez |
| IA | Spring AI con Anthropic u OpenAI | La lectura de tickets y un asistente; el proveedor es un ajuste, no una reescritura |
| Ficheros | Almacenamiento compatible con S3, cifrado por la aplicación | Tickets y fotos solo salen por un endpoint autenticado |
| Avisos | FCM, Resend y WebSocket | Push, email y mensajes dentro de la app con un mismo contrato |

Backend y web funcionan como imágenes Docker en un servidor, con una copia de staging junto a producción. Cada despliegue pasa primero por staging, y la versión anterior no se retira hasta que la nueva dice que está sana. Los iPhone instalan la app con TestFlight y los Android descargan un APK que el administrador publica desde el panel; al arrancar, la app pregunta si hay una versión nueva y si actualizar es obligatorio. Una app interna no necesita una tienda pública.

## Un gasto a partir de la foto del ticket

Un comercial paga la comida con un cliente, hace una foto al ticket y sigue con su día. La app tiene su propia cámara, con guía de encuadre y flash, y también acepta una foto de la galería o un PDF de Archivos: JPEG, PNG, WebP, HEIC o PDF, hasta 15 MB.

- La IA lee el comercio, la base, el IVA y el total, la moneda, la fecha y la hora de compra, la ciudad y el país y la categoría. Sus instrucciones le piden dejar vacío lo que el documento no muestra y no adivinar nunca el total.
- Después el servidor comprueba las cuentas por su cuenta: la base más el IVA tiene que dar el total con un margen de dos céntimos, y una cifra que falte se calcula a partir de las otras dos.
- El resultado es un borrador, nunca un gasto presentado. El comercial ve lo segura que fue la lectura, corrige lo que esté mal y solo entonces lo presenta.
- La foto se sube y se lee en segundo plano, así que el comercial puede cerrar la app y le llega un aviso cuando está lista. Sin cobertura espera en una cola, y una clave de idempotencia por ticket hace que un doble toque o un reintento nunca creen dos gastos.
- Si un ticket se parece a otro que la misma persona ya presentó, con la misma fecha, importe y moneda, la app avisa antes de que entre dos veces.
- La app pregunta dónde es el ticket, aquí o en otro sitio, porque un ticket de la comida subido por la noche caía en el hotel. En otro sitio abre un mapa con la ruta y las paradas de ese día para elegir el lugar.

**La IA rellena, la persona presenta**

Ningún gasto llega a finanzas porque lo haya leído un modelo. El modelo rellena un borrador, el código comprueba sus cuentas, el comercial lo confirma y finanzas lo aprueba o lo rechaza con una nota.

## Del ticket a la contabilidad

Un gasto pasa por cuatro estados: borrador, pendiente, aprobado o rechazado. Finanzas y los administradores revisan toda la organización. Cada veredicto le llega al comercial por push, por email y dentro de la app, y queda en un registro de auditoría.

- Cada importe conserva su moneda. El panel y los informes dan un total por moneda y nunca suman euros con dólares.
- El CSV está pensado para el Excel en español: punto y coma, coma decimal, fechas como día, mes y año, y etiquetas legibles en vez de códigos.
- Los gastos aprobados salen como asientos contables, con la cuenta de gasto de cada categoría (por defecto las del Plan General Contable, todas configurables), la base, el IVA y su tipo.
- Cuando la empresa conecta Holded, un gasto aprobado se envía allí como documento de compra, una sola vez: un segundo envío se rechaza.
- Finanzas puede recibir un informe semanal o mensual en PDF, y descargarlo cuando quiera.

## Una agenda para un equipo en varios países

La agenda se parece a Google Calendar a propósito: es lo que el equipo ya conocía. Cada evento lleva el color del país de su dueño, el mismo en la web y en el móvil. Un comercial ve la agenda de su país y las reuniones a las que le invitan; los demás roles ven toda la organización.

- Una reunión invita a compañeros, que responden desde la app, y a invitados de fuera por email, con un enlace que caduca.
- Al cerrar una reunión, la app pregunta cómo fue: venta cerrada, interesado, seguimiento o sin interés, con una nota de hasta 2.000 caracteres y fotos de la visita. Sin cobertura, el cierre espera en una cola con lo escrito, y las fotos se suben solas después.
- Un ticket añadido desde una reunión se coloca en el lugar, el día y la ruta de esa reunión, sin leer el GPS.
- La agenda se pone al día cada minuto mientras está en pantalla y cada vez que la app vuelve, porque el equipo nos contó que a veces tenían que salir y volver a entrar para ver una reunión que acababan de crear.

**Un solo reloj: el del móvil**

Las horas siguen al dispositivo, y el dispositivo sigue a la persona: un comercial que vuela de Madrid a Dubái ve la app en hora de Dubái. Los eventos se guardan como la hora de pared con su zona horaria al lado y cada app los convierte, y una hora que escribe el usuario se pasa a un instante antes de enviarla, porque si no el servidor la leería como UTC.

## La ruta del día

El comercial inicia la ruta del día con un botón. Se finaliza sola como mucho a las ocho horas y se puede volver a iniciar. Administradores y finanzas ven a todo el equipo en un mapa en directo por WebSocket, un manager solo su parte del organigrama, y quien lleva más de cinco minutos sin dar señal aparece como desconectado.

- Una posición de GPS con una precisión peor que 100 metros se guarda, pero ni se pinta ni se mide.
- Una posición que supone hasta 160 km/h desde la última buena entra. Una más rápida espera hasta que las dos siguientes posiciones precisas la confirman a 1.200 km/h como mucho, así que un AVE o un vuelo se pintan y un salto aislado nunca. Esa segunda velocidad la añadimos en octubre, después de que una persona que había volado siguiera apareciendo horas en el origen.
- Una parada son más de 10 minutos a menos de 100 metros. El mapa del equipo enseña las paradas de cada persona, el inicio y el fin de su ruta, sus reuniones del día y sus gastos, en el color de esa persona.
- El filtro se aplica al leer los datos, no al guardarlos, así que cambiar la regla corrige también el pasado. Está escrito dos veces, en Java y en TypeScript, con los mismos casos de prueba, para que el mapa en directo y el histórico nunca discrepen.

Una posición de GPS con ruido no es un viaje. La guardamos, pero no la pintamos.

Las posiciones se borran a los 90 días. Geolocalizar a los empleados tiene su propia norma en España, el artículo 90 de la LOPDGDD, y antes de usar la app cada persona lee hasta el final y acepta la información previa que redactó el abogado de la empresa, con una constancia que no se puede alterar y un justificante.

## Datos personales, cifrados desde el principio

La app guarda nombres, emails y teléfonos de un equipo en varios países, fotos de sus tickets y sus posiciones. La diseñamos para que una copia de la base de datos o de los ficheros no le diga a nadie quién es quién.

- Cada campo personal se cifra en la base de datos con AES-256-GCM, con claves que se pueden rotar, y se encuentra con un índice ciego (un HMAC), así que buscar a alguien por su email funciona sin guardar el email en claro.
- Tickets, fotos y avatares se cifran en la aplicación antes de llegar al almacenamiento, y no hay enlaces públicos a ellos: solo salen por un endpoint autenticado que los descifra.
- Nadie se da de alta solo. Una cuenta nace de una solicitud de acceso que aprueba un administrador o de una invitación, y el rol de administrador nunca se ofrece en un formulario público.
- Acceso con contraseña, Google, Apple o passkey; sesiones cortas con tokens de refresco que rotan; Face ID o huella para desbloquear la app; y cada persona puede ver y cerrar sus sesiones en cada dispositivo.
- Los derechos del RGPD son autoservicio: cada persona puede descargar sus datos y borrar su cuenta. Los gastos se conservan seudonimizados durante el plazo que pide la ley fiscal, y el resto se borra.

## Cómo se construyó

| Cuándo | Qué llegó |
| --- | --- |
| May 2026 | Una demo navegable de la web y la app, con un lector de tickets simulado, para acordar las pantallas |
| Jun 2026 | El backend de agenda, gastos y rutas, la IA que lee los tickets y las dos apps con datos reales |
| Jul 2026 | El mapa en directo, las notificaciones push, el GPS en segundo plano, las passkeys, el export contable y Holded, las solicitudes de acceso y el registro de jornada |
| Ago 2026 | Producción en el dominio de la empresa, y la app en TestFlight y como APK con avisos de versión nueva |
| Sep 2026 | El cierre de reuniones con su resultado, cada gasto en la ruta del día, el aviso de duplicados, el equipo en directo y la información previa |
| Oct 2026 | Canales de versiones, vuelos y trenes confirmados en el mapa, las paradas y reuniones de todo el equipo y las subidas en segundo plano |

El backend lleva 714 clases de test, 48 de ellas contra una base de datos, con un mínimo del 78 % de líneas cubiertas, y el monorepo 685 ficheros de test. De los más de 1.200 commits, unos 120 son de agentes de IA y el resto son nuestros, de los dos. Muchos de los cambios recientes responden a algo que pidió el equipo, y la documentación apunta cada uno con su fecha.

## Lo que nos llevamos

- Deja que la IA rellene un borrador, nunca que lo presente. Leer un ticket ahorra teclear; comprobar las cuentas y pedir a una persona que lo confirme es lo que lo hace seguro.
- Cada importe con su moneda, y nunca sumes dos monedas distintas.
- Guarda la hora de pared con su zona, y enséñala en la zona de quien la lee.
- Una regla que aplican dos lados, como el filtro del GPS, lleva los mismos casos de prueba en los dos, o el mapa en directo y el histórico acaban contando historias distintas.

Si tu equipo sigue planificando en una hoja de cálculo y guardando los tickets en un sobre, este es el tipo de [software a medida](https://alhertech.com/es/servicios/desarrollo-software-a-medida/) que construimos, con una [app móvil](https://alhertech.com/es/servicios/desarrollo-movil/) para la gente que está en la calle.

## Preguntas

### ¿Qué hace la app de Leaderbrock?

Le da a un equipo comercial repartido por varios países su agenda, la ruta del día y los gastos con la foto del ticket en el móvil, y a la oficina un panel web para planificar, seguir al equipo en un mapa en directo y revisar y aprobar los gastos.

### ¿Cómo lee la app un ticket?

La foto o el PDF van al backend, donde un modelo de IA lee el comercio, los importes, el IVA, la moneda, la fecha y la categoría. El servidor comprueba que la base más el IVA da el total y crea un borrador que el comercial revisa, corrige si hace falta y después presenta.

### ¿La IA puede aprobar un gasto por su cuenta?

No. La IA solo rellena un borrador. El comercial lo confirma y finanzas o un administrador lo aprueba o lo rechaza, y cada veredicto queda en un registro de auditoría.

### ¿La app está en la App Store y en Google Play?

No, es una app interna. Los iPhone la instalan con TestFlight y los Android con un APK que publica el administrador, y la app avisa al arrancar cuando hay una versión nueva.

### ¿Cómo trata los datos de ubicación de los empleados?

Cada persona lee y acepta antes de usar la app la información previa que redactó el abogado de la empresa, como pide el artículo 90 de la LOPDGDD, las posiciones se borran a los 90 días y cada campo personal va cifrado.

## Fuentes

- [Spring Boot](https://spring.io/projects/spring-boot)
- [Spring AI](https://spring.io/projects/spring-ai)
- [Documentación de Expo](https://docs.expo.dev/)
- [MapLibre](https://maplibre.org/)
- [Ley Orgánica 3/2018 de protección de datos (LOPDGDD), BOE](https://www.boe.es/buscar/act.php?id=BOE-A-2018-16673)

## Sigue leyendo

- [Caso de estudio ReservPark: el móvil que sabe que dejas tu plaza](https://alhertech.com/es/blog/caso-estudio-reservpark/)
Casos de estudio · 26 oct 2026 · 12 min de lectura

ReservPark detecta por el Bluetooth del coche que has aparcado, te pregunta si te vas cuando vuelves a él y avisa a los conductores cercanos, y deja alquilar un garaje por horas o con abono. Cómo construimos la detección nativa, las reglas de la ubicación en segundo plano, las plazas libres de 30 minutos y unas reservas de garaje que no se pueden vender dos veces.

- [Caso de estudio Almacén-Pro: el albarán que la tienda comprueba escaneando](https://alhertech.com/es/blog/caso-estudio-almacen-pro/)
Casos de estudio · 26 oct 2026 · 12 min de lectura

Una tienda recibe una entrega y tiene que saber qué ha llegado. Almacén-Pro, una herramienta interna que construimos para las tiendas de un cliente, lee el PDF del albarán y lo convierte en una lista que el personal comprueba escaneando cada producto. Cómo leemos el PDF sin adivinar, escaneamos sin cobertura y juntamos el trabajo de dos móviles sin perder un escaneo.

- [Caso de estudio Boathous: un marketplace náutico con reservas, pagos, chat e IA](https://alhertech.com/es/blog/caso-estudio-boathous/)
Casos de estudio · 28 mar 2026 · 9 min de lectura

Boathous une a dueños de barcos con quien quiere alquilarlos, en la web y en una app para iOS. Cómo construimos su backend reactivo en Java, los pagos fraccionados con Stripe, el chat en tiempo real con traducción, la búsqueda en doce idiomas y un asistente de IA que responde por el dueño pero nunca confirma una reserva.

[Blog](https://alhertech.com/es/blog/)
