9 min read

Hechicería Cotlang: filtros y funciones para hechizos más poderosos (parte 2)

Hechicería Cotlang: filtros y funciones para hechizos más poderosos (parte 2)

Si lograste llegar hasta aquí sin que tu $VALUE#answer|data te convierta en una rana o sin inundar de correos a las Artes Oscuras ([email protected]) con gritos de auxilio desesperados, felicitaciones: ya no eres un muggle de Cotlang y estás lista para la magia avanzada.

En la primera parte dominaste el Wingardium Leviosa de este lenguaje. Pero hoy aprenderás hechizos más poderosos que me fueron enseñados bajo la tutela del mismísimo Brujo Calvo en persona. Solo que esta vez, espero sean practicados en un ambiente de staging.

Si aún sientes dificultad al utilizar un $VALUE#answer|data o necesitas practicar nuevamente los hechizos básicos, te invito a repasar la parte 1:

Hechicería Cotlang: el conjuro inicial para dominar Cotalker (parte 1)
Oh, el gran Cotlang... La palabra que resuena como un eco en las profundidades de Cotalker. Cada vez más fuerte. Cada vez más insistente. Cada vez más implacable... hasta que llega el momento de aceptar tu inevitable destino: Ya no hay escapatoria. ”¿Qué es Cotlang?” Son las palabras que producen
⚠️
Este artículo asume que ya tienes conocimientos básicos de Cotalker (como la estructura de formularios, funciones básicas y manejo de objetos json, entre otros). Si es tu primera vez con Cotlang, te recomiendo leer primero la guía introductoria donde explico los fundamentos.

Capítulo 1: Tu nuevo contexto

Supongamos como contexto el siguiente formulario, el cuál está diseñado para que equipos de logística y almacén registren y actualicen información crítica sobre productos electrónicos en stock.

{
    "answer": {
      "_id": "7890123c5c77b31459033e70",
      "data": [
        {
          "question": "7890123c5c77b31459033e71",
          "contentType": "application/vnd.cotalker.survey+text",
          "identifier": "title_inventory_update",
          "display": ["# Actualización de Inventario - Productos Electrónicos"],
          "responses": [],
          "process": []
        },
        {
          "question": "7890123c5c77b31459033e72",
          "contentType": "application/vnd.cotalker.survey+textinput",
          "identifier": "operator_name",
          "display": ["Nombre del operador"],
          "responses": ["{\"_id\":\"78901262f5af107b02ec0817\",\"accessRoles\":[\"7890126a5088d08806bd9b10\"],\"email\":\"[email protected]\",\"job\":\"7890126b5088d08806bd9b11\",\"jobTitle\":\"Supervisora de Inventario\",\"name\":{\"secondLastName\":\"Pricila\",\"lastName\":\"Badilla\",\"names\":\"Pricila Badilla\",\"displayName\":\"Pricila Badilla\"},\"role\":\"user\",\"permissionsV2\":[\"inventory-modify\",\"reports-generate\"]}"],
          "process": ["78901262f5af107b02ec0817"]
        },
        {
          "question": "7890123c5c77b31459033e73",
          "contentType": "application/vnd.cotalker.survey+number",
          "identifier": "total_items",
          "display": ["Total de productos a registrar"],
          "responses": [15],
          "process": [15]
        },
        {
          "question": "7890123c5c77b31459033e74",
          "contentType": "application/vnd.cotalker.survey+property",
          "identifier": "product_list",
          "display": ["Lista de productos"],
          "responses": ["{\"_id\":\"682ec8550ecabad970088e70\",\"company\":\"6390a2268277602c17845656\",\"propertyType\":\"lista_de_productos\",\"subproperty\":[],\"name\":{\"code\":\"laptop_x\",\"display\":\"Laptop X\"},\"isActive\":true,\"schemaInstance\":{\"sku\":\"P1001\",\"price\":1200,\"nombre\":\"Laptop X\",\"categoria\":\"computers\",\"stock\":3},\"createdAt\":\"2025-05-22T06:46:45.460Z\",\"modifiedAt\":\"2025-05-22T06:47:47.358Z\",\"extra\":{}}","{\"_id\":\"682ec870bb0d140e8d0379c7\",\"company\":\"6390a2268277602c17845656\",\"propertyType\":\"lista_de_productos\",\"subproperty\":[],\"name\":{\"code\":\"smartphone_y\",\"display\":\"Smartphone Y\"},\"isActive\":true,\"schemaInstance\":{\"sku\":\"P2002\",\"price\":800,\"nombre\":\"Smartphone Y\",\"categoria\":\"phones\",\"stock\":10},\"createdAt\":\"2025-05-22T06:47:12.703Z\",\"modifiedAt\":\"2025-05-22T06:47:58.460Z\",\"extra\":{}}"],
          "process": ["682ec8550ecabad970088e70","682ec870bb0d140e8d0379c7"]
        },
        {
          "question": "7890123c5c77b31459033e75",
          "contentType": "application/vnd.cotalker.survey+property",
          "identifier": "priority",
          "display": ["Prioridad de actualización"],
          "responses": ["{\"_id\":\"682ec8b70ecabad970089508\",\"company\":\"6390a2268277602c17845656\",\"propertyType\":\"prioridad_actualizacion\",\"subproperty\":[],\"name\":{\"code\":\"high\",\"display\":\"High\"},\"isActive\":true,\"createdAt\":\"2025-05-22T06:48:23.793Z\",\"modifiedAt\":\"2025-05-22T06:48:23.808Z\"}"],
          "process": ["682ec8b70ecabad970089508"]
        },
        {
          "question": "682ec9b90ecabad97008a466",
          "contentType": "application/vnd.cotalker.survey+textnumber",
          "identifier": "peso_total_estimado_kg",
          "display": ["Peso total estimado (kg)"],
          "responses": ["10.5"],
          "process": ["10.5"]
        },
        {
          "question": "7890123c5c77b31459033e76",
          "contentType": "application/vnd.cotalker.survey+textinput",
          "identifier": "etiquetas_de_categorizacion",
          "display": ["Etiquetas de categorización"],
          "responses": ["__ON__","__ON__","__ON__","__OFF__"],
          "process": ["electronico","alta_gama","importado"]
        }
      ],
      "uuid": "7890124e9d7024fc8624c8b7",
      "company": "7890125ef618ab89d55940d8",
      "user": "78901262f5af107b02ec0817",
      "createdAt": "2025-05-22T08:30:00.000Z",
      "startDate": "2025-05-22T08:30:00.000Z",
      "modifiedAt": "2025-05-22T08:35:00.000Z"
    },
    "task": {
        "_id": "682f6d7f0ecabad9700d46d7",
        "extensions": {
            "asset_inventario": {
                "registro_historico": ["Pricila Badilla -- 22/05/2024", "Tamara Angulo -- 22/12/2024"]
                }
        }
    },
    "meta": {
      "taskGroup": "7890126c5088d08806bd9b0f"
    }
  }

