Exemple #1
0
        /// <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);
        }
Exemple #2
0
        /// <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}");
        }