4) Sincronização offline

Esta rota envia ao ERP os registros criados offline no aplicativo e recebe atualizações do produtor, vínculo atual com o franqueado e controle de versão do aplicativo.

Auth: X-APP-KEY + X-DEVICE-TOKEN Offline-first Retirada de produto Aplicação com trilha GPS Obrigatório: app_version

Objetivo deste fluxo

A sincronização offline do G10 Bio Produtor não baixa QR Codes antecipadamente. O produtor apenas lê o QR Code existente na embalagem, registra a ação no SQLite e envia o evento ao ERP.

A rota também sincroniza sessões de aplicação, pontos GPS coletados a cada 3 segundos, dados atualizados do produtor, vínculo com o franqueado e versão do aplicativo.

Como funciona no aplicativo

  1. Toda ação é salva primeiro no SQLite.
  2. Cada evento recebe um client_event_id único.
  3. Havendo internet, o app tenta enviar imediatamente.
  4. Sem internet ou em caso de falha, o evento permanece na fila local.
  5. Quando o app voltar a ficar online, chama f=sincronizacao_offline.
  6. O ERP confirma os eventos processados.
  7. O app remove da fila somente os eventos confirmados.
  8. O app atualiza localmente os dados do produtor e o vínculo ativo.

Endpoint

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

Headers obrigatórios

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

Body

action=apiG10bio_produtor
f=sincronizacao_offline
app_version=1.0.0
last_sync_at=YYYY-MM-DD HH:MM:SS
eventos_retirada=<JSON>
sessoes_aplicacao=<JSON>
pontos_aplicacao=<JSON>
Campo Obrigatório Descrição
app_version Sim Versão instalada no aparelho.
last_sync_at Não Data e hora da última sincronização concluída.
eventos_retirada Não Lista JSON com eventos pendentes de retirada de produto.
sessoes_aplicacao Não Lista JSON com sessões de aplicação iniciadas ou finalizadas.
pontos_aplicacao Não Lista JSON com pontos GPS coletados durante a aplicação.

Evento: retirada de produto

[
  {
    "client_event_id": "550e8400-e29b-41d4-a716-446655440000",
    "qrcode_embalagem": "G10BIO_PRODUTO_ABC123",
    "data": "2026-07-23",
    "hora": "08:30:00",
    "latitude": -21.864500,
    "longitude": -47.499700,
    "device_name": "Celular do produtor"
  }
]

O id_franqueado não deve ser confiado somente ao valor enviado pelo app. A API deve identificar o franqueado pelo vínculo ativo do produtor associado ao X-DEVICE-TOKEN.

Evento: sessão de aplicação

[
  {
    "client_event_id": "650e8400-e29b-41d4-a716-446655440001",
    "qrcode_embalagem": "G10BIO_PRODUTO_ABC123",
    "data_inicio": "2026-07-23",
    "hora_inicio": "09:00:00",
    "data_fim": "2026-07-23",
    "hora_fim": "10:20:00",
    "latitude_inicio": -21.864500,
    "longitude_inicio": -47.499700,
    "latitude_fim": -21.865100,
    "longitude_fim": -47.500200,
    "status": "FINALIZADA",
    "device_name": "Celular do produtor"
  }
]

Pontos GPS da aplicação

Durante a aplicação, o app deve registrar localmente um ponto a cada 3 segundos. Os pontos devem ser enviados em lotes para evitar timeout.

[
  {
    "client_event_id": "750e8400-e29b-41d4-a716-446655440010",
    "aplicacao_client_event_id": "650e8400-e29b-41d4-a716-446655440001",
    "ordem": 1,
    "data": "2026-07-23",
    "hora": "09:00:03",
    "latitude": -21.864510,
    "longitude": -47.499710,
    "accuracy": 8.5,
    "speed": 2.1,
    "heading": 180
  }
]
  • Cada ponto deve possuir seu próprio client_event_id.
  • aplicacao_client_event_id vincula o ponto à sessão principal.
  • O app deve manter a ordem dos pontos.
  • Em caso de falha, reenviar com os mesmos identificadores.

Resposta esperada — HTTP 200

{
  "success": true,
  "msg": "Sincronização realizada com sucesso.",
  "data": {
    "server_time": "2026-07-23 10:30:00",
    "device_id": 123,
    "cliente_id": 550,
    "account_type": "produtor",
    "id_franquia": 1,
    "id_franqueado": 10,
    "id_vinculo_produtor": 85,
    "vinculo_atual": {
      "situacao": "ATIVO",
      "data_inicio": "2026-07-01",
      "data_fim": null
    },
    "dados_produtor": {
      "nome": "José da Silva",
      "telefone": "(18) 99999-9999",
      "cidade": "Presidente Prudente",
      "uf": "SP"
    },
    "versao_app": {
      "versao_instalada": "1.0.0",
      "versao_atual": "1.0.1",
      "atualizado": 0,
      "atualizacao_obrigatoria": 0,
      "bloqueado_por_versao": 0,
      "observacao": "Nova versão disponível."
    },
    "eventos_confirmados": {
      "retiradas": [
        "550e8400-e29b-41d4-a716-446655440000"
      ],
      "sessoes_aplicacao": [
        "650e8400-e29b-41d4-a716-446655440001"
      ],
      "pontos_aplicacao": [
        "750e8400-e29b-41d4-a716-446655440010"
      ]
    }
  }
}

Como tratar a resposta

Controle de vínculo com o franqueado

A sincronização deve sempre retornar o vínculo ativo identificado pelo ERP.

Caso a franqueadora aprove uma transferência, o app receberá o novo id_franqueado na próxima sincronização e deverá atualizar o contexto local.

SE id_franqueado retornado for diferente do salvo localmente
→ atualizar id_franqueado
→ atualizar id_franquia
→ atualizar id_vinculo_produtor
→ manter o mesmo device_token
→ continuar usando o app normalmente

Controle de versão do aplicativo

  • O app deve enviar app_version
  • Se atualizacao_obrigatoria=0, apenas exibir aviso.
  • Se atualizacao_obrigatoria=1 e atualizado=0, bloquear novas operações.
  • Eventos já salvos no SQLite não devem ser apagados.

Erros comuns

Em qualquer falha, manter os eventos no SQLite e tentar novamente depois.

NÃO IMPLEMENTAR nesta sincronização

  • Download de QR Codes antecipados.
  • Cache de QR Codes com TTL.
  • Blocos de fazendas ou geocercas do Regenera G10.
  • Perfis colaborador ou produtor_funcionario.
  • Preparação Eko´s Bio.
  • Coleta de análise.
  • Página pública.
  • Chamadas ao controlador apiG10bio_franqueado.

Exemplo de chamada cURL

curl -X POST "https://agroecologia.grupoekos.com.br/router/action.php" \
  -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \
  -H "X-APP-KEY: SUA_APP_KEY" \
  -H "X-DEVICE-TOKEN: SEU_DEVICE_TOKEN" \
  --data-urlencode "action=apiG10bio_produtor" \
  --data-urlencode "f=sincronizacao_offline" \
  --data-urlencode "app_version=1.0.0" \
  --data-urlencode "last_sync_at=2026-07-23 08:00:00" \
  --data-urlencode "eventos_retirada=[]" \
  --data-urlencode "sessoes_aplicacao=[]" \
  --data-urlencode "pontos_aplicacao=[]"