Recuerda que si usáramos javascript, almacenaríamos este objeto en una variable (const value = {...}) y utilizaríamos las funciones de arreglos; pero con cotlang simplemente utilizamos: $VALUE.

Capítulo 2: Los nuevos hechizos de Cotlang

2.1 Casteo de números: Necesito saber cuál es el valor del peso como número entero, ya que por temas de gestión interna, la empresa necesita calcular pallets completos.

💡
[cast=>]es una función de Cotlang que te permite convertir un tipo de dato en otro. Es útil cuando los sistemas requieren formatos específicos.
  • En Javascript:
return parseInt(
  value.answer.data.find(
    question => question.identifier === "peso_total_estimado_kg"
  ).process[0]
);
  • En Cotlang: $VALUE#answer|data|[find=>identifier=peso_total_estimado_kg]|process|0|[cast=>parseInt]
  • Resultado: 10

Explicación:

  • [cast=>parseInt]: "Dame solo el valor entero del número que te estoy pasando".

2.2 Transformando valores a string: El cliente necesita que el valor de total_items se envíe a su sistema SAP, el cuál solo admite valores string. Para esto debemos transformar el valor numérico a un texto.

💡
[toString=>*]es una función de Cotlang que te permite convertir cualquier tipo de dato en texto plano.
  • En Javascript:
return String(
  value.answer.data.find(question => question.identifier === "total_items")
    .responses[0]
);
  • En Cotlang: $VALUE#answer|data|[find=>identifier=total_items]|responses|0|[toString=>*]
  • Resultado: "15"

Explicación:

  • [toString=>*] : "Convierte el valor que te entregué a un texto plano".

2.3 Extrayendo información de una lista: Necesito generar un reporte en el inventario, y para eso el sistema necesita solo los ids de los productos que el usuario seleccionó.

💡
[map=>]es una función de Cotlang nos permite extraer un dato específico de una lista.
  • En Javascript:
return value.answer.data
  .find(question => question.identifier === "product_list")
  .responses.map(JSON.parse)
  .map(register => register._id);
  • En Cotlang: $VALUE#answer|data|[find=>identifier=product_list]|responses|[json=>parse]|[map=>_id]
  • Resultado: [ "682ec8550ecabad970088e70", "682ec870bb0d140e8d0379c7"]

Explicación:

  • [json=>parse]: "Convierte este string en un objeto JSON".
  • [map=>_id]: "Cotlang, dame solo los valores _id de esta lista de elementos."

