Python脚本分组路径修复功能【分享】
金蝶云社区-云社区用户4u731234
云社区用户4u731234
4人赞赏了该文章 1,824次浏览 未经作者许可,禁止转载编辑于2017年11月30日 16:44:09

本帖子是发现在使用选项里的取消勾选“只显示下一级明细数据”时,下级分组可以过滤出数据时,反而上一级分组过滤不出数据,
经过分析,发现分组全路径存在问题,
整理了如下脚本进行修复,
当列表插件注册本脚本后,如存在错误的分组全路径数据,会给出提示:

配置列表菜单后,可进行数据的修复,如上图的“分组全路径修复”菜单,菜单设置标识为:tbGroupFullPathRepair即可进行修复。
修复的操作记录信息,执行的更新sql语句,可以在【上机操作日志中】查到。

附上修复的Python脚本:
[code]'''
GroupFullPathRepair
说明: 分组全路径修复
by wanghl 2017-11-30
使用:列表插件注册本脚本,当点击导航树时,会对所有节点的分组全路径进行检查,以确认是否存在异常数据,需要进行修复。
页面加载会定位到跟节点,即相当于有分组的界面,在打开单据后就会进行检查。
想修复数据,需配置列表菜单,命名 tbGroupFullPathRepair,当点击菜单时会进行分组修复。
当修复完成后,所有修复的执行更新的数据库Sql语句,可在【上级操作日志】中进行查看记录。
注意:在做实际修复时,需要做好数据备份。
'''
import clr
clr.AddReference("System")
clr.AddReference("System.Core")
clr.AddReference("Kingdee.BOS")
clr.AddReference("Kingdee.BOS.Core")
clr.AddReference("Kingdee.BOS.ServiceHelper")

from System import *
from System.Collections.Generic import *
from System.Threading import *
from Kingdee.BOS.Log import *
from Kingdee.BOS.ServiceHelper import *
from Kingdee.BOS.Core.Log import *
from Kingdee.BOS.Core import *
from Kingdee.BOS.Core.DynamicForm import *
from Kingdee.BOS.KDThread import *

dictNodes = {};#导航树节点字典(缓存,避免获取第二次)
dictNodesFullPath = {};#分组全路径字典(缓存,避免获取第二次)

currentNodeId = "";#当前分组节点Id
currentParentNodeId = "";#当前分组父节点Id
formId = "";#当前业务对象标识
needRepair = False;#需要修复全路径标识
groupTableName = "";#分组对应的表名
processRateValue = 0;#控制修复进度条
errorCount = 0;#统计错误数据量

def BarItemClick(e):
#this.View.ShowMessage(e.BarItemKey);
if e.BarItemKey == "tbGroupFullPathRepair":#分组全路径修复菜单标识
if needRepair == False:
this.View.ShowMessage("未检测到需要修复的数据!");
this.View.ShowMessage("详细信息", MessageBoxOptions.YesNo, YesNo, "即将进行数据库分组全路径修复操作,注意做好数据备份,是否继续?", MessageBoxType.Notice);

def YesNo(ret):
if (ret == MessageBoxResult.Yes):
ShowProcessForm("正在处理数据,请稍候...");

MainWorker.QuequeTask(DoUpdate,None);

def DoUpdate():
global processRateValue;
global needRepair;

#获取第一级树节点
treeNodes = this.View.GetTreeViewData("FGroupTreeView", "0");
processRateValue += 5;
this.View.Session["ProcessRateValue"] = processRateValue;
if treeNodes.Count > 0:
processRateValue += 5;
this.View.Session["ProcessRateValue"] = processRateValue;
GetAllNodesForUpdateDb(treeNodes);
needRepair = False;
this.View.Session["ProcessRateValue"] = 100;

def ShowProcessForm(caption):
progressFormParameter = DynamicFormShowParameter();
progressFormParameter.PageId = Guid.NewGuid().ToString();
progressFormParameter.FormId = "BOS_ReportProgressMsg";
progressFormParameter.OpenStyle.ShowType = ShowType.Modal;
progressFormParameter.Caption = caption;
progressFormParameter.HiddenCloseButton = True;
progressFormParameter.CustomParams.Add("UseTruePro", "true");
this.View.ShowForm(progressFormParameter,ShowInfo);

def ShowInfo(ret):
this.View.ShowMessage("分组路径修复完成,修复记录可查看【上级操作日志】!");

def TreeNodeClick(e):
if needRepair:
if errorCount > 0:
ShowCountException(errorCount);
else:
ShowException();

#global dictNodes;
global currentNodeId;
global currentParentNodeId;

if dictNodesFullPath.Count == 0:
GetDBNodesFullPath();
#获取第一级树节点
treeNodes = this.View.GetTreeViewData("FGroupTreeView", "0");
#获取所有树节点保存到字典中
if treeNodes.Count > 0 and dictNodes.Count == 0:
GetAllNodesForCheck(treeNodes);

