6) Trajeto de aplicação

Registra o produto aplicado e o trajeto percorrido pelo produtor durante a aplicação. O app lê o QR Code ou código de barras da embalagem, inicia a sessão ao tocar em Play e grava a localização no SQLite a cada 3 segundos.

Offline-first Leitura da embalagem Coleta GPS: 3 segundos Geocerca offline Encerramento fora por 20 minutos Envio: sincronizacao_offline

Objetivo deste fluxo

Registrar uma aplicação realizada pelo produtor, identificando o produto pela leitura do código existente na embalagem e armazenando o trajeto percorrido durante a operação.

O app não depende de um QR Code criado pelo ERP e não precisa receber previamente um id_aplicacao. A sessão nasce no aparelho, recebe um client_event_id e depois é enviada ao ERP pela sincronização offline.

Como funciona no aplicativo

  1. O produtor acessa o menu Aplicação.
  2. O app abre a câmera para ler o QR Code ou código de barras da embalagem.
  3. O conteúdo lido é salvo no SQLite como produto selecionado.
  4. O produtor toca no botão Play.
  5. O app cria uma sessão com client_event_id único.
  6. O app salva data, hora, latitude e longitude iniciais.
  7. O app começa a gravar pontos GPS no SQLite a cada 3 segundos.
  8. O app verifica, a cada ponto, se a posição está dentro ou fora da geocerca.
  9. O produtor pode encerrar manualmente pelo botão Stop.
  10. Se permanecer continuamente fora da geocerca por 20 minutos, o app encerra automaticamente.
  11. A sessão e os pontos permanecem na fila até confirmação do ERP.

Leitura do produto

A aplicação utiliza o mesmo princípio da retirada de produtos: o app lê o código já existente na embalagem e armazena o conteúdo exatamente como foi capturado.

{
  "codigo_lido": "7891234567890",
  "tipo_codigo": "codigo_barras"
}
Campo Obrigatório Descrição
codigo_lido Sim Conteúdo bruto lido pelo scanner na embalagem.
tipo_codigo Sim Tipo detectado pelo scanner, como qrcode ou codigo_barras.

Sessão de aplicação

{
  "client_event_id": "650e8400-e29b-41d4-a716-446655440001",
  "codigo_lido": "7891234567890",
  "tipo_codigo": "codigo_barras",
  "data_inicio": "2026-07-24",
  "hora_inicio": "08:00:00",
  "latitude_inicio": -21.864500,
  "longitude_inicio": -47.499700,
  "data_fim": "2026-07-24",
  "hora_fim": "09:25:00",
  "latitude_fim": -21.865100,
  "longitude_fim": -47.500200,
  "status": "FINALIZADA",
  "motivo_encerramento": "MANUAL",
  "finalizada_automaticamente": 0,
  "amostragem_segundos": 3,
  "device_name": "Celular do produtor"
}
Campo Obrigatório Descrição
client_event_id Sim Identificador único da sessão, gerado no aparelho.
codigo_lido Sim Código do produto aplicado.
data_inicio / hora_inicio Sim Momento em que o produtor tocou em Play.
latitude_inicio / longitude_inicio Sim Localização inicial da aplicação.
data_fim / hora_fim Ao finalizar Momento do encerramento manual ou automático.
status Sim Exemplos: EM_ANDAMENTO ou FINALIZADA.
motivo_encerramento Ao finalizar MANUAL ou FORA_GEOCERCA_20_MIN.
finalizada_automaticamente Sim 1 quando encerrada pela regra da geocerca; caso contrário, 0.

Pontos GPS

Cada ponto deve ser salvo primeiro no SQLite e possuir identificador próprio. O vínculo com a sessão é feito por aplicacao_client_event_id.

{
  "client_event_id": "750e8400-e29b-41d4-a716-446655440010",
  "aplicacao_client_event_id": "650e8400-e29b-41d4-a716-446655440001",
  "ordem": 1,
  "data": "2026-07-24",
  "hora": "08:00:03",
  "latitude": -21.864510,
  "longitude": -47.499710,
  "accuracy": 8.5,
  "speed": 2.1,
  "heading": 180,
  "dentro_geocerca": 1
}
  • Cada ponto usa seu próprio client_event_id.
  • O mesmo ponto deve manter o mesmo identificador em todos os reenvios.
  • accuracy, speed e heading são opcionais.
  • dentro_geocerca registra o resultado da validação local.
  • A ordem dos pontos deve ser mantida.

Geocerca recebida na sincronização

A rota f=sincronizacao_offline deve retornar a geocerca atual do produtor. O app salva o polígono no SQLite para permitir a validação mesmo sem internet.

"geocerca": {
  "id_geocerca": 15,
  "descricao": "Propriedade principal",
  "atualizado_em": "2026-07-24 07:30:00",
  "pontos": [
    {
      "ordem": 1,
      "latitude": -21.864000,
      "longitude": -47.500000
    },
    {
      "ordem": 2,
      "latitude": -21.863500,
      "longitude": -47.498500
    },
    {
      "ordem": 3,
      "latitude": -21.865500,
      "longitude": -47.498000
    }
  ]
}

Caso o ERP ainda não possua geocerca cadastrada, o retorno pode trazer geocerca=null. Nessa situação, o app pode registrar o trajeto normalmente, mas não aplica o encerramento automático.

Regra de encerramento automático

O app não deve verificar a geocerca apenas uma vez a cada 20 minutos. A validação deve ocorrer em cada ponto coletado.

  1. Ao detectar um ponto fora da geocerca, salvar fora_geocerca_desde.
  2. Enquanto os novos pontos continuarem fora, manter o mesmo horário inicial.
  3. Se o produtor retornar para dentro antes de 20 minutos, limpar fora_geocerca_desde.
  4. Se permanecer continuamente fora por 20 minutos, encerrar a sessão automaticamente.
