获取电子面单清空体积值二开案例(Python插件模拟继承业务表单插件)

栏目:云星空知识作者:金蝶来源:金蝶云社区发布:2024-09-23浏览:1

获取电子面单清空体积值二开案例(Python插件模拟继承业务表单插件)

    在获取电子面单中,默认的体积字段值是从物料中的长宽高和单据的数量计算到的,如果物料没有配置长宽高,则获取电子面单界面中的体积字段为空,如下图1-1和图1-2所示:

图1-1


图1-2


    这里的体积逻辑赋值是在表单插件'Kingdee.K3.SCM.Sal.Business.PlugIn.GetKuaidiBillEdit'中干预的,因此客户比较难通过BOS设计器去干预,在设计GetKuaidiBillEdit类时,标准功能有考虑字段的自定义赋值逻辑,所以在GetKuaidiBillEdit自定义了多个虚方法以方便外部客户通过C#二开继承的方式干预字段赋值。如果标准的体积字段赋值逻辑不满足客户要求,比如客户要求就是要强制清空体积字段值,无论物料上是否有配置长宽高,那应该如何处理呢?本文将演示一种使用Python插件的方式来达到目的,由于Python表单插件无法指定基类(至少我在论坛上是没有找到相关帖子,如有错误可留言指正),这里使用Python编译C#源码的方式来模拟Python继承指定基类(严格来讲并不是Python继承指定的表单插件而是借用动态编译出来的类)。

    首先扩展'获取电子面单'动态表单,禁用GetKuaidiBillEdit标准插件,注册并启用Python插件,如下图1-3所示:   

图1-3


上图的Python代码如下:(请不要直接从论坛复制以下脚本,可使用右侧附件)Demo.zip

clr.AddReference('System')
clr.AddReference('Kingdee.BOS')
clr.AddReference('Kingdee.BOS.Core')
clr.AddReference('Kingdee.K3.SCM.Sal.Business.PlugIn')
clr.AddReference('Kingdee.K3.SCM.Core');
from System import AppDomain
from System.IO import FileInfo
from System.Reflection import Assembly
from System.Reflection import BindingFlags
from System.CodeDom.Compiler import CompilerParameters
from Microsoft.CSharp import CSharpCodeProvider
from Kingdee.BOS.Core.Util import MD5Compute
from Kingdee.BOS.Cache import KCacheManagerFactory
from Kingdee.K3.SCM.Sal.Business.PlugIn import GetKuaidiBillEdit
from Kingdee.K3.SCM.Core.SAL import Kuaidi100Parameter
refDlls = '''
Kingdee.BOS
Kingdee.BOS.App
Kingdee.BOS.Core
Kingdee.BOS.DataEntity
Kingdee.BOS.Business.DynamicForm
Kingdee.BOS.Business.PlugIn
Kingdee.BOS.BusinessEntity
Kingdee.K3.SCM.Sal.Business.PlugIn
Kingdee.K3.SCM.Core
System
System.Core
'''
code = '''
using System;
using System.ComponentModel;
using System.Linq;
using System.Text;
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.K3.SCM.Sal.Business.PlugIn;
using Kingdee.K3.SCM.Core.SAL;
using Kingdee.BOS.Core.List;
using Kingdee.BOS.Core.Bill;
namespace Kingdee.K3.SCM.Custom.BusinessPlugin
{
    public class CustomizeKuaidiBillEdit : GetKuaidiBillEdit
    {
        protected override void CustomPopulateRowData(Kuaidi100Parameter parameter, ListSelectedRow row, int rowIndex)
        {
            this.View.Model.SetValue("FVolume", "", rowIndex);
        }
        protected override void CustomPopulateDataFromBillView(string formId, int rowIndex, IBillView billView)
        {
            this.View.Model.SetValue("FVolume", "", rowIndex);
        }
    }
}
'''
def CompileCode(code, refDlls):   
    refAsmNames = filter(lambda y: y != '', map(lambda x: x.strip(), refDlls.split()))
    try:
        kcmgr = KCacheManagerFactory.Instance.GetCacheManager('PyCodeGeneratorCache', 'PyCodeGeneratorCache')
    except:
        return None
    cacheKey = MD5Compute().MDString(code + '-'.join(refAsmNames))
    if(kcmgr.Get(cacheKey) is not None):
        return kcmgr.Get(cacheKey)
    cSharpCodePrivoder = CSharpCodeProvider({'CompilerVersion':'v4.0'})
    codeCompiler = cSharpCodePrivoder.CreateCompiler()
    compilerParameters = CompilerParameters()
    compilerParameters.GenerateExecutable = False; 
    compilerParameters.GenerateInMemory = True; 
    for refAsmName in refAsmNames:
        asms = filter(lambda asm: asm.GetName().Name == refAsmName, AppDomain.CurrentDomain.GetAssemblies())
        if(len(asms) > 0):
            compilerParameters.ReferencedAssemblies.Add(FileInfo(asms[0].CodeBase.Substring(8)).DirectoryName.Replace('\\', '/')+'/' + refAsmName + '.dll')
        else:
            try:
                compilerParameters.ReferencedAssemblies.Add(FileInfo(Assembly.Load(refAsmName).CodeBase.Substring(8)).DirectoryName.Replace('\\', '/') + '/' + refAsmName + '.dll');
            except:
                pass
        compilerResults = codeCompiler.CompileAssemblyFromSource(compilerParameters, code);
    if (compilerResults.Errors.HasErrors):
        raise Exception('\r\n'.join(map(lambda err: err.ErrorText, compilerResults.Errors)))
    compiledAsm = compilerResults.CompiledAssembly;
    kcmgr.Put(cacheKey, compiledAsm)
    return compiledAsm
