3) Modo Off-line

O G10 Bio Produtor deve funcionar em propriedades rurais com internet instável ou indisponível. Por isso, o padrão obrigatório é offline-first: as ações são salvas primeiro no aparelho e enviadas posteriormente ao ERP.

Offline-first Limite offline: 4 dias SQLite + fila local Idempotência por client_event_id

Resumo

Depois que o aparelho estiver aprovado e possuir um device_token, o produtor poderá usar o aplicativo sem internet por até 4 dias, contados desde a última validação online.

Toda ação realizada no aplicativo deve ser registrada primeiro no SQLite. Havendo internet, o app pode tentar enviar imediatamente. Se o envio falhar, o registro permanece na fila local.

Importante: primeiro acesso

O endpoint f=sincronizacao_offline somente pode ser usado depois da aprovação do primeiro acesso, pois exige X-DEVICE-TOKEN.

Antes do pareamento, a solicitação inicial utiliza os endpoints próprios de primeiro acesso documentados na etapa 1.

Regras obrigatórias

  • Salvar toda ação primeiro no SQLite.
  • Gerar um client_event_id único para cada evento.
  • Manter o mesmo client_event_id em todas as tentativas de reenvio.
  • Não apagar o registro local antes da confirmação do ERP.
  • Salvar fotos e arquivos no FileSystem até o envio ser confirmado.
  • Salvar o device_token somente no SecureStore.
  • O ERP continua sendo a fonte oficial dos dados.

Limite de uso offline: 4 dias

  • Após uma validação online bem-sucedida, salvar ultima_validacao_em.
  • Sem internet, permitir o uso por até 4 dias desde essa data.
  • Durante esse período, as ações continuam sendo registradas normalmente no aparelho.
  • Após 4 dias sem validação online, bloquear novas ações que dependam de autorização.
  • Exibir uma mensagem solicitando conexão com a internet para validar novamente.
  • Não apagar dados pendentes quando o limite offline for atingido.
SE agora - ultima_validacao_em <= 4 dias
→ permitir uso offline

SE agora - ultima_validacao_em > 4 dias
→ bloquear novas ações
→ manter eventos já salvos
→ solicitar conexão com a internet

Fila de sincronização

  1. Criar o evento no SQLite.
  2. Gerar o client_event_id.
  3. Salvar o payload e arquivos relacionados.
  4. Definir status_sync = pendente.
  5. Se houver internet, tentar enviar.
  6. Se falhar, manter o evento na fila.
  7. Ao confirmar o recebimento pelo ERP, marcar como enviado.
  8. Remover da fila somente após a confirmação.

Endpoint de sincronização

POST https://agroecologia.grupoekos.com.br/router/action.php

Headers

X-APP-KEY: <APP_KEY_FIXA_DO_APP_PRODUTOR>
X-DEVICE-TOKEN: <DEVICE_TOKEN_SALVO_NO_APARELHO>

Body base

action=apiG10bio_produtor
f=sincronizacao_offline
app_version=<VERSAO_INSTALADA>
last_sync_at=<YYYY-MM-DD HH:MM:SS>

Os dados exatos retornados por esse endpoint serão ampliados conforme os módulos do G10 Bio Produtor forem documentados.

Idempotência

Todo endpoint que grava uma ação deve receber um client_event_id. Esse identificador evita registros duplicados quando o aplicativo reenviar o mesmo evento após timeout ou perda de conexão.

Resposta para evento já registrado

{
  "success": true,
  "msg": "Evento já registrado (idempotente).",
  "data": {
    "already_registered": true,
    "client_event_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}

success=true ou already_registered=true significa que o item pode ser removido da fila de envio.

Tabela local recomendada

CREATE TABLE app_eventos_sync (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    client_event_id TEXT NOT NULL UNIQUE,
    tipo_evento TEXT NOT NULL,
    endpoint TEXT NOT NULL,
    payload_json TEXT NOT NULL,
    arquivo_local TEXT NULL,
    status_sync TEXT NOT NULL DEFAULT 'pendente',
    tentativas_envio INTEGER NOT NULL DEFAULT 0,
    ultimo_erro TEXT NULL,
    criado_em TEXT NOT NULL,
    ultima_tentativa_em TEXT NULL,
    enviado_em TEXT NULL
);

Geração do client_event_id

Usar uma biblioteca confiável de UUID compatível com React Native. Não gerar identificadores com Math.random().

// Exemplo conceitual com biblioteca UUID
import { v4 as uuidv4 } from 'uuid';

const clientEventId = uuidv4();

Regra: um evento local deve possuir um único client_event_id.

Comportamento da sincronização

1. Verificar se existe internet
2. Validar X-APP-KEY e X-DEVICE-TOKEN
3. Buscar eventos pendentes ou com erro
4. Enviar cada evento ao endpoint correspondente
5. Manter o mesmo client_event_id
6. success=true → marcar como enviado
7. already_registered=true → tratar como enviado
8. Falha de rede → manter na fila
9. Erro de validação → guardar a mensagem para análise
10. Atualizar ultima_validacao_em quando houver resposta autenticada válida

Armazenamento local

Cache local

O aplicativo pode armazenar localmente os dados do produtor, vínculo ativo, franqueado responsável, configurações e conteúdos necessários aos módulos já sincronizados.

  • O cache serve apenas para operação offline.
  • O app não deve permitir alterar localmente IDs oficiais recebidos do ERP.
  • Dados atualizados pelo ERP devem substituir o cache na próxima sincronização.
  • Registros removidos ou bloqueados pelo ERP devem ser desativados localmente.

NÃO reutilizar do G10 Cytrus

  • Eventos específicos de entrega de kit do projeto Cytrus.
  • Coleta de análise específica do projeto Cytrus.
  • Cache dos QR Codes específicos do Cytrus.
  • Rastreamento de aplicação com GPS a cada 3 segundos, enquanto esse módulo não existir no Bio.
  • Perfis colaborador e produtor_funcionario.
  • Chamadas ao controlador apiG10.
  • Chamadas ao controlador apiG10bio_franqueado.

Regra final

Registrar localmente
→ tentar enviar
→ manter na fila se falhar
→ reenviar com o mesmo client_event_id
→ confirmar no ERP
→ remover da fila