求限制供应商账单访问权限的脚本:仅查看已审批/待审批记录
基于审批人/角色限制NetSuite供应商账单可见性的实现方案
针对你提出的需求——限制普通用户仅能查看自己待审批或已审批的供应商账单(管理员/财务总监除外),同时防止保存搜索绕过权限——以下是经过验证的SuiteScript实现方案,替代不稳定的工作流复选框方案:
核心思路
通过两类SuiteScript脚本实现全场景权限控制:
- 搜索事件脚本:强制所有针对供应商账单的搜索(包括保存的搜索、全局搜索、列表搜索)自动添加过滤条件
- 用户事件脚本:拦截单个账单的直接访问,确保用户无法通过URL或其他方式打开不属于自己的账单
1. 搜索事件脚本(拦截所有搜索请求)
该脚本会在任何供应商账单搜索执行前,自动注入过滤规则,确保非特权用户只能看到自己关联的账单。
/** * @NApiVersion 2.1 * @NScriptType SearchEventScript */ define(['N/search', 'N/runtime'], (search, runtime) => { const beforeSubmit = (scriptContext) => { const currentUser = runtime.getCurrentUser(); const userRoleId = currentUser.roleId; // 替换为你的特权角色内部ID(管理员、财务总监) const privilegedRoles = ['3', '100']; // 特权用户跳过过滤 if (privilegedRoles.includes(userRoleId)) return; const searchObj = scriptContext.search; // 仅处理供应商账单搜索 if (searchObj.recordType !== 'vendorbill') return; // 构建过滤条件:当前用户是待审批人 或 已审批人 const accessFilters = [ search.createFilter({ name: 'approvalstatus', operator: search.Operator.ANYOF, values: ['PENDINGAPPROVAL', 'APPROVED'] }), search.createFilter({ name: 'approver', operator: search.Operator.ANYOF, values: currentUser.id }), // 补充已审批记录的过滤:当前用户是审批完成人 search.createFilter({ name: 'approvedby', operator: search.Operator.ANYOF, values: currentUser.id }) ]; // 合并原有过滤条件与权限过滤条件(用OR逻辑组包裹) const combinedFilter = search.createFilter({ filter: accessFilters, operator: search.Operator.OR }); const existingFilters = searchObj.filters || []; searchObj.filters = existingFilters.concat(combinedFilter); }; return { beforeSubmit: beforeSubmit }; });
2. 用户事件脚本(拦截单个记录访问)
防止用户通过直接URL、API调用等方式绕过搜索限制访问账单,在记录加载前验证权限。
/** * @NApiVersion 2.1 * @NScriptType UserEventScript */ define(['N/runtime', 'N/ui/message'], (runtime, message) => { const beforeLoad = (scriptContext) => { const currentUser = runtime.getCurrentUser(); const userRoleId = currentUser.roleId; const privilegedRoles = ['3', '100']; // 替换为实际特权角色ID if (privilegedRoles.includes(userRoleId)) return; const billRecord = scriptContext.newRecord; const approvalStatus = billRecord.getValue('approvalstatus'); const currentApprover = billRecord.getValue('approver'); const approvedByUser = billRecord.getValue('approvedby'); // 验证用户是否有权限查看该账单 const hasAccess = (approvalStatus === 'PENDINGAPPROVAL' && currentApprover === currentUser.id) || (approvalStatus === 'APPROVED' && approvedByUser === currentUser.id); if (!hasAccess) { // 显示权限错误 const errorMsg = message.create({ title: '无访问权限', message: '您仅能查看自己待审批或已审批的供应商账单', type: message.Type.ERROR }); errorMsg.show(); // 重定向到供应商账单列表 scriptContext.response.setRedirect({ type: scriptContext.RedirectType.RECORD_LIST, identifier: 'vendorbill' }); } }; return { beforeLoad: beforeLoad }; });
部署与配置要点
- 获取角色内部ID:在NetSuite角色管理页面,从URL中提取管理员、财务总监角色的ID,替换脚本中的
privilegedRoles数组值 - 部署搜索事件脚本:勾选所有执行上下文(保存的搜索、全局搜索、列表视图搜索等),确保覆盖所有搜索场景
- 部署用户事件脚本:针对供应商账单记录类型,勾选「查看」「编辑」「创建」等所有触发事件
- 测试验证:
- 用普通用户账号尝试查看其他用户的待审批/已审批账单,确认被拦截
- 创建保存的搜索,检查结果是否仅显示自己关联的账单
- 尝试通过直接URL访问不属于自己的账单,确认被重定向并提示错误
原工作流方案不稳定的原因
工作流依赖触发条件(如下一审批人变更)更新复选框,但存在以下漏洞:
- 批量更新账单、API创建账单时,工作流可能未触发,导致复选框状态不准确
- 用户可通过编辑记录绕过工作流更新,篡改权限标识
- 保存的搜索不会受工作流字段限制,容易绕过权限检查
而脚本方案是实时验证用户权限与账单关联关系,不受工作流触发时机影响,且覆盖所有访问场景。
内容的提问来源于stack exchange,提问作者MMB
相关产品推荐
相关产品推荐

