6) Seus Dados e Geocerca

Esta página documenta a tela Seus Dados do aplicativo G10 Bio Produtor. A tela deve exibir os dados básicos do produtor, o vínculo ativo com o franqueado e as geocercas cadastradas no ERP.

Esses dados devem ser recebidos diretamente no retorno de f=sincronizacao_offline. O app salva o retorno no SQLite e usa os dados locais para exibir a tela mesmo sem internet.

Tela: Seus Dados Menu: produtor Endpoint: sincronizacao_offline Retorno: produtor + franqueado + geocercas Mapa: polígonos Offline-first

Objetivo desta tela

Exibir ao produtor um resumo dos dados cadastrados no ERP, o franqueado responsável pelo atendimento e as áreas cadastradas para aplicação, representadas por geocercas no mapa.

O app deve renderizar a geocerca usando os pontos do array poligono. Não deve receber uma imagem pronta do mapa. O mapa deve ser montado dinamicamente no aplicativo.

Como os dados são atualizados?

A tela Seus Dados deve usar os dados salvos no banco offline local do app. A atualização desses dados acontece pela rotina de sincronização.

  1. O app chama action=apiG10bio_produtor e f=sincronizacao_offline.
  2. O ERP identifica o produtor pelo X-DEVICE-TOKEN.
  3. A resposta retorna os dados atuais do produtor, vínculo com o franqueado e geocercas.
  4. O app salva ou atualiza esses dados no SQLite.
  5. A tela Seus Dados exibe sempre os dados locais.
A explicação completa do retorno fica na seção 4) Sincronização offline.

Endpoint

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

Headers obrigatórios

X-APP-KEY: <APP_KEY_FIXA_DO_APP>
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

O app não deve enviar id_cliente nem id_franqueado. O ERP identifica o produtor e o vínculo ativo pelo X-DEVICE-TOKEN.

Resposta esperada da API

{
  "success": true,
  "msg": "Sincronização realizada com sucesso.",
  "data": {
    "server_time": "2026-07-24 08: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",
      "razao_social": "Sítio Modelo",
      "documento": "000.000.000-00",
      "telefone": "(18) 99999-9999",
      "email": "produtor@exemplo.com",
      "cidade": "Presidente Prudente",
      "uf": "SP"
    },
    "dados_franqueado": {
      "id_franqueado": 10,
      "nome_franqueado": "G10 Bio Presidente Prudente",
      "telefone": "(18) 99999-0000",
      "email": "franqueado@exemplo.com",
      "cidade_base": "Presidente Prudente",
      "uf_base": "SP"
    },
    "geocercas": [
      {
        "id_geocerca": 5,
        "descricao": "Talhão principal",
        "total_pontos": 4,
        "centro": {
          "latitude": -21.853900,
          "longitude": -47.479800
        },
        "poligono": [
          { "latitude": -21.853901, "longitude": -47.479801, "ordem": 1 },
          { "latitude": -21.853950, "longitude": -47.479700, "ordem": 2 },
          { "latitude": -21.854020, "longitude": -47.479750, "ordem": 3 },
          { "latitude": -21.854000, "longitude": -47.479850, "ordem": 4 }
        ],
        "criado_em": "2026-07-20 10:00:00",
        "atualizado_em": "2026-07-23 11:30:00"
      }
    ]
  }
}

Campos retornados — Dispositivo e vínculo

Campo Descrição
device_id ID do aparelho registrado no ERP.
device_name Nome/apelido do aparelho, informado no pareamento.
account_type Tipo da conta autenticada. Neste aplicativo deve ser produtor.

Campos retornados — Produtor

Campo Descrição
cliente_id ID do produtor cadastrado em clientes.
dados_produtor.nome Nome do produtor.
dados_produtor.razao_social Razão social ou nome da propriedade, quando disponível.
dados_produtor.documento CPF ou CNPJ cadastrado no ERP.
dados_produtor.telefone Telefone atualizado do produtor.
dados_produtor.email E-mail cadastrado.
dados_produtor.cidade / uf Localização principal do produtor.

Campos retornados — Franqueado

Campo Descrição
id_franquia ID da franquia responsável.
id_franqueado ID do franqueado atualmente vinculado ao produtor.
id_vinculo_produtor ID do vínculo ativo em franquias_franqueados_produtores.
dados_franqueado.nome_franqueado Nome do franqueado responsável.
dados_franqueado.telefone Telefone de contato do franqueado.
dados_franqueado.email E-mail de contato.
dados_franqueado.cidade_base / uf_base Cidade-base de atendimento do franqueado.

Campos retornados — Geocercas

Campo Descrição
geocercas[].id_geocerca ID da geocerca no ERP.
geocercas[].descricao Descrição da área, exemplo: Área destinada para aplicação.
geocercas[].total_pontos Total de pontos que formam o polígono.
geocercas[].centro.latitude Latitude sugerida para centralizar o mapa.
geocercas[].centro.longitude Longitude sugerida para centralizar o mapa.
geocercas[].poligono Lista ordenada de pontos da geocerca.
geocercas[].poligono[].latitude Latitude do ponto do polígono.
geocercas[].poligono[].longitude Longitude do ponto do polígono.
geocercas[].poligono[].ordem Ordem do ponto no desenho da geocerca.
geocercas[].atualizado_em Data/hora da última alteração da geocerca no ERP.

Como salvar no app

O app deve salvar o retorno no banco offline local. A tela Seus Dados deve ler primeiro os dados locais, para funcionar mesmo sem internet.

Estrutura sugerida no app

produtor_local
- id_cliente
- nome
- razao_social
- documento
- telefone
- email
- cidade
- uf
- updated_at

