Пример #1
0
        public IHttpActionResult ResubmitWorkflowTask(TaskData model)
        {
            WorkflowInstancePoco instance = GetInstance(model.InstanceGuid);

            try
            {
                WorkflowProcess process     = GetProcess(instance.Type);
                IUser           currentUser = _utility.GetCurrentUser();

                instance = process.ResubmitWorkflow(
                    instance,
                    currentUser.Id,
                    model.Comment
                    );

                Log.Info($"{instance.TypeDescription} request for {instance.Node.Name} [{instance.NodeId}] was resubmitted by {currentUser.Name}");

                return(Json(new
                {
                    message = $"Changes resubmitted successfully. Page will be {instance.TypeDescriptionPastTense.ToLower()} following workflow completion.",
                    status = 200
                }, ViewHelpers.CamelCase));
            }
            catch (Exception ex)
            {
                string msg = $"An error occurred processing the approval on {instance.Node.Name} [{instance.NodeId}]";
                Log.Error(msg, ex);

                return(Content(HttpStatusCode.InternalServerError, ViewHelpers.ApiException(ex, msg)));
            }
        }
Пример #2
0
        public IHttpActionResult RejectWorkflowTask(TaskData model)
        {
            WorkflowInstancePoco instance = GetInstance(model.InstanceGuid);

            try
            {
                WorkflowProcess process     = GetProcess(instance.Type);
                IUser           currentUser = _utility.GetCurrentUser();

                instance = process.ActionWorkflow(
                    instance,
                    WorkflowAction.Reject,
                    currentUser.Id,
                    model.Comment
                    );

                Log.Info($"{instance.TypeDescription} request for {instance.Node.Name} [{instance.NodeId}] was rejected by {currentUser.Name}");

                _hubContext.Clients.All.TaskRejected(
                    _tasksService.ConvertToWorkflowTaskList(instance.TaskInstances.ToList(), instance: instance));

                return(Json(new
                {
                    message = instance.TypeDescription + " request has been rejected.",
                    status = 200
                }, ViewHelpers.CamelCase));
            }
            catch (Exception ex)
            {
                string msg = $"An error occurred rejecting the workflow on {instance.Node.Name} [{instance.NodeId}]";
                Log.Error(msg, ex);

                return(Content(HttpStatusCode.InternalServerError, ViewHelpers.ApiException(ex, msg)));
            }
        }
Пример #3
0
        public void Can_Get_Populated_Instance(int taskCount, int lastGroupId)
        {
            IContent node = Scaffold.Node(ApplicationContext.Current.Services.ContentService);

            Guid guid = Guid.NewGuid();

            WorkflowInstancePoco instance = Scaffold.Instance(guid, (int)WorkflowType.Publish, node.Id);

            _service.InsertInstance(instance);
            for (var i = 1; i <= taskCount; i += 1)
            {
                _tasksService.InsertTask(Scaffold.Task(guid, DateTime.Now,
                                                       i < taskCount ? i : lastGroupId,
                                                       i,
                                                       i < taskCount ? 1 : 3));
            }

            // this has groups, tasks, everything. Or it should.
            WorkflowInstancePoco populatedInstance = _service.GetPopulatedInstance(guid);

            Assert.Equal(taskCount, populatedInstance.TaskInstances.Count);
            Assert.Equal(0, populatedInstance.TotalSteps);                                        // this shouldn't be set yet
            Assert.Equal(lastGroupId, populatedInstance.TaskInstances.First().UserGroup.GroupId); // tasks are descending by id
            Assert.Equal(WorkflowStatus.PendingApproval, populatedInstance.WorkflowStatus);
        }
