Regenera G10 — Evolução

Esta documentação descreve os endpoints do menu Evolução no aplicativo G10. A Evolução reúne galeria de fotos aprovadas, análises em PDF e comparação de índices.

Auth: X-APP-KEY + X-DEVICE-TOKEN Controller: apiG10 Menu: 12) Evolução Galeria, Análises e Comparação

1) Estrutura do menu Evolução

O menu Evolução deve apresentar os seguintes submenus:

12) Evolução
12.1 - Galeria
12.2 - Análises
12.3 - Comparação de índices

2) Regras gerais de autenticação

Todos os endpoints da Evolução devem receber as credenciais do app nos headers.

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

O X-DEVICE-TOKEN identifica o cliente/aparelho. A API deve validar se a participação G10 solicitada pertence ao cliente vinculado ao device.

Para usuários do tipo produtor ou funcionário do produtor, a API deve bloquear qualquer tentativa de consultar dados de outro cliente.

3) 12.1 — Galeria da Evolução

A Galeria da Evolução retorna as fotos aprovadas da área G10. As imagens ficam em pasta protegida, portanto a API retorna apenas uma URL controlada.

Endpoint lista: evolucao_galeria Endpoint imagem: foto_evolucao Regra: status = aprovada Filtro: tipo_foto

3.1) Endpoint — Listar Galeria

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

Body

action=apiG10
f=evolucao_galeria
id_g10_participacao=2

Resposta esperada

{
  "success": true,
  "msg": "Galeria da evolução carregada com sucesso.",
  "data": {
    "id_g10_participacao": 2,
    "cliente_id": 664,
    "total_fotos": 2,
    "fotos": [
      {
        "id_foto": 12,
        "url": "https://agroecologia.grupoekos.com.br/router/action.php",
        "action": "apiG10",
        "f": "foto_evolucao",
        "data_foto": "2026-05-05",
        "hora_foto": "10:35:20",
        "latitude": "-21.86454000",
        "longitude": "-47.49973000",
        "observacao": "Foto da área central do talhão",
        "tipo_foto": "chao"
      }
    ]
  }
}

Campo tipo_foto

O campo tipo_foto identifica a categoria da foto aprovada e deve ser usado pelo app para filtros e comparação visual da evolução.

Valores possíveis: folha, fruto, chao ou pomar.

Regra: fotos de tipos diferentes não devem ser comparadas entre si.

Para a Galeria da Evolução, basta a foto estar com status = 'aprovada'. O campo exibir_pagina_publica é usado somente para a Página Pública, não para o app.

3.2) Endpoint — Entregar imagem da Evolução

POST foto_evolucao

URL

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

Headers

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

Body

action=apiG10
f=foto_evolucao
id_foto=12

Esse endpoint não deve ser chamado via GET, link direto, navegador, <img src=""> ou componente de imagem que não envie headers.

O app deve fazer uma requisição POST, enviando os headers de autenticação e o id_foto no body. Se estiver tudo correto, a API retorna o binário da imagem com Content-Type: image/jpeg ou image/png.

Depois de baixar a imagem, o app deve salvar/cachear o arquivo localmente e exibir a imagem local. A imagem da evolução não deve ser renderizada diretamente pela URL remota.

3.3) Regra de cache da Galeria no app

O app pode armazenar as fotos localmente para melhorar a experiência do usuário. O controle pode ser feito apenas por id_foto, pois a foto em si não será atualizada.

  1. Ao abrir a Galeria, o app chama evolucao_galeria.
  2. A API retorna a lista atual de fotos aprovadas.
  3. O app deve usar tipo_foto para separar as fotos por categoria.
  4. Se um id_foto veio na resposta e não existe no cache local, o app baixa a imagem.
  5. Se um id_foto já existe no cache, o app mantém.
  6. Se um id_foto existe no cache, mas não veio mais na resposta, o app remove do cache.
  7. A exibição pode ser em grade, carrossel, filtro por tipo ou tela cheia.

4) 12.2 — Análises

O submenu Análises retorna os PDFs das análises vinculadas ao cliente/G10. O app recebe metadados e uma URL controlada para abrir ou baixar o PDF.

Endpoint lista: evolucao_analises Endpoint PDF: pdf_evolucao_analise Campos: dia, tipo, label, url_pdf

