ARQUITECTURA-OFFLINE.md - App de Conductores
Proyecto: erp-transportistas
Modulo: MAI-006-tracking / App Conductor
Version: 1.0.0
Fecha: 2026-01-27
GAP Relacionado: GAP-003 (Modo Offline para Conductores)
1) Objetivos
1.1 Objetivo Principal
Permitir que los conductores operen la aplicacion movil sin conexion a internet durante sus viajes en carretera, garantizando la captura de todos los datos operativos y su sincronizacion automatica al recuperar conectividad.
1.2 Objetivos Especificos
| Objetivo |
Descripcion |
Metrica de Exito |
| Operacion continua |
La app funciona 100% sin conexion |
0 bloqueos por falta de red |
| Sin perdida de datos |
Todos los eventos se almacenan localmente |
0% perdida de datos |
| Sincronizacion automatica |
Datos se envian al reconectar |
Sync < 30s post-conexion |
| Transparencia al usuario |
El conductor sabe que esta offline |
Indicador visible en UI |
| Resiliencia |
Recuperacion ante fallos de sync |
Retry automatico con backoff |
1.3 Casos de Uso Criticos Offline
- Registro de eventos de viaje (arribo, carga, descarga, salida)
- Captura de firma POD (Proof of Delivery)
- Toma de fotos con evidencia (carga, dano, sello)
- Checklist de inspeccion pre-viaje
- Consulta de informacion del viaje (rutas, paradas, instrucciones)
- Registro de incidencias (accidente, retraso, dano)
2) Stack Tecnologico
2.1 Componentes Principales
| Componente |
Tecnologia |
Proposito |
| Storage Local |
WatermelonDB |
Base de datos offline-first reactiva |
| Storage Secundario |
IndexedDB (Dexie.js) |
Almacenamiento de blobs (fotos, firmas) |
| Intercepcion HTTP |
Service Workers |
Cache de requests y offline fallback |
| Sincronizacion |
Background Sync API |
Push de datos cuando hay conexion |
| Deteccion de Red |
Network Information API |
Estado de conectividad en tiempo real |
| Queue de Tareas |
Workbox |
Gestion de cola de sincronizacion |
2.2 Arquitectura de Capas
+--------------------------------------------------+
| UI LAYER |
| (React Native / Expo) |
+--------------------------------------------------+
| |
v v
+-------------------+ +----------------------+
| SYNC MANAGER | | OFFLINE DETECTOR |
| - Queue Manager | | - Network Status |
| - Conflict Res. | | - Connectivity Test |
+-------------------+ +----------------------+
| |
v v
+--------------------------------------------------+
| LOCAL DATA LAYER |
| +-------------------+ +---------------------+ |
| | WatermelonDB | | IndexedDB (Blobs) | |
| | - Viajes | | - Fotos | |
| | - Eventos | | - Firmas | |
| | - Checklists | | - Documentos PDF | |
| +-------------------+ +---------------------+ |
+--------------------------------------------------+
|
v
+--------------------------------------------------+
| SYNC TRANSPORT LAYER |
| +-------------------+ +---------------------+ |
| | Background Sync | | Retry Queue | |
| | - Push events | | - Exponential back. | |
| | - Upload files | | - Priority queue | |
| +-------------------+ +---------------------+ |
+--------------------------------------------------+
|
v
+--------------------------------------------------+
| REMOTE API |
| (Backend NestJS - erp-transportistas) |
+--------------------------------------------------+
2.3 Dependencias NPM
{
"dependencies": {
"@nozbe/watermelondb": "^0.27.1",
"@nozbe/with-observables": "^1.6.0",
"dexie": "^4.0.0",
"workbox-window": "^7.0.0",
"workbox-background-sync": "^7.0.0",
"workbox-strategies": "^7.0.0",
"@react-native-community/netinfo": "^9.0.0",
"uuid": "^9.0.0"
}
}
3) Datos Almacenados Localmente
3.1 Datos del Viaje Activo
| Entidad |
Campos Principales |
Tamano Estimado |
| Viaje |
id, numero, estado, fechas, origen, destino |
~2 KB |
| Paradas |
id, secuencia, ubicacion, tipo, ventanas |
~500 B/parada |
| Instrucciones |
id, tipo, contenido, prioridad |
~1 KB/instruccion |
| Contactos |
nombre, telefono, email, rol |
~200 B/contacto |
| Mercancia |
descripcion, peso, volumen, unidades |
~300 B/item |
| Documentos |
tipo, nombre, url_local, checksum |
~50 KB/doc (metadata) |
3.2 Datos Capturados Offline
| Entidad |
Campos |
Tamano Estimado |
Prioridad Sync |
| EventoTracking |
id, tipo, timestamp, lat, lng, viaje_id |
~200 B |
ALTA |
| PosicionGPS |
lat, lng, velocidad, rumbo, timestamp |
~100 B |
MEDIA |
| ChecklistItem |
pregunta, respuesta, evidencia_id, timestamp |
~500 B |
ALTA |
| Foto |
id, blob, metadata, lat, lng, timestamp |
~500 KB-2 MB |
BAJA |
| FirmaPOD |
id, svg_path, receptor_nombre, timestamp |
~50 KB |
ALTA |
| Incidencia |
tipo, descripcion, fotos_ids, timestamp |
~1 KB |
ALTA |
3.3 Cache de Referencia (Read-Only Offline)
| Dato |
Proposito |
Actualizacion |
| Catalogos de eventos |
Tipos de eventos permitidos |
Cada login |
| Checklist templates |
Plantillas de inspeccion |
Cada login |
| Datos de unidad asignada |
Placa, capacidad, documentos |
Cada asignacion |
| Datos del operador |
Licencia, permisos, vigencias |
Cada login |
| Rutas precalculadas |
Polylines, waypoints |
Al asignar viaje |
3.4 Limites de Almacenamiento
| Tipo |
Limite Recomendado |
Limite Maximo |
| Base de datos WatermelonDB |
50 MB |
100 MB |
| IndexedDB (Blobs) |
200 MB |
500 MB |
| Cache de documentos |
50 MB |
100 MB |
| Total por viaje activo |
300 MB |
700 MB |
4) Sincronizacion
4.1 Flujo Push (Local a Server)
+-------------+ +---------------+ +----------------+
| CAPTURA | --> | LOCAL QUEUE | --> | SYNC MANAGER |
| (Evento) | | (Pending) | | (Background) |
+-------------+ +---------------+ +----------------+
|
v
+----------------+
| CONNECTIVITY |
| CHECK |
+----------------+
|
+-------------+-------------+
| |
v v
+-----------+ +---------------+
| OFFLINE | | ONLINE |
| (Queue) | | (Send Now) |
+-----------+ +---------------+
| |
| v
| +---------------+
| | SERVER |
| | RESPONSE |
| +---------------+
| |
| +-------------+-------------+
| | |
| v v
| +-----------+ +---------------+
| | SUCCESS | | ERROR |
| | (Remove) | | (Retry/Log) |
| +-----------+ +---------------+
| |
+------------------<----------------------+
(Retry with backoff)
4.2 Flujo Pull (Server a Local)
+----------------+ +----------------+ +----------------+
| CONNECTIVITY | --> | SYNC MANAGER | --> | FETCH CHANGES |
| (Online) | | (Trigger) | | (Delta Sync) |
+----------------+ +----------------+ +----------------+
|
v
+----------------+
| COMPARE |
| TIMESTAMPS |
+----------------+
|
v
+----------------+
| APPLY CHANGES |
| TO LOCAL DB |
+----------------+
|
v
+----------------+
| NOTIFY UI |
| (Reactive) |
+----------------+
4.3 Datos a Sincronizar
Push (Local a Server)
| Dato |
Prioridad |
Frecuencia |
Retry Policy |
| Eventos de viaje |
CRITICA |
Inmediato |
5 intentos, backoff 1-30s |
| Posiciones GPS |
ALTA |
Batch cada 1 min |
3 intentos, backoff 5-60s |
| Firmas POD |
CRITICA |
Inmediato |
10 intentos, backoff 1-60s |
| Fotos evidencia |
MEDIA |
Background |
5 intentos, backoff 30-300s |
| Checklist completado |
ALTA |
Inmediato |
5 intentos, backoff 1-30s |
| Incidencias |
CRITICA |
Inmediato |
10 intentos, backoff 1-60s |
Pull (Server a Local)
| Dato |
Frecuencia |
Trigger |
| Cambios en viaje |
Cada 5 min online |
Polling + Push notification |
| Nuevas instrucciones |
Inmediato |
Push notification |
| Actualizacion de paradas |
Cada 5 min |
Polling |
| Cancelacion de viaje |
Inmediato |
Push notification |
| Cambio de asignacion |
Inmediato |
Push notification |
4.4 Estrategia de Retry (Exponential Backoff)
Intento 1: Inmediato
Intento 2: 1 segundo
Intento 3: 2 segundos
Intento 4: 4 segundos
Intento 5: 8 segundos
Intento 6: 16 segundos
Intento 7: 32 segundos
Intento 8: 60 segundos (max)
...
Intento N: 60 segundos (cap)
Maximo tiempo total de retry: 1 hora
Despues: Marcar como fallido, notificar soporte
5) Conflict Resolution
5.1 Estrategias por Tipo de Dato
| Tipo de Dato |
Estrategia |
Razon |
| Estado del viaje |
Server Wins |
Estado oficial controlado por dispatch |
| Eventos de tracking |
Append-Only (Merge) |
Nunca se borran, solo se agregan |
| Posiciones GPS |
Client Wins |
El dispositivo es la fuente de verdad |
| Fotos y firmas |
Client Wins |
Evidencia local es oficial |
| Instrucciones |
Server Wins |
Dispatch controla instrucciones |
| Datos del operador |
Server Wins |
RRHH controla datos oficiales |
5.2 Diagrama de Resolucion de Conflictos
+------------------+
| CONFLICTO |
| DETECTADO |
+------------------+
|
v
+------------------+
| IDENTIFICAR |
| TIPO DE DATO |
+------------------+
|
+----+----+----+----+
| | |
v v v
+-------+ +-------+ +-------+
| STATE | | EVENT | | BLOB |
+-------+ +-------+ +-------+
| | |
v v v
+-------+ +-------+ +-------+
| SERVER| | MERGE | |CLIENT |
| WINS | |(Append| | WINS |
| | | Only) | | |
+-------+ +-------+ +-------+
| | |
+----+----+----+----+
|
v
+------------------+
| APLICAR |
| RESOLUCION |
+------------------+
|
v
+------------------+
| REGISTRAR EN |
| AUDIT LOG |
+------------------+
5.3 Reglas de Merge para Eventos (Append-Only)
- Cada evento tiene un UUID unico generado en cliente
- El timestamp es el momento de captura en dispositivo
- Si el servidor ya tiene el UUID, ignorar (idempotente)
- El orden de eventos se determina por timestamp del cliente
- Eventos duplicados se detectan por UUID + viaje_id
5.4 Manejo de Conflictos en Estados
// Matriz de transicion de estados permitidos (cliente)
const TRANSICIONES_VALIDAS = {
'EN_TRANSITO': ['ARRIBADO', 'INCIDENCIA'],
'ARRIBADO': ['EN_CARGA', 'EN_DESCARGA'],
'EN_CARGA': ['CARGADO'],
'EN_DESCARGA': ['DESCARGADO', 'ENTREGADO'],
'CARGADO': ['EN_TRANSITO'],
'DESCARGADO': ['EN_TRANSITO', 'ENTREGADO']
};
// Si el estado del servidor es diferente:
// 1. Aceptar estado del servidor
// 2. Revertir UI al estado correcto
// 3. Notificar al usuario del cambio
6) Indicadores UI
6.1 Componentes de Estado
| Indicador |
Ubicacion |
Estados |
| Icono de conexion |
Header (esquina superior derecha) |
Online (verde), Offline (rojo), Sincronizando (amarillo) |
| Contador de pendientes |
Header (junto a icono) |
Badge numerico (0-99+) |
| Ultima sincronizacion |
Drawer / Settings |
Timestamp legible |
| Barra de progreso |
Toast inferior |
Durante sync activa |
| Alertas de error |
Modal / Banner |
Errores de sync criticos |
+----------------------------------------------------------+
| VIAJE #VJ-2026-00123 [12] (o) 4G/LTE |
| En transito a: Monterrey |
+----------------------------------------------------------+
Leyenda:
- [12] = 12 eventos pendientes de sincronizar
- (o) = Icono de estado (o=online, x=offline, ~=sync)
- 4G/LTE = Tipo de conexion
Estados del icono:
- Verde (o) : Online, sincronizado
- Amarillo (~): Sincronizando
- Rojo (x) : Offline
- Naranja (!): Error de sync
6.3 Panel de Estado de Sincronizacion
+----------------------------------------------------------+
| ESTADO DE SINCRONIZACION [X] |
+----------------------------------------------------------+
| |
| Estado de conexion: OFFLINE (desde hace 15 min) |
| Ultima sync exitosa: 2026-01-27 14:35:22 |
| |
| PENDIENTES DE ENVIAR: |
| +----------------------------------------------------+ |
| | Tipo | Cantidad | Tamano | Estado | |
| +----------------------------------------------------+ |
| | Eventos | 5 | 2 KB | [Cola] | |
| | Posiciones GPS | 45 | 5 KB | [Cola] | |
| | Fotos | 3 | 4.5 MB | [Cola] | |
| | Firma POD | 1 | 32 KB | [Cola] | |
| +----------------------------------------------------+ |
| | TOTAL | 54 | 4.6 MB | | |
| +----------------------------------------------------+ |
| |
| [!] 2 fotos fallaron al subir - Reintentando... |
| |
| [ FORZAR SINCRONIZACION ] [ VER ERRORES ] |
| |
+----------------------------------------------------------+
6.4 Notificaciones al Usuario
| Evento |
Tipo |
Mensaje |
| Perdida de conexion |
Toast |
"Modo offline activado. Tus datos se guardaran localmente." |
| Conexion restaurada |
Toast |
"Conexion restaurada. Sincronizando datos..." |
| Sync completada |
Toast |
"Sincronizacion completada. 12 eventos enviados." |
| Error de sync |
Banner |
"Error al sincronizar. Reintentando automaticamente..." |
| Sync critica fallida |
Modal |
"No se pudo enviar la firma POD. Verifica tu conexion." |
| Almacenamiento lleno |
Modal |
"Almacenamiento casi lleno. Sincroniza para liberar espacio." |
7) Diagrama de Flujo Completo
7.1 Flujo de Captura de Evento Offline
+-----------------------------------------------------------------------+
| FLUJO: CAPTURA DE EVENTO OFFLINE |
+-----------------------------------------------------------------------+
CONDUCTOR APP LOCAL DB
| | |
| [Toca "Arribado"] | |
|------------------------>| |
| | |
| | Generar UUID |
| | Capturar timestamp |
| | Obtener GPS actual |
| | |
| | Validar datos |
| |------------------------+ |
| | | |
| |<-----------------------+ |
| | |
| | Guardar evento local |
| |----------------------------->|
| | |
| | Evento guardado |
| |<-----------------------------|
| | |
| | Agregar a cola de sync |
| |----------------------------->|
| | |
| | Actualizar UI |
| | (badge +1) |
| | |
| [UI actualizada] | |
|<------------------------| |
| "Arribado registrado | |
| (pendiente de sync)" | |
| | |
| | Check conectividad |
| |------------------------+ |
| | | |
| |<-----------------------+ |
| | (OFFLINE - no hacer nada) |
| | |
+-----------------------------------------------------------------------+
7.2 Flujo de Sincronizacion al Reconectar
+-----------------------------------------------------------------------+
| FLUJO: SINCRONIZACION AL RECONECTAR |
+-----------------------------------------------------------------------+
NETWORK SYNC MANAGER LOCAL DB SERVER
| | | |
| [Conexion OK] | | |
|--------------------->| | |
| | | |
| | Obtener pendientes | |
| |--------------------->| |
| | | |
| | [Lista de items] | |
| |<---------------------| |
| | | |
| | Ordenar por prioridad |
| | (CRITICA > ALTA > MEDIA > BAJA) |
| | | |
| | POST /api/sync/events |
| |----------------------------------------->|
| | | |
| | | 200 OK |
| |<-----------------------------------------|
| | | |
| | Marcar como enviado | |
| |--------------------->| |
| | | |
| | POST /api/sync/files (fotos) |
| |----------------------------------------->|
| | | |
| | | 200 OK |
| |<-----------------------------------------|
| | | |
| | Borrar blobs locales| |
| |--------------------->| |
| | | |
| | GET /api/sync/pull?since=timestamp |
| |----------------------------------------->|
| | | |
| | | [Cambios] |
| |<-----------------------------------------|
| | | |
| | Aplicar cambios | |
| |--------------------->| |
| | | |
| | Notificar UI | |
| | (Sync completa) | |
| | | |
+-----------------------------------------------------------------------+
8) Consideraciones de Seguridad
8.1 Proteccion de Datos Locales
| Aspecto |
Implementacion |
| Cifrado en reposo |
SQLCipher para WatermelonDB |
| Cifrado de blobs |
AES-256 para fotos/firmas |
| Autenticacion |
JWT con refresh token offline (7 dias) |
| Borrado seguro |
Wipe de datos al logout/desasignacion |
| Integridad |
Checksums SHA-256 para archivos |
8.2 Limites de Seguridad
- Maximo 7 dias de operacion offline sin re-autenticar
- Datos locales se borran si el dispositivo reporta compromiso
- Fotos contienen watermark invisible con ID de operador
- Firmas incluyen timestamp y coordenadas GPS inmutables
9) Metricas y Monitoreo
9.1 Metricas a Capturar
| Metrica |
Descripcion |
Alerta |
| sync_queue_size |
Tamano de cola de sync |
> 100 items |
| sync_latency_ms |
Tiempo de sincronizacion |
> 30000 ms |
| offline_duration_min |
Tiempo offline |
> 60 min |
| sync_failures |
Errores de sync |
> 5 consecutivos |
| storage_used_mb |
Almacenamiento usado |
> 80% limite |
| conflict_count |
Conflictos detectados |
> 10/dia |
9.2 Logs para Debugging
// Formato de log para eventos offline
{
"timestamp": "2026-01-27T14:35:22.123Z",
"level": "INFO",
"module": "OfflineSync",
"event": "EVENT_CAPTURED",
"data": {
"event_id": "uuid-xxx",
"event_type": "ARRIBADO",
"viaje_id": "VJ-2026-00123",
"is_online": false,
"queue_position": 5,
"storage_used_mb": 45.2
}
}
10) Referencias
ARQUITECTURA-OFFLINE.md v1.0.0 - erp-transportistas - Sistema SIMCO v4.0.0