Construye una app de inventario con herramientas de IA que nunca llegue a negativo
Construye una app de inventario con herramientas de IA y evita stock negativo usando reglas simples de recibir, vender y ajustar que puedes probar antes de desplegar.

Qué estamos construyendo y por qué el stock falla
Cuando la gente dice que una app de inventario está "mal", normalmente se refieren a una cosa: el stock se vuelve negativo. Una vez que eso ocurre, todos los informes pierden fiabilidad. No sabes si estás sin stock, si vendiste de más o si el número es solo el resultado de una actualización errónea.
El objetivo no es un ERP completo. Es una app pequeña y sencilla que puedas usar en una tienda o con un catálogo reducido donde el conteo siga siendo confiable. Si usas herramientas de IA para generar pantallas y código, las reglas siguen siendo lo primero.
Mantén el sistema en tres acciones:
- Receive: entra stock (entrega, devoluciones a stock, stock inicial).
- Sell: sale stock (una venta, un envío o cualquier uso saliente).
- Adjust: cambia el stock porque la realidad y el sistema no coinciden (daño, pérdida, recuento).
“Correcto” es fácil de definir y probar:
- El stock nunca baja de cero para ningún artículo.
- Cada cambio tiene una razón y una marca temporal.
- Los totales son repetibles: reproduces la historia y obtienes el mismo número.
- Cualquier número es explicable señalando las transacciones que lo crearon.
El stock suele fallar por dos razones:
-
La app edita un campo de “stock actual” directamente en lugar de registrar una transacción.
-
Registra transacciones, pero olvida comprobar lo disponible en el momento de la venta.
Un ejemplo rápido: tienes 5 tazas. Dos personas compran 4 tazas cada una, con minutos de diferencia. Si tu app no bloquea el paso de comprobar y decrementar, ambas ventas pueden pasar la verificación de “en stock” y acabas en -3.
El modelo de datos más pequeño que aún funciona
Comienza con un modelo de datos que sea difícil de romper. La meta principal es hacer imposible “editar el número de stock” directamente. El stock disponible debe ser un total que calcules a partir de un historial de cambios.
Para la mayoría de apps pequeñas, el conjunto mínimo es:
- Product: lo que rastreas (nombre, SKU, flag de activo).
- Transaction: cada cambio de stock (receive, sell, adjust), con cantidad y marca temporal.
- Location (opcional): dónde está el stock (almacén, tienda, furgón). Añádelo solo si lo necesitas ahora.
- User (opcional): quién creó la transacción.
Una regla clave: no guardes “stock on hand” como un campo libre que puedas editar. Calcula el stock como la suma de todas las cantidades de transacción para ese producto (y ubicación, si usas ubicaciones). Eso mantiene el número explicable porque cada unidad tiene una razón.
Una sola ubicación ahora, múltiples después
Si dudas sobre múltiples ubicaciones, elige un camino seguro:
- Single location v1: sin tabla Location, los totales son por producto.
- Future-ready v1: incluye Location y exige
location_iden cada transacción, pero comienza con una ubicación por defecto.
Evita la “ubicación opcional” en las transacciones. Los valores nulos en location casi siempre crean totales confusos después.
IDs y marcas temporales de las que dependerás
Decide esto desde el principio:
- Usa IDs únicos para Product y Transaction.
- Guarda
created_aten cada transacción. - Mantén un
effective_atseparado solo si necesitas correcciones con fecha retroactiva. - No edites cantidades en sitio. Añade una nueva transacción correctora en su lugar.
Ejemplo: si contaste 10 unidades ayer pero ingresaste 8, no sobrescribas 8 por 10. Añade un ajuste de +2 con una nota.
Reglas que evitan que el inventario baje de cero
Las reglas importan más que la UI. La mayoría de los bugs de stock negativo ocurren porque la app “edita el número” en lugar de registrar lo ocurrido.
Piensa en el inventario como una cuenta bancaria: solo la cambias mediante transacciones registradas, y nunca permites que el saldo caiga por debajo de cero.
Aquí están las reglas que sostienen la mayor parte del trabajo:
- El stock no debe quedar por debajo de cero después de aplicar cualquier transacción.
- Cada cambio crea un registro de transacción (sin ediciones silenciosas).
- Las cantidades son números positivos; el tipo de transacción decide sumar o restar.
- Cualquier ajuste necesita una razón y quién lo realizó.
- Protege contra dos acciones ocurriendo al mismo tiempo.
El número “on hand” no es la fuente de la verdad. La historia de transacciones lo es.
Qué significa en la práctica “no stock negativo”
Antes de guardar una transacción que remueva artículos, la app comprueba la cantidad on-hand actual para ese artículo. Si la eliminación lo dejaría en negativo, recházala (o márcala como pendiente, si soportas ese flujo).
La concurrencia es la trampa sutil. Dos personas venden la última unidad al mismo tiempo. Ambas pantallas muestran “1 disponible”, ambas pulsan Guardar y acabas en -1 a menos que la base de datos haga cumplir la comprobación. El patrón seguro es leer el stock actual y escribir la transacción en una sola operación de base de datos, de modo que solo una pueda tener éxito.
Recibir stock: el flujo seguro más sencillo
La recepción es donde empiezan tus números. Si registras mal una entrega, todas las ventas después de eso parecerán erróneas.
Mantén el formulario de recepción pequeño para que la gente realmente lo use. Un mínimo sólido es producto, cantidad y marca temporal, más una nota opcional. Coste y proveedor pueden esperar a menos que sepas que los necesitas.
La validación debe ser estricta y aburrida: la cantidad debe ser mayor que 0, el producto debe existir y la marca temporal debe registrarse. Si alguna comprobación falla, no actualices nada.
Al guardar, crea una transacción RECEIVE. Si además mantienes un valor en caché de on-hand para rendimiento, actualízalo en la misma transacción de base de datos para no acabar con números desajustados.
Caso límite: recepción duplicada
Los duplicados ocurren cuando alguien hace doble clic en Guardar o vuelve a ingresar un recibo que ya registró. No borres la fila antigua. Corrige con historia.
Ejemplo: querías recibir 10 unidades, pero se ingresó dos veces. Añade un ajuste que revierta (o una acción de anulación si la soportas) que reste 10 y referencia el recibo erróneo en la nota.
Vender stock: comprobaciones que evitan sobreventas
Vender es donde las apps de inventario suelen fallar.
Para cada línea de venta, captura producto (o SKU), cantidad y marca temporal. Precio y cliente son opcionales, pero una nota breve puede ayudar después cuando alguien pregunte: “¿Por qué bajó el stock?”
Dos comprobaciones importan:
- La cantidad debe ser mayor que 0.
- La cantidad debe ser menor o igual al stock disponible en el momento de la venta.
Si alguien intenta vender 7 cuando solo hay 5, bloquéalo. Muestra un mensaje que les ayude a actuar, por ejemplo: “Solo hay 5 en stock. Reduce la cantidad o recibe stock primero.” Evita errores vagos.
Actualizar stock sin perder historial
No sobrescribas un número de “stock on hand” directamente. Registra una fila de transacción para la venta (un movimiento que resta) vinculada al producto y al registro de venta. El stock on-hand sigue siendo la suma de todos los movimientos.
Los pedidos pendientes pueden esperar para la v1. La opción más segura al principio es no permitirlos. Si debes soportarlos, mantenlos como un estado separado que no cambia el stock hasta que los artículos realmente se envíen.
Ajustes: correcciones sin romper tu historial
Los ajustes son para la vida real: mercancía dañada, robo, un recuento o limpiar datos erróneos tras una importación. La meta es arreglar el número on-hand de hoy sin pretender que el pasado no ocurrió.
La mayoría de apps pequeñas solo necesitan dos estilos de ajuste:
- Set-to: “Establecer on-hand a X” (mejor tras un conteo físico).
- Delta: “Sumar o restar N” (mejor para un evento conocido como “-2 dañados”).
Valida los ajustes como cualquier otro movimiento de stock:
- El valor set-to debe ser 0 o mayor.
- Delta puede ser positivo o negativo, pero no puede dejar el on-hand por debajo de 0.
- El artículo y la ubicación (si rastreas ubicaciones) deben estar seleccionados.
- Debe registrarse la hora del ajuste.
Haz los ajustes responsables. Exige una razón y quién hizo el cambio. Mantén razones cortas y consistentes (recuento, daño, robo, limpieza de datos), con una nota opcional.
Paso a paso: cómo pedir a una herramienta de IA que lo construya de forma segura
Si usas herramientas de IA para construir la app, sé explícito sobre lo que la herramienta debe producir: un esquema de base de datos, lógica del servidor y unas pocas pruebas básicas. Si solo pides pantallas, a menudo acabas aplicando reglas en la UI, que es exactamente cómo se filtra el stock negativo.
Describe el modelo de datos en lenguaje sencillo. Nombra los tipos de transacción (receive, sell, adjust) y qué debe almacenar cada uno: ítem, cantidad, marca temporal, nota. Pide una tabla de transacciones inmutable y una forma clara de calcular el stock actual desde el ledger.
Las reglas deben vivir en el servidor
Pide validación del lado servidor y deja claro que la UI no es de confianza.
Un conjunto útil de prompts (ajusta según tu stack):
- "Genera tablas DB para items e inventory_transactions. Las transacciones son append-only."
- "Crea una función de servidor applyTransaction(type, itemId, qty, note) que valide y escriba en una transacción de BD."
- "Reglas: receive suma stock, sell resta stock pero no puede dejar stock < 0, adjust puede sumar o restar pero tampoco puede dejar stock < 0."
- "Añade endpoints API que llamen a applyTransaction. La UI es solo cliente y no puede eludir las reglas."
- "Genera 3 items seed y 8 transacciones de ejemplo que demuestren una sobreventa bloqueada."
También pide una vista de auditoría: una página que muestre la lista de transacciones (más nuevas primero) y el stock actual junto a cada producto. Esa pantalla es donde detectas anomalías rápidamente.
Comprobaciones rápidas antes de confiar en los números
Antes de que usuarios reales lo usen, prueba que las reglas funcionan con algunos tests sencillos. Los bugs de inventario se esconden hasta que ocurre la secuencia equivocada exacta.
Escribe de 5 a 10 casos de prueba en lenguaje plano. Por ejemplo:
- Receive 10, sell 3, confirmar que on-hand es 7.
- Intentar vender 8 cuando solo hay 7, confirmar que se bloquea con un mensaje claro.
- Receive 1, sell 1, luego vender 1 otra vez, confirmar que la segunda venta se bloquea.
- Hacer un recuento (set-to), confirmar que las cuentas y el historial siguen teniendo sentido.
Luego prueba “dos ventas a la vez” para el mismo artículo. Abre el artículo en dos pestañas (o dos dispositivos) e intenta vender la última unidad casi al mismo tiempo. Debes ver una que tiene éxito y otra que falla.
Los mensajes claros importan. “No se puede vender: solo hay 2 disponibles” es útil. “Error 500” no lo es.
Finalmente, decide tu política de deshacer. Elige una y síguela:
- Borrado suave (ocultar una transacción, mantenerla para auditoría), o
- Transacciones de reversión (añadir una entrada opuesta para deshacer), que suele ser más seguro.
Errores comunes que igual causan stock negativo
La mayoría de problemas de stock negativo no son errores de cálculo. Vienen de atajos que parecen bien en una demo y luego se rompen cuando dos personas usan la app.
La mayor trampa es tratar “stock on hand” como un único número editable. Parece simple, pero elimina lo único que necesitas después: una historia clara de cómo cambió el número.
Los reincidentes:
- Mantener el stock como un campo editable sin un registro de transacciones.
- Validar solo en el frontend.
- Ignorar la concurrencia.
- Permitir ajustes negativos “temporales”.
- No tener una pista de auditoría cuando alguien pregunta por qué un artículo muestra -3.
Un escenario pequeño que muestra la falla: tienes 5 unidades. Dos empleados venden 3 cada uno al mismo tiempo. Si tu app comprueba “stock >= 3” en el navegador, ambas pantallas ven 5 y ambas pasan. Cada una escribe su actualización y acabas en -1. Arréglalo aplicando la regla en el servidor y haciendo la comprobación y la escritura atómica.
Otro problema fácil de pasar por alto es mezclar ediciones de producto (nombre, SKU, precio) con cambios de stock en el mismo formulario. Invita a cambios accidentales de stock y totales difíciles de explicar.
Escenario de ejemplo: un artículo desde la entrega a la venta y el recuento
Imagina una tienda pequeña con una ubicación y tres artículos: Coffee Beans (bolsa 1 lb), Paper Filters y Oat Milk. Sigue solo un artículo, Coffee Beans.
Inicio del día: on hand = 0.
Una app segura de inventario guarda una lista de transacciones y calcula el número actual desde ese historial.
Aquí está el día con un balance en marcha:
- Receive +10: on hand sube de 0 a 10.
- Sell -3: on hand baja de 10 a 7.
- Adjust -2 (daño): on hand baja de 7 a 5.
- Intento de vender -6: la app lo bloquea porque 5 - 6 sería -1.
Cuando el cajero intenta esa última venta, la app debe detenerla antes de guardar nada. Mantén el mensaje simple: “No hay suficiente stock. Tienes 5, intentas vender 6.” La clave es que la comprobación ocurre en el momento de la transacción.
Ahora el recuento: alguien cuenta 5 bolsas, que coincide con el balance. No hace falta “arreglar” nada porque el ledger ya explica el número: una recepción, una venta y un ajuste por daño.
Próximos pasos: desplegar la v1 y luego endurecerla para uso real
Una vez que la v1 pueda recibir, vender y ajustar sin permitir stock negativo, envíala a un grupo pequeño y úsala con pedidos reales. Aprenderás más con una semana de uso real que con otra ronda de pantallas generadas.
Añade solo lo que los usuarios pidan. Los siguientes pasos comunes son múltiples ubicaciones, roles simples para que no todo el mundo pueda ajustar stock, importación CSV para inventario inicial, alertas de bajo stock y unos informes básicos.
Luego haz una pasada corta de endurecimiento. Aquí es donde los prototipos suelen fallar: autenticación, secretos expuestos y validación inconsistente.
Un checklist simple:
- Autenticación que realmente bloquee el acceso (no solo botones ocultos).
- Secretos fuera del navegador y del repositorio.
- Validación de entrada en cantidades, SKUs e IDs.
- Mensajes de error claros y registros de auditoría para cada movimiento de stock.
- Controles básicos de seguridad para inyecciones comunes y brechas de permisos.
Si ya tienes un prototipo generado por IA que se comporta de forma extraña (stock negativo, validaciones solo en la UI o lógica de negocio dispersa), FixMyMess (fixmymess.ai) puede ayudar auditando la base de código y moviendo las reglas a un flujo de transacción único y aplicable. Un punto de partida práctico es su auditoría de código gratuita, que mapea los problemas antes de decidir qué arreglar o reconstruir.
Preguntas Frecuentes
¿Por qué el stock llega a negativo aunque mis cuentas parezcan correctas?
El stock negativo suele ocurrir cuando actualizas un único número de “stock actual” directamente, o cuando registras transacciones pero no aplicas una comprobación de “disponible ahora” en el momento de la venta. La solución más segura es tratar el inventario como un libro mayor: cada cambio es una transacción, y cualquier transacción que dejaría el stock por debajo de cero se rechaza en el servidor.
¿Cuál es el esquema de base de datos más pequeño que funciona para inventario?
Empieza con una tabla products y una tabla append-only inventory_transactions. Cada transacción debe incluir el ID del producto, el tipo (receive, sell, adjust), la cantidad, la marca temporal y un campo de nota o razón para que cada cambio pueda explicarse después.
¿Debería guardar un campo “stock_on_hand” en el producto?
No, no como fuente de la verdad. Calcula el “stock_on_hand” a partir del historial de transacciones para que puedas reproducir el ledger y siempre obtener la misma respuesta, y para que cada unidad esté trazada hasta una razón.
¿Cómo evito que dos personas vendan la última unidad al mismo tiempo?
Haz la comprobación y la escritura dentro de una única transacción de base de datos para que dos ventas no puedan pasar ambas la verificación de “en stock”. Si tu app comprueba en el navegador y luego escribe, dos personas pueden sobrevender la última unidad aunque ambas pantallas mostraran el número correcto.
¿Qué validaciones debo aplicar al recibir stock?
Mantén la recepción aburrida y estricta: la cantidad debe ser mayor que cero, el producto debe existir y la marca temporal debe registrarse. Al guardar, crea una transacción RECEIVE y evita editar filas previas para que tu historial se mantenga limpio.
¿Qué hago si alguien recibe el mismo envío dos veces por accidente?
No borres la entrada original ni la edites en silencio. Añade una transacción correctora que revierta el error y referencia lo ocurrido en la nota para que puedas entender la pista de auditoría en el futuro.
¿Debería la v1 permitir pedidos pendientes o vender en negativo?
Por defecto bloquéalo. Si alguien intenta vender más de lo disponible, rechaza la transacción y muestra un mensaje claro como “Solo hay 5 disponibles” para que el usuario reduzca la cantidad o reciba stock antes.
¿Cuándo debo usar un ajuste en lugar de editar o borrar una transacción?
Usa los ajustes para la vida real: daños, pérdidas, recuentos o limpieza de datos importados. Prefiere un ajuste “set-to” tras un conteo físico y un ajuste tipo “delta” para eventos conocidos, y exige siempre una razón y el usuario que lo realizó.
¿Cómo le doy instrucciones a una herramienta de IA para que no construya una app de inventario que falle?
Pide al AI reglas del lado servidor y una tabla de transacciones append-only, no solo pantallas. Haz que genere una función central que valide y escriba los movimientos de inventario, y añade un par de pruebas que demuestren que una sobreventa queda bloqueada y que el ledger se reproduce correctamente.
¿Cómo sé si mi prototipo generado por IA es inseguro y qué puedo hacer?
Busca reglas de negocio aplicadas solo en la UI, lógica dispersa por páginas, campos de stock editables, marcas temporales faltantes y sin una vista de auditoría clara. Si heredaste un prototipo generado por IA con estos problemas, FixMyMess puede realizar una auditoría gratuita de código y consolidar las reglas en un flujo de transacción único y aplicable para que los números aguanten en producción.