public async Task <DMCRoutingStatusProcessorResult> UpdateStatusAsync(dmc.Criteria.SetRequestStatusData data)
        {
            PermissionDefinition permission = data.Status == dmc.Enums.DMCRoutingStatus.Hold ? PermissionIdentifiers.DataMartInProject.HoldRequest : (data.Status == dmc.Enums.DMCRoutingStatus.RequestRejected ? PermissionIdentifiers.DataMartInProject.RejectRequest : PermissionIdentifiers.DataMartInProject.UploadResults);

            bool hasPermission = await CheckPermission(data.RequestID, data.DataMartID, permission, Identity.ID);

            if (hasPermission == false)
            {
                string message = data.Status == dmc.Enums.DMCRoutingStatus.Hold ? "You do not have permission to change the status of this request to Hold" :
                                 (data.Status == dmc.Enums.DMCRoutingStatus.RequestRejected ? "You do not have permission to change the status of this request to Rejected" : "You do not have permission to upload results.");

                return(new DMCRoutingStatusProcessorResult(HttpStatusCode.Forbidden, message));
            }

            //var currentResponse = await DataContext.Responses.Include(rsp => rsp.RequestDataMart).Where(rsp => rsp.RequestDataMart.RequestID == data.RequestID && rsp.RequestDataMart.DataMartID == data.DataMartID && rsp.Count == rsp.RequestDataMart.Responses.Select(x => x.Count).Max()).FirstOrDefaultAsync();
            var details = await(
                from rsp in DataContext.Responses
                join rdm in DataContext.RequestDataMarts on rsp.RequestDataMartID equals rdm.ID
                join r in DataContext.Requests on rdm.RequestID equals r.ID
                where rdm.RequestID == data.RequestID && rdm.DataMartID == data.DataMartID &&
                rsp.Count == rdm.Responses.Select(x => x.Count).Max()
                select new
            {
                Response = rsp,
                Routing  = rdm,
                Request  = r
            }
                ).FirstOrDefaultAsync();


            if (details == null)
            {
                return(new DMCRoutingStatusProcessorResult(HttpStatusCode.NotFound, "Unable to determine the routing information based on the specified RequestID and DataMart ID."));
            }

            var currentResponse = details.Response;
            var routing         = details.Routing;
            var request         = details.Request;

            var orginalRequestStatus = request.Status;
            var originalStatus       = routing.Status;

            hasPermission = await CheckPermission(data.RequestID, data.DataMartID, PermissionIdentifiers.DataMartInProject.SkipResponseApproval, request.CreatedByID);

            if (originalStatus == DTO.Enums.RoutingStatus.Hold && data.Status == dmc.Enums.DMCRoutingStatus.Submitted && currentResponse.Count > 1)
            {
                routing.Status = DTO.Enums.RoutingStatus.Resubmitted;
            }
            else if (originalStatus == DTO.Enums.RoutingStatus.Completed || originalStatus == DTO.Enums.RoutingStatus.ResultsModified)
            {
                routing.Status = hasPermission ? DTO.Enums.RoutingStatus.ResultsModified : DTO.Enums.RoutingStatus.AwaitingResponseApproval;
            }
            else
            {
                routing.Status = (Lpp.Dns.DTO.Enums.RoutingStatus)((int)data.Status);

                if (routing.Status == DTO.Enums.RoutingStatus.AwaitingResponseApproval)
                {
                    if (hasPermission)
                    {
                        routing.Status = DTO.Enums.RoutingStatus.Completed;
                    }
                }
            }

            //updating the UpdatedOn property of the routing so that logs will get processed and will allow for status change notification to go out if further uploads are done while status is ResultsModified.
            routing.UpdatedOn  = DateTime.UtcNow;
            routing.Properties = data.Properties == null ? null :
                                 "<P>" + string.Join("",
                                                     from p in data.Properties
                                                     where !string.IsNullOrEmpty(p.Name)
                                                     select string.Format("<V Key=\"{0}\">{1}</V>", p.Name, p.Value)) +
                                 "</P>";

            currentResponse.ResponseMessage = data.Message;

            //only set the response time and ID if the response is completed
            var completeStatuses = new[] {
                Lpp.Dns.DTO.Enums.RoutingStatus.Completed,
                Lpp.Dns.DTO.Enums.RoutingStatus.ResultsModified,
                Lpp.Dns.DTO.Enums.RoutingStatus.RequestRejected,
                Lpp.Dns.DTO.Enums.RoutingStatus.ResponseRejectedBeforeUpload,
                Lpp.Dns.DTO.Enums.RoutingStatus.ResponseRejectedAfterUpload,
                Lpp.Dns.DTO.Enums.RoutingStatus.AwaitingResponseApproval,
                Lpp.Dns.DTO.Enums.RoutingStatus.Hold
            };

            bool routingIsComplete = completeStatuses.Contains(routing.Status);

            if (routingIsComplete)
            {
                currentResponse.ResponseTime  = DateTime.UtcNow;
                currentResponse.RespondedByID = Identity.ID;
            }

            if ((routing.Status == DTO.Enums.RoutingStatus.Completed || routing.Status == DTO.Enums.RoutingStatus.ResultsModified) && routing.Request.WorkflowID.HasValue)
            {
                try
                {
                    var trackingTableProcessor = new DistributedRegressionTrackingTableProcessor(DataContext);
                    await trackingTableProcessor.Process(currentResponse);
                }
                catch (Exception ex)
                {
                    //should not block if fails
                    Logger.Error(string.Format("Error processing tracking table for response ID: {0}\r\n{1}", currentResponse.ID, Lpp.Utilities.ExceptionHelpers.UnwindException(ex, true)), ex.InnerException ?? ex);
                }
            }

            await DataContext.SaveChangesAsync();

            await DataContext.Entry(request).ReloadAsync();

            if (!data.Message.IsEmpty())
            {
                var log = await DataContext.LogsRoutingStatusChange.OrderByDescending(x => x.TimeStamp).FirstOrDefaultAsync(x => x.ResponseID == currentResponse.ID);

                log.Description += $" {data.Message}";


                await DataContext.SaveChangesAsync();
            }

            if (request.WorkflowID.HasValue && request.WorkflowID.Value == VerticalDistributedRegressionWorkflowID && (routing.Status == DTO.Enums.RoutingStatus.Completed || routing.Status == DTO.Enums.RoutingStatus.ResultsModified))
            {
                try
                {
                    await DataContext.Entry(routing).Reference(r => r.Request).LoadAsync();

                    var routingProcessor = new VerticalDistributedRegressionRoutingProcessor(DataContext, Identity.ID);
                    await routingProcessor.Process(routing);
                }
                catch (Exception ex)
                {
                    Logger.Error(string.Format("Error processing distributed regression route transistion for request ID: {0}\r\n{1}", routing.RequestID, Lpp.Utilities.ExceptionHelpers.UnwindException(ex, true)), ex.InnerException ?? ex);
                    throw;
                }
            }
            else if (routingIsComplete && request.Status == DTO.Enums.RequestStatuses.Complete && request.WorkflowID.HasValue)
            {
                if (request.WorkflowID.Value == HorizontalDistributedRegressionWorkflowID && (routing.Status == DTO.Enums.RoutingStatus.Completed || routing.Status == DTO.Enums.RoutingStatus.ResultsModified))
                {
                    try
                    {
                        await DataContext.Entry(routing).Reference(r => r.Request).LoadAsync();

                        var routingProcessor = new DistributedRegressionRoutingProcessor(DataContext, Identity.ID);
                        await routingProcessor.Process(routing);
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(string.Format("Error processing distributed regression route transistion for request ID: {0}\r\n{1}", routing.RequestID, Lpp.Utilities.ExceptionHelpers.UnwindException(ex, true)), ex.InnerException ?? ex);
                        throw;
                    }
                }

                //reload the request to get the current request status.
                await DataContext.Entry(request).ReloadAsync();

                if (request.Status == DTO.Enums.RequestStatuses.Complete)
                {
                    //send the request status complete notification
                    var      requestStatusLogger = new Dns.Data.RequestLogConfiguration();
                    string[] emailText           = await requestStatusLogger.GenerateRequestStatusChangedEmailContent(DataContext, request.ID, Identity.ID, orginalRequestStatus, request.Status);

                    var logItems = requestStatusLogger.GenerateRequestStatusEvents(DataContext, Identity, false, orginalRequestStatus, request.Status, request.ID, emailText[1], emailText[0], "Request Status Changed");

                    await DataContext.SaveChangesAsync();

                    await Task.Run(() =>
                    {
                        List <Utilities.Logging.Notification> notifications = new List <Utilities.Logging.Notification>();

                        foreach (Lpp.Dns.Data.Audit.RequestStatusChangedLog logitem in logItems)
                        {
                            var items = requestStatusLogger.CreateNotifications(logitem, DataContext, true);
                            if (items != null && items.Any())
                            {
                                notifications.AddRange(items);
                            }
                        }

                        if (notifications.Any())
                        {
                            requestStatusLogger.SendNotification(notifications);
                        }
                    });
                }
            }

            return(new DMCRoutingStatusProcessorResult());
        }
