通过向金蝶库存单据注册Python脚本,用于实时监听库存单据审核/反审核,并且将数据发送到DATAHUB
向金蝶的库存单据注册脚本
注意修改脚本中的三个变量参数,MAIN_NAME表描述,MAIN_TABLE主表名,ENTRY_TABLE分录表名。关键库存单据表名参考:
| 库存变动表单 | 表头 | 表体 |
|---|---|---|
| 采购入库单 | t_STK_InStock | T_STK_INSTOCKENTRY |
| 采购退料单 | t_PUR_MRB | T_PUR_MRBENTRY |
| 销售出库单 | T_SAL_OUTSTOCK | T_SAL_OUTSTOCKENTRY |
| 销售退货单 | T_SAL_RETURNSTOCK | T_SAL_RETURNSTOCKENTRY |
更多表单名与字段可以自行查阅金蝶BOS平台,不在此赘述。
注意正式运行时将python脚本中的 SHOW_DEBUG 设置为 False 当然这不是必需的
注册金蝶列表插件
ListViewBarItemClick.py
import clrclr.AddReference("System")clr.AddReference("System.Web.Extensions")clr.AddReference("Kingdee.BOS.Core")clr.AddReference("Kingdee.BOS")clr.AddReference('Kingdee.BOS.App')clr.AddReference("Kingdee.BOS.DataEntity")clr.AddReference("Kingdee.BOS.ServiceHelper")clr.AddReference("Newtonsoft.Json")import sysfrom System import *from System.Collections.Generic import *from System.Web.Script.Serialization import *from System.Security.Cryptography import *from System.Text import *from System.Net import *from System.IO import *from System.Threading import *from System.Collections.Generic import Dictionaryfrom Newtonsoft.Json import *from Newtonsoft.Json.Linq import *from Kingdee.BOS.ServiceHelper import *from Kingdee.BOS.Core.DynamicForm import *from Kingdee.BOS.App.Data import *reload(sys)sys.setdefaultencoding('utf-8')# 金蝶Cloud列表插件# 用于监听审核、反审核事件后查询变动物料的库存数据,并将数据发送到DATAHUB# 在应用到需要监听的不同表单时,注意需要更换 MAIN_NAME,MAIN_TABLE,ENTRY_TABLE 三个变量# 开启debug调试消息提醒SHOW_DEBUG = True# DataHub Host 服务器主机DATAHUB_HOST = 'http://datahub-service.kdyunchuang.com'# StrategyId 集线器IDSTRATEGY_ID = '2509d92a-a91e-30a3-ae4e-33eead036a97'# 当前表名MAIN_NAME = '外购入库';# 当前表的主表名MAIN_TABLE = 't_STK_InStock'# 当前表的分录表名ENTRY_TABLE = 'T_STK_INSTOCKENTRY'# 当前表的单据编码字段BILL_FIELD = 'FBILLNO';# 物料字段名,通常情况下应该是 FMATERIALID 不需要修改MATERIAL_FIELD = 'FMATERIALID'# 仓库字段名,通常情况下应该是 FSTOCKID 不需要修改STOCK_FIELD = 'FSTOCKID'# 库位字段名,通常情况下应该是 FSTOCKLOCID 不需要修改STOCKLOC_FIELD = 'FSTOCKLOCID'# 批次号字段名,通常情况下应该是 FLOT 不需要修改LOT_FIELD = 'FLOT'# 货主字段名,通常情况下应该是 FOWNERID 不需要修改OWNER_FIELD = 'FOWNERID'class Inventory:def __init__(self,BarItemKey):keys = this.ListView.SelectedRowsInfo.GetPrimaryKeyValues()self.BarItemKey = BarItemKeyself.PKS = ','.join(keys)def fetch(self):return DBServiceHelper.ExecuteDynamicObject(this.Context, self.__generateSQL())def collectionToJson(self, collection):json = '['for row in collection:json += '{"FID":"'+row[0].ToString() + '"' \',"FStockId":"'+row[1].ToString()+'"' \',"FMaterialId":"'+row[2].ToString()+'"' \',"FBaseQty":"'+row[3].ToString()+'"' \',"FBaseAVBQty":"'+row[4].ToString()+'"' \',"FLot":"'+row[5].ToString()+'"' \',"FUpdateTime":"'+row[6].ToString()+'"' \',"FOwnerId":"'+row[7].ToString()+'"' \',"FKeeperId":"'+row[8].ToString()+'"' \',"FStockOrgId":"'+row[9].ToString()+'"' \',"FOwnerTypeId":"'+row[10].ToString()+'"' \',"FMaterialId_FNumber":"'+row[11].ToString()+'"' \',"FOwnerId_FNumber":"'+row[12].ToString()+'"' \',"FKeeperId_FNumber":"'+row[13].ToString()+'"' \',"FStockOrgId_FNumber":"'+row[14].ToString()+'"' \',"FProduceDate":"'+row[15].ToString()+'"' \',"FMtoNo":"'+row[16].ToString()+'"' \',"FStockStatusId":"'+row[17].ToString()+'"' \',"FBILLNO":"'+row[18].ToString()+'"' \',"id":"'+row[0].ToString()+'"' \',"FormName":"'+MAIN_NAME+'"},'json = json.rstrip(',') + ']'return '{"idCheck":false,"content":'+json+',"multiple":true,"id":1}';def __generateSQL(self):sqlArray = ['SELECT DISTINCT','INV.FID,','INV.FStockId,','INV.FMaterialId,','INV.FBaseQty,','INV.FBaseAVBQty,','INV.FLot,','INV.FUpdateTime,','INV.FOwnerId,','INV.FKeeperId,','INV.FStockOrgId,','INV.FOwnerTypeId,','MATE.FNUMBER AS FMaterialId_FNumber,','ORG1.FNUMBER AS FOwnerId_FNumber,','ORG2.FNUMBER AS FKeeperId_FNumber,','ORG3.FNUMBER AS FStockOrgId_FNumber,','INV.FProduceDate,','INV.FMtoNo,','INV.FStockStatusId,',# 如果现实单据号,则可能导致会重复发送多一些数据.但是这并不影响真实库存.如果非要传入单号,可以开启# 'MAIN.'+BILL_FIELD,# 将单号现实为0,避免POST数据中存在重复"'0' AS FBillNo",'FROM T_STK_INVENTORY INV','LEFT JOIN '+ENTRY_TABLE+' BILL ON','INV.FMATERIALID = BILL.'+MATERIAL_FIELD,'AND INV.FSTOCKID = BILL.'+STOCK_FIELD,'AND INV.FSTOCKLOCID = BILL.'+STOCKLOC_FIELD,'AND INV.FLOT = BILL.'+LOT_FIELD,'AND INV.FOWNERID = BILL.'+OWNER_FIELD,'LEFT JOIN t_bd_material MATE ON INV.FMATERIALID = MATE.FMATERIALID','LEFT JOIN t_ORG_Organizations ORG1 ON INV.FOwnerId = ORG1.FORGID','LEFT JOIN t_ORG_Organizations ORG2 ON INV.FKeeperId = ORG2.FORGID','LEFT JOIN t_ORG_Organizations ORG3 ON INV.FStockOrgId = ORG3.FORGID','LEFT JOIN '+MAIN_TABLE+' MAIN ON BILL.FID = MAIN.FID','WHERE BILL.FID IN ('+self.PKS+')',]sql = ' '.join(sqlArray)if self.BarItemKey == 'tbApprove':sql += " AND MAIN.FDOCUMENTSTATUS = 'C'"else:sql += " AND MAIN.FDOCUMENTSTATUS = 'D'"# this.View.ShowMessage(sql)return sqldef AfterBarItemClick(e):if e.BarItemKey == 'tbApprove' or e.BarItemKey == 'tbReject':if len(this.ListView.SelectedRowsInfo.GetPrimaryKeyValues()) > 0:handle(e.BarItemKey)def handle(BarItemKey):inv = Inventory(BarItemKey)url = DATAHUB_HOST + '/api/open/operation/'+STRATEGY_IDcollection = inv.fetch()if len(collection) == 0:return;webRequest = post(url, inv.collectionToJson(collection))result = JObject.Parse(webRequest)if SHOW_DEBUG == True:this.View.ShowMessage(webRequest)def get(url):webRequest = WebRequest.Create(url)webRequest.Method = "GET"webResponse = webRequest.GetResponse()stream = webResponse.GetResponseStream()streamReader = StreamReader(stream, Encoding.GetEncoding("utf-8"))result = streamReader.ReadToEnd()return resultdef post(url, postdata):webRequest = HttpWebRequest.Create(url)webRequest.Method = "POST"webRequest.Accept = "application/json, text/plain, */*"webRequest.ContentType = "application/json;charset=UTF-8"data = Encoding.ASCII.GetBytes(postdata)webRequest.ContentLength = data.LengthwebRequest.GetRequestStream().Write(data, 0, data.Length)webRequest.GetRequestStream().Flush()webRequest.GetRequestStream().Close()webResponse = webRequest.GetResponse()streamReader = StreamReader(webResponse .GetResponseStream(), Encoding.GetEncoding("utf-8"))result = streamReader.ReadToEnd()return result
注册金蝶表单插件
DynamicFormDataChanged.py
import clrclr.AddReference("System")clr.AddReference("System.Web.Extensions")clr.AddReference("Kingdee.BOS.Core")clr.AddReference("Kingdee.BOS")clr.AddReference('Kingdee.BOS.App')clr.AddReference("Kingdee.BOS.DataEntity")clr.AddReference("Kingdee.BOS.ServiceHelper")clr.AddReference("Newtonsoft.Json")import sysfrom System import *from System.Collections.Generic import *from System.Web.Script.Serialization import *from System.Security.Cryptography import *from System.Text import *from System.Net import *from System.IO import *from System.Threading import *from System.Collections.Generic import Dictionaryfrom Newtonsoft.Json import *from Newtonsoft.Json.Linq import *from Kingdee.BOS.ServiceHelper import *from Kingdee.BOS.Core.DynamicForm import *from Kingdee.BOS.App.Data import *reload(sys)sys.setdefaultencoding('utf-8')# 金蝶Cloud表单插件# 用于监听数据变动审核、反审核事件后查询变动物料的库存数据,并将数据发送到DATAHUB# 在应用到需要监听的不同表单时,注意需要更换 MAIN_NAME,MAIN_TABLE,ENTRY_TABLE 三个变量# 开启debug调试消息提醒SHOW_DEBUG = True# DataHub Host 服务器主机DATAHUB_HOST = 'http://datahub-service.kdyunchuang.com'# StrategyId 集线器IDSTRATEGY_ID = '2509d92a-a91e-30a3-ae4e-33eead036a97'# 当前表名MAIN_NAME = '外购入库';# 当前表的主表名MAIN_TABLE = 't_STK_InStock'# 当前表的分录表名ENTRY_TABLE = 'T_STK_INSTOCKENTRY'# 当前表的单据编码字段BILL_FIELD = 'FBILLNO';# 物料字段名,通常情况下应该是 FMATERIALID 不需要修改MATERIAL_FIELD = 'FMATERIALID'# 仓库字段名,通常情况下应该是 FSTOCKID 不需要修改STOCK_FIELD = 'FSTOCKID'# 库位字段名,通常情况下应该是 FSTOCKLOCID 不需要修改STOCKLOC_FIELD = 'FSTOCKLOCID'# 批次号字段名,通常情况下应该是 FLOT 不需要修改LOT_FIELD = 'FLOT'# 货主字段名,通常情况下应该是 FOWNERID 不需要修改OWNER_FIELD = 'FOWNERID'class Inventory:def __init__(self):self.PK = this.View.Model.GetPKValue().ToString()def fetch(self):return DBServiceHelper.ExecuteDynamicObject(this.Context, self.__generateSQL())def collectionToJson(self, collection):json = '['for row in collection:json += '{"FID":"'+row[0].ToString() + '"' \',"FStockId":"'+row[1].ToString()+'"' \',"FMaterialId":"'+row[2].ToString()+'"' \',"FBaseQty":"'+row[3].ToString()+'"' \',"FBaseAVBQty":"'+row[4].ToString()+'"' \',"FLot":"'+row[5].ToString()+'"' \',"FUpdateTime":"'+row[6].ToString()+'"' \',"FOwnerId":"'+row[7].ToString()+'"' \',"FKeeperId":"'+row[8].ToString()+'"' \',"FStockOrgId":"'+row[9].ToString()+'"' \',"FOwnerTypeId":"'+row[10].ToString()+'"' \',"FMaterialId_FNumber":"'+row[11].ToString()+'"' \',"FOwnerId_FNumber":"'+row[12].ToString()+'"' \',"FKeeperId_FNumber":"'+row[13].ToString()+'"' \',"FStockOrgId_FNumber":"'+row[14].ToString()+'"' \',"FProduceDate":"'+row[15].ToString()+'"' \',"FMtoNo":"'+row[16].ToString()+'"' \',"FStockStatusId":"'+row[17].ToString()+'"' \',"FBILLNO":"'+row[18].ToString()+'"' \',"id":"'+row[0].ToString()+'"' \',"FormName":"'+MAIN_NAME+'"},'json = json.rstrip(',') + ']'return '{"idCheck":false,"content":'+json+',"multiple":true,"id":1}';def __generateSQL(self):sqlArray = ['SELECT DISTINCT','INV.FID,','INV.FStockId,','INV.FMaterialId,','INV.FBaseQty,','INV.FBaseAVBQty,','INV.FLot,','INV.FUpdateTime,','INV.FOwnerId,','INV.FKeeperId,','INV.FStockOrgId,','INV.FOwnerTypeId,','MATE.FNUMBER AS FMaterialId_FNumber,','ORG1.FNUMBER AS FOwnerId_FNumber,','ORG2.FNUMBER AS FKeeperId_FNumber,','ORG3.FNUMBER AS FStockOrgId_FNumber,','INV.FProduceDate,','INV.FMtoNo,','INV.FStockStatusId,','MAIN.'+BILL_FIELD,'FROM T_STK_INVENTORY INV','LEFT JOIN '+ENTRY_TABLE+' BILL ON','INV.FMATERIALID = BILL.'+MATERIAL_FIELD,'AND INV.FSTOCKID = BILL.'+STOCK_FIELD,'AND INV.FSTOCKLOCID = BILL.'+STOCKLOC_FIELD,'AND INV.FLOT = BILL.'+LOT_FIELD,'AND INV.FOWNERID = BILL.'+OWNER_FIELD,'LEFT JOIN t_bd_material MATE ON INV.FMATERIALID = MATE.FMATERIALID','LEFT JOIN t_ORG_Organizations ORG1 ON INV.FOwnerId = ORG1.FORGID','LEFT JOIN t_ORG_Organizations ORG2 ON INV.FKeeperId = ORG2.FORGID','LEFT JOIN t_ORG_Organizations ORG3 ON INV.FStockOrgId = ORG3.FORGID','LEFT JOIN '+MAIN_TABLE+' MAIN ON BILL.FID = MAIN.FID','WHERE BILL.FID = '+self.PK,]return ' '.join(sqlArray)def DataChanged(e):if e.Key.ToString() == 'FDocumentStatus' and e.OldValue.ToString() == 'B' and e.NewValue.ToString() == 'C':handle()elif e.Key.ToString() == 'FDocumentStatus' and e.OldValue.ToString() == 'C' and e.NewValue.ToString() == 'D':handle()def handle():inv = Inventory()url = DATAHUB_HOST + '/api/open/operation/'+STRATEGY_IDcollection = inv.fetch()if len(collection) == 0:return;webRequest = post(url, inv.collectionToJson(collection))result = JObject.Parse(webRequest)if SHOW_DEBUG == True:this.View.ShowMessage(webRequest)def get(url):webRequest = WebRequest.Create(url)webRequest.Method = "GET"webResponse = webRequest.GetResponse()stream = webResponse.GetResponseStream()streamReader = StreamReader(stream, Encoding.GetEncoding("utf-8"))result = streamReader.ReadToEnd()return resultdef post(url, postdata):webRequest = HttpWebRequest.Create(url)webRequest.Method = "POST"webRequest.Accept = "application/json, text/plain, */*"webRequest.ContentType = "application/json;charset=UTF-8"data = Encoding.ASCII.GetBytes(postdata)webRequest.ContentLength = data.LengthwebRequest.GetRequestStream().Write(data, 0, data.Length)webRequest.GetRequestStream().Flush()webRequest.GetRequestStream().Close()webResponse = webRequest.GetResponse()streamReader = StreamReader(webResponse .GetResponseStream(), Encoding.GetEncoding("utf-8"))result = streamReader.ReadToEnd()return result
金蝶发送get post请求
import clrclr.AddReference("System")clr.AddReference("System.Web.Extensions")clr.AddReference("Kingdee.BOS.Core")clr.AddReference("Kingdee.BOS")clr.AddReference('Kingdee.BOS.App')clr.AddReference("Kingdee.BOS.DataEntity")clr.AddReference("Kingdee.BOS.ServiceHelper")clr.AddReference("Newtonsoft.Json")import sysfrom System import *from System.Collections.Generic import *from System.Web.Script.Serialization import *from System.Security.Cryptography import *from System.Text import *from System.Net import *from System.IO import *from System.Threading import *from System.Collections.Generic import Dictionaryfrom Newtonsoft.Json import *from Newtonsoft.Json.Linq import *from Kingdee.BOS.ServiceHelper import *from Kingdee.BOS.Core.DynamicForm import *from Kingdee.BOS.App.Data import *reload(sys)sys.setdefaultencoding('utf-8')# 开启debug调试消息提醒SHOW_DEBUG = True# DataHub Host 服务器主机DATAHUB_HOST = 'http://datahub-service.kdyunchuang.com'def DataChanged(e):if e.Key.ToString() == 'FDocumentStatus' and e.OldValue.ToString() == 'B' and e.NewValue.ToString() == 'C':handle()def handle():# 拿到当前页面那两个事件# self.PK = this.View.Model.GetPKValue().ToString()begin = this.Model.GetValue('')end = this.Model.GetValue('')url = DATAHUB_HOST + '/api/open/operation/'+beginwebRequest = get(url);if SHOW_DEBUG == True:this.View.ShowMessage(webRequest)def get(url):webRequest = WebRequest.Create(url)webRequest.Method = "GET"webResponse = webRequest.GetResponse()stream = webResponse.GetResponseStream()streamReader = StreamReader(stream, Encoding.GetEncoding("utf-8"))result = streamReader.ReadToEnd()return resultdef post(url, postdata):webRequest = HttpWebRequest.Create(url)webRequest.Method = "POST"webRequest.Accept = "application/json, text/plain, */*"webRequest.ContentType = "application/json;charset=UTF-8"data = Encoding.ASCII.GetBytes(postdata)webRequest.ContentLength = data.LengthwebRequest.GetRequestStream().Write(data, 0, data.Length)webRequest.GetRequestStream().Flush()webRequest.GetRequestStream().Close()webResponse = webRequest.GetResponse()streamReader = StreamReader(webResponse .GetResponseStream(), Encoding.GetEncoding("utf-8"))result = streamReader.ReadToEnd()return result