4.1) Endpoint — Listar análises

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

Body

action=apiG10
f=evolucao_analises
id_g10_participacao=2

Ligação das tabelas

g10_participacoes.id_cliente
↓
clientes_analises.id_cliente
↓
clientes_analises.id_analise
↓
analises.id

Resposta esperada

{
  "success": true,
  "msg": "Análises da evolução carregadas com sucesso.",
  "data": {
    "id_g10_participacao": 2,
    "cliente_id": 664,
    "total_analises": 2,
    "analises": [
      {
        "id_analise": 15,
        "dia": "2026-04-20",
        "tipo": "folha",
        "label": "20/04/26 - Análise de Folha",
        "url_pdf": "https://agroecologia.grupoekos.com.br/router/action.php?action=apiG10&f=pdf_evolucao_analise&id_analise=15"
      }
    ]
  }
}

4.2) Endpoint — Entregar PDF da análise

GET pdf_evolucao_analise

URL

https://agroecologia.grupoekos.com.br/router/action.php?action=apiG10&f=pdf_evolucao_analise&id_analise=15

Esse endpoint deve validar novamente X-APP-KEY e X-DEVICE-TOKEN. A API só entrega o PDF se a análise pertencer ao cliente do device.

O arquivo PDF não deve ser exposto diretamente pela pasta física. O app deve usar a URL controlada retornada em url_pdf.

5) 12.3 — Comparação de índices

A comparação de índices possui dois modos:

  1. Comparação por indicador selecionado: o usuário escolhe duas análises e um indicador em cada uma delas.
  2. Comparação completa: o usuário escolhe duas análises e compara todos os indicadores em comum.

5.1) Comparação por indicador selecionado

A comparação por indicador selecionado deve ser feita entre duas análises escolhidas pelo usuário. Primeiro o app lista as análises disponíveis do cliente/G10. Depois, ao selecionar uma análise, o app lista somente os indicadores existentes naquela análise.

O select da segunda análise deve iniciar vazio. Ele só será alimentado depois que o usuário selecionar a primeira análise e o primeiro indicador.

Fluxo no app

  1. Ao entrar na tela, o app chama evolucao_analises_indicador.
  2. A API retorna total_analises, pode_comparar e a lista de análises.
  3. Se total_analises < 2, o app informa que não há análises suficientes para comparação.
  4. O select da primeira análise é preenchido.
  5. O select do primeiro indicador fica vazio até o usuário escolher a primeira análise.
  6. O select da segunda análise inicia vazio.
  7. O select do segundo indicador inicia vazio.
  8. O botão Comparar inicia bloqueado.
  9. Ao selecionar a primeira análise, o app chama evolucao_indicadores_analise.
  10. Ao selecionar o primeiro indicador, o app libera o select da segunda análise.
  11. O select da segunda análise lista todas as análises, exceto a primeira análise já escolhida.
  12. Ao selecionar a segunda análise, o app chama novamente evolucao_indicadores_analise.
  13. Ao selecionar o segundo indicador, o app libera o botão Comparar.
  14. Ao clicar em Comparar, o app chama evolucao_comparar_indicadores_selecionados.

5.1.1) Endpoint — Listar análises para comparação por indicador

POST evolucao_analises_indicador

Body

action=apiG10
f=evolucao_analises_indicador
id_g10_participacao=2

Resposta esperada

{
  "success": true,
  "msg": "Análises para comparação por indicador carregadas com sucesso.",
  "data": {
    "id_g10_participacao": 2,
    "cliente_id": 664,
    "total_analises": 3,
    "pode_comparar": true,
    "analises": [
      {
        "id_analise": 10,
        "dia": "2026-05-01",
        "tipo": "solo",
        "label": "01/05/26 - Análise de Solo",
        "total_indicadores": 18
      },
      {
        "id_analise": 15,
        "dia": "2026-05-15",
        "tipo": "folha",
        "label": "15/05/26 - Análise de Folha",
        "total_indicadores": 20
      },
      {
        "id_analise": 22,
        "dia": "2026-05-30",
        "tipo": "micro",
        "label": "30/05/26 - Análise Microbiológica",
        "total_indicadores": 16
      }
    ]
  }
}

Regra no app

Se total_analises for menor que 2 ou pode_comparar vier como falso, o app deve exibir:

