单据列表获取即时库存更新到实体字段实现方案
金蝶云社区-KD_丁昱翔
KD_丁昱翔
8人赞赏了该文章 970次浏览 未经作者许可,禁止转载编辑于2023年08月18日 09:51:36

此文章参考 https://vip.kingdee.com/link/s/lSYyT 基础上进行的细化。

一、【业务需求】

列表中查询物料的即时库存能否直接更新到实体字段,能保存到指定字段用于业务人员查看和导出Excel作为业务评估一个参数。

二、【功能分析】

当前列表中获取即时库存调用的方式是操作方法,配置"获取即时库存操作",只能在列表中自动生成一个非实体字段用于展示即时库存,有几个问题

1、该字段不支持引出

2、无法持久化,每次触发查询刷新列表等操作需要重新获取

列表配置获取即时库存参考文章:列表如何显示即时库存

三、【实现】

1、单据扩展数量类型,实体字段,如:"当前库存"

 image.png

说明:增加字段的标识、字段名、绑定实体属性均为:FINVENTORYQTY如果提示标识重复,可以修改标识为FINVENTORYQTY1,字段名和绑定实体属性不能改。

2、启用系统标准功能,配置"获取即时库存操作",启用对应的列表插件

 image.png

说明:1)需要先检查是否有系统标准获取即时库存的插件:Kingdee.K3.SCM.Business.PlugIn.GetInvStockOperationForList,Kingdee.K3.SCM.Business.PlugIn

如果没有则需要手工注册,注册时在安装目录的bin目录下查找名称为Kingdee.K3.SCM.Business.PlugIn dll文件。

2)注册步骤3的二开Python插件。

3、二开插件,重写AfterDoOperation事件,触发获取即时库存操作后,插件会返回获取到的即时库存的数据包,根据即时库存数据包进行对应更新处理

以其他出库单为例:

***********************以下为Python脚本,本行可以不复制*****************************

'''

1、单据扩展"当前库存",数量类型,实体字段

2、结合系统标准功能,启用列表插件:列表如何显示即时库存:https://vip.kingdee.com/article/157910505003723264?productLineId=1

3、针对不同单据修改更新sql语句中的表名,配置二开插件

'''

import clr

clr.AddReference('System')

clr.AddReference('System.Data')

clr.AddReference('Kingdee.BOS')

clr.AddReference('Kingdee.BOS.Core')

clr.AddReference('Kingdee.BOS.App.Core')

clr.AddReference('Kingdee.BOS.App')

clr.AddReference('Kingdee.BOS.DataEntity')

clr.AddReference('Kingdee.BOS.ServiceHelper')

clr.AddReference('Kingdee.BOS.Contracts')

clr.AddReference('Kingdee.K3.Core')

 

from System import *

from Kingdee.BOS.Log import Logger

from Kingdee.BOS import *

from Kingdee.BOS.Core import *

from Kingdee.BOS.Contracts import *

from System.Data import *

from System.Collections import *

from Kingdee.BOS.App.Data import *

from System.Collections.Generic import List

from System.Collections.Generic import Dictionary

from System import StringComparison

from Kingdee.BOS.ServiceHelper import *

from Kingdee.BOS.Core.DynamicForm.PlugIn.Args import *

from Kingdee.K3.Core.SCM.Args import *

from Kingdee.BOS.Core.List.PlugIn import *

     