assembly = CompileCode(code, refDlls)
csPlugin = assembly.CreateInstance('Kingdee.K3.SCM.Custom.BusinessPlugin.CustomizeKuaidiBillEdit') if assembly is not None else None
def getPlugIn():
    csPlugin.SetContext(this.Context, this.View)
    return csPlugin
def CustomPopulateRowData(e):
    getPlugIn().CustomPopulateRowData(e)
def CustomPopulateDataFromBillView(e):
    getPlugIn().CustomPopulateDataFromBillView(e)
def AfterBindData(e):
    getPlugIn().AfterBindData(e)
def OnInitialize(e):
    getPlugIn().OnInitialize(e)
def DataChanged(e):
    getPlugIn().DataChanged(e)
def BeforeF7Select(e):
    getPlugIn().BeforeF7Select(e)
def AfterDoOperation(e):
    getPlugIn().AfterDoOperation(e)
def AfterCopyRow(e):
    getPlugIn().AfterCopyRow(e)


    上文中的代码核心是将C#代码(此代码二开创建了一个继承至GetKuaidiBillEdit的自定义CustomizeKuaidiBillEdit类并重写相关方法)当作文本赋值Python变量,然后再利用动态编译功能实现本类的方法调用CustomizeKuaidiBillEdit类的同名方法(比如DataChanged方法就是调用CustomizeKuaidiBillEdit.DataChanged,只不过这个最终是调用了GetKuaidiBillEdit.DataChanged方法),这里要定义的方法一定要反编译标准GetKuaidiBillEdit方法中带有override 的方法,有可能后面标准版本还会重写其它方法,升级后就必须同步修改。Python插件配置保存后无论是在'获取电子面单'中选择销售单据,还是从销售单据点击'获取电子面单'跳转到界面,都不再给体积字段赋值,如下图1-4所示:

图1-4


写在最后:

    由于无法写出继承特定领域表单插件的Python子插件,所以本文使用了动态编译中间类的功能,这种估计会有性能损耗,如果性能导致执行很慢,建议使用其它方式比如实体服务规则来清空体积字段值。

获取电子面单清空体积值二开案例(Python插件模拟继承业务表单插件)

在获取电子面单中,默认的体积字段值是从物料中的长宽高和单据的数量计算到的,如果物料没有配置长宽高,则获取电子面单界面中的体积字...
点击下载文档
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息