KEPLIN Docs

Lógica y automatización

Escribir el script Python que resume el pipeline comercial, ejecutarlo a mano y programarlo para todas las mañanas.

La app ya muestra datos y deja editarlos. Falta la parte que trabaja sola: un script que, todas las mañanas, mira el pipeline, cuenta lo que está abierto y registra los cierres previstos para la semana.

En esta etapa escribes ese script en Python, lo ejecutas a mano para ver el resultado, y le marcas una hora — todos los días a las 07:00.

Qué va a hacer el script

El atualizar_indicadores responde a tres preguntas, y las devuelve en un resultado que queda en el historial:

Pregunta Qué devuelve
¿Cuántas oportunidades están abiertas? oportunidades_abertas
¿Cuánto vale el pipeline? valor_pipeline
¿Cuántos cierres están previstos para los próximos 7 días? fechos_proximos_7_dias

Además del resultado, escribe logs — una línea por cierre de la semana — para que quien abra el historial entienda, sin cuentas, qué estaba marcado aquel día.

Crear el script

  1. Elige el panel Código en la barra lateral.
  2. En la fila Scripts, haz clic en el + (Nuevo script). Se abre el diálogo Nuevo script — «Elige el runtime y crea — el código se edita a continuación, con el contrato a la vista.»
  3. En Nombre, escribe atualizar_indicadores. El nombre identifica el script en todas partes — en las programaciones, en los pasos de API, en las dependencias de otros scripts.
  4. Runtime está fijo en Python.
  5. En Descripción, escribe Recalcula los indicadores comerciales y avisa cuando hay cierres para esta semana.
  6. En Tiempo límite, deja 1 minuto. Es el techo de la ejecución: pasado ese tiempo, la plataforma corta.
  7. Haz clic en Crear script. El editor se abre con el main.py listo.

El diálogo Nuevo script — nombre, runtime, descripción y tiempo límite.
El diálogo Nuevo script — nombre, runtime, descripción y tiempo límite.

Consejo

Un tiempo límite generoso no es amabilidad: si este script se usa como paso de una API, los clientes esperan ese tiempo en el peor caso. Un minuto llega y sobra para lo que vamos a hacer.

Escribir el main.py

El contrato de un script es corto: una función main(input) que devuelve algo. Lo que devuelves queda en el historial de ejecuciones y, si el script es llamado por una API, es su respuesta.

Escribe esto en el editor:

from datetime import date, timedelta

from api_manager import db, log


def main(input):
    """Recalcula los indicadores del panel comercial.

    Corre todos los días a las 7h00 (programación "Indicadores diários") y
    devuelve el resumen — el historial de ejecuciones queda con un registro
    legible por día.
    """
    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),
    }

El editor del script atualizar_indicadores — el main.py y, abajo, el panel Resultado de la ejecución.
El editor del script atualizar_indicadores — el main.py y, abajo, el panel Resultado de la ejecución.

Cuatro cosas para retener de este código:

Línea Qué hace
from api_manager import db, log El acceso de la plataforma: db abre bases de datos, log escribe en el historial.
db("Dados CRM") La base de datos por el nombre interno del datasource — el mismo que registraste en la etapa del modelo. Cambia el nombre allí y esta línea deja de funcionar.
crm.query(sql, [valores]) Consulta parametrizada. Los valores van siempre aparte de la query — nunca pegados al texto.
return { … } El resultado de la ejecución. Queda en el historial y es lo que una API devolvería.

El input que la función recibe trae los argumentos de la ejecución — los de una API, los de una programación o los que escribas a mano a continuación. Aquí no usamos ninguno.

Nota

No hay botón de guardar: el editor guarda solo. El interruptor Activo en la esquina superior derecha es otra cosa — un script inactivo sigue existiendo pero no corre, ni a mano ni por programación.

Ejecutar el script a mano

  1. En la parte superior del editor, haz clic en Ejecutar ahora.
  2. Se abre el diálogo — «Define los argumentos de esta ejecución (opcional). Los valores llegan al script como texto.» No necesitamos ninguno.
  3. Haz clic en Ejecutar.

El diálogo Ejecutar ahora — argumentos opcionales de esta ejecución, entregados al script como texto.
El diálogo Ejecutar ahora — argumentos opcionales de esta ejecución, entregados al script como texto.

El panel Resultado de la ejecución, abajo, se llena: el sello Éxito con la duración, el valor devuelto en JSON y el bloque Logs con las líneas que el log() escribió.

El panel Resultado de la ejecución, con el valor devuelto y los logs.
El panel Resultado de la ejecución, con el valor devuelto y los logs.

Consejo

La primera ejecución de un script Python es siempre la más lenta — el entorno se prepara en ese momento. Las siguientes corren en milisegundos.

El historial de ejecuciones

