Acumatica按公司/分支动态过滤仓库选择器实现方案咨询
实现方案
要实现多个页面的仓库选择器动态过滤,推荐通过自定义选择器特性实现,一次开发即可在所有目标页面复用,无需单独为每个页面写重复逻辑。
步骤1:编写自定义仓库选择器特性
新建继承自PXSiteAttribute(Acumatica原生仓库选择器特性)的自定义类,重写过滤逻辑:
public class FilteredSiteAttribute : PXSiteAttribute { public FilteredSiteAttribute() : base() { } public override IEnumerable GetRecords() { // 先获取原生选择器的所有仓库结果 var allSites = base.GetRecords().Cast<INSite>().ToList(); // 读取库存参数配置 INSetupExt setupExt = PXSelect<INSetup>.SelectSingleBound(Base, null).GetExtension<INSetupExt>(); // 未开启过滤直接返回全部 if (setupExt.UsrAllowBlockin != true) return allSites; // 获取当前上下文信息 int? currentBranch = Base.Accessinfo.BranchID; // 优先取当前单据的分支,没有的话取登录用户默认分支 if (Base is SOOrderEntry soEntry) currentBranch = soEntry.Document.Current?.BranchID ?? currentBranch; if (Base is POOrderEntry poEntry) currentBranch = poEntry.Document.Current?.BranchID ?? currentBranch; if (Base is CROpportunityMaint oppEntry) currentBranch = oppEntry.Document.Current?.BranchID ?? currentBranch; if (Base is CRQuoteMaint quoteEntry) currentBranch = quoteEntry.Document.Current?.BranchID ?? currentBranch; if (Base is RQRequisitionEntry reqEntry) currentBranch = reqEntry.Document.Current?.BranchID ?? currentBranch; int currentCompany = Base.Accessinfo.CompanyID; if (setupExt.UsrByBranch == true && currentBranch.HasValue) { // 按分支过滤:仅返回当前分支关联的仓库 return allSites.Where(s => s.BranchID == currentBranch).ToList(); } else if (setupExt.UsrByCompany == true) { // 按公司过滤:返回当前公司下所有分支关联的仓库 var companyBranches = PXSelect<Branch, Where<Branch.companyID, Equal<Required<Branch.companyID>>>> .Select(Base, currentCompany).RowCast<Branch>().Select(b => b.BranchID).ToList(); return allSites.Where(s => companyBranches.Contains(s.BranchID)).ToList(); } return allSites; } }
步骤2:替换所有目标页面DAC的仓库字段特性
通过DAC扩展替换对应字段的原生仓库选择器,以下是各页面需要修改的DAC:
- 销售订单:
SOOrder/SOLine的SiteID字段 - 采购订单:
POOrder/POLine的SiteID字段 - 商机:
CROpportunity的SiteID字段 - 销售报价:
CRQuote的SiteID字段 - 申请单:
RQRequisition/RQRequisitionLine的SiteID字段
以销售订单SOLine为例,扩展代码如下:
public class SOLineExt : PXCacheExtension<SOLine> { [PXMergeAttributes(Method = MergeMethod.Replace)] [FilteredSite] public virtual int? SiteID { get; set; } }
步骤3:补充分支变更触发刷新逻辑(可选)
如果需要切换单据分支后仓库选择器立即刷新结果,在对应Graph的扩展中添加分支字段更新事件,强制重置SiteID的选择器缓存:
protected void SOLine_BranchID_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e, PXFieldUpdated InvokeBaseHandler) { InvokeBaseHandler?.Invoke(cache, e); var row = e.Row as SOLine; if (row == null) return; // 强制清空SiteID的选择器缓存,下次打开时重新加载过滤后的结果 PXUIFieldAttribute.SetEnabled<SOLine.siteID>(cache, row, false); PXUIFieldAttribute.SetEnabled<SOLine.siteID>(cache, row, true); // 如果需要清空原有不符合规则的仓库值,可以加以下逻辑 // cache.SetDefaultExt<SOLine.siteID>(row); }
注意事项
- 你现有的
INSetupExt代码无需修改,直接沿用即可 - 所有DAC扩展的特性替换都要加
[PXMergeAttributes(Method = MergeMethod.Replace)],否则会和原生特性冲突 - 如果需要支持多公司跨分支权限,可根据实际业务调整按公司过滤的逻辑,增加权限校验判断
内容的提问来源于stack exchange,提问作者Charl
相关产品推荐
相关产品推荐

