Casos de uso "Guest code" - Bproc de viewer

Esta entrada detalla casos de uso utilizados en conjunto con bproc de viewer y la aplicacion “guest code”.

Primer caso:

Ver JSON

Este script actúa como una herramienta de depuración o diagnóstico. Recibe los datos crudos (JSON) enviados por una acción en el bproc de viewer, los procesa de manera segura para evitar fallos de renderizado y los muestra formateados de manera limpia en una interfaz HTML, obteniendo la estructura deseada, en este caso un pedido de venta.

Segmentacion explicada en partes:

Función de escape y armado de HTML (build_html):

def build_html(data: dict) -> str:
    json_crudo = json.dumps(data, indent=2, ensure_ascii=False)
    json_seguro = (
        json_crudo
        .replace("&", "&")
        .replace("<", "&lt;")
        .replace(">", "&gt;")
    )

Plantilla de Diseño (CSS y Estructura):
html = f"""... <pre>{json_seguro}</pre> ... """ return html

Inserta el JSON procesado dentro de una etiqueta (que respeta los espacios y saltos de línea de origen) y aplica un estilo CSS con fuentes monoespaciadas y ajuste de palabras (word-break) para que quepa bien en la pantalla.

Función Principal (main) y Captura de Datos:
try: body_bytes = request.get_body() or b"{}" data = json.loads(body_bytes.decode("utf-8")) except Exception: return HTTPResponse(400, body="<p>Error: el JSON recibido no es válido.</p>")
Obtiene el cuerpo del request en bytes. Intenta decodificarlo a texto UTF-8 y transformarlo en un diccionario JSON. Si el formato viene roto o dañado, el bloque except atrapa el error y frena la ejecución devolviendo un código 400 (Bad Request) con un mensaje de error.

Renderizado Exitoso:

html = build_html(data) return HTTPResponse(200, body=html)

Si el JSON es correcto, llama a la función anterior, genera el HTML completo y lo retorna con un estado HTTP 200 para mostrarlo en pantalla.

Se presenta en guest code, el siguiente script:

Dicho script fue utilizado en un bproc de tipo viewer, asociado a la transacción “Pedido de venta”

El bproc es el siguiente:
y la configuración se realiza asociando el guest code configurado anteriormente en el campo “URL” esto permitirá al ejecutarse el bproc, ejecutar la petición hacia el script y devolver el resultado.


Resultado de ejecución:

Script completo:

# Script para Finnegans GO Guest Code
# Validado con información del MCP
import json
from finnegans.scripting import request, HTTPResponse




def build_html(data: dict) -> str:
   json_crudo = json.dumps(data, indent=2, ensure_ascii=False)
   json_seguro = (
       json_crudo
       .replace("&", "&amp;")
       .replace("<", "&lt;")
       .replace(">", "&gt;")
   )


   html = f"""<!DOCTYPE html>
<html lang="es">
<head>
   <meta charset="UTF-8">
   <title>Pedido de Venta</title>
   <style>
       body {{
           font-family: Arial, sans-serif;
           font-size: 13px;
           padding: 16px;
           margin: 0;
       }}
       h3 {{
           margin: 0 0 12px 0;
           font-size: 14px;
           border-bottom: 1px solid #000;
           padding-bottom: 6px;
       }}
       pre {{
           white-space: pre-wrap;
           word-break: break-word;
           font-family: "Courier New", monospace;
           font-size: 12px;
           line-height: 1.5;
           margin: 0;
       }}
   </style>
</head>
<body>
   <h3>Webhook de la Transaccion</h3>
   <pre>{json_seguro}</pre>
</body>
</html>"""
   return html




def main():
   try:
       body_bytes = request.get_body() or b"{}"
       data = json.loads(body_bytes.decode("utf-8"))
   except Exception:
       return HTTPResponse(400, body="<p>Error: el JSON recibido no es válido.</p>")


   html = build_html(data)
   return HTTPResponse(200, body=html)

Segundo caso

Consultar Vendedor

