KEPLIN Docs

Lógica e automação

Escrever o script Python que resume o pipeline comercial, corrê-lo à mão e agendá-lo para todas as manhãs.

A app já mostra dados e deixa editá-los. Falta a parte que trabalha sozinha: um script que, todas as manhãs, olha para o pipeline, conta o que está aberto e regista os fechos previstos para a semana.

Nesta etapa escreves esse script em Python, corre-lo à mão para ver o resultado, e marcas-lhe uma hora — todos os dias às 07:00.

O que o script vai fazer

O atualizar_indicadores responde a três perguntas, e devolve-as num resultado que fica no histórico:

Pergunta O que devolve
Quantas oportunidades estão abertas? oportunidades_abertas
Quanto vale o pipeline? valor_pipeline
Quantos fechos estão previstos para os próximos 7 dias? fechos_proximos_7_dias

Além do resultado, escreve logs — uma linha por fecho da semana — para quem abrir o histórico perceber, sem contas, o que estava marcado naquele dia.

Criar o script

  1. Escolhe o painel Código na barra lateral.
  2. Na linha Scripts, clica no + (Novo script). Abre o diálogo Novo script"Escolhe o runtime e cria — o código edita-se a seguir, com o contrato à vista."
  3. Em Nome, escreve atualizar_indicadores. O nome identifica o script em todo o lado — nos agendamentos, nos passos de API, nas dependências de outros scripts.
  4. Runtime está fixo em Python.
  5. Em Descrição, escreve Recalcula os indicadores comerciais e avisa quando há fechos para esta semana.
  6. Em Tempo limite, deixa 1 minuto. É o tecto da execução: passado esse tempo, a plataforma corta.
  7. Clica em Criar script. O editor abre com o main.py pronto.

O diálogo Novo script — nome, runtime, descrição e tempo limite.
O diálogo Novo script — nome, runtime, descrição e tempo limite.

Dica

Um tempo limite generoso não é gentileza: se este script for usado como passo de uma API, os clientes ficam à espera esse tempo no pior caso. Um minuto chega e sobra para o que vamos fazer.

Escrever o main.py

O contrato de um script é curto: uma função main(input) que devolve alguma coisa. O que devolves fica no histórico de execuções e, se o script for chamado por uma API, é a resposta dela.

Escreve isto no editor:

from datetime import date, timedelta

from api_manager import db, log


def main(input):
    """Recalcula os indicadores do painel comercial.

    Corre todos os dias às 7h00 (agendamento "Indicadores diários") e
    devolve o resumo — o histórico de execuções fica com um registo
    legível por dia.
    """
    crm = db("Dados CRM")

    abertas = crm.query(
        "select count(*) as n, coalesce(sum(valor), 0) as total "
        "from oportunidades where fase not in ('fechada_ganha', 'fechada_perdida')"
    )[0]

    limite = (date.today() + timedelta(days=7)).isoformat()
    fechos_semana = crm.query(
        "select titulo, data_fecho from oportunidades "
        "where fase not in ('fechada_ganha', 'fechada_perdida') "
        "and data_fecho <= ? order by data_fecho",
        [limite],
    )

    log("pipeline:", abertas["n"], "oportunidades /", abertas["total"], "EUR")
    for op in fechos_semana:
        log("fecho esta semana:", op["titulo"], "(", op["data_fecho"], ")")

    return {
        "oportunidades_abertas": abertas["n"],
        "valor_pipeline": abertas["total"],
        "fechos_proximos_7_dias": len(fechos_semana),
    }

O editor do script atualizar_indicadores — o main.py e, em baixo, o painel Resultado da execução.
O editor do script atualizar_indicadores — o main.py e, em baixo, o painel Resultado da execução.

Quatro coisas para reter deste código:

Linha O que faz
from api_manager import db, log O acesso da plataforma: db abre bases de dados, log escreve no histórico.
db("Dados CRM") A base de dados pelo nome interno do datasource — o mesmo que registaste na etapa do modelo. Muda o nome ali e esta linha deixa de funcionar.
crm.query(sql, [valores]) Consulta parametrizada. Os valores vão sempre à parte da query — nunca colados ao texto.
return { … } O resultado da execução. Fica no histórico e é o que uma API devolveria.

O input que a função recebe traz os argumentos da execução — os de uma API, os de um agendamento ou os que escreveres à mão a seguir. Aqui não usamos nenhum.

Nota

Não há botão de gravar: o editor grava sozinho. O interruptor Activo no canto superior direito é outra coisa — um script inactivo continua a existir mas não corre, nem à mão nem por agendamento.

Correr o script à mão

  1. No topo do editor, clica em Executar agora.
  2. Abre o diálogo — "Define os argumentos desta execução (opcional). Os valores chegam ao script como texto." Não precisamos de nenhum.
  3. Clica em Executar.

O diálogo Executar agora — argumentos opcionais desta execução, entregues ao script como texto.
O diálogo Executar agora — argumentos opcionais desta execução, entregues ao script como texto.

