La mayoría de las operaciones del noroeste no tienen un problema de falta de datos. Tienen un problema de datos atrapados: en una libreta que se moja, en un chat de WhatsApp que nadie vuelve a leer, en la cabeza del encargado que se va de vacaciones. El reto no es capturar más — es capturar una sola vez, bien, y que sirva.
En este artículo te cuento cómo abordamos la captura de datos en campo, qué decisiones técnicas tomamos y por qué la mayoría de los proyectos fallan antes de escribir una línea de código.
El problema real no es el formulario
Es tentador pensar que digitalizar el campo es “hacer un formulario en el celular”. Lo intentas, funciona en la oficina, y se cae el primer día en el rancho. ¿Y sabes por qué? Porque el formulario no era el problema.
El problema es el contexto de uso:
- No hay señal a mitad del lote.
- El operador trae guantes y polvo en la pantalla.
- Hay prisa: nadie va a llenar 14 campos por animal.
- El que captura no es el que decide qué se captura.
Si tu solución ignora cualquiera de estos cuatro puntos, no importa qué tan bonito sea el código. Se va a abandonar.
Diseñar para offline primero
Acá no hay vuelta: en campo offline es el estado normal, no la excepción. La conexión es el lujo. Por eso diseñamos la captura para funcionar completa sin red, y sincronizar cuando haya señal.
Si tu app necesita internet para guardar un dato, no es una app de campo. Es una app de oficina que a veces sale a pasear.
La regla técnica que seguimos: el dato se considera guardado en cuanto toca el dispositivo, no cuando llega al servidor. La sincronización es un detalle de infraestructura, no parte del flujo del usuario.
Cola de sincronización idempotente
Cada captura se escribe local con un identificador único generado en el cliente. Cuando hay red, se empuja la cola. Si la sincronización se interrumpe a la mitad y se reintenta, el id evita duplicados.
function encolarCaptura(captura) {
const registro = {
id: crypto.randomUUID(), // generado en el cliente, no en el server
capturadoEn: Date.now(),
sincronizado: false,
datos: captura,
};
db.cola.put(registro); // se "guarda" aquí, no en la red
intentarSincronizar(); // best-effort; si falla, queda en cola
return registro.id;
}
El id del cliente es lo que hace la operación idempotente: reenviar el mismo registro diez veces produce un solo resultado en el servidor. Sin eso, cada reintento es un duplicado esperando a confundir el reporte.
Capturar menos, no más
El instinto del dueño es pedir 20 campos “por si acaso”. El instinto correcto es preguntar: ¿qué decisión vas a tomar con este dato? Si no hay decisión detrás, el campo sobra.
Reducimos la captura a lo mínimo que mueve una decisión real:
- Identidad (qué/quién).
- Evento (qué pasó).
- Una métrica que importe.
Todo lo demás se deriva, se infiere del contexto, o simplemente no se pide. Menos campos significan capturas más rápidas, menos errores y — lo más importante — gente que de verdad usa el sistema.
Qué medimos para saber si funciona
Un sistema de captura no se mide por features. Se mide por adopción y confianza en el dato:
- Tasa de captura: ¿se registra el evento el día que ocurre, o tres días después de memoria?
- Tiempo por captura: si sube, la gente lo está evadiendo.
- Correcciones posteriores: muchas correcciones = el formulario pregunta mal.
Cuando estos tres números están sanos, el dato es confiable. Y un dato confiable es lo único que justifica todo lo demás: reportes, automatización, IA. Sin esa base, lo demás es decoración.
Lo que nos llevamos
Automatizar la captura en campo no es un problema de framework. Es un problema de respetar la realidad de quien captura: sin señal, con prisa, con las manos sucias. Resuelve eso primero y el código se vuelve la parte fácil.
Si tu operación todavía vive en libretas y chats, no necesitas la app más sofisticada. Necesitas la más honesta con tu campo.