Пример #4
0
        /// <summary>
        /// Builds workflow instance details markup.
        /// </summary>
        /// <returns>HTML tr inner html definition</returns>
        public static string BuildProcessSummary(this WorkflowInstancePoco instance)
        {
            string result = $"<b>Workflow history</b><br/><br/>{instance.WorkflowType.Description(instance.ScheduledDate)} requested by {instance.AuthorUser.Name} on {instance.CreatedDate:d MMM yyyy}<br/>";

            if (instance.AuthorComment.HasValue())
            {
                result += $"&nbsp;&nbsp;Change description: <i>{instance.AuthorComment}</i><br/>";
            }

            var statusColor = instance.WorkflowStatus.In(WorkflowStatus.Errored, WorkflowStatus.Rejected, WorkflowStatus.Cancelled) ? "red" :
                              instance.WorkflowStatus.In(WorkflowStatus.PendingApproval, WorkflowStatus.Resubmitted) ? "orange" : "green";

            result += $"<br/>Current status: <span style='color: {statusColor}'>{instance.StatusName}</span><br/><br/>";

            bool first = true;

            foreach (WorkflowTaskPoco taskInstance in instance.TaskInstances.OrderBy(t => t.ApprovalStep).ThenByDescending(t => t.Id))
            {
                if (first)
                {
                    result += taskInstance.BuildTaskSummary(first);
                    first   = false;
                }
                else
                {
                    result += taskInstance.BuildTaskSummary(first);
                }
            }

            return($"{result}<br/>");
        }
Пример #5
0
        public IHttpActionResult CancelWorkflowTask(TaskData model)
        {
            WorkflowInstancePoco instance = GetInstance(model.InstanceGuid);

            try
            {
                WorkflowProcess process     = GetProcess(instance.Type);
                IUser           currentUser = _utility.GetCurrentUser();

                instance = process.CancelWorkflow(
                    instance,
                    currentUser.Id,
                    model.Comment
                    );

                Log.Info($"{instance.TypeDescription} request for {instance.Node.Name} [{instance.NodeId}] was cancelled by {currentUser.Name}");

                return(Json(new
                {
                    status = 200,
                    message = instance.TypeDescription + " workflow cancelled"
                }, ViewHelpers.CamelCase));
            }
            catch (Exception ex)
            {
                string msg = $"An error occurred cancelling the workflow on {instance.Node.Name} [{instance.NodeId}]";
                Log.Error(msg, ex);

                return(Content(HttpStatusCode.InternalServerError, ViewHelpers.ApiException(ex, msg)));
            }
        }
Пример #6
0
        public IHttpActionResult ResubmitWorkflowTask(TaskData model)
        {
            WorkflowInstancePoco instance = GetInstance(model.InstanceGuid);

            try
            {
                WorkflowApprovalProcess process = GetProcess(instance.Type);

                instance = process.ResubmitWorkflow(
                    instance,
                    Utility.GetCurrentUser().Id,
                    model.Comment
                    );

                return(Json(new
                {
                    message = "Changes resubmitted successfully. Page will be " + instance.TypeDescriptionPastTense.ToLower() + " following workflow completion.",
                    status = 200
                }, ViewHelpers.CamelCase));
            }
            catch (Exception ex)
            {
                string msg = "An error occurred processing the approval: " + ex.Message + ex.StackTrace;
                Log.Error(msg + " for workflow " + instance.Id, ex);

                return(Json(new
                {
                    message = msg,
                    status = 500
                }, ViewHelpers.CamelCase));
            }
        }
        /// <summary>
        /// Maps Users to the UserGroup property of a WorkflowTaskInstance
        /// </summary>
        /// <param name="task"></param>
        /// <param name="instance"></param>
        /// <param name="userGroup"></param>
        /// <returns></returns>
        public WorkflowInstancePoco MapIt(WorkflowInstancePoco instance, WorkflowTaskPoco task, UserGroupPoco userGroup)
        {
            if (instance == null)
            {
                return(_current);
            }

            if (userGroup.GroupId == task.GroupId)
            {
                task.UserGroup = userGroup;
            }

            if (_current != null && _current.Guid == instance.Guid)
            {
                if (_current.TaskInstances.All(t => t.ApprovalStep != task.ApprovalStep))
                {
                    _current.TaskInstances.Add(task);
                }
                return(null);
            }

            WorkflowInstancePoco prev = _current;

            _current = instance;
            _current.TaskInstances.Add(task);

            return(prev);
        }