O painel Resultado da execução, em baixo, enche-se: o selo Sucesso com a duração, o valor devolvido em JSON e o bloco Logs com as linhas que o log() escreveu.

O painel Resultado da execução, com o valor devolvido e os logs.
O painel Resultado da execução, com o valor devolvido e os logs.

Dica

A primeira execução de um script Python é sempre a mais lenta — o ambiente é preparado nesse momento. As seguintes correm em milissegundos.

O histórico de execuções

O resultado no editor é só o da sessão actual. O histórico completo está no botão Execuções, ao lado do Executar agora:

O histórico Execuções do script — início, origem, estado e duração de cada corrida.
O histórico Execuções do script — início, origem, estado e duração de cada corrida.

Cada linha diz Início, Origem (Manual, quando foste tu; Agendamento, quando foi a hora marcada), Estado e Duração, e o link Detalhes abre a execução: os argumentos, o resultado devolvido e os logs daquela corrida em concreto. É por aqui que se percebe, três semanas depois, o que o script viu na manhã em que ninguém estava a ver.

Agendar para todas as manhãs

Um script que só corre quando alguém carrega no botão não é automação. É altura de lhe marcar uma hora.

  1. Na árvore do painel Código, expande o nó do script atualizar_indicadores. Aparecem três secções: Ficheiros, Dependências e Agendamentos.
  2. Passa o rato sobre Agendamentos e clica no + (Novo agendamento).
  3. Dá-lhe o nome Indicadores diários e cria. O editor do agendamento abre num separador.
  4. Em Frequência, escolhe Em momentos certos"Numa hora do dia, nos dias que escolheres."
  5. Em Repete, escolhe Todos os dias (nos dias escolhidos).
  6. Em À hora, escreve 07:00.
  7. Em Dias, deixa os sete seleccionados (ou clica em Úteis se o fim-de-semana não interessar).
  8. Em Fuso horário, escolhe Europe/Lisbon. É o fuso que decide o que são "sete da manhã" — sem ele, a hora certa muda com a mudança da hora.
  9. Em Se ficar por correr, escolhe Ignorar.
  10. Confirma que o interruptor Activo está ligado e clica em Gravar.

O agendamento Indicadores diários — todos os dias às 07:00 (Europe/Lisbon), com o painel Execuções à direita.
O agendamento Indicadores diários — todos os dias às 07:00 (Europe/Lisbon), com o painel Execuções à direita.

As três frequências

Frequência Quando usar
Repetir A cada N minutos ou horas, sem parar. Sincronizações, sondagens.
Em momentos certos Numa hora do dia, nos dias escolhidos. É o nosso caso — e o mais comum.
Janela de vigilância Sonda de N em N minutos entre duas horas e pára quando o trabalho do dia estiver feito. Para esperar por um ficheiro que chega "de manhã, a horas variáveis".

Quem preferir escrever a expressão de agendamento à mão tem o link Escrever a expressão à mão por baixo das três opções.

O que fazer com o que ficou por correr

O servidor esteve em baixo às sete da manhã. Quando voltar, o que acontece à ocorrência falhada? É o que Se ficar por correr decide:

Opção O que faz
Ignorar Não recupera. Fica registado que se perdeu.
Só a mais recente Recupera a última que ficou por fazer; as anteriores ficam registadas como perdidas.
Todas Recupera todas as que ficaram por fazer, pela ordem em que estavam marcadas.

Para um resumo diário, Ignorar é o certo: correr o resumo de terça na quinta-feira não serve a ninguém. Para uma facturação mensal, Todas faz todo o sentido.

O painel de execuções do agendamento

À direita do editor fica o painel Execuções, com as horas previstas e o que aconteceu a cada uma: Feita, Por fazer, Perdida ou Saltada.

Atenção

Se este painel avisar que "o agendador não está a correr nesta instalação — nada será executado", as horas marcadas ficam à espera e nada corre. O agendador liga-se na instalação, não na app — fala com quem administra a plataforma.

E a seguir?

O script fica pronto para mais do que a hora marcada: pode ser um passo de uma API (para o resumo ser calculado a pedido), pode chamar outros scripts como dependência, e pode instalar packages de Python que precise. O capítulo Scripts percorre tudo isso, e o SDK dos scripts documenta o api_manager — base de dados, ficheiros, secrets, notificações e chamadas HTTP.

Porque não…?

  • Porque é que o script falha com "datasource não encontrado"? O nome em db("…") tem de ser exactamente o Nome interno do datasource, maiúsculas incluídas.
  • Porque não vejo o botão Executar agora? O script está inactivo — liga o interruptor no topo.
  • Porque é que a execução foi cortada a meio? Bateu no Tempo limite. Ou o script demora mesmo, e aumentas o limite, ou está a fazer trabalho a mais para o sítio onde é chamado.
  • Porque é que o agendamento nunca correu? Vê, por ordem: o agendamento está Activo? O script está Activo? O agendador está a correr nesta instalação? E o Fuso horário é o que pensas que é?

O CRM está completo. Falta pô-lo no ar: publicar e usar.