如何通过SuiteScript完成Transfer Order并将状态更新为Received?
问题:SuiteScript处理调拨单(Transfer Order)无法更新状态至“Received”
我一直在尝试用SuiteScript完成调拨单的履行,但始终没成功。不确定是否需要同时创建Item Fulfillment和Item Receipt,查了很多地方答案都不一致。我的需求是脚本能履行调拨单上所有物料的数量,并把调拨单状态更新为“Received”。
目前脚本已经能成功创建Item Fulfillment,调拨单物料的“complete”数量有更新,但“fulfilled”数量没变化,状态一直停留在“Pending Fulfillment”。
测试代码如下:
require(['N/record', 'N/search', 'N/log'], function(record, search, log) { try { var transferOrderId = 533010; var transferOrder = record.load({ type: record.Type.TRANSFER_ORDER, id: transferOrderId }); var transferOrderType = transferOrder.type; // Ensure the record being processed is a Transfer Order if (transferOrderType !== 'transferorder') { log.debug('Not a Transfer Order', 'Skipping processing.'); return; } // ********** Item Fulfillment Logic ********** // Check if an Item Fulfillment already exists for the Transfer Order var fulfillmentSearch = search.create({ type: record.Type.ITEM_FULFILLMENT, filters: [ ['createdfrom', 'is', transferOrderId] ], columns: ['internalid'] }); var fulfillmentResults = fulfillmentSearch.run().getRange({ start: 0, end: 1 }); if (fulfillmentResults && fulfillmentResults.length > 0) { log.debug('Item Fulfillment Exists', 'Item Fulfillment already exists for Transfer Order ID: ' + transferOrderId); } else { // Transform the Transfer Order to an Item Fulfillment var itemFulfillment = record.transform({ fromType: record.Type.TRANSFER_ORDER, fromId: transferOrderId, toType: record.Type.ITEM_FULFILLMENT, isDynamic: true }); // Iterate over the lines to ensure quantities are properly set var fulfillmentLineCount = itemFulfillment.getLineCount({ sublistId: 'item' }); for (var i = 0; i < fulfillmentLineCount; i++) { itemFulfillment.selectLine({ sublistId: 'item', line: i }); // Set the quantity to fulfill as the quantity remaining to be fulfilled var quantityToFulfill = itemFulfillment.getCurrentSublistValue({ sublistId: 'item', fieldId: 'quantityremaining' }); itemFulfillment.setCurrentSublistValue({ sublistId: 'item', fieldId: 'quantity', value: quantityToFulfill }); itemFulfillment.commitLine({ sublistId: 'item' }); } // Save the Item Fulfillment var itemFulfillmentId = itemFulfillment.save(); log.debug('Item Fulfillment Created', 'Item Fulfillment ID: ' + itemFulfillmentId); } // ********** Item Receipt Logic ********** // Check if an Item Receipt already exists for the Transfer Order var receiptSearch = search.create({ type: record.Type.ITEM_RECEIPT, filters: [ ['createdfrom', 'is', transferOrderId] ], columns: ['internalid'] }); var receiptResults = receiptSearch.run().getRange({ start: 0, end: 1 }); if (receiptResults && receiptResults.length > 0) { log.debug('Item Receipt Exists', 'Item Receipt already exists for Transfer Order ID: ' + transferOrderId); } else { // Transform the Transfer Order to an Item Receipt var itemReceipt = record.transform({ fromType: record.Type.TRANSFER_ORDER, fromId: transferOrderId, toType: record.Type.ITEM_RECEIPT, isDynamic: true }); // Iterate over the lines to ensure quantities are properly set var receiptLineCount = itemReceipt.getLineCount({ sublistId: 'item' }); for (var i = 0; i < receiptLineCount; i++) { itemReceipt.selectLine({ sublistId: 'item', line: i }); // Set the quantity to receive as the quantity remaining to be received var quantityRemaining = itemReceipt.getCurrentSublistValue({ sublistId: 'item', fieldId: 'quantityremaining' }); itemReceipt.setCurrentSublistValue({ sublistId: 'item', fieldId: 'quantity', value: quantityRemaining }); itemReceipt.commitLine({ sublistId: 'item' }); } // Save the Item Receipt var itemReceiptId = itemReceipt.save(); log.debug('Item Receipt Created', 'Item Receipt ID: ' + itemReceiptId); } } catch (e) { log.error('Error Processing Transfer Order', e); } });
解决方案
1. 调拨单流转核心逻辑
NetSuite中,调拨单的完整履行必须同时执行Item Fulfillment(源仓库出库)和Item Receipt(目标仓库入库):
- Item Fulfillment:完成源仓库出库,更新调拨单
fulfilled数量,将状态从Pending Fulfillment推进至Partially Fulfilled或Fulfilled - Item Receipt:完成目标仓库入库,更新调拨单
received数量,最终将状态变为Received
你的脚本框架是对的,但问题出在Item Fulfillment的字段处理细节上。
2. 代码修复点
(1)动态模式的字段获取问题
动态模式下,quantityremaining字段的读取存在不稳定情况,建议切换为静态模式处理子列表,避免字段加载顺序或值映射的问题。
(2)增加状态前置检查
避免对已完成的调拨单重复执行操作,提升脚本效率。
3. 修正后的完整代码
require(['N/record', 'N/search', 'N/log'], function(record, search, log) { try { var transferOrderId = 533010; // 加载调拨单并检查当前状态 var transferOrder = record.load({ type: record.Type.TRANSFER_ORDER, id: transferOrderId, isDynamic: false }); var currentStatus = transferOrder.getValue({fieldId: 'status'}); log.debug('当前调拨单状态', currentStatus); // 已完成则直接跳过 if (currentStatus === 'Received') { log.debug('无需处理', '调拨单ID: ' + transferOrderId + ' 已处于Received状态'); return; } // ********** 处理Item Fulfillment ********** var fulfillmentSearch = search.create({ type: record.Type.ITEM_FULFILLMENT, filters: [['createdfrom', 'is', transferOrderId]], columns: ['internalid'] }); var fulfillmentResults = fulfillmentSearch.run().getRange({start: 0, end: 1}); if (!fulfillmentResults || fulfillmentResults.length === 0) { // 使用静态模式转换,避免动态模式的字段问题 var itemFulfillment = record.transform({ fromType: record.Type.TRANSFER_ORDER, fromId: transferOrderId, toType: record.Type.ITEM_FULFILLMENT, isDynamic: false }); // 设置每行履行数量为调拨单原始数量 var lineCount = itemFulfillment.getLineCount({sublistId: 'item'}); for (var i = 0; i < lineCount; i++) { var qty = itemFulfillment.getSublistValue({ sublistId: 'item', fieldId: 'quantity', line: i }); itemFulfillment.setSublistValue({ sublistId: 'item', fieldId: 'quantity', line: i, value: qty }); } var itemFulfillmentId = itemFulfillment.save({enableSourcing: true, ignoreMandatoryFields: false}); log.debug('Item Fulfillment创建成功', 'ID: ' + itemFulfillmentId); } else { log.debug('Item Fulfillment已存在', '调拨单ID: ' + transferOrderId); } // ********** 处理Item Receipt ********** var receiptSearch = search.create({ type: record.Type.ITEM_RECEIPT, filters: [['createdfrom', 'is', transferOrderId]], columns: ['internalid'] }); var receiptResults = receiptSearch.run().getRange({start: 0, end: 1}); if (!receiptResults || receiptResults.length === 0) { // 使用静态模式转换 var itemReceipt = record.transform({ fromType: record.Type.TRANSFER_ORDER, fromId: transferOrderId, toType: record.Type.ITEM_RECEIPT, isDynamic: false }); var receiptLineCount = itemReceipt.getLineCount({sublistId: 'item'}); for (var j = 0; j < receiptLineCount; j++) { var recQty = itemReceipt.getSublistValue({ sublistId: 'item', fieldId: 'quantity', line: j }); itemReceipt.setSublistValue({ sublistId: 'item', fieldId: 'quantity', line: j, value: recQty }); } var itemReceiptId = itemReceipt.save({enableSourcing: true, ignoreMandatoryFields: false}); log.debug('Item Receipt创建成功', 'ID: ' + itemReceiptId); } else { log.debug('Item Receipt已存在', '调拨单ID: ' + transferOrderId); } // 验证最终状态 var updatedTO = record.load({ type: record.Type.TRANSFER_ORDER, id: transferOrderId }); log.debug('最终调拨单状态', updatedTO.getValue({fieldId: 'status'})); } catch (e) { log.error('处理失败', e.message + '\n' + e.stack); } });
4. 关键说明
- 静态模式优势:静态模式下子列表字段的读取和设置更稳定,不会出现动态模式中字段未加载或值异常的情况
- 保存参数配置:
enableSourcing: true让系统自动填充关联字段,ignoreMandatoryFields: false确保必填字段合规 - 状态校验:前置状态检查避免无效操作,同时可以在脚本末尾添加状态验证,确认处理结果
内容的提问来源于stack exchange,提问作者Jordan van Zyl
相关产品推荐
相关产品推荐

