/// <summary> /// create workflow signing rows /// </summary> /// <param name="row"></param> /// <param name="userFid">field of user id that own row</param> /// <param name="flowName"></param> /// <param name="sourceType"></param> /// <param name="sourceId"></param> /// <param name="db"></param> /// <returns>error msg if any</returns> public static string CreateSignRows(JObject row, string userFid, string flowName, string sourceType, string sourceId, Db db) { //var //var profile = db.GetUserProfile(); var error = string.Empty; //var db = new Db(); //return error if sign rows existed //get flow lines var sql = string.Format(@" select FromNodeId=l.FromNode, FromNodeName=nf.Name, FromNodeType=nf.NodeType, ToNodeId=l.ToNode, ToNodeName=nt.Name, ToNodeType=nt.NodeType, nf.SignerType, nf.SignerValue, l.Sort, l.CondStr from dbo._FlowLine l join dbo._Flow f on l.FlowId=f.Id join dbo._FlowNode nf on l.FromNode=nf.Id join dbo._FlowNode nt on l.ToNode=nt.Id where f.Name='{0}' order by l.FromNode, l.Sort ", flowName); var lines = db.GetModels <SignLineDto>(sql); /* * //get start node * var checkLines = lines * .Where(a => a.FromNodeType == EnumNodeType.Start) * .OrderBy(a => a.Sort) * .ToList(); * var firstLine = checkLines.FirstOrDefault(); * * //now start node * var nowNodeId = firstLine.FromNodeId; * var nowNodeName = firstLine.FromNodeName; */ //get now line var firstLine = lines .Where(a => a.FromNodeType == NodeTypeEstr.Start) .OrderBy(a => a.Sort) .FirstOrDefault(); if (firstLine == null) { error = "No Start Node for Flow " + flowName; goto lab_exit; } var nowNodeId = firstLine.FromNodeId; var nowNodeName = firstLine.FromNodeName; // //string nowNodeId = "", nowNodeName = ""; //var first = true; var findIdxs = new List <int>(); //find index list //List<SignLineModel> checkLines = null; while (true) { /* * if (first) * { * checkLines = lines * .Where(a => a.FromNodeType == EnumNodeType.Start) * .OrderBy(a => a.Sort) * .ToList(); * * first = false; * * //now start node * var firstLine = checkLines.FirstOrDefault(); * nowNodeId = firstLine.FromNodeId; * nowNodeName = firstLine.FromNodeName; * } * else * { */ var checkLines = lines .Where(a => a.FromNodeId == nowNodeId) .OrderBy(a => a.Sort) .ToList(); //} //get matched line SignLineDto findLine = null; foreach (var line in checkLines) { var status = IsLineMatch(row, line.CondStr); if (status == "1") //case of match { findLine = line; break; } if (status != "0") //case of error { return(status); } } //return error if no matched line if (findLine == null) { error = "No Match Line for FromNode=" + nowNodeName; goto lab_exit; } //check endless loop var idx = lines.IndexOf(findLine); if (findIdxs.IndexOf(idx) >= 0) { error = "Find Node Twice(" + checkLines[idx].FromNodeName + ")"; goto lab_exit; } //add find index findIdxs.Add(idx); //case of end node if (findLine.ToNodeType == NodeTypeEstr.End) { break; } //set variables nowNodeId = findLine.ToNodeId; nowNodeName = findLine.ToNodeName; } //case of ok, write db sql = @" insert into dbo._FlowSign( Id, SourceType, SourceId, NodeName, LevelNo, TotalLevel, SignerValue, SignerName, SignTime) values( @Id, @SourceType, @SourceId, @NodeName, @LevelNo, @TotalLevel, @SignerValue, @SignerName, @SignTime ) "; //write first node var totalLevel = findIdxs.Count - 1; /* * string signerValue = "", signerName = ""; * if (row[userFid] == null) * { * error = "row[" + userFid + "] is empty."; * goto lab_exit; * } * * signerValue = row[userFid].ToString(); * signerName = db.GetStr(string.Format(SqlUserName, signerValue)); * * db.Update(sql, new List<object>() { * "Id", _Str.NewId(), * "SourceType", sourceType, * "SourceId", sourceId, * "NodeName", firstLine.FromNodeName, * "LevelNo", 0, * "TotalLevel", totalLevel, * "SignerValue", signerValue, * "SignerName", signerName, * }); */ //string signerValue = "", signerName = ""; var level = 0; foreach (var idx in findIdxs) { #region get signerValue by rules var line = lines[idx]; var signerValue = ""; DateTime?signTime = null; if (level == 0) { signTime = DateTime.Now; if (row[userFid] != null) { signerValue = row[userFid].ToString(); } } else { switch (line.SignerType) { /* * case EnumSignerType.User: * signerValue = line.SignerValue; * break; */ case SignerTypeEstr.Field: if (row[line.SignerValue] != null) { signerValue = row[line.SignerValue].ToString(); } break; case SignerTypeEstr.UserMgr: if (row[userFid] != null) { signerValue = db.GetStr(string.Format(SqlUserMgr, row[userFid].ToString())); } break; case SignerTypeEstr.DeptMgr: if (line.SignerValue != null) { signerValue = db.GetStr(string.Format(SqlDeptMgr, line.SignerValue)); } break; } } #endregion if (string.IsNullOrEmpty(signerValue)) { error = "cannot get signerValue"; goto lab_exit; } //get signer Name var signerName = db.GetStr(string.Format(SqlUserName, signerValue)); //update db: add row db.Update(sql, new List <object>() { "Id", _Str.NewId(), "SourceType", sourceType, "SourceId", sourceId, "NodeName", line.FromNodeName, "LevelNo", level, "TotalLevel", totalLevel, "SignerValue", signerValue, "SignerName", signerName, "SignTime", signTime, }); level++; } lab_exit: //db.Dispose(); if (error != string.Empty) { error = "_Flow.cs CreateSignRows() wrong: " + error; } return(error); }
/// <summary> /// create workflow signing rows /// </summary> /// <param name="row">flow data</param> /// <param name="userFid">fid of owner user id of row</param> /// <param name="flowCode">Flow.Code</param> /// <param name="sourceId">source row Id(key)</param> /// <param name="db"></param> /// <returns>error msg if any</returns> public static async Task <string> CreateSignRowsAsync(JObject row, string userFid, string flowCode, string sourceId, bool isTest, Db db) { #region 1.get flow lines by flow code var error = string.Empty; var sql = string.Format(@" select FlowId=f.Id, StartNodeId=l.StartNode, StartNodeName=nf.Name, StartNodeType=nf.NodeType, EndNodeId=l.EndNode, EndNodeName=nt.Name, EndNodeType=nt.NodeType, nf.SignerType, nf.SignerValue, l.Sort, l.CondStr from dbo.XpFlowLine l join dbo.XpFlow f on l.FlowId=f.Id join dbo.XpFlowNode nf on l.StartNode=nf.Id join dbo.XpFlowNode nt on l.EndNode=nt.Id where f.Code='{0}' order by l.StartNode, l.Sort ", flowCode); var flowLines = await db.GetModelsAsync <SignLineDto>(sql); #endregion #region 2.get start node id/name var firstLine = flowLines .Where(a => a.StartNodeType == NodeTypeEstr.Start) .OrderBy(a => a.Sort) .FirstOrDefault(); if (firstLine == null) { error = "No Start Node."; goto lab_exit; } var nowNodeId = firstLine.StartNodeId; var nowNodeName = firstLine.StartNodeName; #endregion //3.get matched lines var signTable = GetSignTable(isTest); var findIdxs = new List <int>(); //found lines for insert XpFlowSign/XpFlowSignTest while (true) { #region 4.get lines of current node //CondStr with value will check first !! var nodeLines = flowLines .Where(a => a.StartNodeId == nowNodeId) //.OrderByDescending(a => string.IsNullOrEmpty(a.CondStr)) .OrderBy(a => string.IsNullOrEmpty(a.CondStr)) .ThenBy(a => a.Sort) .ToList(); #endregion #region 5.get matched line by condition string SignLineDto findLine = null; foreach (var line in nodeLines) { if (IsLineMatch(ref error, row, line.CondStr)) { findLine = line; break; } else if (!_Str.IsEmpty(error)) { goto lab_exit; } } //return error if no matched line if (findLine == null) { error = "No Match Line for StartNode=" + nowNodeName; goto lab_exit; } //check endless loop var idx = flowLines.IndexOf(findLine); if (findIdxs.IndexOf(idx) >= 0) { error = "Find Node Twice(" + nodeLines[idx].StartNodeName + ")"; goto lab_exit; } #endregion //add found line index findIdxs.Add(idx); //when end node then exit loop if (findLine.EndNodeType == NodeTypeEstr.End) { break; } //set node id/name for next loop nowNodeId = findLine.EndNodeId; nowNodeName = findLine.EndNodeName; }//loop #region 6.prepare sql for insert XpFlowSign/XpFlowSignTest sql = $@" insert into dbo.{signTable}( Id, FlowId, SourceId, NodeName, FlowLevel, TotalLevel, SignerId, SignerName, SignStatus, SignTime) values( @Id, @FlowId, @SourceId, @NodeName, @FlowLevel, @TotalLevel, @SignerId, @SignerName, @SignStatus, @SignTime) "; #endregion //insert XpFlowSign/XpFlowSignTest rows var totalLevel = findIdxs.Count - 1; var level = 0; //current flow level, start 0 var userType = ""; foreach (var idx in findIdxs) { #region 7.get signer Id/name by rules var line = flowLines[idx]; var signerId = ""; DateTime?signTime = null; if (level == 0) { userType = "UserId"; signTime = DateTime.Now; if (row[userFid] != null) { signerId = row[userFid].ToString(); } } else { switch (line.SignerType) { /* * case EnumSignerType.User: * signerValue = line.SignerValue; * break; */ case SignerTypeEstr.Fid: userType = line.SignerValue; if (row[line.SignerValue] != null) { signerId = row[line.SignerValue].ToString(); } break; case SignerTypeEstr.UserMgr: userType = "User Manager"; if (row[userFid] != null) { signerId = await db.GetStrAsync(string.Format(SqlUserMgr, row[userFid].ToString())); } break; case SignerTypeEstr.DeptMgr: userType = "Depart Manager"; if (line.SignerValue != null) { signerId = await db.GetStrAsync(string.Format(SqlDeptMgr, line.SignerValue)); } break; case SignerTypeEstr.Role: userType = "Role"; if (line.SignerValue != null) { signerId = await db.GetStrAsync(string.Format(SqlRole, line.SignerValue)); } break; } } if (string.IsNullOrEmpty(signerId)) { error = $"SignerId is empty. ({userType})"; goto lab_exit; } //get signer Name var signerName = await db.GetStrAsync(string.Format(SqlUserName, signerId)); if (string.IsNullOrEmpty(signerName)) { error = $"SignerId not existed. ({userType}={signerId})"; goto lab_exit; } #endregion #region 8.insert XpFlowSign/XpFlowSignTest await db.ExecSqlAsync(sql, new List <object>() { "Id", _Str.NewId(), "FlowId", line.FlowId, "SourceId", sourceId, "NodeName", line.StartNodeName, "FlowLevel", level, "TotalLevel", totalLevel, "SignerId", signerId, "SignerName", signerName, "SignStatus", (level == 0) ? "1" : "0", "SignTime", signTime, }); level++; #endregion } //case of ok return(""); //case of error lab_exit: return(isTest ? error : $"_XpFlow.cs CreateSignRows() failed(Flow.Code={flowCode}): {error}"); }