SuiteScript实现:将发票子列表数据复制至供应商账单
解决NetSuite发票子列表数据传递到供应商账单的方案
方案一:使用自定义临时记录存储子列表数据
这种方式适合子列表数据量较大的场景,通过中间自定义记录暂存数据,完全规避URL长度限制:
创建自定义记录类型
新建一个自定义记录类型(比如命名为「临时发票子项缓存」),添加以下核心字段:- 发票ID(关联到发票记录)
- 项目ID(关联到商品/项目记录)
- 数量(数字字段)
- 金额(货币字段)
- 按需添加其他需要传递的子列表字段(如税率、描述等)
修改按钮点击逻辑
在发票的客户端脚本中,点击「创建供应商账单」按钮时,先读取发票的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'); }供应商账单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格式的子列表数据,无需持久化存储:
修改按钮点击逻辑,调用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'); }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 }; });供应商账单客户端脚本读取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
相关产品推荐
相关产品推荐

