Control de stock en Enolisa: convertir una vinoteca en inventario útil sin perder simplicidad
Un caso de estudio técnico-producto sobre cómo evolucioné la Vinoteca de Enolisa con control de stock, auditoría de movimientos, analítica local y una UX pensada para el uso real.
Una mejora pequeña solo en apariencia
Una de las mejoras recientes de Enolisa que más me interesa como caso de producto es el evolutivo de control de stock en la Vinoteca.
Sobre el papel podía parecer una feature sencilla: permitir que una persona indique cuántas botellas tiene. Pero en una app real esa frase se queda corta. Una vinoteca personal no es una lista plana de vinos. Es una mezcla de memoria, inventario, consumo, valor, hábitos y contexto.
El problema no era únicamente guardar un número. El problema era responder bien a preguntas que un usuario se hace de forma natural:
- cuántas botellas sigo teniendo;
- cuáles he consumido;
- cuáles he regalado;
- qué movimiento hice y cuándo;
- si mi bodega está creciendo o se está vaciando;
- qué valor aproximado tiene lo que todavía conservo;
- cómo evoluciona mi actividad con el tiempo.
Ese cambio obligaba a conectar producto, UX, modelo de datos, persistencia local, sincronización, analítica y QA. Y por eso me parece un buen ejemplo de cómo intento construir Enolisa: no como una colección de pantallas, sino como un producto donde cada mejora visible se apoya en una base técnica razonable.
El problema real: un contador no basta
La versión simple habría sido añadir un campo stock y mostrarlo en la ficha del vino.
Habría funcionado para una demo.
No habría funcionado bien para una vinoteca de uso real.
Un usuario puede comprar tres botellas de un vino, beber una, regalar otra y conservar la tercera. Si el sistema solo guarda “quedan 1”, pierde historia. Si solo guarda “compré 3”, pierde estado actual. Si mezcla el cambio de unidades con el formulario general de edición del vino, la experiencia se vuelve confusa: editar la bodega, la región o una nota personal no es lo mismo que mover inventario.
La decisión fue separar claramente dos conceptos:
- la ficha del vino como registro estable;
- el stock como estado táctico que cambia con el uso.
Esa separación tiene una consecuencia importante: el control de stock vive en la ficha del vino, pero no como otro campo más del formulario. Tiene una superficie propia, con su propio modelo mental, sus propias validaciones y su propio historial.
Es una decisión de producto, no solo de interfaz. El usuario no está “editando un vino”. Está gestionando una pequeña parte de su bodega.
La decisión de producto: dos modos de edición
Había dos formas razonables de plantear la edición del stock.
La primera era un modo guiado. Si marcas una botella como consumida, se descuenta automáticamente de las unidades que sigues teniendo en la vinoteca. Es el comportamiento más natural para el uso diario.
La segunda era un modo flexible. Permite ajustar cada cifra de manera independiente cuando el usuario necesita corregir datos, reconstruir una situación anterior o cuadrar un registro que no nació perfecto.
Elegir solo una de las dos opciones habría dejado fuera casos reales. El modo guiado reduce fricción. El modo flexible evita encerrar al usuario en una lógica demasiado rígida.
El equilibrio que tomé fue:
- modo guiado como experiencia principal;
- modo flexible disponible para correcciones;
- consumo rápido desde la ficha cuando solo quieres marcar una botella como consumida;
- auditoría visible para que el usuario entienda qué ha pasado.
Este tipo de decisiones me parecen importantes porque reflejan una forma de construir producto: no imponer complejidad a quien solo quiere hacer una acción sencilla, pero tampoco esconder las herramientas necesarias cuando el dato necesita precisión.
El modelo de datos: una invariante sencilla y fuerte
La base técnica del evolutivo se apoyó en una invariante muy simple:
1
unidades_totales = unidades_en_vinoteca + unidades_consumidas + unidades_regaladas
No es una fórmula sofisticada. Pero es el tipo de contrato pequeño que evita muchos problemas posteriores.
El modelo distingue cuatro valores:
- unidades totales históricas;
- unidades todavía en vinoteca;
- unidades consumidas;
- unidades regaladas.
Además, el sistema no permite que el total quede por debajo de uno ni que la distribución rompa la suma. Esto no está pensado solo para mostrar números bonitos. Está pensado para que la app pueda construir analítica, validar estados, sincronizar cambios y explicar al usuario su propia bodega sin depender de interpretaciones ambiguas.
La implementación siguió un patrón local-first. Enolisa trabaja con SQLite local para que la experiencia sea rápida y resistente. El cambio de stock tenía que convivir con datos ya existentes, así que la migración inicial transforma los vinos antiguos de una forma conservadora: lo que antes era simplemente “unidades” pasa a interpretarse como “unidades en vinoteca”, y los contadores de consumidas y regaladas arrancan en cero.
Es una decisión deliberadamente prudente. No intenta reconstruir historia que no existía. Preserva el dato que el usuario ya tenía y crea una base más rica para el futuro.
El ledger: no solo estado, también trazabilidad
El segundo componente importante fue añadir una tabla de movimientos.
Guardar solo el estado final responde a la pregunta:
¿Cómo está mi stock ahora?
Pero no responde a:
¿Cómo he llegado hasta aquí?
Para eso hace falta un ledger, aunque sea sencillo. Cada cambio relevante puede dejar un movimiento con el tipo de acción, unidades antes, unidades después, distribución resultante y una nota opcional.
Esto aporta tres ventajas.
La primera es confianza. Si el usuario ve que el sistema recuerda los cambios, la cifra deja de parecer arbitraria.
La segunda es soporte. Cuando una funcionalidad toca datos personales, los errores difíciles no suelen estar en el estado final, sino en la secuencia de pasos que llevó a ese estado.
La tercera es analítica. El historial permite construir lecturas de consumo y actividad sin forzar al usuario a registrar todo manualmente como si estuviera usando un ERP.
Aquí hay un trade-off claro: un ledger añade complejidad. Hay más tabla, más sincronización, más validación y más casos límite. Pero en este caso sí estaba justificado porque el stock no era un campo decorativo. Era una pieza de producto con impacto en confianza y lectura de datos.
UX: editar, auditar y actuar rápido
La parte visible se organizó en tres niveles.
El primero es la acción rápida. Desde la ficha del vino, si todavía quedan botellas en la vinoteca, el usuario puede marcar una unidad como consumida sin abrir todo el editor. Es el flujo más frecuente y no merece una pantalla compleja.
El segundo es el control completo. Un bottom sheet permite ajustar la distribución entre en vinoteca, consumidas y regaladas. Ahí entra el modo guiado o flexible, según lo que el usuario necesite.
El tercero es la auditoría. En la misma superficie se puede revisar el histórico de movimientos y añadir notas. No hace falta llevar al usuario a otra zona de la app para entender qué ha pasado con ese vino.
Esta arquitectura de interfaz evita dos errores comunes.
El primero es meter demasiada responsabilidad en el formulario de edición del vino. Eso habría mezclado metadatos del producto con operaciones de inventario.
El segundo es obligar a abrir un panel avanzado para una acción cotidiana. Si beber una botella exige demasiados pasos, el usuario deja de registrarlo.
La UX buena no es la que enseña toda la potencia del sistema de golpe. Es la que acerca la acción correcta en el momento correcto.
Analítica de vinoteca: convertir datos locales en lectura útil
El evolutivo no se quedó en la edición de stock. También añadí una lectura agregada en “Mis vinos”.
La idea era que la persona no solo pudiera cambiar datos, sino entender su bodega:
- vinos distintos registrados;
- unidades totales;
- unidades en vinoteca;
- unidades consumidas;
- unidades regaladas;
- ratio de consumo;
- registros recientes;
- ventanas temporales de 7, 30 y 90 días;
- lectura acumulada del año en curso.
Este punto es importante para el posicionamiento de Enolisa. La app no quiere ser solo un almacén de fichas. Quiere ayudar a entender la relación del usuario con el vino: qué guarda, qué consume, qué registra y cómo evoluciona su actividad.
Técnicamente, esta capa se resolvió como un servicio separado de la UI. Las consultas agregadas viven fuera de las pantallas y devuelven snapshots tipados. Eso permite probar el cálculo sin depender del render y evita que una pantalla de Flutter acabe convertida en una mezcla de SQL, estado visual y reglas de negocio.
Es una decisión menos vistosa que diseñar una tarjeta bonita, pero mucho más importante para mantener el producto.
QA: validar reglas, no solo pantallas
Una parte que me parece clave en este tipo de evolutivos es probar las reglas pequeñas.
No basta con abrir la pantalla y ver que los botones funcionan. Hay que validar la semántica:
- el modo guiado descuenta de “en vinoteca” al mover a consumidas;
- devolver una botella consumida la devuelve a “en vinoteca”;
- no se puede consumir si no quedan botellas disponibles;
- el modo flexible puede aumentar una categoría sin mover otra;
- la invariante del total se mantiene;
- una distribución inválida falla de forma explícita;
- el ratio de consumo y las ventanas temporales se calculan como se espera.
Este tipo de tests son pequeños, pero protegen lo que de verdad importa. La interfaz puede cambiar. El diseño visual puede evolucionar. Pero si el modelo de stock empieza a mentir, la confianza del usuario se rompe.
En producto, la calidad no siempre está en la parte más visible. Muchas veces está en que una regla sencilla siga siendo cierta seis meses después.
IA en el proceso: más revisión que magia
En este evolutivo la IA no fue una “feature”. Fue parte de mi forma de trabajar.
La utilicé como capa de análisis, revisión y ejecución asistida:
- ordenar el alcance funcional;
- detectar casos límite;
- separar lógica de dominio, UI y servicios;
- revisar textos de release;
- comprobar documentación;
- reforzar tests;
- validar que la explicación pública no revelara detalles sensibles.
Este punto me parece relevante para mi perfil profesional porque resume bastante bien cómo entiendo el uso de IA en desarrollo. No se trata de pedirle a un modelo que invente una funcionalidad. Se trata de usar agentes, specs y documentación para aumentar la capacidad de análisis y ejecución sin perder ownership técnico.
La IA ayuda especialmente cuando hay muchas capas pequeñas que no deben olvidarse: migración, invariante, UI, i18n, sincronización, analítica, QA y comunicación. Pero la decisión de producto y el criterio de cierre siguen siendo humanos.
Por qué esto refuerza Enolisa
El control de stock no es una funcionalidad llamativa en el sentido habitual. No es IA generativa, no es una animación espectacular y no es una integración de moda.
Pero refuerza Enolisa precisamente porque toca una necesidad básica del producto: si una app promete ser tu vinoteca personal, tiene que tratar tus botellas con seriedad.
Para mí, una buena app de producto no se construye solo con features grandes. Se construye cuidando las capas que hacen que el uso diario sea fiable:
- datos locales consistentes;
- flujos rápidos para acciones frecuentes;
- historial cuando hay cambios relevantes;
- lectura agregada que devuelve valor;
- migraciones prudentes;
- tests que protegen reglas de negocio;
- comunicación clara al usuario.
Ese tipo de trabajo no siempre se ve desde fuera, pero se nota en la experiencia. Y también es el tipo de trabajo que da credibilidad técnica a un producto.
Enolisa puede tener IA aplicada, recomendaciones, maridajes, escaneo de etiquetas y notificaciones inteligentes. Pero necesita al mismo tiempo fundamentos sólidos: inventario, persistencia, sincronización, privacidad, soporte, analítica y QA.
La credibilidad de un producto está en esa combinación.
Aprendizajes transferibles
Hay varias lecciones de este evolutivo que aplican más allá de Enolisa.
La primera: antes de añadir campos, hay que entender el dominio. Un contador puede parecer suficiente hasta que aparecen estados, historia, correcciones y analítica.
La segunda: las invariantes simples valen mucho. Una fórmula pequeña puede ser la diferencia entre un modelo mantenible y una acumulación de excepciones.
La tercera: una acción frecuente merece un camino corto. El consumo rápido existe porque abrir el editor completo para algo cotidiano habría sido demasiado pesado.
La cuarta: un ledger se justifica cuando hay confianza, soporte o analítica en juego. No todo necesita historial, pero algunos cambios pierden valor si no se puede explicar su trayectoria.
La quinta: la analítica de producto empieza en el modelo de datos. No puedes sacar buenas lecturas de datos ambiguos.
La sexta: la IA aporta más cuando trabaja dentro de un proceso. Specs, revisión, tests y documentación son mejores palancas que pedir código aislado.
Cierre
El control de stock de Enolisa es una mejora concreta, pero resume una forma de construir producto.
Empieza con una necesidad de usuario aparentemente sencilla. Se convierte en una decisión de modelo. Pasa por arquitectura local-first, migración, ledger, UX, analítica y pruebas. Y termina comunicándose como una mejora comprensible para quien solo quiere gestionar mejor su vinoteca.
Ese puente entre uso real, criterio de producto y ejecución técnica es donde intento que Enolisa tenga más valor. Y también es el tipo de trabajo que quiero que refleje mi perfil: convertir problemas concretos en producto funcional, mantenible y verificable.
Lecturas relacionadas
- Cómo uso Codex como capa operativa de desarrollo en Enolisa
- De la idea a la spec: cómo convierto intuiciones de producto en planes de trabajo con IA
- Creando un modelo generativo propio con Genkit y arquitectura orquestada sobre Firebase
- Arquitectura de Engagement basada en reglas: así diseñé un orquestador serverless para campañas en Enolisa