适用场景:
金蝶k3cloud物料表(数据库对应表:t_bd_material)缺少成本字段,这对于日常进行销售单据毛利预估造成一定困难,为了解决这一问题需要在物料表中,通过BOS开发平台进行自定义添加,但添加后字段如何实现随每次成本结算进行更新成了新的课题。由于k3中成本一般在<存货收发汇总>中体现,但是该表为账表类型,为前端计算体现。因此,常规解决方式进行存储过程编写平均成本运算逻辑,并将结果定期进行刷新,一般企业寻找二开进行。我们换一种思维假设在<存货收发汇总>自定义插件通过点击按钮将该表体现成本反写物料表(t_bd_material)指定字段不就可以了吗?不多说直接上插件代码:
import clr
clr.AddReference('Kingdee.BOS.App')
clr.AddReference('Kingdee.BOS')
clr.AddReference('Kingdee.BOS.Core')
clr.AddReference('Kingdee.BOS.DataEntity')
clr.AddReference("Kingdee.BOS.ServiceHelper")
from Kingdee.BOS.App.Data import *
from Kingdee.BOS.Core import *
from Kingdee.BOS.Core.DependencyRules import *
from Kingdee.BOS.Core.Bill import *
import Kingdee.BOS.Orm.DataEntity
import Kingdee.BOS.Core.Metadata.EntityElement
from Kingdee.BOS.Core.Metadata.FieldElement import *
from Kingdee.BOS.ServiceHelper import *
from Kingdee.BOS.Core.Bill.PlugIn import *
from Kingdee.BOS.Core.Bill.PlugIn.Args import *
from Kingdee.BOS.Core.DynamicForm.PlugIn.Args import *
from Kingdee.BOS.Core.DynamicForm.PlugIn import *
from Kingdee.BOS.Core.DynamicForm.PlugIn.ControlModel import *
from Kingdee.BOS.Core.DynamicForm import *
from Kingdee.BOS.KDThread import *
from System import *
###########################以上是必要模块引入##############################
##声明全局变量,便于后期多函数引用
global relist
##全局变量初始化
relist=[]
##调用进度条将开启子线程,子线程中出现了代码异常,会执行此方法,显示错误信息
def showRslt(asynResult):
if (asynResult <> None and asynResult.Exception <>None):
this.View.ShowErrMessage(asynResult.Exception.Message);
##当进度条达到100%时,自动显示完成信息
def showFinishMsg(formResult):
this.View.ShowMessage("数据更新完成!");
##执行主函数并向进度条进行赋值,此处主函数为updte t_bd_material中的f_paez_amount字段,条件为fmasterid
def setData():
#引用全局变量值进行循环刷新物料主档信息
tcount=len(relist)
recount=0
for re in relist:
masterid=re[0].ToString()
price=re[1].ToString()
sql="/*dialect*/ set nocount on update t_bd_material set f_paez_amount='"+price+"' where fmasterid='"+masterid+"' select case when @@rowcount>0 then 1 else 0 end"
result = DBServiceHelper.ExecuteDynamicObject(this.Context, sql)[0][0]
recount+=result
#进度条直接收int值,因此进行四舍五入后取整
pvalue=int(round(recount*100/tcount,0))
if pvalue >=10:
billObj = this.Model.DataObject
this.View.Session["ProcessRateValue"] = pvalue;
#加载进度条函数,k3插件固定方法实现
def ShowProgressBar():
#定义进度条参数
progressFormParameter = DynamicFormShowParameter();
#给进度条参数赋值,包含显示位置、Formid、标题文字、允许更新进度条value等,标准话东西只修改标题(progressFormParameter.Caption)即可.
progressFormParameter.PageId = Guid.NewGuid().ToString();
progressFormParameter.FormId = "BOS_ReportProgressMsg";
progressFormParameter.OpenStyle.ShowType = ShowType.Modal;
progressFormParameter.Caption = "正在更新物料主档数据...";
progressFormParameter.HiddenCloseButton = True;
progressFormParameter.CustomParams.Add("UseTruePro", "true");
this.View.ShowForm(progressFormParameter,Action[FormResult](showFinishMsg));
MainWorker.QuequeTask(Action(setData),Action[AsynResult](showRslt));
#自定义按钮功能及预处理数据筛选
def BarItemClick(e):
#此处需要调用全局变量,并将结果传递给全局变量
global relist
#按钮标识大写处理
key=e.BarItemKey.ToUpperInvariant();
if(key=="test01".ToUpperInvariant()):
#获取当前账表模块属性
reportModel=this.Model;
#获取当前账表所有行数,分页不影响
rowCount=reportModel.GetRowCount();
#当账表无数据时,用return 直接结束函数,返回提示信息
if rowCount==0:
return this.View.ShowMessage("无可刷新数据!")
#获取当前账表所有数据返回dataTable数据格式,分页不影响;dataTable解析方式:dataTable[row][colnum_name]
mytab=reportModel.GetData(0,rowCount)
lists=[]
#循环筛选可更新的物料信息,成本取值逻辑,当出库成本不为空,且不等于0时,作为预更新成本值,否则取结存成本作为预更新成本值;当预更新成本值大于0时作为最终更新,否则不更新
for row in range(0,rowCount):
#逐行读取数据,并获取合计行的值
mid=mytab.Rows[row]['FMATERIALBASEID'];
当mid等于0时,该行为合计数值所在位置
if mid==0:
#由于合计行物料内码为0,因此取合计行上一行物料内码值
baseid=mytab.Rows[row-1]['FMATERIALBASEID'];
#分别提取合计行的出库成本单价和结存库存成本
cp=mytab.Rows[row]['FSENDPRICE'];
kp=mytab.Rows[row]['FENDPRICE'];
#预更新成本值,取值逻辑
if len(str(cp))==0 or cp==0:
p=kp
else:
p=cp
#最终预更新确认,并存入基础列表
if p>0:
lists.append([baseid,p])
#判断基础列表有无数据
if len(lists)==0:
return this.View.ShowMessage("无可刷新数据!")
#如基础列表有数据,将基础列表赋值给全局变量relist
relist=lists
#调用python lambda方法创建提示信息框。
this.View.ShowMessage("本次将更新"+str(len(relist))+"个物料的平均成本,是否继续?", MessageBoxOptions.YesNo,lambda result:updateprice(result))
def updateprice(result):
global progressValue,progressBar
if (result == MessageBoxResult.Yes):
ShowProgressBar()