El resultado en el editor es solo el de la sesión actual. El historial completo está en el botón Ejecuciones, junto al Ejecutar ahora:

El historial Ejecuciones del script — inicio, origen, estado y duración de cada corrida.
El historial Ejecuciones del script — inicio, origen, estado y duración de cada corrida.

Cada fila dice Inicio, Origen (Manual, cuando fuiste tú; Programación, cuando fue la hora marcada), Estado y Duración, y el enlace Detalles abre la ejecución: los argumentos, el resultado devuelto y los logs de aquella corrida en concreto. Por aquí se entiende, tres semanas después, qué vio el script la mañana en que nadie estaba mirando.

Programar para todas las mañanas

Un script que solo corre cuando alguien pulsa el botón no es automatización. Es hora de marcarle una hora.

  1. En el árbol del panel Código, expande el nodo del script atualizar_indicadores. Aparecen tres secciones: Archivos, Dependencias y Programaciones.
  2. Pasa el ratón sobre Programaciones y haz clic en el + (Nueva programación).
  3. Dale el nombre Indicadores diários y crea. El editor de la programación se abre en una pestaña.
  4. En Frecuencia, elige En momentos concretos — «A una hora del día, en los días que elijas.»
  5. En Repite, elige Todos los días (en los días elegidos).
  6. En A la hora, escribe 07:00.
  7. En Días, deja los siete seleccionados (o haz clic en Laborables si el fin de semana no interesa).
  8. En Zona horaria, elige Europe/Lisbon. Es la zona la que decide qué son «las siete de la mañana» — sin ella, la hora correcta cambia con el cambio de hora.
  9. En Si queda sin ejecutar, elige Ignorar.
  10. Confirma que el interruptor Activo está encendido y haz clic en Guardar.

La programación Indicadores diários — todos los días a las 07:00 (Europe/Lisbon), con el panel Ejecuciones a la derecha.
La programación Indicadores diários — todos los días a las 07:00 (Europe/Lisbon), con el panel Ejecuciones a la derecha.

Las tres frecuencias

Frecuencia Cuándo usarla
Repetir Cada N minutos u horas, sin parar. Sincronizaciones, sondeos.
En momentos concretos A una hora del día, en los días elegidos. Es nuestro caso — y el más común.
Ventana de vigilancia Sondea cada N minutos entre dos horas y para cuando el trabajo del día esté hecho. Para esperar un archivo que llega «por la mañana, a horas variables».

Quien prefiera escribir la expresión de programación a mano tiene el enlace Escribir la expresión a mano bajo las tres opciones.

Qué hacer con lo que quedó sin ejecutar

El servidor estuvo caído a las siete de la mañana. Cuando vuelva, ¿qué pasa con la ocurrencia fallida? Es lo que decide Si queda sin ejecutar:

Opción Qué hace
Ignorar No recupera. Queda registrado que se perdió.
Solo la más reciente Recupera la última que quedó por hacer; las anteriores quedan registradas como perdidas.
Todas Recupera todas las que quedaron por hacer, en el orden en que estaban marcadas.

Para un resumen diario, Ignorar es lo correcto: ejecutar el resumen del martes el jueves no le sirve a nadie. Para una facturación mensual, Todas tiene todo el sentido.

El panel de ejecuciones de la programación

A la derecha del editor queda el panel Ejecuciones, con las horas previstas y qué pasó con cada una: Hecha, Por hacer, Perdida o Saltada.

Atención

Si este panel avisa de que «el programador no está corriendo en esta instalación — nada será ejecutado», las horas marcadas quedan a la espera y nada corre. El programador se activa en la instalación, no en la app — habla con quien administra la plataforma.

¿Y después?

El script queda listo para más que la hora marcada: puede ser un paso de una API (para que el resumen se calcule a petición), puede llamar a otros scripts como dependencia, y puede instalar packages de Python que necesite. El capítulo Scripts recorre todo eso, y el SDK de los scripts documenta el api_manager — base de datos, archivos, secrets, notificaciones y llamadas HTTP.

¿Por qué no…?

  • ¿Por qué el script falla con «datasource no encontrado»? El nombre en db("…") tiene que ser exactamente el Nombre interno del datasource, mayúsculas incluidas.
  • ¿Por qué no veo el botón Ejecutar ahora? El script está inactivo — enciende el interruptor de arriba.
  • ¿Por qué la ejecución se cortó a medias? Chocó con el Tiempo límite. O el script tarda de verdad, y aumentas el límite, o está haciendo trabajo de más para el sitio desde donde se llama.
  • ¿Por qué la programación nunca corrió? Mira, por orden: ¿la programación está Activa? ¿El script está Activo? ¿El programador está corriendo en esta instalación? ¿Y la Zona horaria es la que crees que es?

El CRM está completo. Falta ponerlo en marcha: publicar y usar.