NetSuite Suitelet 2.0:选中商品发货单创建及校验需求求助
NetSuite Suitelet 2.0 发货单(Item Fulfillment)创建实现方案
针对你的需求,我会补全POST请求的核心逻辑,实现销售订单数据校验与发货单创建功能,同时修正表单字段的细节问题:
第一步:优化表单字段类型
把数量字段从TEXT改为INTEGER,避免用户输入非数字值:
sublist.addField({ id: "quantity", type: serverWidget.FieldType.INTEGER, // 改为整数类型 label: "Quantity" });
第二步:实现POST请求核心逻辑
替换你现有代码中else if (context.request.method === 'POST')块的内容,完整逻辑如下:
else if (context.request.method === 'POST') { try { var request = context.request; var soNumber = request.parameters.custpage_so_number; var lineCount = request.getLineCount({ sublistId: 'item_sublist' }); var errors = []; // 1. 加载对应销售订单记录 var soRecord = record.load({ type: record.Type.SALES_ORDER, id: soNumber, isDynamic: true }); var soLineCount = soRecord.getLineCount({ sublistId: 'item' }); // 2. 构建销售订单的商品数据映射(用于快速校验) var soItemMap = {}; for (var i = 0; i < soLineCount; i++) { var itemId = soRecord.getSublistValue({ sublistId: 'item', fieldId: 'item', line: i }); var remainingQty = soRecord.getSublistValue({ sublistId: 'item', fieldId: 'quantityremaining', line: i }); var lotNumber = soRecord.getSublistValue({ sublistId: 'item', fieldId: 'inventorynumber', line: i }); // 若SO有批号则取对应值 soItemMap[itemId] = { remainingQty: remainingQty, lotNumber: lotNumber }; } // 3. 校验提交的子列表数据 var fulfillmentLines = []; for (var j = 0; j < lineCount; j++) { var itemId = request.getSublistValue({ sublistId: 'item_sublist', fieldId: 'itemname', line: j }); var inputQty = parseInt(request.getSublistValue({ sublistId: 'item_sublist', fieldId: 'quantity', line: j })); var inputLot = request.getSublistValue({ sublistId: 'item_sublist', fieldId: 'lotnumber', line: j }); // 校验商品是否存在于销售订单中 if (!soItemMap[itemId]) { errors.push(`第${j+1}行商品不在销售订单${soNumber}中`); continue; } // 校验发货数量是否超过剩余可发货量 if (inputQty > soItemMap[itemId].remainingQty) { errors.push(`第${j+1}行商品发货数量超过剩余可发货量(剩余:${soItemMap[itemId].remainingQty})`); continue; } // 校验批号(仅当销售订单中有批号要求时) if (soItemMap[itemId].lotNumber && inputLot !== soItemMap[itemId].lotNumber) { errors.push(`第${j+1}行商品批号不匹配,销售订单中批号为:${soItemMap[itemId].lotNumber}`); continue; } // 校验通过,收集发货单行数据 fulfillmentLines.push({ itemId: itemId, qty: inputQty, lotNumber: inputLot }); } // 4. 处理校验结果 if (errors.length > 0) { // 错误时返回表单并展示错误信息 var form = serverWidget.createForm({ title: "Create Item Fulfillment" }); form.addSubmitButton({ label: 'Submit' }); // 重建表单字段 var soNumberField = form.addField({ id : 'custpage_so_number', type : serverWidget.FieldType.TEXT, label : 'Sales Order Number', defaultValue: soNumber // 保留用户输入的SO号 }); var sublist = form.addSublist({ id: "item_sublist", type: serverWidget.SublistType.INLINEEDITOR, label: "Item" }); sublist.addField({ id: "itemname", type: serverWidget.FieldType.SELECT, label: "Item", source: "item" }); sublist.addField({ id: "lotnumber", type: serverWidget.FieldType.TEXT, label: "Lot/Heat Number" }); sublist.addField({ id: "quantity", type: serverWidget.FieldType.INTEGER, label: "Quantity" }); // 回填用户已输入的子列表数据 for (var k = 0; k < lineCount; k++) { sublist.setSublistValue({ id: 'itemname', line: k, value: request.getSublistValue({ sublistId: 'item_sublist', fieldId: 'itemname', line: k }) }); sublist.setSublistValue({ id: 'lotnumber', line: k, value: request.getSublistValue({ sublistId: 'item_sublist', fieldId: 'lotnumber', line: k }) }); sublist.setSublistValue({ id: 'quantity', line: k, value: request.getSublistValue({ sublistId: 'item_sublist', fieldId: 'quantity', line: k }) }); } // 添加错误提示 form.addErrorMessage({ message: errors.join('<br>'), type: serverWidget.MessageType.ERROR }); context.response.writePage(form); } else { // 5. 校验通过,创建Item Fulfillment var ifRecord = record.create({ type: record.Type.ITEM_FULFILLMENT, isDynamic: true }); // 关联销售订单 ifRecord.setValue({ fieldId: 'createdfrom', value: soNumber }); // 设置发货单商品行 for (var l = 0; l < fulfillmentLines.length; l++) { ifRecord.selectNewLine({ sublistId: 'item' }); ifRecord.setCurrentSublistValue({ sublistId: 'item', fieldId: 'item', value: fulfillmentLines[l].itemId }); ifRecord.setCurrentSublistValue({ sublistId: 'item', fieldId: 'quantity', value: fulfillmentLines[l].qty }); if (fulfillmentLines[l].lotNumber) { ifRecord.setCurrentSublistValue({ sublistId: 'item', fieldId: 'inventorynumber', value: fulfillmentLines[l].lotNumber }); } ifRecord.commitLine({ sublistId: 'item' }); } // 保存发货单 var ifId = ifRecord.save({ enableSourcing: true, ignoreMandatoryFields: false }); // 返回成功信息 var successForm = serverWidget.createForm({ title: "Create Item Fulfillment" }); successForm.addField({ id: 'custpage_success', type: serverWidget.FieldType.INLINEHTML, label: 'Result' }).defaultValue = `<h3>发货单创建成功!ID:${ifId}</h3>`; successForm.addButton({ label: '返回创建页面', id: 'custpage_back', functionName: 'window.location.reload()' }); context.response.writePage(successForm); } } catch (er) { log.debug("error in post method", er); // 捕获全局错误并展示 var errorForm = serverWidget.createForm({ title: "Create Item Fulfillment" }); errorForm.addErrorMessage({ message: `系统错误:${er.message}`, type: serverWidget.MessageType.ERROR }); errorForm.addSubmitButton({ label: '重新尝试' }); context.response.writePage(errorForm); } }
关键说明
- 数据校验逻辑:覆盖商品存在性、发货数量上限、批号匹配三个核心校验点,错误信息精准定位到具体行。
- 表单回填:校验失败时保留用户已输入的数据,避免重复录入。
- 动态记录操作:使用
isDynamic: true处理销售订单和发货单子列表,确保数据关联正确。 - 错误捕获:全局捕获异常,避免页面崩溃,同时记录日志便于排查问题。
内容的提问来源于stack exchange,提问作者Maria S
相关产品推荐
相关产品推荐

