DEV Community

Rafael Mendoza Delgado
Rafael Mendoza Delgado

Posted on

NetSuite SuiteScript 2.1: Automatiza tu ERP sin volverte loco

Si alguna vez has trabajado con NetSuite, sabes que la configuración nativa te lleva hasta cierto punto. Después de ahí, necesitas código. Ahí entra SuiteScript — el runtime JavaScript de la plataforma que te permite automatizar procesos, validar datos y conectar NetSuite con el mundo exterior.En este artículo te muestro lo esencial para arrancar, con ejemplos que puedes adaptar hoy mismo.

¿Por qué SuiteScript 2.1 y no 1.0?La versión 1.0 todavía existe en instancias viejas, pero tiene globals por todos lados y un modelo de ejecución confuso. Desde 2.0 todo usa módulos AMD (estilo RequireJS), lo cual hace el código mucho más predecible. La versión 2.1 además soporta async/await y otras features modernas. Úsala siempre que puedas.La estructura base de cualquier script luce así:

/**
 * @NApiVersion 2.1
 * @NScriptType ScheduledScript
 */
define(['N/search', 'N/log'], (search, log) => {
  const execute = (context) => {
    log.audit({ title: 'Hola', details: 'Script corriendo' });
  };
  return { execute };
});
Enter fullscreen mode Exit fullscreen mode

Esas anotaciones @N al inicio no son opcionales — NetSuite las lee para identificar el tipo de script y la versión del API.


El tipo de script que más vas a usar: User Event
Los User Event Scripts se enganchan al ciclo de vida de un registro. Quieres validar antes de guardar? Modificar campos al cargar? Este es tu tipo.
El ejemplo más clásico: bloquear el guardado si falta un campo crítico.

/**
 * @NApiVersion 2.1
 * @NScriptType UserEventScript
 */
define(['N/error'], (error) => {
  const beforeSubmit = (context) => {
    if (context.type === context.UserEventType.DELETE) return;

    const record = context.newRecord;
    const codigo = record.getValue({ fieldId: 'custbody_codigo_aprobacion' });

    if (!codigo) {
      throw error.create({
        name: 'MISSING_FIELD',
        message: 'El código de aprobación es obligatorio.',
        notifyOff: true
      });
    }
  };
  return { beforeSubmit };
});
Enter fullscreen mode Exit fullscreen mode

El throw error.create() cancela el guardado automáticamente y muestra el mensaje al usuario en la UI. No necesitas hacer nada más.


Scheduled Scripts y el problema del governance
Los Scheduled Scripts corren en background, sin usuario. Perfectos para sincronizaciones nocturnas, reportes automáticos, limpieza de datos.
El catch: cada operación consume governance units. Cargar un registro cuesta 10, guardarlo cuesta 20, una búsqueda cuesta 10. El límite por ejecución es 10,000 unidades. Si lo superas, el script muere a la mitad.
Para procesos masivos, el Map/Reduce Script es la solución correcta. Divide el trabajo en fases paralelas, cada una con su propio pool de governance. Es más complejo de escribir pero escala bien.
Para saber cuánto te queda en tiempo real:

import runtime from 'N/runtime';
const restante = runtime.getCurrentScript().getRemainingUsage();
Enter fullscreen mode Exit fullscreen mode

RESTlets: tu API dentro de NetSuite
¿Necesitas que un sistema externo consulte o cree registros en NetSuite? Un RESTlet es básicamente un endpoint HTTP que vive dentro de la plataforma.

/**
 * @NApiVersion 2.1
 * @NScriptType Restlet
 */
define(['N/search'], (search) => {
  const get = (params) => {
    const { email } = params;
    if (!email) return { error: 'email requerido' };

    const results = [];
    search.create({
      type: search.Type.CUSTOMER,
      filters: [['email', search.Operator.IS, email]],
      columns: ['companyname', 'phone']
    }).run().each((r) => {
      results.push({
        nombre: r.getValue('companyname'),
        telefono: r.getValue('phone')
      });
      return true;
    });

    return { clientes: results };
  };

  return { get };
});
Enter fullscreen mode Exit fullscreen mode

Lo despliegas, le asignas un deployment ID, y ya tienes un endpoint que puedes llamar con OAuth 2.0 desde cualquier sistema externo.


Tres cosas que ojalá me hubieran dicho al empezar
Primero: instala el SuiteCloud CLI. Subir scripts desde la UI de NetSuite es tedioso. Con la CLI puedes hacer suitecloud file:upload y manejar tus scripts como cualquier proyecto normal.
Segundo: los logs son tu mejor amigo y tu peor enemigo. N/log tiene cuatro niveles — debug, audit, error, emergency. En producción, desactiva los debug o van a llenar el log rápidamente. NetSuite guarda los últimos 5,000 registros por script.
Tercero: usa search.runPaged() en lugar de search.run().each() cuando no sabes cuántos resultados vas a tener. El .each() tiene límite de 4,000 resultados. El paginado no.

const paged = miSearch.runPaged({ pageSize: 1000 });
paged.pageRanges.forEach((range) => {
  const page = paged.fetch({ index: range.index });
  page.data.forEach((result) => { /* procesa */ });
});
Enter fullscreen mode Exit fullscreen mode

¿Por dónde seguir?
La documentación oficial de Oracle (SuiteAnswers) es densa pero completa. El punto de entrada real es buscar el módulo que necesitas: N/record, N/search, N/email, N/https — todos siguen el mismo patrón.
Si tienes preguntas sobre algún tipo de script específico o casos de integración, déjalos en los comentarios.

Top comments (1)

Collapse
 
rafael_mendoza_b077f3f96d profile image
Rafael Mendoza Delgado

Este post se hizo con ayuda de Ricardo Aponte, Ingeniero de Software especializado en ERP Netsuite. linkedin.com/in/ricardo-jr-aponte-...