业务流程.案例.指定业务对象全单据激活

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

业务流程.案例.指定业务对象全单据激活

【场景】指定业务对象全单据激活 历史版本业务流程归档按照流程实例归档,当出现业务流程图时并不会归档到一起,导致归档后全流程跟踪无法看全之类的逻辑; 历史的处理方案是让客户手动激活异常单据,或者全激活的逻辑。 手动激活过于繁琐;全激活又不适用于数据量大的客户; 以下提供一个指定业务对象全激活的场景 【方案】请在专业人士指导下使用 (0)先确定激活的单据节点 A -----》 B          B ----- 》C ------》D 常见的跨流程图流程如上,需要找到跨流程的节点,激活的同时把上和下流程都能够同时激活,激活一次就能完整。 (1)确定好单据节点后,准备待激活流程数据表 ```sql --<0>创建 需要处理的修复表, FPKID 主键,FTABLENUMBER表标识,FTID表主键,FStatus状态,FDatetime更新时间 create table T_TMP_RECOVERYSPEC20240626 ( FPKID VARCHAR(50) NOT NULL Primary key, FTABLENUMBER VARCHAR(50) NOT NULL, FTID BIGINT NOT NULL, FStatus INT NOT NULL, FDatetime DateTime NULL ); --<1>以采购订单为例,导入所有单据分录,作为需要处理的流程数据 INSERT INTO T_TMP_RECOVERYSPEC20240626 SELECT NEWID() as FPKID, 't_PUR_POOrderEntry' as FTableNumber ,FENTRYID as FTID, 0 as FStatus, null as FDatetime FROM T_PUR_POORDERENTRY; ``` (2)准备好待激活流程数据表后,创建执行计划进行激活 创建执行计划,关联的组件 Fk.App.Core.ScheduleService.RecoverySpecService, Fk.App.Core.ScheduleService 生成好表后,将当前表作为执行计划的参数传入 ```json {"TableName":"T_TMP_RECOVERYSPEC20240626"} ``` ![image.webp](/download/010031d1b93c70c2493abbf3ae3c92e48f18.webp) (3)运行验证,根据第一次测试的执行时间略微调整执行间隔和异常恢复间隔 ```sql --<2>查询当前各状态的记录数 select '0' as FStatus,count(1) from T_TMP_RECOVERYSPEC20240626 where FStatus = 0 union all select '1' as FStatus,count(1) from T_TMP_RECOVERYSPEC20240626 where FStatus = 1 union all select '2' as FStatus,count(1) from T_TMP_RECOVERYSPEC20240626 where FStatus = 2 --<3>扫描当前表中处理后的记录数 /* --联查脚本,不建议使用,因为原表只有主键索引 select count(1) from T_TMP_RECOVERYSPEC20240626 mlog inner join T_BF_INSTANCEENTRY node on mlog.FTABLENUMBER = node.FTTABLENAME and mlog.FTID = node.FTID */ --直接查询原表脚本 select 'T_BF_INSTANCEENTRY' as tablename,count(1) from T_BF_INSTANCEENTRY where FTTABLENAME = 't_PUR_POOrderEntry' union select 'T_BF_INSTANCEENTRYhis' as tablename,count(1) from T_BF_INSTANCEENTRYhis node inner join T_BF_TABLEDEFINE td on node.FTTABLEID = td.FSEQ where td.FTABLENUMBER = 't_PUR_POOrderEntry' union select 'T_BF_INSTENTRYBACKUP' as tablename,count(1) from T_BF_INSTENTRYBACKUP node inner join T_BF_TABLEDEFINE td on node.FTTABLEID = td.FSEQ where td.FTABLENUMBER = 't_PUR_POOrderEntry' union select 'T_BF_INSTARCHIVELOG' as tablename,count(1) from T_BF_INSTARCHIVELOG bffile inner join T_BF_TABLEDEFINE td on bffile.FTTABLEID = td.FSEQ where td.FTABLENUMBER = 't_PUR_POOrderEntry' ``` ![20240626 1451.webp](/download/01008060815d760e469685fcd72a1dede332.webp) 【参考代码】 引用工程 ![image.webp](/download/01006d770b8692bc46e58f5d351be4b06829.webp) ```csharp using Kingdee.BOS; using Kingdee.BOS.App.Core; using Kingdee.BOS.App.Data; using Kingdee.BOS.Contracts; using Kingdee.BOS.Core; using Kingdee.BOS.Util; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; namespace Fk.App.Core.ScheduleService { public class RecoverySpecService : IScheduleService { public static class TmpConst { public static string FPKID = "FPKID"; public static string FTableNumber = "FTableNumber"; public static string FTID = "FTID"; public static string FStatus = "FStatus"; public static string FDatetime = "FDatetime"; public enum Status { Ready = 0, Running = 1, Finish = 2, } public static int Day_Running2Ready = 5; public static int BatchCnt_Read = 1000; public static int BatchCnt_Run = 100; } public void Run(Context ctx, Schedule schedule) { var param = RecoverySpecParam.ConvertFromJsonString(schedule.Parameters); if (param == null || param.TableName.IsNullOrEmptyOrWhiteSpace()) return; param.Context = ctx; DateTime curDateTime = new TimeService().GetSystemDateTime(ctx); /* * <0>处理一天前的运行状态变为准备状态 */ string sqlRun2Ready = string.Format("UPDATE {0} Set FStatus = 0 WHERE FStatus = 1 AND FDatetime < @FDatetime", param.TableName); List<SqlParam> paramList = new List<SqlParam>(); paramList.Add(new SqlParam("@FDatetime", KDDbType.DateTime, curDateTime.AddDays(TmpConst.Day_Running2Ready))); DBUtils.Execute(ctx, sqlRun2Ready, paramList); /* * <1>获取前N条记录做激活 */ Dictionary<string, List<RecoveryItem>> tableNumberPkList = new Dictionary<string, List<RecoveryItem>>(); string sqlGetReady = string.Format("SELECT TOP {1} FPKID,FTableNumber,FTID FROM {0} WHERE FStatus = 0", param.TableName, TmpConst.BatchCnt_Read); using (var dr = DBUtils.ExecuteReader(ctx, sqlGetReady)) { while (dr.Read()) { string pkId = dr.GetValue<string>(TmpConst.FPKID); string tableNumber = dr.GetValue<string>(TmpConst.FTableNumber); long tid = dr.GetValue<long>(TmpConst.FTID); if (!tableNumberPkList.ContainsKey(tableNumber)) tableNumberPkList[tableNumber] = new List<RecoveryItem>(); var item = new RecoveryItem() { PkId = pkId, TableNumber = tableNumber, TID = tid }; tableNumberPkList[tableNumber].Add(item); } } if (tableNumberPkList.IsEmpty()) return; /* * <2>激活逻辑 */ foreach (var tableNumerPair in tableNumberPkList) { string tableNumber = tableNumerPair.Key; List<RecoveryItem> recoveryItemList = tableNumerPair.Value; List<RecoveryItem> curTurnRunList = new List<RecoveryItem>(); for (int i = 0; i < recoveryItemList.Count; ++i) { var recoveryItem = recoveryItemList[i]; if (!ConvertStataus(param, recoveryItem.PkId, TmpConst.Status.Ready, TmpConst.Status.Running)) continue; curTurnRunList.Add(recoveryItem); if (curTurnRunList.Count >= TmpConst.BatchCnt_Run) { MoveInstToCurBatch(param, curTurnRunList); curTurnRunList.Clear(); } } if (curTurnRunList.Count >= 0) { MoveInstToCurBatch(param, curTurnRunList); } } } private bool ConvertStataus(RecoverySpecParam param, string pkId, TmpConst.Status oldStatus, TmpConst.Status newStataus) { string strSql = string.Format("UPDATE {0} SET FStatus = @FNewStatus, FDatetime = GetDate() WHERE FPKID = @FPKID AND FStatus = @FOldStatus", param.TableName); List<SqlParam> paramList = new List<SqlParam>(); paramList.Add(new SqlParam("@FNewStatus", KDDbType.Int32, (int)newStataus)); paramList.Add(new SqlParam("@FPKID", KDDbType.AnsiString, pkId)); paramList.Add(new SqlParam("@FOldStatus", KDDbType.Int32, (int)oldStatus)); int cnt = DBUtils.Execute(param.Context, strSql, paramList); return cnt == 1; } private void MoveInstToCurBatch(RecoverySpecParam param, List<RecoveryItem> recoveryItemList) { if (param == null || recoveryItemList == null || recoveryItemList.IsEmpty()) return; var bfServiceType = TypesContainer.GetOrRegister("Kingdee.BOS.App.Core.BusinessFlow.Repositories.BFHisDataRepository,Kingdee.BOS.App.Core"); var bfService = Activator.CreateInstance(bfServiceType, param.Context); var method = bfService.GetType().GetMethod("MoveInstToCurrTable"); string tableNumber = recoveryItemList.FirstOrDefault().TableNumber; var tidList = recoveryItemList.Select(x => x.TID).ToList(); object[] paramArray = { tableNumber, tidList }; bool hasError = false; using (var scope = new KDTransactionScope(System.Transactions.TransactionScopeOption.Required)) { for (int i = 0; i < recoveryItemList.Count; ++i) { if (!ConvertStataus(param, recoveryItemList[i].PkId, TmpConst.Status.Running, TmpConst.Status.Finish)) { hasError = true; break; } } if (hasError) return; method.Invoke(bfService, paramArray); scope.Complete(); } } } [Serializable] public class RecoverySpecParam { /* * 要处理的表结构 create table T_TMP_RECOVERYSPEC20240626 ( FPKID VARCHAR(50) NOT NULL Primary key, FTABLENUMBER VARCHAR(50) NOT NULL, FTID BIGINT NOT NULL, FStatus INT NOT NULL, FDatetime DateTime NULL ); INSERT INTO T_TMP_RECOVERYSPEC20240626 SELECT NEWID() as FPKID, 't_PUR_POOrderEntry' as FTableNumber ,FENTRYID as FTID, 0 as FStatus, null as FDatetime FROM T_PUR_POORDERENTRY; */ public string TableName; [JsonIgnore] public Context Context; public static RecoverySpecParam ConvertFromJsonString(string jsonString) { if (jsonString == null || jsonString.Trim().Length <= 0) return null; return JsonConvert.DeserializeObject<RecoverySpecParam>(jsonString); } } public class RecoveryItem { public string PkId; public string TableNumber; public long TID; } } ```

202406261534.zip

业务流程.案例.指定业务对象全单据激活

【场景】指定业务对象全单据激活历史版本业务流程归档按照流程实例归档,当出现业务流程图时并不会归档到一起,导致归档后全流程跟踪无法看...
点击下载文档
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息