Este script automatiza la consulta masiva de datos. Está diseñado para integrarse con una vista de Finnegans GO donde el usuario selecciona varios registros. El script toma esos registros seleccionados, extrae el identificador del documento, hace una petición interna a la API de la plataforma por cada uno para averiguar qué vendedor tienen asignado, y genera un reporte consolidado en un popup.

Extracción y Validación de Registros Seleccionados (extraer_selected_records):

def extraer_selected_records():
    ...
    raw_body = request.get_body() or b"{}"
    data_input = json.loads(raw_body.decode())
    ...
    selected_records = data_input.get("selectedRecords")

Lee los datos del entorno. El sistema de Finnegans suele enviar un JSON que incluye una lista llamada selectedRecords (los elementos marcados con un check por el usuario). La función valida que la lista exista y sea un array válido; de lo contrario, devuelve un error 400 en formato JSON.

Consulta a la API (consultar_vendedor):

def consultar_vendedor(documento):
    try:
        data_api = obtener_entidad("pedidoVenta", documento)
        vendedor_codigo = data_api.get("VendedorCodigo")
        if vendedor_codigo:
            return f"{documento}  →  Vendedor: {vendedor_codigo}"
        else:
            return f"{documento}   El pedido no tiene vendedor asignado"

Para cada documento, utiliza la función nativa obtener_entidad apuntando a la API de “pedidoVenta”. Extrae el campo VendedorCodigo. Si tiene uno, arma un texto informativo; si está vacío, avisa que no posee un vendedor. Cuenta con manejo de excepciones (ApiException) por si el documento no existe o falla la conexión.

Bucle de Procesamiento Central (main):

for record in selected_records:
    documento = record.get("DOCUMENTO")
    ...
    linea = consultar_vendedor(str(documento))
    lineas_mensaje.append(linea)

En la función principal, se itera (recorre uno a uno) cada registro de la lista de seleccionados. Extrae el campo “DOCUMENTO”, llama a la función de consulta individual y guarda el resultado en una lista de líneas de texto.

Generación del Mensaje Final:

mensaje_final = "</br>".join(lineas_mensaje)
return HTTPResponse(200, body=mensaje_final)

Se presenta en guest code, el siguiente script:

Dicho script fue utilizado en un bproc de tipo viewer, asociado a la transacción “Pedido de venta”

Para realizar la ejecución, se configuro una actividad llamada “Consultar vendedor”, con las características de:
Tipo acción: API - En este campo se asocia la url del endpoint obtenido en el guest code configurado.
URL: Se asocia el guest code correspondiente mediante el endpoint.

Este al ejecutarse en “pedido de venta”, realiza la siguiente visualización:

Script completo:

# Consulta VendedorCodigo por cada DOCUMENTO en selectedRecords y muestra popup
# Validado con información del MCP
import json
from finnegans.scripting import request, HTTPResponse
from finnegans.api import obtener_entidad, ApiException




def extraer_selected_records():
   """
   Parsea el body del request y retorna la lista selectedRecords.
   Ejemplo de entrada:
   {
       "selectedRecords": [
           { "DOCUMENTO": "PEDVTA - 6546" },
           { "DOCUMENTO": "PEDVTA - 6547" }
       ]
   }
   """
   try:
       raw_body = request.get_body() or b"{}"
       data_input = json.loads(raw_body.decode())
   except json.JSONDecodeError:
       return None, HTTPResponse(400, body=json.dumps({
           "error": "El formato del JSON de entrada es inválido."
       }))


   selected_records = data_input.get("selectedRecords")


   if not selected_records or not isinstance(selected_records, list):
       return None, HTTPResponse(400, body=json.dumps({
           "error": "No se encontró la lista 'selectedRecords' o está vacía."
       }))


   return selected_records, None




def consultar_vendedor(documento):
   """
   Realiza el GET a api/pedidoVenta/{documento} y retorna el VendedorCodigo.
   Si no tiene vendedor asignado, retorna el mensaje correspondiente.
   """
   try:
       data_api = obtener_entidad("pedidoVenta", documento)
       vendedor_codigo = data_api.get("VendedorCodigo")


       if vendedor_codigo:
           return f"{documento}  →  Vendedor: {vendedor_codigo}"
       else:
           return f"{documento}   El pedido no tiene vendedor asignado"


   except ApiException as e:
       return f" {documento}  →  Error al consultar: {str(e)}"
   except Exception as e:
       return f"{documento}  →  Error inesperado: {str(e)}"




