本文讨论了如何根据客户需求在现有库存服务中设置排除特定仓库的功能。当前服务仅支持获取单个或所有仓库库存,无法满足客户需求。文中分析了场景,并提出了通过二次开发(二开)扩展“仓库”基础资料并编写插件的解决方案。具体步骤包括扩展仓库数据、编写插件、引用标准组件并重写方法以实现条件过滤。最终实现效果是排除了未勾选“允许获取库存”的仓库,如“1019仓库”,无法获取其即时库存信息。
一、【客户需求】:获取库存服务希望可以设置不包含某一个仓库的库存,进行获取。目前只能实现服务里绑定仓库字段之后,获取某一个仓库的库存;或者不绑定仓库,就获取所有仓库的库存。
二、【场景分析】:在单据分录的菜单操作中配置“获取库存”操作,会根据分录物料的库存维度去获取对应的即时库存信息,这个服务操作默认是获取分录物料上的所有仓库的数据,要想实现上述的需求场景,需要做对应的二开
目前BOS中针对该服务预留有相关的配置,具体可参考下面两篇文章:
1、获取即时库存信息服务插件接口介绍
https://vip.kingdee.com/article/27024?share_fromuid=1172
2、获取库存如何自定义条件
https://vip.kingdee.com/article/170261
三、【二开实现】:
1、扩展“仓库”基础资料
从调试服务代码的逻辑发现,获取即时库存时,先根据分录物料编码做了第一层的数据过滤
SELECT t.FId FInvId, t.FMaterialId,t.FStockOrgId,t.FKeeperTypeId,t.FKeeperId,t.FOwnerTypeId,t.FOwnerId,t.FStockId,t.FStockLocId, t.FAuxPropId,t.FStockStatusId,t.FLot,tlot.FNumber as FLotText,t.FBomId,t.FMtoNo,t.FProjectNo, case when tms.fisexppartoflot = '1' then tlot.FProduceDate else t.FProduceDate end as FProduceDate, case when tms.fisexppartoflot = '1' then tlot.FExpiryDate else t.FExpiryDate end as FExpiryDate, t.FBaseQty AS FBaseQty, t.FSecQty AS FSecQty from t_stk_inventory t inner join (select * from fn_StrSplit('503594,544181', ',')) t2 on t2.FId=t.FMaterialId INNER JOIN T_BD_MATERIAL tm ON t.FMATERIALID = tm.FMASTERID AND t.FSTOCKORGID = tm.FUSEORGID inner join t_bd_materialstock tms on tm.FMaterialId=tms.FMaterialId left join t_bd_lotmaster tlot on t.FLot = tlot.FLotId
2、 编写插件需要引用标准组件Kingdee.K3.SCM.App.Core.dll,派生抽象类AbstractGetInvStockPlugIn
RegexGetInvDataSql(bool usePLNReserve, string sql, List<SqlParam> paras): 重写该方法,将扩展的"允许获取库存"作为条件拼接到查询的sql
IEnumerable<STK_Inventory> ApplyExtFilter(IEnumerable<STK_Inventory> data, GetInvStockDetailArg item): 重写该方法,将获取到的全量即时库存数据包,按"允许获取库存"的仓库做过滤
从AbstractGetInvStockPlugIn抽象类的设计来看,两个方法的差别在于
RegexGetInvDataSql: 根据脚本和参数读取的即时库存数据(先筛选,后获取)
ApplyExtFilter: 服务方法已经按照库存维度对库存数据进行过筛选,这里可以对筛选结果再次过滤(先获取,再筛选)
针对这个需求可以简单的这么理解这两个方法的区别,根据需要,重写任意一个方法即可。
插件注册:
四、【实现效果】:
“1019仓库”未勾选“允许获取库存”,则无法获取到即时库存
以上分析及处理方案是一些个人的理解,如有不对之处,还请指正。
推荐阅读