Saiu da geocerca às 10:00
Permaneceu fora até 10:20
→ finalizar automaticamente
→ motivo_encerramento = FORA_GEOCERCA_20_MIN
→ finalizada_automaticamente = 1
Saiu da geocerca às 10:00
Retornou para dentro às 10:15
→ limpar contador
→ manter aplicação ativa

Sincronização com o ERP

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
sessoes_aplicacao=<JSON>
pontos_aplicacao=<JSON>

Não existe endpoint exclusivo para o trajeto. A sincronização identifica o tipo do evento pelo array em que ele foi enviado.

Exemplo de envio

{
  "sessoes_aplicacao": [
    {
      "client_event_id": "650e8400-e29b-41d4-a716-446655440001",
      "codigo_lido": "7891234567890",
      "tipo_codigo": "codigo_barras",
      "data_inicio": "2026-07-24",
      "hora_inicio": "08:00:00",
      "latitude_inicio": -21.864500,
      "longitude_inicio": -47.499700,
      "data_fim": "2026-07-24",
      "hora_fim": "09:25:00",
      "latitude_fim": -21.865100,
      "longitude_fim": -47.500200,
      "status": "FINALIZADA",
      "motivo_encerramento": "FORA_GEOCERCA_20_MIN",
      "finalizada_automaticamente": 1,
      "amostragem_segundos": 3,
      "device_name": "Celular do produtor"
    }
  ],
  "pontos_aplicacao": [
    {
      "client_event_id": "750e8400-e29b-41d4-a716-446655440010",
      "aplicacao_client_event_id": "650e8400-e29b-41d4-a716-446655440001",
      "ordem": 1,
      "data": "2026-07-24",
      "hora": "08:00:03",
      "latitude": -21.864510,
      "longitude": -47.499710,
      "accuracy": 8.5,
      "speed": 2.1,
      "heading": 180,
      "dentro_geocerca": 1
    }
  ]
}

Confirmação do ERP

"eventos_confirmados": {
  "retiradas": [],
  "sessoes_aplicacao": [
    "650e8400-e29b-41d4-a716-446655440001"
  ],
  "pontos_aplicacao": [
    "750e8400-e29b-41d4-a716-446655440010"
  ]
}
  • Remover da fila somente os identificadores confirmados pelo ERP.
  • Uma sessão confirmada não confirma automaticamente todos os pontos.
  • Cada ponto deve ser removido somente quando aparecer em pontos_aplicacao.
  • Eventos não confirmados permanecem no SQLite para novo envio.

Operação offline

  • O app salva todos os eventos antes de tentar qualquer envio.
  • A captura do trajeto não depende de internet.
  • A geocerca deve estar salva localmente.
  • O app pode operar por até 4 dias desde a última validação online.
  • Ao ultrapassar o limite offline, novas operações devem ser bloqueadas até nova validação.
  • Eventos já registrados no SQLite não devem ser apagados.

Estrutura local recomendada

Os nomes abaixo representam apenas a organização local do SQLite do aplicativo e não definem novas tabelas no ERP.

sessoes_aplicacao_local
- client_event_id
- codigo_lido
- tipo_codigo
- data_inicio
- hora_inicio
- latitude_inicio
- longitude_inicio
- data_fim
- hora_fim
- latitude_fim
- longitude_fim
- status
- motivo_encerramento
- finalizada_automaticamente
- fora_geocerca_desde
- amostragem_segundos
- sincronizado
- created_at
- updated_at

pontos_aplicacao_local
- client_event_id
- aplicacao_client_event_id
- ordem
- data
- hora
- latitude
- longitude
- accuracy
- speed
- heading
- dentro_geocerca
- sincronizado

geocerca_local
- id_geocerca
- descricao
- atualizado_em

geocerca_pontos_local
- id_geocerca
- ordem
- latitude
- longitude

Erros e situações especiais

  • missing_device_token: token do aparelho não enviado.
  • device_token_inactive: aparelho revogado ou inativo.
  • vinculo_inativo: produtor sem vínculo ativo com franqueado.
  • invalid_codigo_lido: código da embalagem vazio ou inválido.
  • invalid_location: latitude ou longitude inválida.
  • invalid_session_reference: ponto sem sessão correspondente.
  • invalid_geocerca: polígono recebido está incompleto ou inválido.

Em qualquer falha de rede ou processamento, manter os dados no SQLite e tentar novamente com os mesmos client_event_id.

NÃO IMPLEMENTAR neste fluxo

  • QR Code específico de aplicação gerado pelo ERP.
  • Endpoint exclusivo receber_trajeto_aplicacao.
  • Obrigatoriedade de id_aplicacao
  • Envio de ponto GPS diretamente a cada 3 segundos para a API.
  • Remoção de sessão ou ponto sem confirmação em eventos_confirmados.
  • Encerramento por uma única leitura fora da geocerca.

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-24 07:30:00" \
  --data-urlencode 'sessoes_aplicacao=[{"client_event_id":"650e8400-e29b-41d4-a716-446655440001","codigo_lido":"7891234567890","tipo_codigo":"codigo_barras","data_inicio":"2026-07-24","hora_inicio":"08:00:00","latitude_inicio":-21.864500,"longitude_inicio":-47.499700,"status":"EM_ANDAMENTO","amostragem_segundos":3}]' \
  --data-urlencode 'pontos_aplicacao=[{"client_event_id":"750e8400-e29b-41d4-a716-446655440010","aplicacao_client_event_id":"650e8400-e29b-41d4-a716-446655440001","ordem":1,"data":"2026-07-24","hora":"08:00:03","latitude":-21.864510,"longitude":-47.499710,"dentro_geocerca":1}]'