Exemple #2
0
        /// <summary>
        /// The Method to do what the User decieded
        /// </summary>
        /// <param name="data">The Data payload passed by the User</param>
        /// <param name="activityResultID">The Result ID Passed by the User to indicate which step to proceed to.</param>
        /// <returns></returns>
        public override async Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            if (!activityResultID.HasValue)
            {
                activityResultID = SaveResultID;
            }

            var task = PmnTask.GetActiveTaskForRequestActivity(_entity.ID, ID, db);

            if (activityResultID == SaveResultID)
            {
                await task.LogAsModifiedAsync(_workflow.Identity, db);

                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }
            else if (activityResultID == BulkEditResultID)
            {
                await task.LogAsModifiedAsync(_workflow.Identity, db);

                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = BulkEditResultID
                });
            }
            else if (activityResultID == RemoveDatamartsResultID)
            {
                Guid[] guids    = data.Split(',').Select(s => Guid.Parse(s)).ToArray();
                var    routings = await db.RequestDataMarts.Where(dm => guids.Contains(dm.ID)).ToArrayAsync();

                foreach (var routing in routings)
                {
                    routing.Status = DTO.Enums.RoutingStatus.Canceled;
                }

                await task.LogAsModifiedAsync(_workflow.Identity, db);

                await db.SaveChangesAsync();

                var originalStatus = _entity.Status;
                await db.SaveChangesAsync();

                await db.Entry(_entity).ReloadAsync();

                if (originalStatus != DTO.Enums.RequestStatuses.Complete && _entity.Status == DTO.Enums.RequestStatuses.Complete)
                {
                    await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Complete);
                }

                return(new CompletionResult
                {
                    ResultID = RemoveDatamartsResultID
                });
            }
            else if (activityResultID == CompleteRoutingResultID)
            {
                var uiResponse = Newtonsoft.Json.JsonConvert.DeserializeObject <WebResponseModel>(data);

                var routing = await db.RequestDataMarts.Include("Request").SingleOrDefaultAsync(dm => dm.ID == uiResponse.RequestDM && dm.RequestID == _entity.ID);

                var response = await db.Responses.SingleOrDefaultAsync(res => res.ID == uiResponse.Response && res.RequestDataMartID == uiResponse.RequestDM);

                response.ResponseTime    = DateTime.UtcNow;
                response.RespondedByID   = _workflow.Identity.ID;
                response.ResponseMessage = uiResponse.Comment;
                var originalRequestStatus = routing.Request.Status;
                var originalStatus        = routing.Status;


                //We should only update the routing status if it is not already complete or modified.
                if (originalStatus != DTO.Enums.RoutingStatus.Completed && originalStatus != DTO.Enums.RoutingStatus.ResultsModified)
                {
                    routing.Status = DTO.Enums.RoutingStatus.Completed;
                }

                if (routing.Status == DTO.Enums.RoutingStatus.Completed || routing.Status == DTO.Enums.RoutingStatus.ResultsModified)
                {
                    try
                    {
                        var trackingTableProcessor = new DistributedRegressionTrackingTableProcessor(db);
                        await trackingTableProcessor.Process(response);
                    }
                    catch (Exception ex)
                    {
                        //should not block if fails
                    }
                }

                await db.SaveChangesAsync();

                await db.Entry <RequestDataMart>(routing).ReloadAsync();

                await db.Entry <Request>(_entity).ReloadAsync();

                var completeStatuses = new[] {
                    Lpp.Dns.DTO.Enums.RoutingStatus.Completed,
                    Lpp.Dns.DTO.Enums.RoutingStatus.ResultsModified,
                    Lpp.Dns.DTO.Enums.RoutingStatus.RequestRejected,
                    Lpp.Dns.DTO.Enums.RoutingStatus.ResponseRejectedBeforeUpload,
                    Lpp.Dns.DTO.Enums.RoutingStatus.ResponseRejectedAfterUpload,
                    Lpp.Dns.DTO.Enums.RoutingStatus.AwaitingResponseApproval
                };



                var incompletedRoutings = await db.RequestDataMarts.Where(dm => dm.RequestID == _entity.ID &&
                                                                          dm.RoutingType != DTO.Enums.RoutingType.AnalysisCenter &&
                                                                          !completeStatuses.Contains(dm.Status)).CountAsync();

                if (incompletedRoutings == 0)
                {
                    try
                    {
                        var routingProcessor = new DistributedRegressionRoutingProcessor(db, _workflow.Identity.ID);
                        await routingProcessor.Process(routing);

                        return(new CompletionResult
                        {
                            ResultID = CompleteRoutingResultToAC
                        });
                    }
                    catch (Exception ex)
                    {
                        throw;
                    }
                }
                else
                {
                    await task.LogAsModifiedAsync(_workflow.Identity, db);

                    await db.SaveChangesAsync();

                    return(new CompletionResult
                    {
                        ResultID = CompleteRoutingResultID
                    });
                }
            }
            else if (activityResultID == TerminateResultID)
            {
                db.Requests.Remove(_entity);

                if (task != null)
                {
                    db.Actions.Remove(task);
                }

                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = TerminateResultID
                });
            }
            else
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }
        }
        /// <summary>
        /// The Method to do what the User decieded
        /// </summary>
        /// <param name="data">The Data payload passed by the User</param>
        /// <param name="activityResultID">The Result ID Passed by the User to indicate which step to proceed to.</param>
        /// <returns></returns>
        public override async Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            if (!activityResultID.HasValue)
            {
                activityResultID = SaveResultID;
            }

            var task = PmnTask.GetActiveTaskForRequestActivity(_entity.ID, ID, db);

            if (activityResultID == SaveResultID)
            {
                await task.LogAsModifiedAsync(_workflow.Identity, db);

                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }
            else if (activityResultID == RedistributeResultID)
            {
                if (!await db.HasPermissions <Project>(_workflow.Identity, _entity.ProjectID, Lpp.Dns.DTO.Security.PermissionIdentifiers.Project.ResubmitRequests))
                {
                    throw new System.Security.SecurityException(CommonMessages.RequirePermissionToResubmitRequest, Lpp.Dns.DTO.Security.PermissionIdentifiers.Project.ResubmitRequests.GetType());
                }

                ResubmitRoutingsModel resubmitModel = Newtonsoft.Json.JsonConvert.DeserializeObject <ResubmitRoutingsModel>(data);

                var datamarts = await(
                    from dm in db.RequestDataMarts.Include(dm => dm.Responses)
                    where dm.RequestID == _entity.ID &&
                    dm.Responses.Any(r => resubmitModel.Responses.Contains(r.ID) || (r.ResponseGroupID.HasValue && resubmitModel.Responses.Contains(r.ResponseGroupID.Value)))
                    select dm
                    ).ToArrayAsync();


                //for the last completed routing from the AC
                //look for the file_list.csv document, if does not exist use all files
                //if file_list.csv exists, only use the documents it specifies

                List <Guid> documentRevisionSetIDs = new List <Guid>();

                var previousInputRequestDocuments = await(from d in db.Documents.AsNoTracking()
                                                          join reqDoc in (from rd in db.RequestDocuments
                                                                          where rd.DocumentType == DTO.Enums.RequestDocumentType.Output &&
                                                                          rd.Response.RequestDataMart.RoutingType == DTO.Enums.RoutingType.AnalysisCenter &&
                                                                          rd.Response.Count == rd.Response.RequestDataMart.Responses.Where(rsp => rsp.RespondedByID.HasValue).Max(rsp => rsp.Count) &&
                                                                          rd.Response.RequestDataMart.RequestID == _entity.ID
                                                                          select rd) on d.RevisionSetID equals reqDoc.RevisionSetID
                                                          where d.ID == db.Documents.Where(dd => dd.RevisionSetID == d.RevisionSetID).OrderByDescending(dd => dd.MajorVersion).ThenByDescending(dd => dd.MinorVersion).ThenByDescending(dd => dd.BuildVersion).ThenByDescending(dd => dd.RevisionVersion).Select(dd => dd.ID).FirstOrDefault()
                                                          select d).ToArrayAsync();

                // look for the first document with kind == "DistributedRegression.FileList".
                Document fileListDocument = previousInputRequestDocuments.Where(d => !string.IsNullOrEmpty(d.Kind) && string.Equals("DistributedRegression.FileList", d.Kind, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                if (fileListDocument != null)
                {
                    //only include the files indicated in the manifest
                    byte[] fileListBytes = fileListDocument.GetData(db);
                    using (var ms = new System.IO.MemoryStream(fileListBytes))
                        using (var reader = new System.IO.StreamReader(ms))
                        {
                            //read the header line
                            reader.ReadLine();

                            string line, filename;
                            bool   includeInDistribution = false;
                            while (!reader.EndOfStream)
                            {
                                line = reader.ReadLine();
                                string[] split = line.Split(',');
                                if (split.Length > 0)
                                {
                                    filename = split[0].Trim();
                                    if (split.Length > 1)
                                    {
                                        includeInDistribution = string.Equals(split[1].Trim(), "1");
                                    }
                                    else
                                    {
                                        includeInDistribution = false;
                                    }

                                    if (includeInDistribution == false)
                                    {
                                        continue;
                                    }

                                    if (!string.IsNullOrEmpty(filename))
                                    {
                                        Guid?revisionSetID = previousInputRequestDocuments.Where(d => string.Equals(d.FileName, filename, StringComparison.OrdinalIgnoreCase)).Select(d => d.RevisionSetID).FirstOrDefault();
                                        if (revisionSetID.HasValue)
                                        {
                                            documentRevisionSetIDs.Add(revisionSetID.Value);
                                        }
                                    }
                                }
                            }

                            reader.Close();
                        }
                }
                else
                {
                    //include all documents
                    documentRevisionSetIDs.AddRange(previousInputRequestDocuments.Select(d => d.RevisionSetID.Value).Distinct());
                }


                DateTime reSubmittedOn = DateTime.UtcNow;
                foreach (var dm in datamarts)
                {
                    var response = dm.AddResponse(_workflow.Identity.ID);
                    response.SubmittedOn   = reSubmittedOn;
                    response.SubmitMessage = resubmitModel.ResubmissionMessage;

                    dm.Status = DTO.Enums.RoutingStatus.Resubmitted;

                    foreach (var revisionSetID in documentRevisionSetIDs)
                    {
                        db.RequestDocuments.Add(new RequestDocument {
                            ResponseID = response.ID, RevisionSetID = revisionSetID, DocumentType = DTO.Enums.RequestDocumentType.Input
                        });
                    }
                }

                await SetRequestStatus(DTO.Enums.RequestStatuses.Submitted);

                await task.LogAsModifiedAsync(_workflow.Identity, db);

                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = RedistributeResultID
                });
            }
            else if (activityResultID == BulkEditResultID)
            {
                await task.LogAsModifiedAsync(_workflow.Identity, db);

                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = BulkEditResultID
                });
            }
            else if (activityResultID == AddDatamartsResultID)
            {
                DTO.QueryComposer.QueryComposerRequestDTO requestDTO = Newtonsoft.Json.JsonConvert.DeserializeObject <DTO.QueryComposer.QueryComposerRequestDTO>(_entity.Query);
                var modularTerm = requestDTO.Where.Criteria.SelectMany(c => c.Terms.Where(t => t.Type == DistributedRegressionConfiguration.ModularProgramTermID)).FirstOrDefault();
                var termValues  = Newtonsoft.Json.JsonConvert.DeserializeObject <ModularProgramTermValues>(modularTerm.Values["Values"].ToString());

                string[] datamartIDs = data.Split(',');

                var allTasks = await db.ActionReferences.Where(tr => tr.ItemID == _entity.ID &&
                                                               tr.Type == DTO.Enums.TaskItemTypes.Request &&
                                                               tr.Task.Type == DTO.Enums.TaskTypes.Task
                                                               )
                               .Select(tr => tr.Task.ID).ToArrayAsync();

                var attachments = await(from doc in db.Documents.AsNoTracking()
                                        join x in (
                                            db.Documents.Where(dd => allTasks.Contains(dd.ItemID))
                                            .GroupBy(k => k.RevisionSetID)
                                            .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault())
                                            ) on doc.ID equals x
                                        where allTasks.Contains(doc.ItemID) && doc.Kind == "Attachment.Input"
                                        orderby doc.ItemID descending, doc.RevisionSetID descending, doc.CreatedOn descending
                                        select doc).ToArrayAsync();

                foreach (var guid in datamartIDs)
                {
                    Guid dmGuid = new Guid(guid);

                    var dm = RequestDataMart.Create(_entity.ID, dmGuid, _workflow.Identity.ID);
                    dm.Status      = DTO.Enums.RoutingStatus.Submitted;
                    dm.DueDate     = _entity.DueDate;
                    dm.Priority    = _entity.Priority;
                    dm.RoutingType = DTO.Enums.RoutingType.DataPartner;
                    _entity.DataMarts.Add(dm);

                    Response rsp = dm.Responses.OrderByDescending(r => r.Count).FirstOrDefault();
                    //add the request document associations
                    foreach (var revisionSetID in termValues.Documents.Select(d => d.RevisionSetID))
                    {
                        db.RequestDocuments.Add(new RequestDocument {
                            DocumentType = DTO.Enums.RequestDocumentType.Input, ResponseID = rsp.ID, RevisionSetID = revisionSetID
                        });
                    }

                    foreach (var attachment in attachments)
                    {
                        db.RequestDocuments.Add(new RequestDocument {
                            RevisionSetID = attachment.RevisionSetID.Value, ResponseID = rsp.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput
                        });
                    }
                }

                await task.LogAsModifiedAsync(_workflow.Identity, db);

                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = AddDatamartsResultID
                });
            }
            else if (activityResultID == RemoveDatamartsResultID)
            {
                Guid[] guids    = data.Split(',').Select(s => Guid.Parse(s)).ToArray();
                var    routings = await db.RequestDataMarts.Where(dm => guids.Contains(dm.ID)).ToArrayAsync();

                foreach (var routing in routings)
                {
                    routing.Status = DTO.Enums.RoutingStatus.Canceled;
                }

                await task.LogAsModifiedAsync(_workflow.Identity, db);

                await db.SaveChangesAsync();

                var originalStatus = _entity.Status;
                await db.SaveChangesAsync();

                await db.Entry(_entity).ReloadAsync();

                if (originalStatus != DTO.Enums.RequestStatuses.Complete && _entity.Status == DTO.Enums.RequestStatuses.Complete)
                {
                    await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Complete);
                }

                return(new CompletionResult
                {
                    ResultID = RemoveDatamartsResultID
                });
            }
            else if (activityResultID == CompleteRoutingResultID)
            {
                var uiResponse = Newtonsoft.Json.JsonConvert.DeserializeObject <WebResponseModel>(data);

                var routing = await db.RequestDataMarts.Include("Request").SingleOrDefaultAsync(dm => dm.ID == uiResponse.RequestDM && dm.RequestID == _entity.ID);

                var response = await db.Responses.SingleOrDefaultAsync(res => res.ID == uiResponse.Response && res.RequestDataMartID == uiResponse.RequestDM);

                response.ResponseTime    = DateTime.UtcNow;
                response.RespondedByID   = _workflow.Identity.ID;
                response.ResponseMessage = uiResponse.Comment;
                var originalRequestStatus = routing.Request.Status;
                var originalStatus        = routing.Status;


                //We should only update the routing status if it is not already complete or modified.
                if (originalStatus != DTO.Enums.RoutingStatus.Completed && originalStatus != DTO.Enums.RoutingStatus.ResultsModified)
                {
                    routing.Status = DTO.Enums.RoutingStatus.Completed;
                }

                if (routing.Status == DTO.Enums.RoutingStatus.Completed || routing.Status == DTO.Enums.RoutingStatus.ResultsModified)
                {
                    try
                    {
                        var trackingTableProcessor = new DistributedRegressionTrackingTableProcessor(db);
                        await trackingTableProcessor.Process(response);
                    }
                    catch (Exception ex)
                    {
                        //should not block if fails
                    }
                }

                await db.SaveChangesAsync();

                await db.Entry <RequestDataMart>(routing).ReloadAsync();

                await db.Entry <Request>(_entity).ReloadAsync();

                var completeStatuses = new[] {
                    Lpp.Dns.DTO.Enums.RoutingStatus.Completed,
                    Lpp.Dns.DTO.Enums.RoutingStatus.ResultsModified,
                    Lpp.Dns.DTO.Enums.RoutingStatus.RequestRejected,
                    Lpp.Dns.DTO.Enums.RoutingStatus.ResponseRejectedBeforeUpload,
                    Lpp.Dns.DTO.Enums.RoutingStatus.ResponseRejectedAfterUpload,
                    Lpp.Dns.DTO.Enums.RoutingStatus.AwaitingResponseApproval
                };



                var incompletedRoutings = await db.RequestDataMarts.Where(dm => dm.RequestID == _entity.ID &&
                                                                          dm.RoutingType != DTO.Enums.RoutingType.AnalysisCenter &&
                                                                          !completeStatuses.Contains(dm.Status)).CountAsync();

                if (incompletedRoutings == 0)
                {
                    try
                    {
                        var routingProcessor = new DistributedRegressionRoutingProcessor(db, _workflow.Identity.ID);
                        await routingProcessor.Process(routing);

                        return(new CompletionResult
                        {
                            ResultID = CompleteRoutingResultToAC
                        });
                    }
                    catch (Exception ex)
                    {
                        throw;
                    }
                }
                else
                {
                    await task.LogAsModifiedAsync(_workflow.Identity, db);

                    await db.SaveChangesAsync();

                    return(new CompletionResult
                    {
                        ResultID = CompleteRoutingResultID
                    });
                }
            }
            else if (activityResultID == TerminateResultID)
            {
                db.Requests.Remove(_entity);

                if (task != null)
                {
                    db.Actions.Remove(task);
                }

                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = TerminateResultID
                });
            }
            else
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }
        }