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

SuiteScript实现:将发票子列表数据复制至供应商账单

解决NetSuite发票子列表数据传递到供应商账单的方案

方案一:使用自定义临时记录存储子列表数据

这种方式适合子列表数据量较大的场景,通过中间自定义记录暂存数据,完全规避URL长度限制:

  1. 创建自定义记录类型
    新建一个自定义记录类型(比如命名为「临时发票子项缓存」),添加以下核心字段:

    • 发票ID(关联到发票记录)
    • 项目ID(关联到商品/项目记录)
    • 数量(数字字段)
    • 金额(货币字段)
    • 按需添加其他需要传递的子列表字段(如税率、描述等)
  2. 修改按钮点击逻辑
    在发票的客户端脚本中,点击「创建供应商账单」按钮时,先读取发票的item子列表数据,批量写入临时自定义记录:

    // 客户端脚本按钮点击事件
    function createVendorBill() {
        var invoiceId = currentRecord.id;
        var itemCount = currentRecord.getLineCount({sublistId: 'item'});
        var tempRecordIds = [];
    
        // 遍历子列表,创建临时记录
        for(var i=0; i<itemCount; i++){
            var tempRec = record.create({type: 'customrecord_temp_invoice_item', isDynamic: true});
            tempRec.setValue({fieldId: 'custrecord_temp_inv_id', value: invoiceId});
            tempRec.setValue({fieldId: 'custrecord_temp_item_id', value: currentRecord.getSublistValue({sublistId: 'item', fieldId: 'item', line: i})});
            tempRec.setValue({fieldId: 'custrecord_temp_qty', value: currentRecord.getSublistValue({sublistId: 'item', fieldId: 'quantity', line: i})});
            tempRec.setValue({fieldId: 'custrecord_temp_amount', value: currentRecord.getSublistValue({sublistId: 'item', fieldId: 'amount', line: i})});
            // 按需设置其他字段
            var tempId = tempRec.save();
            tempRecordIds.push(tempId);
        }
    
        // 跳转至供应商账单页面,传递临时记录ID的逗号分隔字符串
        var url = url.resolveRecord({
            recordType: record.Type.VENDOR_BILL,
            isEditMode: true,
            params: {
                custparam_temp_ids: tempRecordIds.join(','),
                custparam_vendor: currentRecord.getValue({fieldId: 'entity'}) // 已有的主体参数
            }
        });
        window.open(url, '_self');
    }
    
  3. 供应商账单beforeLoad脚本读取数据
    在供应商账单的beforeLoad用户事件脚本中,读取临时记录的数据,填充到item子列表,之后删除临时记录清理数据:

    /**
     * @NApiVersion 2.x
     * @NScriptType UserEventScript
     */
    define(['N/record', 'N/search'], function(record, search) {
        function beforeLoad(context) {
            if(context.type === context.UserEventType.CREATE){
                var tempIds = context.request.parameters.custparam_temp_ids;
                if(tempIds){
                    var tempIdArr = tempIds.split(',');
                    var vendorBill = context.newRecord;
    
                    // 遍历临时记录,填充子列表
                    tempIdArr.forEach(function(tempId){
                        var tempRec = record.load({type: 'customrecord_temp_invoice_item', id: tempId});
                        var line = vendorBill.selectNewLine({sublistId: 'item'});
                        vendorBill.setCurrentSublistValue({sublistId: 'item', fieldId: 'item', value: tempRec.getValue({fieldId: 'custrecord_temp_item_id'})});
                        vendorBill.setCurrentSublistValue({sublistId: 'item', fieldId: 'quantity', value: tempRec.getValue({fieldId: 'custrecord_temp_qty'})});
                        vendorBill.setCurrentSublistValue({sublistId: 'item', fieldId: 'amount', value: tempRec.getValue({fieldId: 'custrecord_temp_amount'})});
                        // 按需设置其他字段
                        vendorBill.commitLine({sublistId: 'item'});
    
                        // 删除临时记录
                        record.delete({type: 'customrecord_temp_invoice_item', id: tempId});
                    });
                }
            }
        }
    
        return {
            beforeLoad: beforeLoad
        };
    });
    

方案二:利用Session存储临时数据(适合数据量适中场景)