2.4 Filtrando datos: Ahora necesito saber exclusivamente cuáles son los productos que el usuario seleccionó que tengan la categoría computers.

💡
[filter=>]es una función de Cotlang que nos permite filtrar una lista de objetos y devuelve solo los que cumplen una condición específica.
  • En Javascript:
return value.answer.data
  .find(question => question.identifier === "product_list")
  .responses.map(JSON.parse)
  .map(register => register.schemaInstance)
  .filter(register => register.categoria === "computers"); 
  • $VALUE#answer|data|[find=>identifier=product_list]|responses|[json=>parse]|[map=>schemaInstance]|[filter=>categoria=computers]

Resultado: [{"sku": "P1001", "price": 1200, "nombre": "Laptop X", "categoria": "computers", "stock": 3}]

Explicación:

  • [json=>parse]: "Convierte este string en un objeto JSON".
  • [map=>schemaInstance]: "Extrae solo los valores schemaInstance de cada uno de los elementos".
  • [filter=>categoria=computers]: "Cotlang, dame únicamente los productos electrónicos que pertenecen a la categoría computers de tu inventario".

2.5 Ajustando el peso: Si bien aproximamos el peso a un valor entero, el cliente dice que siempre debemos sumar 2kg al peso registrado con el usuario para evitar el error de medición.

💡
[math=>]es una función de Cotlang que nos permite realizar operaciones matemáticas a valores numéricos.
  • En Javascript:
return (
  parseInt(
    value.answer.data.find(
      question => question.identifier === "peso_total_estimado_kg"
    ).process[0]
  ) + 2
);
  • En Cotlang: $VALUE#answer|data|[find=>identifier=peso_total_estimado_kg]|process|0|[cast=>parseInt]|[math=>add=2]
  • Resultado: 12

Explicación:

  • [math=>add=2]: "Cotlang, toma el valor numérico que te entregué y súmale dos unidades".

2.6 Alertando stock crítico: Al cliente le interesa mucho saber si sus productos tienen stock críticos. Para esto, todos los productos deben tener un stock mínimo de 5 unidades.

💡
[every=>]es una función de Cotlang que verifica si todos los elementos de un array cumplen una condición. Retorna true solo si cada uno pasa el filtro.
  • En Javascript:
return value.answer.data
  .find(question => question.identifier === "product_list")
  .responses.map(JSON.parse)
  .map(register => register.schemaInstance.stock)
  .every(unit => unit <= 5);
  • En Cotlang: $VALUE#answer|data|[find=>identifier=product_list]|responses|[json=>parse]|[map=>schemaInstance]|[map=>stock]|[every=>gt=5]
  • Resultado: false

Explicación:

  • [map=>stock]: "De la lista que te envié, extrae solo el valor de stock".
  • [every=>gt=5]: "Cotlang, de todos los valores que hay en esta lista, quiero que me digas si todos los elementos poseen un valor mayor a 5".

2.7 Validando permisos: Si el usuario que responde el formulario tiene el permiso reports-generate entonces Cotalker debe generar un reporte en pdf automáticamente.

💡
[some=>]es una función de Cotlang que verifica si al menos un elemento de un array cumple una condición. Retorna true si uno o más pasan el filtro.
  • En Javascript:
return JSON.parse(
  value.answer.data.find(question => question.identifier === "operator_name")
    .responses[0]
).permissionsV2.some(permission => permission === "reports-generate");
  • En Cotlang: $VALUE#answer|data|[find=>identifier=operator_name]|responses|0|[json=>parse]|permissionsV2|[some=>eq=reports-generate]
  • Resultado: true

Explicación:

  • [some=>eq=reports-generate]: "Cotlang, de la lista que te di, busca si alguno de esos valores es igual a reports-generate".

2.8 Añadiendo etiquetas no repetibles: Se acercan los "Cyber-days" y el equipo de marketing necesita trazabilidad para saber qué productos tendrán descuentos. Para esto, todos los productos registrados en esta fecha deben tener la etiqueta oferta-cyber, sin importar si el usuario la seleccionó o no en el formulario.

💡
[add=>] es una función de Cotlag que añade un elemento a un array solo si no existe previamente. Ideal para evitar duplicados en listas de valores únicos (como etiquetas o permisos).
  • En Javascript:
const etiquetas = value.answer.data.find(question => question.identifier === "etiquetas_de_categorizacion").process

if (!etiquetas.includes("oferta_cyber")) etiquetas.push("oferta_cyber");

return etiquetas
  • En Cotlang: $VALUE#answer|data|[find=>identifier=etiquetas_de_categorizacion]|process|[add=>string=oferta_cyber]
  • Resultado: ["electronico", "alta_gama", "importado", "oferta_cyber"]