def main():
   # Paso 1: Extraer la lista selectedRecords del body
   selected_records, error = extraer_selected_records()
   if error:
       return error


   # Paso 2: Por cada registro, extraer DOCUMENTO y consultar VendedorCodigo
   lineas_mensaje = []


   for record in selected_records:
       documento = record.get("DOCUMENTO")


       if not documento:
           lineas_mensaje.append(" Registro sin atributo 'DOCUMENTO', se omite.")
           continue


       # Paso 3: GET a api/pedidoVenta/{DOCUMENTO} y armar línea del mensaje
       linea = consultar_vendedor(str(documento))
       lineas_mensaje.append(linea)


   # Paso 4: Construir el mensaje del popup con todos los resultados
   mensaje_final = "</br>".join(lineas_mensaje)
   print(mensaje_final)
   return HTTPResponse(200, body=mensaje_final)


   '''
   return HTTPResponse(200, body=json.dumps({
       #"show_alert": True,
      "title": "Codigo de Vendedor asignado en Pedido de Venta",
       "message": mensaje_final
   }))

Tercer caso

Editar Descripción

Este script permite realizar modificaciones automáticas de datos en lote (en este caso, sobre el primer registro seleccionado). Toma un parámetro escrito por el usuario (“Nueva Descripción”), busca un Pedido de Venta específico en el sistema, descarga su información actual, reemplaza el campo “Descripción” con el nuevo texto y vuelve a subir el registro actualizado a la base de datos de Finnegans mediante la API.

Procesamiento de Parámetros de Entrada (parse_input):

params = body.get("params", {})

nueva_descripcion = params.get("Nueva Descripcion", params.get("Nueva Descripion"))

...

selected_records = body.get("selectedRecords", [])

documento = selected_records[0].get("DOCUMENTO")

Este componente se encarga de recolectar los requisitos necesarios para la operación. Busca dentro de params el texto de la nueva descripción (resolviendo de paso un posible error de tipeo en el sistema: “Nueva Descripion”). También toma el primer elemento ([0]) del array de registros seleccionados para saber qué documento se va a modificar. Si falta alguno de estos datos, corta la ejecución devolviendo un error descriptivo con código 400

Preparación de la Identificación:

doc_encoded = urllib.parse.quote(str(documento), safe="")

Codifica el nombre/código del documento (por ejemplo, si tiene espacios o guiones como “PEDVTA - 6546”) en un formato seguro para URLs de internet (URL Encode).

Paso GET (Obtención de datos):

`pedido_data = obtener_entidad("pedidoVenta", doc_encoded)`

**Modificación y Paso PUT (Actualización de datos):**

pedido_data["Descripcion"] = nueva_descripcion

try:
    actualizar_entidad("pedidoVenta", doc_encoded, pedido_data)
except ApiException as e:
    return HTTPResponse(502, body=f"Error al actualizar...")

Modifica únicamente la propiedad “Descripcion” dentro del diccionario de datos recuperado con el valor del nuevo texto. Posteriormente, usa actualizar_entidad para enviar los datos modificados de regreso al servidor de Finnegans. Si el servidor de la API rechaza el cambio, se captura el error y se devuelve un código 502 (Bad Gateway).

Finalización Exitosa:
return HTTPResponse(200, body="Edición realizada")

Si todo el proceso de descarga y subida sale bien, concluye respondiendo con un estado 200 y el texto confirmando el éxito de la edición.

Se presenta en guest code, el siguiente script:

A diferencia de los bprocs presentados anteriormente, en este caso se agrego un parámetro “nueva descripción”, esto nos permite obtener el texto deseado para aplicar los cambios de forma masiva en los pedidos de venta.

Al estar posicionado en la view “pedidos de venta” y ejecutar el bproc “Editar descripcion se dispone un campo de tipo texto para aplicar el cambio en el pedido seleccionado.

1 me gusta