NetSuite SuiteScript 2.1:自动化你的 ERP 而不发疯

发布: (2026年3月13日 GMT+8 09:20)
5 分钟阅读
原文: Dev.to

Source: Dev.to

如果你曾经使用过 NetSuite,你会知道原生配置只能做到一定程度。之后,你需要编写代码。这时就用得上 SuiteScript —— 平台的 JavaScript 运行时,能够帮助你自动化流程、验证数据并将 NetSuite 与外部世界连接起来。在本文中,我将向你展示入门的要点,并提供可以立即适配的示例。

为什么选择 SuiteScript 2.1 而不是 1.0?

版本 1.0 仍然存在于旧实例中,但到处都是全局变量,执行模型也很混乱。从 2.0 起,全部使用 AMD 模块(类似 RequireJS),这使代码更加可预测。2.1 版本还支持 async/await 等现代特性。尽可能使用它。

任意脚本的基本结构

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

开头的 @N 注释不是可选的——NetSuite 会读取它们以识别脚本类型和 API 版本。

用户事件脚本

User Event 脚本挂接在记录的生命周期上。想在保存前进行验证吗?想在加载时修改字段吗?这就是你的类型。

经典示例:如果缺少关键字段则阻止保存

/**
 * @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 };
});

throw error.create() 会自动取消保存并在 UI 中向用户显示消息。你无需做其他操作。

Scheduled Scripts 与治理问题

Scheduled Scripts 在后台运行,无需用户。非常适合夜间同步、自动报告、数据清理。

问题在于:每个操作都会消耗 governance units。加载一条记录消耗 10,保存一条记录消耗 20,搜索消耗 10。每次执行的上限是 10 000 单位。如果超出,脚本会在执行到一半时终止。

对于大规模处理,Map/Reduce Script 是正确的解决方案。它将工作划分为并行阶段,每个阶段都有自己的治理资源池。编写更复杂,但可很好地扩展。

实时获取剩余单位

import runtime from 'N/runtime';
const restante = runtime.getCurrentScript().getRemainingUsage();

RESTlet:在 NetSuite 中的 API

需要外部系统查询或创建 NetSuite 中的记录吗?RESTlet 基本上是一个位于平台内部的 HTTP 端点。

/**
 * @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 };
});

部署它,分配一个 deployment ID,就拥有了一个可以通过 OAuth 2.0 从任何外部系统调用的端点。

希望在开始时有人告诉我的三件事

  1. 安装 SuiteCloud CLI。 从 NetSuite UI 上传脚本非常繁琐。使用 CLI 可以执行 suitecloud file:upload,并像普通项目一样管理你的脚本。
  2. 日志是你最好的朋友也是最坏的敌人。 N/log 有四个级别 — debugauditerroremergency。在生产环境中,关闭 debug,否则日志会很快被填满。NetSuite 为每个脚本保留最近的 5 000 条记录。
  3. 在不知道会有多少结果时,使用 search.runPaged() 而不是 search.run().each() .each() 有 4 000 条结果的限制;分页则没有。
const paged = miSearch.runPaged({ pageSize: 1000 });
paged.pageRanges.forEach((range) => {
  const page = paged.fetch({ index: range.index });
  page.data.forEach((result) => {
    // procesa cada resultado
  });
});

在哪里继续?

Oracle 官方文档(SuiteAnswers)内容丰富但完整。真正的入口是查找你需要的模块:N/recordN/searchN/emailN/https — 它们都遵循相同的模式。

如果你对某种特定脚本或集成案例有疑问,请在评论中留下。

0 浏览
Back to Blog

相关文章

阅读更多 »

现代 JS 讲座 async function

概述:async 函数返回一个 Async Function 对象。通过使用 async 和 await 关键字,异步处理可以比传统方式更简洁。

[SC] 可发送

在 GCD 与 Swift Concurrency 之间在线程间传递值有什么区别?和 GCD 一样,在 Swift Concurrency 中也需要传递数据……

关于 JavaScript 的简介

介绍 在今天的课堂上,我学习了 JavaScript 的简短介绍,所以我将在这篇博客中分享一些关于 JavaScript 的事实。什么是 JavaScript?JavaScr...