franqueado_local
- id_franquia
- id_franqueado
- id_vinculo_produtor
- nome_franqueado
- telefone
- email
- cidade_base
- uf_base
- situacao
- data_inicio
- data_fim
- updated_at

geocercas_local
- id_geocerca
- descricao
- total_pontos
- centro_latitude
- centro_longitude
- criado_em
- atualizado_em

geocerca_pontos_local
- id_geocerca
- latitude
- longitude
- ordem

Exibição da geocerca no React Native

Em React Native, o app normalmente deve usar um componente de mapa nativo, como react-native-maps. O app deve transformar o array poligono em coordenadas e passar para o componente Polygon.

Instalação recomendada

npm install react-native-maps

Tipos TypeScript sugeridos

type DeviceData = {
  device_id: number;
  device_name: string;
  account_type: 'produtor' | 'produtor_funcionario' | 'colaborador';
};

type ClienteData = {
  id_cliente: number;
  razao_social: string;
  cidade: string;
  uf: string;
  segmento: string;
  variedade_planta: string;
  porta_enxerto: string;
  idade_pomar: string;
  qtde_planta: string;
  capacidade_tanque: string;
  qtde_tanque_aplic: string;
  qtde_planta_tanque: string;
  area_irrigada: string;
  plano_manejo: string;
};

type G10Data = {
  id_g10: number;
  id_fase: number;
  fase: string;
  status: number;
};

type GeoPoint = {
  latitude: number;
  longitude: number;
  ordem: number;
};

type GeocercaData = {
  id_geocerca: number;
  descricao: string;
  total_pontos: number;
  centro: {
    latitude: number;
    longitude: number;
  } | null;
  poligono: GeoPoint[];
  criado_em: string;
  atualizado_em: string;
};

type MeusDadosGeocercaResponse = {
  success: boolean;
  msg: string;
  data: {
    device: DeviceData;
    cliente: ClienteData;
    g10: G10Data;
    geocercas: GeocercaData[];
  };
};

Exemplo de consumo da API

type ApiConfig = {
  appKey: string;
  deviceToken: string;
};

export async function sincronizarDadosProdutor(config: ApiConfig) {
  const body = new URLSearchParams();
  body.append('action', 'apiG10bio_produtor');
  body.append('f', 'sincronizacao_offline');
  body.append('app_version', '1.0.0');

  const response = await fetch('https://agroecologia.grupoekos.com.br/router/action.php', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
      'X-APP-KEY': config.appKey,
      'X-DEVICE-TOKEN': config.deviceToken,
    },
    body: body.toString(),
  });

  const json = await response.json() as MeusDadosGeocercaResponse;

  if (!response.ok || !json.success) {
    throw new Error(json.msg || 'Erro ao sincronizar dados do produtor.');
  }

  return json.data;
}

Exemplo de componente React Native

import React from 'react';
import { View, Text } from 'react-native';
import MapView, { Polygon, PROVIDER_GOOGLE } from 'react-native-maps';

type GeoPoint = {
  latitude: number;
  longitude: number;
  ordem: number;
};

type GeocercaData = {
  id_geocerca: number;
  descricao: string;
  total_pontos: number;
  centro: {
    latitude: number;
    longitude: number;
  } | null;
  poligono: GeoPoint[];
};

type Props = {
  geocerca: GeocercaData;
};

export function MapaGeocerca({ geocerca }: Props) {
  if (!geocerca || !geocerca.centro || geocerca.poligono.length < 3) {
    return (
      <View>
        <Text>Área de aplicação ainda não cadastrada.</Text>
      </View>
    );
  }

  const coordinates = [...geocerca.poligono]
    .sort((a, b) => a.ordem - b.ordem)
    .map((p) => ({
      latitude: Number(p.latitude),
      longitude: Number(p.longitude),
    }));

  return (
    <MapView
      provider={PROVIDER_GOOGLE}
      mapType="satellite"
      style={{ width: '100%', height: 320 }}
      initialRegion={{
        latitude: geocerca.centro.latitude,
        longitude: geocerca.centro.longitude,
        latitudeDelta: 0.01,
        longitudeDelta: 0.01,
      }}
    >
      <Polygon
        coordinates={coordinates}
        strokeColor="red"
        fillColor="rgba(255, 255, 0, 0.35)"
        strokeWidth={2}
      />
    </MapView>
  );
}
O app deve ordenar os pontos por ordem antes de renderizar o polígono.

Observação sobre Google Maps

Em páginas web, o Google Maps é carregado com a tag abaixo:

<script src="https://maps.googleapis.com/maps/api/js?key=<AQUI>&v=weekly&language=pt-BR&libraries=drawing"></script>

Em React Native, essa tag <script> normalmente não é usada diretamente. O app deve usar o SDK nativo do Google Maps através de uma biblioteca como react-native-maps. A chave do Google Maps deve ser configurada no projeto Android/iOS, conforme a biblioteca usada pelo desenvolvedor.

A biblioteca drawing é usada no ERP/web para desenhar e editar polígonos. No app mobile, a necessidade principal é apenas exibir a geocerca já cadastrada.

Exemplo de chamada cURL

curl -i -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: APP_KEY_FIXA_DO_APP" \
  -H "X-DEVICE-TOKEN: dev_xxxxxxxxxxxxxxxxx" \
  --data "action=apiG10bio_produtor&f=sincronizacao_offline&app_version=1.0.0"

Erros comuns

  • missing_app_key: o header X-APP-KEY não foi enviado.
  • invalid_api_key: a chave do app é inválida.
  • missing_device_token: o header X-DEVICE-TOKEN não foi enviado.
  • device_token_not_found: o aparelho não está pareado ou o token é inválido.
  • vinculo_inativo: o produtor não possui vínculo ativo com um franqueado.
  • produtor_not_found: o produtor vinculado ao aparelho não foi localizado.