Пример #8
0
        /// <summary>
        /// Maps Users to the UserGroup property of a WorkflowTaskInstance
        /// </summary>
        /// <param name="wtip"></param>
        /// <param name="wip"></param>
        /// <param name="ugp"></param>
        /// <returns></returns>
        public WorkflowInstancePoco MapIt(WorkflowInstancePoco wip, WorkflowTaskInstancePoco wtip, UserGroupPoco ugp)
        {
            if (wip == null)
            {
                return(Current);
            }

            if (ugp.GroupId == wtip.GroupId)
            {
                wtip.UserGroup = ugp;
            }

            if (Current != null && Current.Guid == wip.Guid)
            {
                if (Current.TaskInstances.All(t => t.ApprovalStep != wtip.ApprovalStep))
                {
                    Current.TaskInstances.Add(wtip);
                }
                return(null);
            }

            var prev = Current;

            Current = wip;
            Current.TaskInstances.Add(wtip);

            return(prev);
        }
Пример #9
0
        public IHttpActionResult ApproveWorkflowTask(TaskData model)
        {
            WorkflowInstancePoco instance = GetInstance(model.InstanceGuid);

            try
            {
                WorkflowProcess process     = GetProcess(instance.Type);
                IUser           currentUser = _utility.GetCurrentUser();

                instance = process.ActionWorkflow(
                    instance,
                    WorkflowAction.Approve,
                    currentUser.Id,
                    model.Comment
                    );

                string msg    = string.Empty;
                string logMsg = string.Empty;

                switch (instance.WorkflowStatus)
                {
                case WorkflowStatus.PendingApproval:
                    msg    = $"Approval completed successfully. Page will be {instance.TypeDescriptionPastTense.ToLower()} following workflow completion.";
                    logMsg = $"Workflow {instance.TypeDescription} task on {instance.Node.Name} [{instance.NodeId}] approved by {currentUser.Name}";
                    break;

                case WorkflowStatus.Approved:
                    msg    = "Workflow approved successfully.";
                    logMsg = $"Workflow approved by {currentUser.Name} on {instance.Node.Name} [{instance.NodeId}]";

                    if (instance.ScheduledDate.HasValue)
                    {
                        string scheduled = $" Page scheduled for {instance.TypeDescription} at {instance.ScheduledDate.Value.ToString("dd MMM YYYY", CultureInfo.CurrentCulture)}";
                        msg    += scheduled;
                        logMsg += scheduled;
                    }
                    else
                    {
                        msg += $" Page has been {instance.TypeDescriptionPastTense.ToLower()}";
                    }
                    break;
                }

                Log.Info(logMsg);

                return(Json(new
                {
                    message = msg,
                    status = 200
                }, ViewHelpers.CamelCase));
            }
            catch (Exception ex)
            {
                string msg = $"An error occurred processing the approval on {instance.Node.Name} [{instance.Node.Id}]";
                Log.Error(msg, ex);

                return(Content(HttpStatusCode.InternalServerError, ViewHelpers.ApiException(ex, msg)));
            }
        }
Пример #10
0
        public IHttpActionResult InitiateWorkflow(InitiateWorkflowModel model)
        {
            try
            {
                WorkflowProcess process;

                if (model.Publish)
                {
                    process = new DocumentPublishProcess();
                }
                else
                {
                    process = new DocumentUnpublishProcess();
                }

                IUser currentUser             = _utility.GetCurrentUser();
                WorkflowInstancePoco instance = process.InitiateWorkflow(int.Parse(model.NodeId), currentUser.Id, model.Comment);

                string msg = string.Empty;

                switch (instance.WorkflowStatus)
                {
                case WorkflowStatus.PendingApproval:
                    msg = $"Page submitted for {(model.Publish ? "publish" : "unpublish")} approval.";
                    break;

                case WorkflowStatus.Approved:
                    msg = (model.Publish ? "Publish" : "Unpublish") + " workflow complete.";

                    if (instance.ScheduledDate.HasValue)
                    {
                        msg += $" Page scheduled for publishing at {instance.ScheduledDate.Value.ToString("dd MMM YYYY", CultureInfo.CurrentCulture)}";
                    }

                    break;
                }

                Log.Info(msg);

                // broadcast the new task back to the client to update dashboards etc
                // needs to be converted from a poco to remove unused properties and force camelCase
                _hubContext.Clients.All.WorkflowStarted(
                    _tasksService.ConvertToWorkflowTaskList(instance.TaskInstances.ToList(), instance: instance)
                    .FirstOrDefault());

                return(Json(new
                {
                    message = msg,
                    status = 200
                }, ViewHelpers.CamelCase));
            }
            catch (Exception e)
            {
                const string msg = "An error occurred initiating the workflow";
                Log.Error(msg, e);

                return(Content(HttpStatusCode.InternalServerError, ViewHelpers.ApiException(e, msg)));
            }
        }
