一、业务背景
(一)公司情况
A/B/C三家公司分别经营不同的业务,但是偶尔也会有交集:比如三家公司向同一家客户销售不同的商品;客户不允许在三家公司中重复建立。
(二)基础资料管控策略
为避免系统内客户重复建立基础资料(客户)和保持统计口径和核算维度的唯一性,基础资料管控策略采用分配模式;但是并不是所有客户都需要进行分配,或者A建立好后只分配给B,不分配给C。因此在基础资料管控策略中设置了三家公司都是创建组织,都允许分配给其他两家(客户的业务有可能先发生在A,也有可能先发生在B,先做业务的来建立客户)。三家公司大部分业务都是隔离开的,因此并不需要将客户集中管控,只会有小部分业务会重叠,集中管控也不方便,需要配置专员建立和分配客户,用户不同意,让销售人员直接建立客户即可。
(三)标准功能分析
参考社区的“防止客户名称重复添加”的相关帖子发现并不能完成这种功能需求。
帖子链接:https://vip.kingdee.com/article/375449053129238528?productLineId=1&isKnowledge=2
这个帖子在创建组织和使用组织下可以防止客户重复添加,但是在集团层面做不到,测试下来主要有以下3个问题;
1、当使用组合字段检查时客户名称必选,勾选创建组织或者使用组织时,只能控制在创建组织或者使用组织下不重复。比如,A建立好一个客户后,只分配给B,但是有一天C公司的业务员也要跟这个客户做业务,在不知道系统中有这个客户的情况下, 是可以新增的,并没有触发重复检查。
2、当使用组合字段检查时客户名称必选,不勾选创建组织或者使用组织时;那么这种情况下从A创建分配给B的客户,在B组织下也不能进行保存,因为客户名称重复,影响了分配功能的使用。
3、单据合法性校验,只勾选客户名称,这个是全局检查名称唯一,影响分配功能的使用。
二、关键步骤
考虑到以上情况,尝试用Python操作插件来进行实现业务需求。
(一)功能逻辑解析
1、要想获取系统中已经有客户名称了,可以通过客户表FID=FMASTERID 来找到创建组织是哪个;
2、如果是创建组织和使用组织不一致,则不用考虑,此种情况一定是分配下来的 FCreateOrgId !=FUseOrgId;
3、只有在新建界面时才检查客户名称是否在系统中存在,重新审核或者已经保存下来的记录的创建状态则不检查,FDocumentStatus =="Z";
(二)Python源码
#引入clr运行库 import clr #添加对cloud插件开发的常用组件的引用 clr.AddReference('System') clr.AddReference('System.Data') clr.AddReference('Kingdee.BOS') clr.AddReference('Kingdee.BOS.Core') clr.AddReference('Kingdee.BOS.App') clr.AddReference('Kingdee.BOS.Contracts') clr.AddReference('Kingdee.BOS.ServiceHelper') #导入cloud基础库中的常用实体对象(分命名空间导入,不会递归导入) from Kingdee.BOS import * from Kingdee.BOS.Core import * from Kingdee.BOS.Core.Bill import * #from Kingdee.BOS.Orm import * from Kingdee.BOS.Contracts import * from Kingdee.BOS.App import * from Kingdee.BOS.Core.DynamicForm.PlugIn import * from Kingdee.BOS.Core.DynamicForm.PlugIn.ControlModel import * from System import * from System.Data import * from System.Text import * from System.Collections import * from Kingdee.BOS.App.Data import * from System.Collections.Generic import * from Kingdee.BOS.ServiceHelper import * def OnPreparePropertys(e): e.FieldKeys.Add("FName");#客户名称 e.FieldKeys.Add("FDocumentStatus");#单据状态 e.FieldKeys.Add("FUseOrgId");#使用组织 e.FieldKeys.Add("FCreateOrgId");#使用组织 def BeginOperationTransaction(e): for billObj in e.DataEntitys: FName = str(billObj["Name"]); FDocumentStatus = str(billObj["DocumentStatus"]); FUseOrgId = str(billObj["UseOrgId"]["ID"]); FCreateOrgId = str(billObj["CreateOrgId"]["ID"]); if FCreateOrgId !=FUseOrgId: return; temp = SearchTheOrg(FName,FUseOrgId); if (FDocumentStatus =="Z" and temp is not None ): forgname = temp["FNAME"]; raise Exception(String.format("客户名称{0}在组织{1}已存在,请联系管理员分配给当前组织!",FName,forgname)); def SearchTheOrg(name , orgid): sql ="/*dialect*/SELECT O.FNAME FROM T_BD_CUSTOMER_L A LEFT JOIN T_BD_CUSTOMER B ON A.FCUSTID = B.FCUSTID AND A.FLOCALEID =2052 LEFT JOIN T_ORG_Organizations_L O ON O.FORGID = B.FCREATEORGID AND O.FLOCALEID =2052 WHERE B.FCUSTID = B.FMASTERID AND A.FNAME = '" + name + "'" + " AND B.FUSEORGID <> " + orgid ; datalist = DBServiceHelper.ExecuteDynamicObject(this.Context,sql); if(datalist.Count>0): return datalist[0];
(三)注册操作服务插件
(四)最终效果
提示:组织内客户名称重复的校验会在python插件之前生效,是通过单据合法校验组合字段唯一控制的,见上文的参考帖子。
注意^_^
需要在BeginOperationTransaction中实现,一开始不太会用在EndOperationTransaction处理的,其实单据状态从Z已经变成A了所以一直不生效,调整了好多次才发现问题,对于不会写代码的人来说,Python调试真费事....。
参考帖子:
https://vip.kingdee.com/article/343426375581169920?fromAction=POST_ARTICLE&productLineId=1
https://vip.kingdee.com/article/158234477305916928?productLineId=1
推荐阅读