Não há análises suficientes para comparação.

5.1.2) Endpoint — Listar indicadores de uma análise

POST evolucao_indicadores_analise

Body

action=apiG10
f=evolucao_indicadores_analise
id_g10_participacao=2
id_analise=10

Resposta esperada

{
  "success": true,
  "msg": "Indicadores da análise carregados com sucesso.",
  "data": {
    "id_g10_participacao": 2,
    "cliente_id": 664,
    "analise": {
      "id_analise": 10,
      "dia": "2026-05-01",
      "tipo": "solo",
      "label": "01/05/26 - Análise de Solo"
    },
    "total_indicadores": 18,
    "indicadores": [
      {
        "id_resultado": 501,
        "indicador_slug": "potassio",
        "indicador_nome": "Potássio",
        "grupo_nome": "Indicadores que estão dentro do parâmetro ideal",
        "subgrupo_nome": "",
        "valor_percentual": 3.8,
        "unidade_medida": "mmolc/dm³",
        "classificacao_texto": "dentro_do_ideal",
        "nivel": "",
        "cor": "verde"
      },
      {
        "id_resultado": 502,
        "indicador_slug": "fosforo",
        "indicador_nome": "Fósforo",
        "grupo_nome": "Indicadores que estão fora do parâmetro ideal",
        "subgrupo_nome": "",
        "valor_percentual": 46,
        "unidade_medida": "mg/dm³",
        "classificacao_texto": "fora_do_ideal",
        "nivel": "",
        "cor": "vermelho"
      }
    ]
  }
}

Regra

Este endpoint deve retornar somente os indicadores da análise informada. O app deve exibir indicador_nome, mas guardar/enviar preferencialmente id_resultado.

5.1.3) Endpoint — Comparar indicadores selecionados

POST evolucao_comparar_indicadores_selecionados

Body recomendado

action=apiG10
f=evolucao_comparar_indicadores_selecionados
id_g10_participacao=2
id_resultado_1=501
id_resultado_2=732

Body alternativo

Usar somente se o app ainda não estiver trabalhando com id_resultado.

action=apiG10
f=evolucao_comparar_indicadores_selecionados
id_g10_participacao=2
id_analise_1=10
indicador_slug_1=potassio
id_analise_2=15
indicador_slug_2=potassio

Resposta esperada

{
  "success": true,
  "msg": "Comparação carregada com sucesso.",
  "data": {
    "id_g10_participacao": 2,
    "cliente_id": 664,
    "comparacao": {
      "status": "informativo",
      "mensagem": "Mesmo indicador, mas com unidades diferentes. Exibir lado a lado sem calcular diferença direta.",
      "mesmo_indicador": true,
      "mesma_unidade": false,
      "diferenca_valor": null
    },
    "colunas": {
      "primeiro": {
        "analise": {
          "id_analise": 10,
          "dia": "2026-05-01",
          "tipo": "solo",
          "label": "01/05/26 - Análise de Solo"
        },
        "indicador": {
          "id_resultado": 501,
          "indicador_slug": "potassio",
          "indicador_nome": "Potássio",
          "grupo_nome": "Indicadores que estão dentro do parâmetro ideal",
          "subgrupo_nome": "",
          "valor_percentual": 3.8,
          "unidade_medida": "mmolc/dm³",
          "parametro_min": 1.6,
          "parametro_max": 5,
          "parametro_unidade": "mmolc/dm³",
          "status_percentual": null,
          "status_direcao": "",
          "classificacao_texto": "dentro_do_ideal",
          "nivel": "",
          "cor": "verde",
          "descricao_o_que_e": "Essencial para a regulação hídrica, fotossíntese e produção de açúcares.",
          "descricao_significado": "",
          "interpretacao_tecnica": "",
          "descricao_o_que_fazer": ""
        }
      },
      "segundo": {
        "analise": {
          "id_analise": 15,
          "dia": "2026-05-15",
          "tipo": "folha",
          "label": "15/05/26 - Análise de Folha"
        },
        "indicador": {
          "id_resultado": 732,
          "indicador_slug": "potassio",
          "indicador_nome": "Potássio",
          "grupo_nome": "Indicadores que estão dentro do parâmetro ideal",
          "subgrupo_nome": "",
          "valor_percentual": 18.5,
          "unidade_medida": "g/kg",
          "parametro_min": 10,
          "parametro_max": 20,
          "parametro_unidade": "g/kg",
          "status_percentual": null,
          "status_direcao": "",
          "classificacao_texto": "dentro_do_ideal",
          "nivel": "",
          "cor": "verde",
          "descricao_o_que_e": "Importante para equilíbrio osmótico, transporte de açúcares e qualidade dos frutos.",
          "descricao_significado": "",
          "interpretacao_tecnica": "",
          "descricao_o_que_fazer": ""
        }
      }
    }
  }
}