Пример #11
0
 /// <summary>
 /// Create the new process object for the instance - publish or unpublish
 /// </summary>
 /// <param name="instance"></param>
 /// <returns></returns>
 public static WorkflowProcess GetProcess(this WorkflowInstancePoco instance)
 {
     if ((WorkflowType)instance.Type == WorkflowType.Publish)
     {
         return(new DocumentPublishProcess());
     }
     return(new DocumentUnpublishProcess());
 }
Пример #12
0
        public void Can_Initiate_Publish_Workflow()
        {
            Scaffold.Config();

            var process = new DocumentPublishProcess();
            WorkflowInstancePoco instance = process.InitiateWorkflow(1073, 3, "A test comment");

            Assert.NotNull(instance);
        }
Пример #13
0
        public void Can_Cancel()
        {
            var instance = new WorkflowInstancePoco();

            instance.Cancel();

            Assert.NotNull(instance.CompletedDate);
            Assert.Equal(WorkflowStatus.Cancelled, instance.WorkflowStatus);
        }
Пример #14
0
        /// <summary>
        /// set the total steps property for a workflow instance
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="steps">The number of approval groups in the current flow (explicit, inherited or content type)</param>
        public static void SetTotalSteps(this WorkflowInstancePoco instance, int steps)
        {
            if (instance.TotalSteps == steps)
            {
                return;
            }

            instance.TotalSteps = steps;
        }
Пример #15
0
        public void Can_Get_Process(WorkflowType type, Type expected)
        {
            var instance = new WorkflowInstancePoco
            {
                Type = (int)type
            };

            WorkflowProcess process = instance.GetProcess();

            Assert.IsType(expected, process);
        }
Пример #16
0
        public void Can_Get_By_Guid()
        {
            var guid = Guid.NewGuid();

            _service.InsertInstance(Scaffold.Instance(guid, 1));

            WorkflowInstancePoco instance = _service.GetByGuid(guid);

            Assert.NotNull(instance);
            Assert.Equal(guid, instance.Guid);
        }
Пример #17
0
        public void Can_Set_Total_Steps(int steps, int instanceSteps)
        {
            var instance = new WorkflowInstancePoco
            {
                TotalSteps = instanceSteps
            };

            instance.SetTotalSteps(steps);

            Assert.Equal(steps, instance.TotalSteps);
        }
Пример #18
0
        /// <summary>
        /// Adds an approval task to this workflow instance, setting the approval step and instance guid
        /// </summary>
        /// <param name="instance"></param>
        public static WorkflowTaskPoco CreateApprovalTask(this WorkflowInstancePoco instance)
        {
            var taskInstance = new WorkflowTaskPoco(TaskType.Approve)
            {
                ApprovalStep         = instance.TaskInstances.Count(x => x.TaskStatus.In(TaskStatus.Approved, TaskStatus.NotRequired)),
                WorkflowInstanceGuid = instance.Guid
            };

            instance.TaskInstances.Add(taskInstance);

            return(taskInstance);
        }
