【求助】NetSuite SuiteScript按钮无法关闭Sales Order问题
SuiteScript关闭Sales Order失败问题排查
作为SuiteScript新手,目前遇到通过按钮关闭Sales Order失败的问题:已为状态为**待审批(pending approval)或待发货(pending fulfillments)**的Sales Order添加用户事件按钮,点击按钮后Suitelet可捕获到Sales Order ID,但无法完成订单关闭操作。以下是相关脚本代码,请求协助排查解决:
Client Script
/** * @NApiVersion 2.1 * @NScriptType ClientScript */ define(['N/url', 'N/ui/dialog', 'N/log', 'N/currentRecord'], (url, dialog, log, currentRecord) => { function pageInit(scriptContext) { } function showPopup() { try { const currentRec = currentRecord.get(); const salesOrderId = currentRec.id; const paramsId = { orderId : salesOrderId } const suiteletUrl = url.resolveScript({ scriptId: 'customscript_bits_ss_close_sales_order', deploymentId: 'customdeploy_bits_ss_close_sales_order', params: paramsId }); dialog.create({ title: 'Cancel/Close Order', message: `<iframe src="${suiteletUrl}" style="width: 100%; height: 200px; border: none;"></iframe>`, buttons: [ { label: 'Cancel', value: 'close', action: () => dialog.close() } ] }); } catch (error) { log.error('Error in showPopup', error.message); alert('An error occurred while opening the popup. Check the logs for details.'); } } return { pageInit, showPopup }; });
Suitelet Script
/** * @NApiVersion 2.1 * @NScriptType Suitelet */ define(['N/record', 'N/ui/serverWidget', 'N/log'], (record, serverWidget, log) => { const onRequest = (scriptContext) => { const request = scriptContext.request; const response = scriptContext.response; const salesOrderId = request.parameters['orderId'] ; log.debug('Sales Order ID Received', salesOrderId); if (!salesOrderId) { response.write('<p>Error: Sales Order ID is missing.</p>'); return; } if (request.method === 'GET') { try { const salesOrder = record.load({ type: record.Type.SALES_ORDER, id: salesOrderId }); log.debug('Sales Order Loaded Successfully', salesOrder); const form = serverWidget.createForm({ title: `Close Sales Order - ID: ${salesOrderId}`, hideNavBar: true }); form.addField({ id: 'custpage_message', type: serverWidget.FieldType.INLINEHTML, label: 'Message' }).defaultValue = `<p>Are you sure you want to cancel Sales Order ID: ${salesOrderId}?</p>`; form.addSubmitButton({ label: 'Confirm Cancellation' }); form.addButton({ id: 'custpage_cancel', label: 'Cancel', functionName: 'window.close();' }); response.writePage(form); } catch (error) { log.error('Error Loading Sales Order', error); response.write('<p>Error: Unable to load the Sales Order. Check the ID and try again.</p>'); } } else if (request.method === 'POST') { try { const salesOrder = record.load({ type: record.Type.SALES_ORDER, id: salesOrderId }); const lineCount = salesOrder.getLineCount({ sublistId: 'item' }); for (let i = 0; i < lineCount; i++) { salesOrder.setSublistValue({ sublistId: 'item', fieldId: 'isclosed', line: i, value: true }); } salesOrder.save(); response.write('<script>alert("Sales Order canceled successfully."); window.close();</script>'); } catch (error) { log.error('Error Cancelling Sales Order', error); response.write('<script>alert("Failed to cancel the Sales Order."); window.close();</script>'); } } }; return { onRequest }; });
排查与解决要点
- 检查订单状态与工作流锁定:待审批的订单可能处于工作流审批环节,此时订单被系统锁定无法编辑。需先确认订单是否在工作流中,必要时暂停或完成审批后再操作;同时确保脚本部署的角色拥有编辑Sales Order及关闭订单行的权限。
- 修正订单关闭的逻辑:NetSuite中关闭/取消Sales Order的标准方式不是仅设置行项目的
isclosed字段,建议直接使用record.cancel()API,或者同时设置订单头部的status字段(如Cancelled):// 使用cancel API取消订单 record.cancel({ type: record.Type.SALES_ORDER, id: salesOrderId }); - 传递POST请求的orderId参数:当前Suitelet的POST请求中,
orderId参数会丢失,因为表单提交时没有传递该值。需在GET方法创建表单时添加隐藏字段存储订单ID:
然后在POST中改为// 在GET的form创建代码中添加 form.addField({ id: 'custpage_orderid', type: serverWidget.FieldType.TEXT, label: 'Order ID' }).updateDisplayType({displayType: serverWidget.FieldDisplayType.HIDDEN}).defaultValue = salesOrderId;const salesOrderId = request.parameters['custpage_orderid'];获取参数。 - 查看详细错误日志:登录NetSuite后台,进入
Setup > Audit Trail > Script Execution Logs,找到Suitelet对应的POST请求日志,查看具体错误信息(如权限不足、字段不可编辑等),这是最直接的排查依据。 - 优化save方法参数:调用
salesOrder.save()时,可添加参数避免必填字段或 sourcing 问题导致保存失败:salesOrder.save({ enableSourcing: false, ignoreMandatoryFields: true });
内容的提问来源于stack exchange,提问作者Amit Kadlag
相关产品推荐
相关产品推荐