5.1.4) Regras da comparação por indicador selecionado

A comparação deve ser exibida lado a lado.

┌─────────────────────────────┬─────────────────────────────┐
│ 01/05/26 - Análise de Solo  │ 15/05/26 - Análise de Folha │
├─────────────────────────────┼─────────────────────────────┤
│ Potássio                    │ Potássio                    │
│ 3,80 mmolc/dm³              │ 18,50 g/kg                  │
│ Dentro do ideal             │ Dentro do ideal             │
│ Verde                       │ Verde                       │
└─────────────────────────────┴─────────────────────────────┘
  • Se os indicadores tiverem o mesmo indicador_slug e a mesma unidade_medida, a API pode retornar diferenca_valor.
  • Se os indicadores tiverem o mesmo indicador_slug, mas unidades diferentes, a API deve retornar diferenca_valor = null.
  • Se os indicadores forem diferentes, a API deve retornar mesmo_indicador = false.
  • Indicadores diferentes também podem ser exibidos lado a lado para análise técnica.

5.2) Comparação por análise completa

Neste modo, o app carrega as análises disponíveis e permite que o usuário escolha uma análise inicial e uma análise final.

A análise final deve ser posterior à análise inicial.

5.2.1) Endpoint — Listar análises comparáveis

POST evolucao_analises_comparaveis

Body

action=apiG10
f=evolucao_analises_comparaveis
id_g10_participacao=2

Resposta esperada

{
  "success": true,
  "msg": "Análises comparáveis carregadas com sucesso.",
  "data": {
    "id_g10_participacao": 2,
    "cliente_id": 664,
    "total_analises": 3,
    "analises": [
      {
        "id_analise": 10,
        "dia": "2026-05-01",
        "tipo": "solo",
        "label": "01/05/26 - Análise de Solo",
        "total_indicadores": 18
      },
      {
        "id_analise": 15,
        "dia": "2026-05-15",
        "tipo": "folha",
        "label": "15/05/26 - Análise de Folha",
        "total_indicadores": 20
      },
      {
        "id_analise": 22,
        "dia": "2026-05-30",
        "tipo": "solo",
        "label": "30/05/26 - Análise de Solo",
        "total_indicadores": 18
      }
    ]
  }
}

Regra no app

5.2.2) Endpoint — Comparar análises completas

POST evolucao_comparar_analises

Body

action=apiG10
f=evolucao_comparar_analises
id_g10_participacao=2
id_analise_inicial=10
id_analise_final=22

Resposta esperada

{
  "success": true,
  "msg": "Comparação entre análises carregada com sucesso.",
  "data": {
    "id_g10_participacao": 2,
    "cliente_id": 664,

    "analise_inicial": {
      "id_analise": 10,
      "dia": "2026-05-01",
      "tipo": "solo",
      "label": "01/05/26 - Análise de Solo"
    },

    "analise_final": {
      "id_analise": 22,
      "dia": "2026-05-30",
      "tipo": "solo",
      "label": "30/05/26 - Análise de Solo"
    },

    "resumo": {
      "total_indicadores_comparados": 16,
      "melhoraram": 8,
      "pioraram": 2,
      "estaveis": 5,
      "informativos": 1,
      "somente_na_inicial": 1,
      "somente_na_final": 2
    },

    "indicadores_melhoraram": [],
    "indicadores_pioraram": [],
    "indicadores_estaveis": [],
    "indicadores_informativos": [],
    "indicadores_somente_inicial": [],
    "indicadores_somente_final": [],
    "indicadores": []
  }
}

5.3) Regra de interpretação por cor

A comparação completa deve usar o campo cor salvo em analises_resultados.

Vermelho Fora do ideal
Amarelo Atenção
Verde Dentro do ideal
Azul Apenas informativo