如果子列表数据量不大,可以用NetSuite的Session对象存储JSON格式的子列表数据,无需持久化存储:

  1. 修改按钮点击逻辑,调用Suitelet中转
    按钮点击时先调用Suitelet,将子列表数据存入Session:

    // 客户端脚本按钮点击事件
    function createVendorBill() {
        var invoiceId = currentRecord.id;
        var itemCount = currentRecord.getLineCount({sublistId: 'item'});
        var items = [];
    
        // 收集子列表数据
        for(var i=0; i<itemCount; i++){
            items.push({
                itemId: currentRecord.getSublistValue({sublistId: 'item', fieldId: 'item', line: i}),
                quantity: currentRecord.getSublistValue({sublistId: 'item', fieldId: 'quantity', line: i}),
                amount: currentRecord.getSublistValue({sublistId: 'item', fieldId: 'amount', line: i})
                // 其他字段
            });
        }
    
        // 调用Suitelet存储数据并跳转
        var suiteletUrl = url.resolveScript({
            scriptId: 'customscript_sl_temp_item_session',
            deploymentId: 'customdeploy_sl_temp_item_session',
            params: {
                custparam_items: JSON.stringify(items),
                custparam_vendor: currentRecord.getValue({fieldId: 'entity'})
            }
        });
        window.open(suiteletUrl, '_self');
    }
    
  2. Suitelet脚本存储Session并跳转

    /**
     * @NApiVersion 2.x
     * @NScriptType Suitelet
     */
    define(['N/url', 'N/r'], function(url, runtime) {
        function onRequest(context) {
            if(context.request.method === 'GET'){
                var itemsStr = context.request.parameters.custparam_items;
                var vendorId = context.request.parameters.custparam_vendor;
    
                // 将数据存入Session
                runtime.getCurrentSession().set({
                    name: 'invoice_vendor_bill_items',
                    value: itemsStr
                });
    
                // 跳转至供应商账单页面
                var billUrl = url.resolveRecord({
                    recordType: record.Type.VENDOR_BILL,
                    isEditMode: true,
                    params: {
                        custparam_vendor: vendorId
                    }
                });
                context.response.sendRedirect({url: billUrl});
            }
        }
    
        return {
            onRequest: onRequest
        };
    });
    
  3. 供应商账单客户端脚本读取Session并填充
    在供应商账单的客户端脚本中,页面加载时读取Session数据并填充子列表:

    /**
     * @NApiVersion 2.x
     * @NScriptType ClientScript
     */
    define(['N/runtime', 'N/currentRecord'], function(runtime, currentRecord) {
        function pageInit(context) {
            var session = runtime.getCurrentSession();
            var itemsStr = session.get({name: 'invoice_vendor_bill_items'});
            if(itemsStr){
                var items = JSON.parse(itemsStr);
                var billRec = currentRecord.get();
    
                items.forEach(function(item){
                    var line = billRec.selectNewLine({sublistId: 'item'});
                    billRec.setCurrentSublistValue({sublistId: 'item', fieldId: 'item', value: item.itemId});
                    billRec.setCurrentSublistValue({sublistId: 'item', fieldId: 'quantity', value: item.quantity});
                    billRec.setCurrentSublistValue({sublistId: 'item', fieldId: 'amount', value: item.amount});
                    billRec.commitLine({sublistId: 'item'});
                });
    
                // 清除Session中的临时数据
                session.set({name: 'invoice_vendor_bill_items', value: ''});
            }
        }
    
        return {
            pageInit: pageInit
        };
    });
    

方案三:直接在客户端获取数据并填充(SuiteScript 2.1+)

如果使用SuiteScript 2.1及以上版本,可以在客户端脚本中直接调用服务器端逻辑获取发票子列表数据,无需中转:

/**
 * @NApiVersion 2.1
 * @NScriptType ClientScript
 */
define(['N/record', 'N/url', 'N/currentRecord'], function(record, url, currentRecord) {
    async function createVendorBill() {
        var invoiceId = currentRecord.id;
        var vendorId = currentRecord.getValue({fieldId: 'entity'});

        // 异步获取发票子列表数据(使用promise封装服务器调用)
        async function getInvoiceItems(invId) {
            return new Promise((resolve, reject) => {
                var scriptUrl = url.resolveScript({
                    scriptId: 'customscript_ss_get_invoice_items',
                    deploymentId: 'customdeploy_ss_get_invoice_items',
                    params: {custparam_inv_id: invId}
                });
                fetch(scriptUrl)
                    .then(response => response.json())
                    .then(data => resolve(data))
                    .catch(err => reject(err));
            });
        }

        var items = await getInvoiceItems(invoiceId);

        // 打开供应商账单页面并填充数据
        var billRec = record.create({type: record.Type.VENDOR_BILL, isDynamic: true});
        billRec.setValue({fieldId: 'entity', value: vendorId});

        items.forEach(item => {
            billRec.selectNewLine({sublistId: 'item'});
            billRec.setCurrentSublistValue({sublistId: 'item', fieldId: 'item', value: item.itemId});
            billRec.setCurrentSublistValue({sublistId: 'item', fieldId: 'quantity', value: item.quantity});
            billRec.setCurrentSublistValue({sublistId: 'item', fieldId: 'amount', value: item.amount});
            billRec.commitLine({sublistId: 'item'});
        });

        var billId = billRec.save({enableSourcing: true, ignoreMandatoryFields: true});
        window.open(url.resolveRecord({recordType: record.Type.VENDOR_BILL, id: billId, isEditMode: true}), '_self');
    }

    return {
        pageInit: function() {},
        createVendorBill: createVendorBill // 绑定到按钮的点击事件
    };
});

对应的服务器脚本(Suitelet):

/**
 * @NApiVersion 2.1
 * @NScriptType Suitelet
 */
define(['N/record', 'N/https'], function(record, https) {
    function onRequest(context) {
        var invId = context.request.parameters.custparam_inv_id;
        var invoiceRec = record.load({type: record.Type.INVOICE, id: invId});
        var itemCount = invoiceRec.getLineCount({sublistId: 'item'});
        var items = [];

        for(var i=0; i<itemCount; i++){
            items.push({
                itemId: invoiceRec.getSublistValue({sublistId: 'item', fieldId: 'item', line: i}),
                quantity: invoiceRec.getSublistValue({sublistId: 'item', fieldId: 'quantity', line: i}),
                amount: invoiceRec.getSublistValue({sublistId: 'item', fieldId: 'amount', line: i})
            });
        }

        context.response.write(JSON.stringify(items));
        context.response.setHeader({name: https.ResponseHeader.CONTENT_TYPE, value: 'application/json'});
    }

    return {
        onRequest: onRequest
    };
});

内容的提问来源于stack exchange,提问作者Vernita

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 04:15:29