if errorCount > 0:
ShowCountException(errorCount);
#获取当前节点
if e.NodeId <> "0":#全部
currentNodeId = e.NodeId;
currentNode = dictNodes.get(currentNodeId);
currentParentNodeId = currentNode.parentid;

def GetDBNodesFullPath():
#global dictNodesFullPath;
global groupTableName;
global formId;

currentGroupId = this.Model.CurrGroupId;
form = this.View.BillBusinessInfo.GetForm();
formId = form.Id;
currFormGroup = form.GetFormGroup(currentGroupId);
groupTableName = currFormGroup.GroupTableName;

#查询当前所有的全路径
strFullPathSQL = "SELECT FID, FFULLPARENTID FROM "+ groupTableName;
dataSet = DBServiceHelper.ExecuteDataSet(this.Context, strFullPathSQL) ;
for item in dataSet.Tables[0].Rows:
#Logger.Info("GetNodesFullPath", "【"+str(item["FID"])+str(item["FFULLPARENTID"])+"】");
dictNodesFullPath[str(item["FID"])] = str(item["FFULLPARENTID"]);

#检测是否需要更新分组全路径(导航树检测用)
def CheckNeedRepairDbFullPath(node):
global needRepair;
global errorCount;

currentNodeFullPath = dictNodesFullPath.get(node.id);#节点当前的FullPath
currentParentNodeId = node.parentid;
#节点应该的FullPath:父节点的FullPath + . + 父节点Id
if currentParentNodeId == "0":
currentNodeNeedFullPath = "";
else:
currentNodeNeedFullPath = dictNodesFullPath.get(currentParentNodeId) + "." + currentParentNodeId;
if currentNodeFullPath.strip() <> currentNodeNeedFullPath.strip():
needRepair = True;
#errorCount += 1;
ShowException();

def ShowException():
info = "分组数据全路径需进行修复,请联系系统管理员!"
raise Exception(info);

def ShowCountException(count):
info = "存在【"+str(count)+"】条分组数据全路径需进行修复,请联系系统管理员!"
raise Exception(info);

#生成更新全路径SQL(数据库更新用)
def CreateUpdateSql(node):
#global needRepair;
global processRateValue;

if processRateValue <= 100:
processRateValue += 1;
this.View.Session["ProcessRateValue"] = processRateValue;

currentNodeFullPath = dictNodesFullPath.get(node.id);#节点当前的FullPath
currentParentNodeId = node.parentid;
#节点应该的FullPath:父节点的FullPath + . + 父节点Id
if currentParentNodeId == "0":
currentNodeNeedFullPath = "";
else:
currentNodeNeedFullPath = dictNodesFullPath.get(currentParentNodeId) + "." + currentParentNodeId;
if currentNodeFullPath.strip() <> currentNodeNeedFullPath.strip():
#needRepair = True;
info = "节点Id:" + node.id + " 节点名称:" + node.text + " 父节点Id:" + currentParentNodeId + " 当前全路径:" + currentNodeFullPath + " 应该的全路径:"+ currentNodeNeedFullPath;
updateFullPathSQL = "update "+groupTableName+" set FFULLPARENTID = '"+ currentNodeNeedFullPath + "' where FID = " + node.id ;
#记录log日志
#Logger.Info("分组全路径节点修复", info + " 执行的sql:" + updateFullPathSQL);
#记录【上机操作日志】
SetLog(info + " 执行的sql:" + updateFullPathSQL);
#执行更新
DBServiceHelper.Execute(this.Context, updateFullPathSQL) ;

#写上机操作日志
def SetLog(info):
log = LogObject();
log.OperateName = "分组全路径节点修复";
log.ObjectTypeId = formId;
log.Environment = OperatingEnvironment.BizOperate;
log.Description = info;
log.pkValue = "";
LogServiceHelper.WriteLog(this.Context, log);

#根据根节点循环查找所有子节点(修复检测)
def GetAllNodesForCheck(nodes):
for node in nodes:
#Logger.Info("GetAllNodes", "【"+ node.id + node.text +"】");
dictNodes[node.id] = node;
CheckNeedRepairDbFullPath(node);
tempnodes = this.View.GetTreeViewData("FGroupTreeView", node.id);
if tempnodes.Count > 0:
#Logger.Info("childrens for ", "【" + node.text + "】");
GetAllNodesForCheck(tempnodes);

#根据根节点循环查找所有子节点(执行sql)
def GetAllNodesForUpdateDb(nodes):
for node in nodes:
#Logger.Info("GetAllNodes", "【"+ node.id + node.text +"】");
#dictNodes[node.id] = node;
CreateUpdateSql(node);
tempnodes = this.View.GetTreeViewData("FGroupTreeView", node.id);
if tempnodes.Count > 0:
#Logger.Info("childrens for ", "【" + node.text + "】");
GetAllNodesForUpdateDb(tempnodes);

[/code]