You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 03:05:22