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
- Escolhe o painel Código na barra lateral.
- 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."
- 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. - Runtime está fixo em Python.
- Em Descrição, escreve
Recalcula os indicadores comerciais e avisa quando há fechos para esta semana. - Em Tempo limite, deixa 1 minuto. É o tecto da execução: passado esse tempo, a plataforma corta.
- Clica em Criar script. O editor abre com o
main.pypronto.

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),
}

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
- No topo do editor, clica em Executar agora.
- Abre o diálogo — "Define os argumentos desta execução (opcional). Os valores chegam ao script como texto." Não precisamos de nenhum.
- Clica em Executar.

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.

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:

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.
- Na árvore do painel Código, expande o nó do script
atualizar_indicadores. Aparecem três secções: Ficheiros, Dependências e Agendamentos. - Passa o rato sobre Agendamentos e clica no + (Novo agendamento).
- Dá-lhe o nome
Indicadores diáriose cria. O editor do agendamento abre num separador. - Em Frequência, escolhe Em momentos certos — "Numa hora do dia, nos dias que escolheres."
- Em Repete, escolhe Todos os dias (nos dias escolhidos).
- Em À hora, escreve
07:00. - Em Dias, deixa os sete seleccionados (ou clica em Úteis se o fim-de-semana não interessar).
- 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. - Em Se ficar por correr, escolhe Ignorar.
- Confirma que o interruptor Activo está ligado e clica em Gravar.

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.