Situación
Un equipo de ventas de campo operaba visitando clientes y facturando directamente en el punto de venta.
El problema NO era menor:
- el proceso original era manual
- muchas rutas atravesaban zonas sin cobertura celular
- la emisión debía respetar reglas fiscales locales
- cada transacción necesitaba trazabilidad desde su creación hasta su sincronización posterior
En ese contexto, depender de conexión estable no era una opción seria.
Tarea
Había que construir una aplicación móvil que resolviera varios problemas acoplados al mismo tiempo:
- operación offline-first real
- validación de ubicación del vendedor
- emisión e impresión de comprobantes
- integración con un ERP legacy expuesto por stored procedures
- sincronización segura sin pérdida ni duplicados
- actualizaciones rápidas para equipos distribuidos en campo
La complejidad no estaba en cada requisito por separado, sino en hacer que todos convivieran sin romper la operación.
Acción técnica
Arquitectura
La app se estructuró con una base de Clean Architecture, combinada con MVVM, Repository Pattern y una capa de sincronización tratada como preocupación de primer nivel.
Se separaron responsabilidades en cuatro áreas:
domainpara entidades, contratos y casos de usodatapara implementaciones concretas y sincronizaciónpresentationpara screens y viewmodelscorepara infraestructura, base local, red y manejo de errores
La decisión importante fue esta: la sincronización no vive como un detalle escondido. Tiene estados, reintentos, conflictos y reglas propias.
Estrategia offline-first
Se diseñó un flujo dual:
- descarga de datos operativos hacia SQLite local
- upload de transacciones pendientes al reconectar
Cada factura se identificó con UUID para sostener idempotencia, evitando duplicados cuando el dispositivo recuperaba señal o reintentaba envíos.
Validación GPS multi-capa
La validación de ubicación no se resolvía con una simple lectura del dispositivo.
Se construyó una estrategia por capas:
- cálculo local de distancia
- verificación backend
- auditoría de incidentes
- manejo resiliente de respuestas inconsistentes desde el sistema legacy
Esto fue especialmente crítico porque la integración devolvía formatos variables según el caso. En lugar de asumir consistencia ideal, se diseñó el cliente para tolerar esa realidad.
Interacción con sistemas legacy
La integración no ocurría contra una API moderna bien diseñada, sino contra lógica corporativa expuesta mediante stored procedures.
Eso obligó a diseñar:
- parsing defensivo
- manejo explícito de errores
- sincronización desacoplada
- una arquitectura testeable para validar branches críticos sin tocar infraestructura real
Actualizaciones y operación en campo
También se incorporó una estrategia de actualización de versión que permitiera forzar upgrades y reducir el tiempo de entrega de fixes críticos para equipos que ya estaban operando en ruta.
Resultado
- Operación móvil continua incluso en zonas sin cobertura
- Sincronización posterior sin duplicados
- Trazabilidad más confiable de transacciones de campo
- Validación GPS para reducir riesgos operativos
- Base técnica preparada para mantener presión de negocio sin colapsar
Decisiones técnicas relevantes
| Tema | Decisión |
|---|---|
| Persistencia local | SQLite como fuente operativa offline |
| Sincronización | upload/download desacoplados con idempotencia |
| Integración legacy | adaptación resiliente a stored procedures |
| Ubicación | validación GPS multi-capa |
| Evolución | mecanismo de actualización rápida para fixes críticos |
Aprendizajes
Offline-first de verdad no significa “guardar algo local y después vemos”.
Significa diseñar estados, conflictos, idempotencia, auditoría y tolerancia a datos inconsistentes desde el inicio. Si no hacés eso, la app funciona solo en la demo.