Пример #19
0
        public IHttpActionResult ResubmitWorkflowTask(TaskData model)
        {
            WorkflowInstancePoco instance = _instancesService.GetPopulatedInstance(model.InstanceGuid);
            WorkflowProcess      process  = instance.GetProcess();

            try
            {
                IUser currentUser = _utility.GetCurrentUser();

                instance = process.ResubmitWorkflow(
                    instance,
                    currentUser.Id,
                    model.Comment
                    );

                string typeDescription     = instance.WorkflowType.Description(instance.ScheduledDate);
                string typeDescriptionPast = instance.WorkflowType.DescriptionPastTense(instance.ScheduledDate);

                Log.Info($"{typeDescription} request for {instance.Node.Name} [{instance.NodeId}] was resubmitted by {currentUser.Name}");

                _hubContext.Clients.All.TaskResubmitted(
                    _tasksService.ConvertToWorkflowTaskList(instance.TaskInstances.ToList(), instance: instance));

                return(Json(new
                {
                    message = $"Changes resubmitted successfully. Page will be {typeDescriptionPast.ToLower()} following workflow completion.",
                    status = 200,
                    notifications = NotificationHelpers.MapEventMessagesToNotifications(process.EventMessages)
                }, ViewHelpers.CamelCase));
            }
            catch (UmbracoOperationFailedException e)
            {
                string msg = $"A Publishing failure occurred processing the approval on {instance.Node.Name} [{instance.Node.Id}]";
                Log.Error(msg, e);

                return(Json(new
                {
                    message = msg,
                    status = 200,
                    isUmbracoOperationError = true,
                    notifications = NotificationHelpers.MapEventMessagesToNotifications(process.EventMessages)
                }
                            , ViewHelpers.CamelCase));
            }
            catch (Exception ex)
            {
                string msg = $"An error occurred processing the approval on {instance.Node.Name} [{instance.NodeId}]";
                Log.Error(msg, ex);

                return(Content(HttpStatusCode.InternalServerError, ViewHelpers.ApiException(ex, msg)));
            }
        }
Пример #20
0
        public IHttpActionResult InitiateWorkflow(InitiateWorkflowModel model)
        {
            try
            {
                WorkflowProcess process;

                if (model.Publish)
                {
                    process = new DocumentPublishProcess();
                }
                else
                {
                    process = new DocumentUnpublishProcess();
                }

                WorkflowInstancePoco instance = process.InitiateWorkflow(int.Parse(model.NodeId), _utility.GetCurrentUser().Id, model.Comment);

                string msg = string.Empty;

                switch (instance.WorkflowStatus)
                {
                case WorkflowStatus.PendingApproval:
                    msg = $"Page submitted for {(model.Publish ? "publish" : "unpublish")} approval.";
                    break;

                case WorkflowStatus.Approved:
                    msg = (model.Publish ? "Publish" : "Unpublish") + " workflow complete.";

                    if (instance.ScheduledDate.HasValue)
                    {
                        msg += $" Page scheduled for publishing at {instance.ScheduledDate.Value.ToString("dd MMM YYYY", CultureInfo.CurrentCulture)}";
                    }

                    break;
                }

                Log.Info(msg);

                return(Json(new
                {
                    message = msg,
                    status = 200
                }, ViewHelpers.CamelCase));
            }
            catch (Exception e)
            {
                const string msg = "An error occurred initiating the workflow";
                Log.Error(msg, e);

                return(Content(HttpStatusCode.InternalServerError, ViewHelpers.ApiException(e, msg)));
            }
        }
Пример #21
0
        /// <summary>
        /// Quickly scaffold a set of instances with arbitrary values and no tasks
        /// This method adds the instances to the db
        /// </summary>
        /// <param name="count"></param>
        /// <param name="type"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        public static IEnumerable <WorkflowInstancePoco> Instances(int count, int type = 1, int status = (int)WorkflowStatus.PendingApproval, int?nodeId = null)
        {
            List <WorkflowInstancePoco> response = new List <WorkflowInstancePoco>();

            for (var i = 0; i < count; i++)
            {
                WorkflowInstancePoco instance = Instance(Guid.NewGuid(), type, nodeId ?? Utility.RandomInt(), Utility.RandomInt(), status);

                InstancesService.InsertInstance(instance);
                response.Add(instance);
            }

            return(response);
        }
Пример #22
0
        public string GetNotifications(Guid instanceGuid, int emailType)
        {
            try
            {
                WorkflowInstancePoco instance = _instancesService.GetByGuid(instanceGuid);

                Notifications.Send(instance, (EmailType)emailType);

                return("done - check the mail drop folder");
            }
            catch (Exception e)
            {
                return(ViewHelpers.ApiException(e).ToString());
            }
        }
