01
el reto
El laboratorio de ortodoncia organizaba su producción en Monday.com. Como tablero funcionaba, pero arrastraba tres problemas que no se arreglan con más configuración: se paga por usuario y por mes, indefinidamente; los datos —ligados a pacientes— viven en un servidor ajeno; y nada de lo específico del oficio existe en una herramienta genérica. Lotes, caducidades, escaneo de códigos médicos, consumo de material por trabajo: o se construye a mano encima con automatizaciones frágiles, o no está.
En paralelo corría una obligación legal. Un laboratorio que fabrica dispositivos médicos a medida debe, bajo el reglamento europeo MDR, poder vincular cada aparato entregado al lote concreto de material con el que se hizo: si un lote de resina sale defectuoso, hay que saber en qué pacientes se usó. Eso se llevaba en una hoja de cálculo y en la memoria de quien fabricaba.
El encargo tenía entonces dos mitades: sustituir la suscripción por algo propio, y que ese algo resolviera lo que la suscripción no resolvía.
02
la solución
Una aplicación de escritorio diseñada, construida y desplegada de cero, instalada en los ordenadores de la clínica.
La decisión de producto que marca toda la interfaz: copiar deliberadamente la ergonomía de Monday —tableros, columnas de estado con etiquetas de color, edición en línea— para que nadie tuviera que reaprender a trabajar. Cambiar de herramienta no debía sentirse como cambiar de herramienta. Debajo, en cambio, todo lo que faltaba: lotes y caducidades, escaneo GS1 DataMatrix que trae código, lote y fecha en un solo disparo del lector, descuento automático de stock, etapas de fabricación fechadas, y la cadena lote → consumo → caso cerrada sin añadir trabajo manual.
La decisión estructural: el núcleo de la aplicación nunca habla con una base de datos, habla con una interfaz única, con dos implementaciones intercambiables —SQLite en local, PostgreSQL en compartido—. Eso permitió arrancar en un solo puesto y pasar meses después a base común sin reescribir la aplicación.
El salto a toda la clínica va escrito, no improvisado: PostgreSQL en Docker sobre el NAS del gabinete y deliberadamente no sobre el servidor de dominio, puestos apuntando a un nombre DNS y nunca a una IP, instalación por usuario sin permisos de administrador, migración del histórico en una sola transacción verificada con vuelta atrás, y un manual de puesta en servicio en francés: alojamiento y alternativas, red y cortafuegos, copias de seguridad y prueba de restauración, síntomas frecuentes.
03
el resultado
En producción, seis puestos, base compartida y actualización en tiempo real entre ellos.
La suscripción está eliminada y la clínica es propietaria del software que usa; los datos de pacientes se quedaron en casa; el requisito regulatorio está cerrado: de un lote defectuoso se llega a los pacientes, y de un paciente a sus lotes. Hasta hoy: 293 casos trazados, 1 738 etapas de producción fechadas, 8 tablas y 20 807 líneas de TypeScript.
Lo que me llevo cabe en tres averías. Un stock en −6 porque dos puestos leían antes de escribir, resuelto con bloqueo de fila y verificado con dos instancias contra un PostgreSQL real. Un corte de red que cerraba la aplicación entera en lugar de degradarla, convertido en una reconexión con espera creciente que se resincroniza al volver. Y previsiones de ruptura absurdas —diecinueve años de autonomía en una placa— nacidas de la misma fórmula copiada tres veces y divergida. Desde entonces, cuando la base de cálculo es demasiado fina, los paneles se niegan a responder y dicen por qué: un número inventado sobre el que alguien va a comprar material es peor que un guion.