金蝶云星空实时库存专题

通过向金蝶库存单据注册Python脚本,用于实时监听库存单据审核/反审核,并且将数据发送到轻易云系统集成平台

。通过集成平台将数据分发到对应的目标系统。

向金蝶的库存单据注册脚本

注意修改脚本中的三个变量参数,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 clr
clr.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 sys
from 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 Dictionary
from 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 = 'https://www.qliang.cloud' # StrategyId 集线器ID
STRATEGY_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 = BarItemKey
self.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 sql def 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_ID
collection = 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 result def 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.Length
webRequest.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 clr
clr.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 sys
from 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 Dictionary
from 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 = 'https://www.qliang.cloud' # StrategyId 集线器ID
STRATEGY_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_ID
collection = 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 result def 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.Length
webRequest.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

金蝶对接电商ERP库存数据,实现监听库存变化的更多相关文章

  1. 电商ERP如何接入智选物流平台?

    智选物流是综合地址库+时效库+逻辑库(成本.订单属性.仓库)选择出最优快递,通过多家快递网点地址库精准数据,点对点的运输时间,各种行业包裹的所有快递价格逻辑,不同产品类型.支付方式等分析,实现不同仓库 ...

  2. 关于电商ERP的想法

    原文地址: http://www.chinaodoo.net/thread-465-1-1.html 试用了下odoo的淘宝订单处理模块,从整个业务流程上已经打通,如果要求不是很高的话,现有的功能基本 ...

  3. 小特跨境电商ERP桌面版 1.不止包括进销存 还能算毛利

    经过近几年跨境电商ERP的开发,加上对跨境电商行业的业务积累,开发出一套适合中小跨境电商公司使用的ERP软件.欢迎选购.支持目前流行的各大电商平台,如速卖通.敦煌网.亚马逊.Shopee.Wish等. ...

  4. 电商ERP常见功能模块

      电商ERP是适用企业卖家的专业电子商务ERP,支持淘宝.天猫.京东.1688.当当.苏宁.拍拍.唯品会.亚马逊.独立B2C等多网络销售渠道:也包括 异地多仓..货位管理.智能配货等专业的WMS(仓 ...

  5. Java生鲜电商平台-高并发核心技术订单与库存实战

    Java生鲜电商平台-高并发核心技术订单与库存实战 一. 问题 一件商品只有100个库存,现在有1000或者更多的用户来购买,每个用户计划同时购买1个到几个不等商品. 如何保证库存在高并发的场景下是安 ...

  6. R系列:关联分析;某电商平台的数据;做捆绑销售和商品关联推荐

    附注:不要问我为什么写这么快,是16年写的. 一.分析目的 I用户在某电商平台买了A,那么平台接下来应该给用户推荐什么,即用户在买了商品A之后接下来买什么的倾向性最大: II应该把哪些商品在一起做捆绑 ...

  7. Zookeeper 客户端API调用示例(基本使用,增删改查znode数据,监听znode,其它案例,其它网络参考资料)

    9.1 基本使用 org.apache.zookeeper.Zookeeper是客户端入口主类,负责建立与server的会话 它提供以下几类主要方法  : 功能 描述 create 在本地目录树中创建 ...

  8. es6的set和get实现数据双向绑定,监听变量变化。

    直接上代码吧,这个用法真的是效仿了.net的枚举. vue的数据双向绑定就是用这个实现的. 代码: html: <input type="text" id="inp ...

  9. 09.VUE学习之watch监听属性变化实现类百度搜索栏功能ajax异步请求数据,返回字符串

    cmd下安装axios npm install axios 安装好后,会多出node_modules文件夹 思路: 监听data里的word改变时,发送ajax异步请求数据, 把返回的数据赋值给dat ...

  10. linkedin databus介绍——监听数据库变化,有新数据到来时通知其他消费者app,新数据存在内存里,多份快照

    概要结构如下图. 图中显示:Search Index和Read Replicas等系统是Databus的消费者.当主OLTP数据库发生写操作时,连接其上的中继系统会将数据拉到中继中.签入在Search ...

随机推荐

  1. css美化

    编辑网页文本 span标签:能让某几个字凸显出来结构:span{color:red:}    <span>123<span> 字体样式:一般设置两个字体.如果浏览器第一个字体不 ...

  2. 聚焦Web前端安全:最新揭秘漏洞防御方法

    在 Web 安全中,服务端一直扮演着十分重要的角色.然而前端的问题也不容小觑,它也会导致信息泄露等诸如此类的问题.在这篇文章中,我们将向读者介绍如何防范Web前端中的各种漏洞.[万字长文,请先收藏再阅 ...

  3. Unity的AssetPostprocessor之Model:深入解析与实用案例 1

    Unity AssetPostprocessor模型相关函数详解 在Unity中,AssetPostprocessor是一个非常有用的工具,它可以在导入资源时自动执行一些操作.在本文中,我们将重点介绍 ...

  4. 三维模型OSGB格式轻量化技术在大规模场景的加载和渲染的作用分析

    三维模型OSGB格式轻量化技术在大规模场景的加载和渲染的作用分析 在移动设备上,大规模场景的加载和渲染是一个不容忽视的问题.对于OSGB格式轻量化处理来说,大规模场景的加载和渲染也是其中一项重要的任务 ...

  5. Java 中的日期时间总结

    前言 大家好,我是 god23bin,在日常开发中,我们经常需要处理日期和时间,日期和时间可以说是一定会用到的,现在总结下 Java 中日期与时间的基本概念与一些常用的用法. 基本概念 日期(年月日, ...

  6. 循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(2)

    在前面随笔<循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(1)>中介绍了Mvvm 的开发,以及一些界面效果,本篇随笔继续深入探讨 ...

  7. 提高 MySQL查询效率的方法

    当涉及到提高MySQL查询效率时,以下是一些重要的策略和技巧,可以帮助你优化数据库性能.无论你是一个Web开发者.数据工程师还是系统管理员,这些方法都可以帮助你确保你的MySQL数据库运行得更快.更有 ...

  8. WPF中以MVVM方式,实现RTSP视频播放

    前言视频播放在上位机开发中经常会遇到,基本上是两种常见的解决方案 1.采用厂家提供的sdk和前端控件进行展示,常见的海康/大华都提供了相关sdk及文档 2.开启相机onvif协议,捅过rtsp视频流进 ...

  9. Springboot简单功能示例-2 KEY初始化功能和全局错误处理

    springboot-sample 介绍 springboot简单示例 跳转到发行版 查看发行版说明 软件架构(当前发行版使用) springboot hutool-all 非常好的常用java工具库 ...

  10. Python并发编程——操作系统发展史、多道技术、进程理论、开启进程、join方法、进程间的数据隔离

    文章目录 必备知识回顾 今日内容详细 操作系统发展史 多道技术 必备知识点 多道技术图解 多道技术重点知识 进程理论 必备知识点 进程调度 进程运行的三状态图 两对重要概念 开启进程的两种方式 joi ...