Explicación:

  • [add=>string=oferta_cyber]: "De la lista que te di, quiero que añadas un string con el nombre oferta_cyber, si la etiqueta no existe, añádelo; pero si ya existe, no hagas nada".

2.9 Registro histórico con repeticiones: El sistema debe almacenar cada envío del usuario (nombre + fecha) en un log contenido en el asset, permitiendo valores duplicados para casos como actualizaciones múltiples en un mismo día.

💡
[push=>] es una función de Cotlag que añade un elemento a un array siempre, aunque ya exista. Usado cuando se necesitan registros históricos o valores repetidos (como logs de cambios).
  • En Javascript:
const date = new Date(value.answer.createdAt);

const day = String(date.getDate()).padStart(2, '0');
const month = String(date.getMonth() + 1).padStart(2, '0');
const year = date.getFullYear();

const formatedDate = `${year}-${month}-${day}`;

const user = JSON.parse(value.answer.data.find(question=>question.identifier === "operator_name")).responses[0]
const displayName = user.name.displayName

const log = `${displayName} -- ${formatDate}`

const historico = value.task.extensions.asset_inventario.registro_historico

historico.push(log)

return historico
  • En Cotlang: $VALUE#task|extensions|asset_inventario|registro_historico|[push=>string=($JOIN# – #($VALUE#answer|data|[find=>identifier=operator_name]|responses|0|[json=>parse]|name|displayName)#($VALUE#answer|createdAt|[date=>format=YYYY/MM/DD]))]

Resultado: ["Pricila Badilla – 22/05/2024", "Tamara Angulo – 22/12/2024", "Pricila Badilla – 2025/05/23"]

Explicación:

  • $VALUE#answer|data|[find=>identifier=operator_name]|responses|0|[json=>parse]|name|displayName: "Cotlang, dame el nombre de la persona que está respondiendo el formulario".
  • $VALUE#answer|createdAt|[date=>format=YYYY/MM/DD]: "Dame la fecha en la que el usuario envió el formulario".
  • $JOIN# – #($VALUE#answer|data|[find=>identifier=operator_name]|responses|0|[json=>parse]|name|displayName)#($VALUE#answer|createdAt|[date=>format=YYYY/MM/DD])): "Necesito que unas el nombre con la fecha, y que exista un --entre medio".
  • $VALUE#task|extensions|asset_inventario|registro_historico|[push=>string=...: "Quiero que tomes el valor actual de registro histórico y añadas el nuevo texto que he creado sin importar si ya existe algún elemento igual".

Capítulo 3: El camino del Archimago

Si llegaste hasta aquí sin que tu $VALUE#log_errores explotara como una poción de Snape, felicitaciones: ya dominas la varita (sintaxis) y los hechizos (funciones). Pero el camino para destruir el último Horrocrux y convertirte en Archimago de Cotlang recién comienza.

3.1 Más allá de formularios: Cotlang no vive solo en formularios. Este lenguaje es el alma secreta de Cotalker, capaz de dar vida a bots inteligentes, automatizaciones en los flujos y hasta llamadas de red. El poder está en tus manos: Ya no solo automatizarás formularios, podrás orquestar flujos completos.

3.2 El cielo es el límite: Cotlang es tan poderoso en Cotalker, que podrás crear bots que aprueben solicitudes si cumplen múltiples reglas de negocio, sincronizar los datos de Cotalker con tus sistemas internos como SAP o algún otro CRM, o incluso generar documentos PDF que podrán ser enviados por correo.

3.3 El viaje recién empieza: Es tu turno de lanzar hechizos más grandes. Explora la documentación, experimenta en staging y sobre todo atrévete a automatizar esos procesos que todos creen "imposibles".

Las varitas eligen a los magos, pero los sistemas automatizados los construyen magos persistentes. ¿Qué crearás hoy con tu $VALUE#conocimiento recién adquirido?


Referencias:

Array - JavaScript | MDN
El objeto Array de JavaScript es un objeto global que es usado en la construcción de arrays, que son objetos tipo lista de alto nivel.
COTLang Guide | Cotalker Technical Documentation
Esta página aún no se encuentra traducida al español.
Harry Potter y el misterio del príncipe (2009) ⭐ 7.6 | Acción, Aventura, Familia
2h 33m | B
Cotlang: El hechizo secreto para dominar Cotalker
Oh, el gran Cotlang... La palabra que resuena como un eco en las profundidades de Cotalker. Cada vez más fuerte. Cada vez más insistente. Cada vez más implacable... hasta que llega el momento de aceptar tu inevitable destino: Ya no hay escapatoria. ”¿Qué es Cotlang?” Son las palabras que producen