def AfterDoOperation(e):

    if e.Operation.OperationId != 149:

        return

    

    invStockResult = e.OperationResult.FuncResult    

    if invStockResult == None:

        return

        

    havaUpdateInvs = Dictionary[object,object]()

    for stockResult in invStockResult:

        entryId = stockResult.EntryId

        stockQty = stockResult.StockQty

        havaUpdateInvs[entryId] = stockQty

 

    if havaUpdateInvs.Count > 0:

        lstSqlObj = List[SqlObject]()    

        invTmpTable = DBServiceHelper.CreateTemporaryTableName(this.Context)

        BuildUpdateInvQtyTmpTable(this.Context, invTmpTable)

        

        InvQtyDt = DataTable(invTmpTable)

        otColumn1 = DataColumn()

        otColumn1.ColumnName = "FENTRYID"

        InvQtyDt.Columns.Add(otColumn1)

        

        otColumn2 = DataColumn()

        otColumn2.ColumnName = "FSTOCKQTY"

        InvQtyDt.Columns.Add(otColumn2)

        

        pdict = dict(havaUpdateInvs)

        for key,value in pdict.items():

            dr = InvQtyDt.NewRow()

            dr["FENTRYID"] = Convert.ToInt64(key)

            dr["FSTOCKQTY"] = Convert.ToDecimal(value)

            InvQtyDt.Rows.Add(dr)

            

        DBUtils.BulkInserts(this.Context, InvQtyDt)

        

        sql = '''MERGE INTO T_STK_MISDELIVERYENTRY IT USING   

                        (

                            SELECT T1.FENTRYID, T1.FSTOCKQTY FROM {0} T1 JOIN T_STK_MISDELIVERYENTRY T2 ON T1.FENTRYID = T2.FENTRYID

                        ) UT ON (IT.FENTRYID = UT.FENTRYID)

                        WHEN MATCHED THEN UPDATE

                        SET IT.FINVENTORYQTY = UT.FSTOCKQTY;'''.format(invTmpTable)

        paras = List[SqlParam]()

        sqlObject = SqlObject(sql, paras)

        lstSqlObj.Add(sqlObject)

        

        sql = "DROP TABLE {0}".format(invTmpTable)

        lstSqlObj.Add(sqlObject)

        

        if lstSqlObj.Count > 0:

            DBUtils.ExecuteBatch(this.Context, lstSqlObj)    

            

def BuildUpdateInvQtyTmpTable(ctx, tempTableName):

    sqlTM = " ( FENTRYID INT NOT NULL DEFAULT(0), FSTOCKQTY DECIMAL(23,10) NOT NULL DEFAULT (0))"

    sql = " CREATE TABLE {0} {1} ".format(str(tempTableName), str(sqlTM))

    sqls = List[str]()

    sqls.Add(sql)

 

DBUtils.ExecuteBatchWithTime(ctx, sqls, sqls.Count, 120)

 

***********************以上为Python脚本,本行可以不复制*****************************

代码使用说明:

浅蓝色内容:此部分内容为单据体的表名,即在销售出库单获取,则为销售出库单明细的表名;

绿色内容:此部分内容为需要将获取到的即时库存更新到的实体字段名。即步骤1增加的实体字段。

详细内码见附件《单据列表刷新即时库存更新实体字段.py》

 


实现效果:

 image.png

说明:可以对出库数量增加过滤比较符:字段比较,则在过滤实现出库数量和获取的即时库存的比较。

 

【内容扩展】

系统标准功能获取即时库存默认最高选择2000条数据,如需要调整,则采用以下代码调整:

/*dialect*/

UPDATE T_BAS_SYSTEMPROFILE SET FVALUE = '10000' WHERE FCATEGORY = 'STK' AND FORGID = 0 AND FACCOUNTBOOKID = 0 AND FKEY = 'MAXGETINVSTOCKROWS';

 

说明:以上代码标记红色部分为需要修改的选择数量。

 

【注意事项】

1、e.Operation.OperationId == 149 表示是"获取即时库存操作"按钮触发

2、针对不同单据需修改更新sql语句中的单据明细表名

3、更新取决于列表页选中的数据,涉及到列表分页的数据将无法处理到

 




本文转载自:官方知识

作者:官方知识

原文链接:https://vip.kingdee.com/link/s/lSYyT

图标赞 8
8人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
0人打赏
还没有人打赏,快来当第一个打赏的人吧!