Пример #23
0
        public string GetNotifications(Guid instanceGuid, int emailType)
        {
            try
            {
                WorkflowInstancePoco instance = _instancesService.GetByGuid(instanceGuid);

                _emailer.Send(instance, (EmailType)emailType);

                return($"Notifications sent for { instance.Id }. Check the mail pickup folder.");
            }
            catch (Exception e)
            {
                return(ViewHelpers.ApiException(e).ToString());
            }
        }
Пример #24
0
        public string GetNotifications(int instanceId, int emailType)
        {
            try
            {
                WorkflowInstancePoco instance = Pr.GetAllInstances().FirstOrDefault(x => x.Id == instanceId);

                Notifications.Send(instance, (EmailType)emailType);

                return("done - check the mail drop folder");
            }
            catch (Exception e)
            {
                return(ViewHelpers.ApiException(e).ToString());
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public WorkflowInstancePoco GetPopulatedInstance(Guid guid)
        {
            WorkflowInstancePoco instance = GetByGuid(guid);

            // TODO -> fix this
            List <WorkflowTaskPoco> tasks = _tasksService.GetTasksWithGroupByInstanceGuid(instance.Guid);

            if (tasks.Any())
            {
                // ordering by descending id to allow for cases with multiple rejections
                // most recent will be highest id
                instance.TaskInstances = tasks.OrderByDescending(t => t.Id).ToList();
            }

            return(instance);
        }
Пример #26
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="instanceGuid"></param>
        /// <returns></returns>
        private static WorkflowInstancePoco GetInstance(Guid instanceGuid)
        {
            WorkflowInstancePoco instance = Pr.InstanceByGuid(instanceGuid);

            instance.SetScheduledDate();

            // TODO -> fix this
            List <WorkflowTaskInstancePoco> tasks = Pr.TasksAndGroupByInstanceId(instance.Guid);

            if (tasks.Any())
            {
                instance.TaskInstances = tasks;
            }

            return(instance);
        }
Пример #27
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="instanceGuid"></param>
        /// <returns></returns>
        private WorkflowInstancePoco GetInstance(Guid instanceGuid)
        {
            WorkflowInstancePoco instance = _instancesService.GetByGuid(instanceGuid);

            instance.SetScheduledDate();

            // TODO -> fix this
            List <WorkflowTaskInstancePoco> tasks = _tasksService.GetTasksWithGroupByInstanceGuid(instance.Guid);

            if (tasks.Any())
            {
                instance.TaskInstances = tasks;
            }

            return(instance);
        }
Пример #28
0
        public void Can_Update_Instance()
        {
            Guid         guid    = Guid.NewGuid();
            const string comment = "This here is an update";

            _service.InsertInstance(Scaffold.Instance(guid, 1));

            WorkflowInstancePoco instance = _service.GetByGuid(guid);

            instance.AuthorComment = comment;

            _service.UpdateInstance(instance);
            WorkflowInstancePoco updatedInstance = _service.GetByGuid(guid);

            Assert.Equal(comment, updatedInstance.AuthorComment);
        }
Пример #29
0
        public string GetNotifications(Guid instanceGuid, int emailType)
        {
            try
            {
                WorkflowInstancePoco instance = _instancesService.GetByGuid(instanceGuid);

                var node = _utility.GetPublishedContent(1078);

                _notifications.Send(instance, (EmailType)emailType);

                return(node.Name);
            }
            catch (Exception e)
            {
                return(ViewHelpers.ApiException(e).ToString());
            }
        }
Пример #30
0
        /// <summary>
        /// Builds workflow instance details markup.
        /// </summary>
        /// <returns>HTML tr inner html definition</returns>
        public static string BuildProcessSummary(this WorkflowInstancePoco instance)
        {
            string result = $"{instance.WorkflowType.Description(instance.ScheduledDate)} requested by {instance.AuthorUser.Name} on {instance.CreatedDate:dd/MM/yy} - {instance.StatusName}<br/>";

            if (instance.AuthorComment.HasValue())
            {
                result += $"&nbsp;&nbsp;Comment: <i>{instance.AuthorComment}</i>";
            }
            result += "<br/>";

            foreach (WorkflowTaskPoco taskInstance in instance.TaskInstances.OrderBy(t => t.ApprovalStep))
            {
                result += taskInstance.BuildTaskSummary() + "<br/>";
            }

            return($"{result}<br/>");
        }