Comparação

vermelho → amarelo = melhorou
amarelo  → verde   = melhorou
vermelho → verde   = melhorou

verde    → amarelo  = piorou
amarelo  → vermelho = piorou
verde    → vermelho = piorou

mesma cor = estável

azul envolvido = informativo

6) Sugestão de exibição no app

A API entrega os dados. O app pode organizar visualmente da seguinte forma:

Galeria

  • Grade de miniaturas.
  • Filtro por tipo de foto: Folha, Fruto, Chão e Pomar.
  • Não comparar fotos de tipos diferentes entre si.
  • Baixar a imagem via POST no endpoint foto_evolucao.
  • Salvar a imagem localmente no cache do app.
  • Ao tocar, abrir a imagem local em tela cheia ou carrossel.
  • Usar cache local por id_foto.

Análises

  • Lista por data e tipo.
  • Botão para abrir PDF.
  • PDF carregado pela URL controlada com headers.

Comparação por indicador selecionado

  • Select da primeira análise.
  • Select do primeiro indicador.
  • Select da segunda análise.
  • Select do segundo indicador.
  • Botão Comparar.
  • Resultado em duas colunas.
  • Cada coluna mostra os dados da análise e do indicador escolhido.

Comparação completa

  • Dois selects: análise inicial e análise final.
  • Cards de resumo: melhoraram, pioraram, estáveis e informativos.
  • Lista por indicador com leitura simples: melhorou, piorou, estável ou informativo.

7) Regras de segurança e validação

  • Nenhuma imagem ou PDF deve expor caminho real da pasta protegida.
  • Fotos e PDFs devem ser entregues por endpoint controlado.
  • Todos os endpoints da Evolução devem validar X-APP-KEY.
  • Todos os endpoints da Evolução devem validar X-DEVICE-TOKEN.
  • A participação G10 precisa pertencer ao cliente do device.
  • Fotos de tipos diferentes não devem ser comparadas entre si.
  • A análise final deve ser posterior à análise inicial.
  • O app deve bloquear a seleção invertida, mas a API também valida.

8) Lista final de endpoints da Evolução

Submenu Endpoint Função
12.1 Galeria evolucao_galeria Lista fotos aprovadas da evolução.
12.1 Galeria foto_evolucao Entrega imagem protegida da evolução.
12.2 Análises evolucao_analises Lista PDFs das análises.
12.2 Análises pdf_evolucao_analise Entrega PDF protegido da análise.
12.3 Comparação por indicador evolucao_analises_indicador Lista análises disponíveis para comparação por indicador.
12.3 Comparação por indicador evolucao_indicadores_analise Lista indicadores de uma análise específica.
12.3 Comparação por indicador evolucao_comparar_indicadores_selecionados Compara dois indicadores selecionados.
12.3 Comparação completa evolucao_analises_comparaveis Lista análises disponíveis para comparação completa.
12.3 Comparação completa evolucao_comparar_analises Compara duas análises usando os indicadores em comum.

9) Endpoints removidos

Os endpoints abaixo pertenciam ao fluxo antigo e não serão mais usados pela nova tela:

evolucao_indicadores
evolucao_comparar_indicador

Motivo da remoção

O fluxo antigo listava indicadores globais por indicador_slug e comparava esse indicador em todas as análises do cliente.

O novo fluxo exige que o usuário escolha:

1ª análise
1º indicador daquela análise

2ª análise
2º indicador daquela análise

Por isso, os novos endpoints trabalham com análise específica e, preferencialmente, com id_resultado.

Atualizações

Atualização 15/07/2026 — Tipo da foto na Galeria

O endpoint evolucao_galeria passa a retornar o campo tipo_foto dentro de cada item do array fotos.

Esse campo deve ser usado pelo aplicativo para filtros da galeria e para impedir comparações visuais entre fotos de tipos diferentes.

  • Adicionado campo tipo_foto na resposta da Galeria.
  • Valores possíveis: folha, fruto, chao, pomar.
  • O app pode exibir os filtros como: Folha, Fruto, Chão e Pomar.
  • Fotos antigas sem tipo_foto podem ser tratadas como sem classificação.
  • Fotos de tipos diferentes não devem ser comparadas entre si.
{
  "id_foto": 12,
  "tipo_foto": "chao"
}