NetSuite入库单脚本问题:到期日同步至库存明细及模式困惑
问题解决与NetSuite Record模式说明
1. 报错原因
你碰到的错误是因为User Event脚本里默认获取的context.newRecord是Standard模式,而getCurrentLineItemValue、selectNewLineItem这类函数属于Dynamic模式专属的行操作方法,Standard模式下根本调用不了。
2. Dynamic与Standard模式核心差异
| 特性 | Standard模式 | Dynamic模式 |
|---|---|---|
| 适用场景 | 只需要读取/修改字段值、不需要模拟用户界面操作时用 | 需要模拟用户交互(比如选行、子记录编辑)、处理字段联动逻辑时用 |
| 行操作方式 | 必须通过带line参数的sublist方法(比如getSublistValue、setSublistValue)直接操作指定行 | 得先selectLine选中目标行,再用getCurrentLineItemValue/setCurrentLineItemValue操作,最后commitLine提交修改 |
| 性能表现 | 性能更高,不用加载UI相关逻辑 | 性能稍低,因为要模拟前端UI状态 |
| 获取方式 | User Event里的context.newRecord/context.oldRecord默认是Standard;record.load默认也是Standard(除非加isDynamic: true参数) | 调用record.load({isDynamic: true})或者record.create({isDynamic: true})生成 |
3. 脚本选型合理性
User Event Script(Before Submit触发)完全适合你的需求——要在入库单保存前批量修改子记录的到期日,Before Submit能保证修改内容被正常持久化到数据库。
4. 修正后的代码
/** *@NApiVersion 2.0 *@NScriptType UserEventScript *@NModuleScope Public */ define(['N/record'], function (record) { function beforeSubmit(context) { // User Event的newRecord是Standard模式,要操作子记录得用Dynamic模式重新加载 var irId = context.newRecord.id; var expirationDate = context.newRecord.getValue({ fieldId: 'custbody_expiration_date' }); // 以Dynamic模式重新加载入库单 var irRecord = record.load({ type: context.newRecord.type, id: irId, isDynamic: true }); var lineCount = irRecord.getLineCount({ sublistId: 'item' }); for (var i = 0; i < lineCount; i++) { // Dynamic模式下必须先选中行才能操作 irRecord.selectLine({ sublistId: 'item', line: i }); // 获取当前行的批次号和数量 var lotNumber = irRecord.getCurrentLineItemValue({ sublistId: 'item', fieldId: 'receiptinventorynumber' }); var quantity = irRecord.getCurrentLineItemValue({ sublistId: 'item', fieldId: 'quantity' }); // 只处理有批次号的物料(避免非批次/序列号物料报错) if (lotNumber) { // 获取当前行的Inventory Detail子记录 var inventoryDetail = irRecord.getCurrentLineItemSubrecord({ sublistId: 'item', fieldId: 'inventorydetail' }); // 清空原有库存分配(防止重复添加记录) var assignCount = inventoryDetail.getLineCount({ sublistId: 'inventoryassignment' }); for (var j = assignCount - 1; j >= 0; j--) { inventoryDetail.selectLine({ sublistId: 'inventoryassignment', line: j }); inventoryDetail.removeLine({ sublistId: 'inventoryassignment', line: j }); } // 添加新的库存分配并设置到期日 inventoryDetail.selectNewLine({ sublistId: 'inventoryassignment' }); inventoryDetail.setCurrentLineItemValue({ sublistId: 'inventoryassignment', fieldId: 'issueinventorynumber', value: lotNumber }); inventoryDetail.setCurrentLineItemValue({ sublistId: 'inventoryassignment', fieldId: 'quantity', value: quantity }); if (expirationDate) { inventoryDetail.setCurrentLineItemValue({ sublistId: 'inventoryassignment', fieldId: 'expirationdate', value: expirationDate }); } inventoryDetail.commitLine({ sublistId: 'inventoryassignment' }); // 提交行修改 irRecord.commitLine({ sublistId: 'item' }); } } // 保存修改后的入库单(用NS2.0标准API替代过时的nlapiSubmitRecord) irRecord.save({ enableSourcing: false, ignoreMandatoryFields: false }); } return { beforeSubmit: beforeSubmit }; });
关键修正点
- 用
isDynamic: true重新加载入库单,启用Dynamic模式以支持子记录操作 - 删除了无用的
setSublistValue('item', 'item')代码 - 增加非批次物料判断,避免无意义的报错
- 清空原有库存分配后再添加新记录,防止数据重复
- 替换NS1.0的
nlapiSubmitRecord为NS2.0标准的save()方法(NS2.0中禁止混用新旧API)
内容的提问来源于stack exchange,提问作者devilg11
相关产品推荐
相关产品推荐

