> ## Documentation Index
> Fetch the complete documentation index at: https://woku.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Transformaciones de datos con código

> Transforma y deriva campos con JavaScript dentro de Flujo de datos, con código generado por un agente que puedes revisar, editar y simular antes de ejecutar

<Info>
  **Disponible en el plan Corporate.** Esta funcionalidad forma parte de las capacidades empresariales de woku. [Conversa con nuestro equipo comercial](https://woku.app/pricing).
</Info>

woku permite **transformar y derivar campos con JavaScript** sobre los
registros de tus fuentes de datos, dentro de la misma plataforma y **sin
middleware externo** (ni Zapier, ni una Lambda propia, ni un proceso ETL
aparte). Estas transformaciones viven en el módulo
[Flujo de datos](/docs/data/data-flow), donde el código se genera, se prueba
y se ejecuta.

## Dónde viven las transformaciones

Las transformaciones forman parte de un **flujo de datos**. Un flujo trabaja
sobre una [fuente de datos](/docs/data/data-sources) publicada y decide, fila
por fila, qué acción ejecutar: enviar una encuesta, invitar a dejar una
opinión, crear un cliente o actualizar sus datos. Antes de evaluar esas
reglas, el flujo puede transformar cada registro: limpiar valores, derivar
campos nuevos, normalizar formatos o descartar filas que no sirven.

Encuentras el módulo en el grupo **Datos** del menú lateral, junto a
**Fuente de datos**.

## Cómo se construye una transformación

No escribes la transformación desde cero. El constructor del flujo es
conversacional:

<Steps>
  <Step title="Describe lo que necesitas">
    En el chat del constructor explicas en lenguaje natural qué quieres
    hacer, por ejemplo "combina nombre y apellido en un solo campo, clasifica
    el NPS en promotor, pasivo o detractor, y descarta las filas sin email ni
    teléfono".
  </Step>

  <Step title="El agente genera el código">
    El agente escribe el código JavaScript completo del flujo, incluidas las
    transformaciones, y lo muestra en dos representaciones sincronizadas:
    **Pseudocódigo**, una descripción humana de cada paso, y **Código**, el
    JavaScript real, que puedes editar a mano si prefieres ajustar algo
    directamente.
  </Step>

  <Step title="Valida con una simulación">
    La pestaña **Simulación** ejecuta el código sobre los registros de
    muestra de la fuente, sin enviar mensajes ni modificar clientes, y te
    muestra el efecto de cada transformación fila por fila.
  </Step>
</Steps>

<h2 id="transformacion-de-campos">
  Transformación de campos
</h2>

Dentro del código del flujo, las transformaciones operan sobre cada registro
con operaciones explícitas: `setField` deriva o modifica un campo,
`discardRecord` descarta la fila con un motivo, y `hold` la deja en espera
sin acción. También hay ayudas como `normalizePhone`, que lleva teléfonos a
formato internacional, y `hasContent`, que verifica que un campo tenga
contenido real.

Estos son ejemplos de fragmentos como los que genera el agente, y que puedes
ajustar en la pestaña **Código**:

<CodeGroup>
  ```js Derivar un campo nuevo theme={null}
  // Genera un campo "fullName" combinando nombre y apellido.
  setField(
    record,
    'fullName',
    `${record.firstName ?? ''} ${record.lastName ?? ''}`.trim(),
  );
  ```

  ```js Lógica condicional theme={null}
  // Clasifica un NPS (0..10) en promotor / pasivo / detractor.
  const score = Number(record.npsScore);

  if (score >= 9) {
    setField(record, 'npsCategory', 'promotor');
  } else if (score >= 7) {
    setField(record, 'npsCategory', 'pasivo');
  } else {
    setField(record, 'npsCategory', 'detractor');
  }
  ```

  ```js Normalizar fechas y teléfonos theme={null}
  // Deriva la fecha en formato YYYY-MM-DD y normaliza el teléfono.
  setField(
    record,
    'purchaseDate',
    new Date(record.createdAt).toISOString().slice(0, 10),
  );
  setField(record, 'phone', normalizePhone(record.phone));
  ```

  ```js Descartar registros theme={null}
  // Descarta las filas sin ningún canal de contacto, con motivo.
  if (!hasContent(record.email) && !hasContent(record.phone)) {
    discardRecord(record, 'Sin email ni teléfono de contacto');
  }
  ```
</CodeGroup>

Las transformaciones se aplican antes de evaluar las reglas del flujo, por lo
que las condiciones y las acciones de envío trabajan sobre los campos ya
derivados y normalizados.

## Simulación y versiones

La pestaña **Simulación** es la forma de validar una transformación antes de
que toque datos reales. Ejecuta el código sobre la muestra guardada de la
fuente y devuelve un desglose por resultado, ejemplos de registros con el
detalle de las transformaciones aplicadas a cada fila, y una validación de
que los campos referenciados existen y los comandos son válidos.

El código del flujo está **versionado**. Al ejecutar, si el código cambió
desde la última ejecución, se congela una nueva versión. Desde el historial
puedes ver cualquier versión anterior en modo solo lectura y restaurarla como
la versión actual, y cada ejecución queda registrada con la versión que usó.

## Ejecución y aislamiento del runtime

La ejecución del flujo es manual y corre **siempre del lado del servidor**.
El código se ejecuta en un contexto aislado, **sin acceso a red ni al sistema
de archivos**: solo puede leer el registro de entrada y expresar qué hacer
con él mediante las operaciones del flujo. No expones credenciales ni
mantienes infraestructura propia.

## Buenas prácticas

* **Tolerancia a nulos:** los datos de origen pueden venir incompletos; usa
  `??` y `hasContent` antes de calcular o concatenar.
* **Campos derivados explícitos:** prefiere crear campos nuevos
  (`fullName`, `npsCategory`, `purchaseDate`) en lugar de sobrescribir los
  originales, para que las reglas del flujo y el detalle de la simulación
  sean fáciles de leer.
* **Descarta con motivo:** cuando una fila no sirve, usa `discardRecord` con
  un motivo claro. El motivo aparece en la simulación y en el historial, y
  facilita entender por qué un registro no generó acción.
* **Simula antes de ejecutar:** valida la transformación en la pestaña
  **Simulación** y revisa el detalle por fila antes de ejecutar el flujo con
  envíos reales.
