Beispiel #1
0
        /// <summary>
        /// Performs tasks associated to the start of the activity. By default confirms that an active PmnTask has been created for the current activity, and also records any comment entered when leaving the previous activity.
        /// </summary>
        /// <param name="comment"></param>
        /// <returns></returns>
        public virtual async Task Start(string comment)
        {
            var task = await PmnTask.GetActiveTaskForRequestActivityAsync(_entity.ID, ID, db);

            if (task == null)
            {
                task = db.Actions.Add(PmnTask.CreateForWorkflowActivity(_entity.ID, ID, _workflow.ID, db, CustomTaskSubject));
                await db.SaveChangesAsync();
            }

            if (!string.IsNullOrWhiteSpace(comment))
            {
                var cmt = db.Comments.Add(new Comment
                {
                    CreatedByID = _workflow.Identity.ID,
                    ItemID      = _entity.ID,
                    Text        = comment
                });

                db.CommentReferences.Add(new CommentReference
                {
                    CommentID = cmt.ID,
                    Type      = DTO.Enums.CommentItemTypes.Task,
                    ItemTitle = task.Subject,
                    ItemID    = task.ID
                });

                await db.SaveChangesAsync();
            }
        }
Beispiel #2
0
        public override async Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            if (!activityResultID.HasValue)
            {
                activityResultID = SaveResultID;
            }

            if (activityResultID == SaveResultID)
            {
                var task = PmnTask.GetActiveTaskForRequestActivity(_entity.ID, ID, db);
                if (task != null)
                {
                    await task.LogAsModifiedAsync(_workflow.Identity, db);

                    await db.SaveChangesAsync();
                }

                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }
            else
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }
        }
        public override async Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            //Handle what happens in each of the completions.
            if (!activityResultID.HasValue)
            {
                throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired);
            }

            if (activityResultID.Value != CompleteResultID &&
                activityResultID.Value != RedistributeResultID &&
                activityResultID.Value != SubmitReportResultID &&
                activityResultID.Value != SaveResultID && activityResultID != CompleteWorkflowResultID)
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }

            if (activityResultID.Value == SaveResultID)
            {
                //save, no change to current activity for the request
                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }

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

            if (activityResultID.Value == CompleteWorkflowResultID)
            {
                await SetRequestStatus(DTO.Enums.RequestStatuses.Complete);

                await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Complete);
            }
            else if (activityResultID.Value == RedistributeResultID)
            {
                //re-submits the requests and goes back to the distribute step
                //TODO: should this be resubmitting all the routes, or add as pending, or do nothing and just redirect back to view status and results?

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

                await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Resubmitted);
            }
            else if (activityResultID.Value == SubmitReportResultID)
            {
                //move to draft report review

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

                await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.DraftReportPendingApproval);
            }

            await MarkTaskComplete(task);

            return(new CompletionResult
            {
                ResultID = activityResultID.Value
            });
        }
Beispiel #4
0
        /// <summary>
        /// Marks the specified task as complete and saves.
        /// </summary>
        /// <param name="task"></param>
        /// <returns></returns>
        protected async Task MarkTaskComplete(PmnTask task)
        {
            task.Status          = DTO.Enums.TaskStatuses.Complete;
            task.EndOn           = DateTime.UtcNow;
            task.PercentComplete = 100d;

            await db.SaveChangesAsync();
        }
Beispiel #5
0
        /// <summary>
        /// Marks the current activity's task as modified.
        /// </summary>
        /// <param name="optionalMessage"></param>
        /// <returns></returns>
        protected async Task LogTaskModified(string optionalMessage = null)
        {
            var task = await PmnTask.GetActiveTaskForRequestActivityAsync(_entity.ID, ID, db);

            if (task == null)
            {
                task = db.Actions.Add(PmnTask.CreateForWorkflowActivity(_entity.ID, ID, _workflow.ID, db));
                return;
            }

            await task.LogAsModifiedAsync(_workflow.Identity, db, optionalMessage);
        }
Beispiel #6
0
        public override async Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            if (activityResultID == null)
            {
                throw new NotSupportedException(CommonMessages.ActivityResultIDRequired);
            }

            if (activityResultID.Value == SaveResultID) //Save Metadata
            {
                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }

            var responseData = JsonConvert.DeserializeObject <ApproveRejectResponseDTO>(data);

            if (activityResultID.Value == ApproveResultID) //Approve
            {
                var Response = await db.Responses.FindAsync(responseData.ResponseID);

                Response.RequestDataMart.Status = DTO.Enums.RoutingStatus.Completed;

                if (await(from rdm in db.RequestDataMarts where rdm.RequestID == _entity.ID select rdm).AllAsync(rdm => rdm.Status == DTO.Enums.RoutingStatus.Completed))
                {
                    _entity.Status = DTO.Enums.RequestStatuses.Complete;
                }
            }
            else if (activityResultID.Value == RejectID) //Reject
            {
                var Response = await db.Responses.FindAsync(responseData.ResponseID);
            }
            else
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }

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

            if (task != null)
            {
                task.Status = DTO.Enums.TaskStatuses.Complete;
                task.EndOn  = DateTime.UtcNow;
            }

            await db.SaveChangesAsync();

            return(new CompletionResult
            {
                ResultID = activityResultID.Value
            });
        }
Beispiel #7
0
        public override async Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            if (!activityResultID.HasValue)
            {
                throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired);
            }

            if (activityResultID.Value != ApproveResultID &&
                activityResultID.Value != RejectResultID &&
                activityResultID.Value != SaveResultID)
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }

            if (activityResultID.Value == SaveResultID)
            {
                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }

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

            if (activityResultID.Value == ApproveResultID) //Edit here
            {
                await SetRequestStatus(DTO.Enums.RequestStatuses.CompleteWithReport);

                await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.CompleteWithReport);

                return(new CompletionResult
                {
                    ResultID = activityResultID.Value
                });
            }
            else
            {
                await SetRequestStatus(DTO.Enums.RequestStatuses.PendingFinalReport);

                await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.PendingFinalReport);
            }


            await MarkTaskComplete(task);

            return((activityResultID.Value == ApproveResultID) ? null : new CompletionResult {
                ResultID = activityResultID.Value
            });
        }
Beispiel #8
0
        public async Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            if (!activityResultID.HasValue)
            {
                throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired);
            }

            var task = await PmnTask.GetActiveTaskForRequestActivityAsync(Request.ID, ID, db);

            if (activityResultID.Value == SaveResultID ||
                activityResultID.Value == SubmitResultID)
            {
                if (activityResultID.Value == SubmitResultID)
                {
                    task.Status = DTO.Enums.TaskStatuses.Complete;
                    task.EndOn  = DateTime.UtcNow;
                }
                else
                {
                    await task.LogAsModifiedAsync(Workflow.Identity, db);
                }

                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = activityResultID.Value
                });
            }
            else if (activityResultID.Value == DeleteResultID)
            {
                Request.CancelledByID = Workflow.Identity.ID;
                Request.CancelledOn   = DateTime.UtcNow;

                task.Status = DTO.Enums.TaskStatuses.Cancelled;
                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = DeleteResultID
                });
            }
            else
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }
        }
Beispiel #9
0
        public override async Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            if (!activityResultID.HasValue)
            {
                throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired);
            }

            var task = await PmnTask.GetActiveTaskForRequestActivityAsync(_workflow.Entity.ID, ID, db);

            if (task == null)
            {
                task = db.Actions.Add(PmnTask.CreateForWorkflowActivity(_workflow.Entity.ID, ID, _workflow.ID, db));
            }

            if (activityResultID.Value == SaveResultID)
            {
                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }

            if (activityResultID.Value == EditRoutingStatusResultID)
            {
                var dataMarts = Newtonsoft.Json.JsonConvert.DeserializeObject <IEnumerable <RoutingChangeRequestModel> >(data);
                await UpdateDataMartRoutingStatus(dataMarts);

                return(new CompletionResult
                {
                    ResultID = EditRoutingStatusResultID
                });
            }
            else if (activityResultID.Value == RoutingsBulkEditID)
            {
                return(new CompletionResult
                {
                    ResultID = RoutingsBulkEditID
                });
            }
            else if (activityResultID.Value == 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 LogTaskModified();

                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);
                }
            }
            else if (activityResultID.Value == 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 == SimpleModularProgramWorkflowConfiguration.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;
                    _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 LogTaskModified();

                await db.SaveChangesAsync();
            }
            //Grouping
            if (activityResultID.Value == GroupResultID)
            {
                GroupingRequestModel model = Newtonsoft.Json.JsonConvert.DeserializeObject <GroupingRequestModel>(data);

                var responses = await db.Responses.Include(r => r.RequestDataMart).Where(r => model.Responses.Any(x => x == r.ID)).ToArrayAsync();

                if (responses.Select(r => r.RequestDataMart.RequestID).Distinct().Count() > 1)
                {
                    throw new ArgumentException("Cannot group responses that come from different requests.");
                }

                Guid[] requestDataMartIDs = responses.Select(rsp => rsp.RequestDataMartID).Distinct().ToArray();
                var    pq = (from rdm in db.RequestDataMarts
                             let permissionID = PermissionIdentifiers.DataMartInProject.GroupResponses.ID
                                                let identityID = _workflow.Identity.ID
                                                                 let acls = db.GlobalAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID)).Select(a => a.Allowed)
                                                                            .Concat(db.ProjectAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Project.Requests.Any(r => r.ID == rdm.RequestID)).Select(a => a.Allowed))
                                                                            .Concat(db.DataMartAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.DataMartID == rdm.DataMartID).Select(a => a.Allowed))
                                                                            .Concat(db.ProjectDataMartAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Project.Requests.Any(r => r.ID == rdm.RequestID) && a.DataMartID == rdm.DataMartID).Select(a => a.Allowed))
                                                                            .Concat(db.OrganizationAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Organization.Requests.Any(r => r.ID == rdm.RequestID)).Select(a => a.Allowed))
                                                                            where requestDataMartIDs.Contains(rdm.ID) &&
                                                                            acls.Any() && acls.All(a => a == true)
                                                                            select rdm.ID);

                var allowedResponses = await pq.ToArrayAsync();


                if (allowedResponses.Length != requestDataMartIDs.Length)
                {
                    throw new SecurityException("Insufficient permission to group one or more of the specified responses.");
                }

                if (string.IsNullOrWhiteSpace(model.GroupName))
                {
                    model.GroupName = string.Join(", ", db.Responses.Where(r => model.Responses.Any(x => x == r.ID)).Select(r => r.RequestDataMart.DataMart.Name).Distinct());
                }

                ResponseGroup grouping = db.ResponseGroups.Add(new ResponseGroup(model.GroupName));
                foreach (var response in responses)
                {
                    grouping.Responses.Add(response);
                    response.RequestDataMart.ResultsGrouped = true;
                }

                await LogTaskModified("Grouped results.");

                await db.SaveChangesAsync();
            }
            //Un-grouping
            if (activityResultID.Value == UngroupResultID)
            {
                IEnumerable <Guid> groupID = (from r in data.Split(',')
                                              where !string.IsNullOrWhiteSpace(r)
                                              select Guid.Parse(r.Trim())).ToArray();

                List <Guid> requestDataMartIDs = await db.ResponseGroups.Include(g => g.Responses).Where(g => groupID.Contains(g.ID)).SelectMany(g => g.Responses.Select(r => r.RequestDataMartID)).ToListAsync();

                var pq = (from rdm in db.RequestDataMarts
                          let permissionID = PermissionIdentifiers.DataMartInProject.GroupResponses.ID
                                             let identityID = _workflow.Identity.ID
                                                              let acls = db.GlobalAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID)).Select(a => a.Allowed)
                                                                         .Concat(db.ProjectAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Project.Requests.Any(r => r.ID == rdm.RequestID)).Select(a => a.Allowed))
                                                                         .Concat(db.DataMartAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.DataMartID == rdm.DataMartID).Select(a => a.Allowed))
                                                                         .Concat(db.ProjectDataMartAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Project.Requests.Any(r => r.ID == rdm.RequestID) && a.DataMartID == rdm.DataMartID).Select(a => a.Allowed))
                                                                         .Concat(db.OrganizationAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Organization.Requests.Any(r => r.ID == rdm.RequestID)).Select(a => a.Allowed))
                                                                         where requestDataMartIDs.Contains(rdm.ID) &&
                                                                         acls.Any() && acls.All(a => a == true)
                                                                         select rdm.ID);

                var allowedResponses = await pq.ToArrayAsync();


                if (allowedResponses.Length != requestDataMartIDs.Count)
                {
                    throw new SecurityException("Insufficient permission to ungroup routings for the specified request.");
                }

                var groups = await db.ResponseGroups.Include(g => g.Responses).Where(g => groupID.Contains(g.ID)).ToArrayAsync();

                foreach (var group in groups)
                {
                    requestDataMartIDs.AddRange(group.Responses.Select(r => r.RequestDataMartID));
                    group.Responses.Clear();
                    db.ResponseGroups.Remove(group);
                }

                var routings = await db.RequestDataMarts.Where(dm => requestDataMartIDs.Contains(dm.ID)).ToArrayAsync();

                foreach (var routing in routings)
                {
                    routing.ResultsGrouped = false;
                }

                await LogTaskModified("Ungrouped results.");

                await db.SaveChangesAsync();
            }

            if (activityResultID.Value == TerminateResultID)
            {
                _workflow.Entity.CancelledByID = _workflow.Identity.ID;
                _workflow.Entity.CancelledOn   = DateTime.UtcNow;

                task.Status = DTO.Enums.TaskStatuses.Cancelled;
                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = TerminateResultID
                });
            }

            if (activityResultID.Value == 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());
                }

                //TODO: is this applicable in workflow?
                //bool canSkipSubmissionApproval = await db.HasPermissions<Request>(Workflow.Identity, Request.ID, Lpp.Dns.DTO.Security.PermissionIdentifiers.Request.SkipSubmissionApproval);

                //data will contain a list of routings to resubmit, the ID may also be for a group
                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();

                //get the previously submitted input RequestDocument links
                var previousInputRequestDocuments = await(from rd in db.RequestDocuments
                                                          where rd.DocumentType == DTO.Enums.RequestDocumentType.Input &&
                                                          resubmitModel.Responses.Contains(rd.ResponseID)
                                                          select new { RequestDataMartID = rd.Response.RequestDataMartID, RevisionSetID = rd.RevisionSetID }).ToArrayAsync();

                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();

                //attachments are associated to the task they were uploaded on, any existing attachment should be included with the routing
                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();

                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 requestDoc in previousInputRequestDocuments.Where(rd => rd.RequestDataMartID == dm.ID))
                    {
                        db.RequestDocuments.Add(new RequestDocument {
                            ResponseID = response.ID, RevisionSetID = requestDoc.RevisionSetID, DocumentType = DTO.Enums.RequestDocumentType.Input
                        });
                    }

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

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

                await LogTaskModified();

                await MarkTaskComplete(task);
            }
            else if (activityResultID.Value == CompleteResultID)
            {
                var originalStatus = _entity.Status;
                await SetRequestStatus(DTO.Enums.RequestStatuses.PendingDraftReport);

                await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.PendingDraftReport);

                await MarkTaskComplete(task);
            }
            else if (activityResultID.Value == CompleteWorkflowResultID)
            {
                var originalStatus = _entity.Status;
                if (originalStatus != DTO.Enums.RequestStatuses.Complete && originalStatus != DTO.Enums.RequestStatuses.CompleteWithReport)
                {
                    await SetRequestStatus(DTO.Enums.RequestStatuses.Complete);

                    await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Complete);
                }

                await MarkTaskComplete(task);
            }


            return(new CompletionResult
            {
                ResultID = activityResultID.Value
            });
        }
        public override async Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            if (!activityResultID.HasValue)
            {
                throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired);
            }

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

            if (activityResultID.Value == SaveResultID)
            {
                if (_entity.Private)
                {
                    await db.Entry(_entity).ReloadAsync();

                    _entity.Private = false;

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

                    await db.SaveChangesAsync();
                }

                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }
            else if (activityResultID.Value == SubmitResultID)
            {
                var requestJSON = ParseRequestJSON();
                IEnumerable <DTO.QueryComposer.QueryComposerTermDTO> fileUploadTerms = GetAllTerms(QueryComposer.ModelTermsFactory.FileUploadID, requestJSON);

                if (fileUploadTerms.Any())
                {
                    await db.LoadCollection(_entity, (r) => r.DataMarts);

                    if (!_entity.DataMarts.Any())
                    {
                        throw new Exception("At least one routing needs to be specified when submitting a requests.");
                    }

                    //prepare the request documents, save created documents same as legacy
                    //IList<Guid> documentRevisionSets = Newtonsoft.Json.JsonConvert.DeserializeObject<IList<Guid>>(data);

                    Guid[] documentRevisionSets = await(from d in db.Documents.AsNoTracking()
                                                        join ar in db.ActionReferences on d.ItemID equals ar.TaskID
                                                        where ar.ItemID == _entity.ID &&
                                                        d.RevisionSetID.HasValue
                                                        select d.RevisionSetID.Value).Distinct().ToArrayAsync();

                    IEnumerable <Document> documents = await(from d in db.Documents.AsNoTracking()
                                                             join x in (
                                                                 db.Documents.Where(dd => documentRevisionSets.Contains(dd.RevisionSetID.Value))
                                                                 .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 d.ID equals x
                                                             orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending
                                                             select d).ToArrayAsync();

                    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();

                    await db.Entry(_entity).Reference(r => r.Activity).LoadAsync();

                    await db.Entry(_entity).Reference(r => r.RequestType).LoadAsync();

                    string submitterEmail = await db.Users.Where(u => u.ID == _workflow.Identity.ID).Select(u => u.Email).SingleAsync();

                    //update the request
                    var previousStatus = await db.LogsRequestStatusChanged.Where(x => x.RequestID == _entity.ID && x.NewStatus == DTO.Enums.RequestStatuses.RequestPendingDistribution).OrderByDescending(x => x.TimeStamp).FirstOrDefaultAsync();

                    _entity.SubmittedByID         = previousStatus.UserID;
                    _entity.SubmittedOn           = previousStatus.TimeStamp.UtcDateTime;
                    _entity.AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion;
                    _entity.RejectedByID          = null;
                    _entity.RejectedOn            = null;
                    _entity.Private = false;


                    //save the changes to the request now since the trigger for routings will change the status invalidating the object before save
                    await db.SaveChangesAsync();

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

                    var originalStatus = _entity.Status;
                    await SetRequestStatus(DTO.Enums.RequestStatuses.Submitted, false);

                    foreach (var dm in _entity.DataMarts.Where(dm => dm.Status == 0 || dm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval || dm.Status == DTO.Enums.RoutingStatus.Draft))
                    {
                        dm.Status = DTO.Enums.RoutingStatus.Submitted;

                        var currentResponse = db.Responses.Include(rsp => rsp.RequestDocument).FirstOrDefault(r => r.RequestDataMartID == dm.ID && r.Count == r.RequestDataMart.Responses.Max(rr => rr.Count));
                        if (currentResponse == null)
                        {
                            currentResponse = dm.AddResponse(previousStatus.UserID);
                        }

                        currentResponse.SubmittedByID = previousStatus.UserID;
                        currentResponse.SubmittedOn   = previousStatus.TimeStamp.UtcDateTime;

                        //add the request document associations
                        for (int i = 0; i < documentRevisionSets.Count(); i++)
                        {
                            if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == documentRevisionSets[i]))
                            {
                                db.RequestDocuments.Add(new RequestDocument {
                                    RevisionSetID = documentRevisionSets[i], ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input
                                });
                            }
                        }

                        foreach (var attachment in attachments)
                        {
                            if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == attachment.RevisionSetID.Value))
                            {
                                db.RequestDocuments.Add(new RequestDocument {
                                    RevisionSetID = attachment.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput
                                });
                            }
                        }
                    }

                    await db.SaveChangesAsync();

                    //reload the request since altering the routings triggers a change of the request status in the db by a trigger.
                    await db.Entry(_entity).ReloadAsync();

                    var fileUploadTerm = fileUploadTerms.FirstOrDefault();
                    var termValues     = Newtonsoft.Json.JsonConvert.DeserializeObject <FileUploadValues>(fileUploadTerm.Values["Values"].ToString());

                    //update the request.json term value to include system generated documents revisionsetIDs
                    termValues.Documents.Clear();

                    for (int i = 0; i < documentRevisionSets.Count(); i++)
                    {
                        termValues.Documents.Add(new FileUploadValues.Document {
                            RevisionSetID = documentRevisionSets[i]
                        });
                    }

                    fileUploadTerm.Values["Values"] = termValues;
                    _entity.Query = Newtonsoft.Json.JsonConvert.SerializeObject(requestJSON);

                    await db.SaveChangesAsync();

                    await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Submitted);
                }
                else
                {
                    //This forces a reload because of a trigger issue that results in the timestamp not being updated.
                    await db.Entry(_entity).ReloadAsync();

                    await db.LoadCollection(_entity, (r) => r.DataMarts);

                    var parentDocument = db.Documents.FirstOrDefault(d => d.ItemID == _entity.ID && d.Kind == DocumentKind && d.ParentDocumentID == null);

                    byte[] documentContent = System.Text.UTF8Encoding.UTF8.GetBytes(_entity.Query ?? string.Empty);
                    var    document        = new Document
                    {
                        Name             = "Request Criteria",
                        MajorVersion     = parentDocument == null ? 1 : parentDocument.MajorVersion,
                        MinorVersion     = parentDocument == null ? 0 : parentDocument.MinorVersion,
                        RevisionVersion  = parentDocument == null ? 0 : parentDocument.RevisionVersion,
                        MimeType         = "application/json",
                        Viewable         = false,
                        UploadedByID     = _workflow.Identity.ID,
                        FileName         = "request.json",
                        CreatedOn        = DateTime.UtcNow,
                        BuildVersion     = parentDocument == null ? 0 : parentDocument.BuildVersion,
                        ParentDocumentID = parentDocument == null ? (Guid?)null : parentDocument.ID,
                        ItemID           = task.ID,
                        Length           = documentContent.LongLength,
                        Kind             = Dns.DTO.Enums.DocumentKind.Request
                    };

                    db.Documents.Add(document);
                    document.RevisionSetID = document.ID;
                    await db.SaveChangesAsync();

                    document.SetData(db, documentContent);

                    var previousStatus = await db.LogsRequestStatusChanged.Where(x => x.RequestID == _entity.ID && x.NewStatus == DTO.Enums.RequestStatuses.DraftReview).OrderByDescending(x => x.TimeStamp).FirstOrDefaultAsync();

                    _entity.SubmittedByID         = previousStatus.UserID;
                    _entity.SubmittedOn           = previousStatus.TimeStamp.UtcDateTime;
                    _entity.AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion;
                    _entity.Private      = false;
                    _entity.RejectedByID = null;
                    _entity.RejectedOn   = null;

                    await db.SaveChangesAsync();

                    var originalStatus = _entity.Status;
                    await SetRequestStatus(DTO.Enums.RequestStatuses.Submitted, false);

                    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 dm in _entity.DataMarts.Where(dm => dm.Status == 0 || dm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval || dm.Status == DTO.Enums.RoutingStatus.Draft))
                    {
                        dm.Status = DTO.Enums.RoutingStatus.Submitted;

                        var currentResponse = db.Responses.Include(rsp => rsp.RequestDocument).FirstOrDefault(r => r.RequestDataMartID == dm.ID && r.Count == r.RequestDataMart.Responses.Max(rr => rr.Count));
                        if (currentResponse == null)
                        {
                            currentResponse = dm.AddResponse(previousStatus.UserID);
                        }

                        currentResponse.SubmittedByID = previousStatus.UserID;
                        currentResponse.SubmittedOn   = previousStatus.TimeStamp.UtcDateTime;

                        if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == document.RevisionSetID.Value))
                        {
                            db.RequestDocuments.Add(new RequestDocument {
                                RevisionSetID = document.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input
                            });
                        }

                        foreach (var attachment in attachments)
                        {
                            if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == attachment.RevisionSetID.Value))
                            {
                                db.RequestDocuments.Add(new RequestDocument {
                                    RevisionSetID = attachment.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput
                                });
                            }
                        }
                    }

                    await db.SaveChangesAsync();

                    //reload the request since altering the routings triggers a change of the request status in the db by a trigger.
                    await db.Entry(_entity).ReloadAsync();

                    await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Submitted);

                    await MarkTaskComplete(task);
                }

                return(new CompletionResult
                {
                    ResultID = SubmitResultID
                });
            }
            else if (activityResultID.Value == ModifyResultID)
            {
                await db.Entry(_entity).ReloadAsync();

                //moves back to Request Review
                var originalStatus = _entity.Status;
                await SetRequestStatus(DTO.Enums.RequestStatuses.DraftReview);

                await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.DraftReview);

                await MarkTaskComplete(task);

                IEnumerable <DTO.QueryComposer.QueryComposerTermDTO> fileUploadTerms = GetAllTerms(QueryComposer.ModelTermsFactory.FileUploadID, ParseRequestJSON());
                if (fileUploadTerms.Any())
                {
                    return(new CompletionResult
                    {
                        ResultID = ModifyResultID
                    });
                }
                else
                {
                    return(new CompletionResult
                    {
                        ResultID = ModifyResultID
                    });
                }
            }
            else if (activityResultID.Value == TerminateResultID)
            {
                _entity.CancelledByID = _workflow.Identity.ID;
                _entity.CancelledOn   = DateTime.UtcNow;

                if (task != null)
                {
                    task.Status = DTO.Enums.TaskStatuses.Cancelled;
                }

                await db.SaveChangesAsync();

                return(null);
            }
            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.Entry(_entity).ReloadAsync();

                _entity.Private = false;

                if (data != "null")
                {
                    JObject incoming = JObject.Parse(data);

                    var matrixDoc = incoming["TrustMatrix"].ToObject <TrustMatrix[]>();

                    Document existingDocument = await(from d in db.Documents.AsNoTracking()
                                                      where d.ItemID == _entity.ID &&
                                                      d.FileName == TrustMatrixFileAndExtension &&
                                                      d.Kind == TrustMatrixKind
                                                      select d).FirstOrDefaultAsync();


                    if (existingDocument == null)
                    {
                        byte[] documentContent = System.Text.UTF8Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(matrixDoc));

                        Document trustMatrixDoc = db.Documents.Add(new Document
                        {
                            Name         = TrustMatrixFile,
                            FileName     = TrustMatrixFileAndExtension,
                            ItemID       = _entity.ID,
                            Kind         = TrustMatrixKind,
                            MimeType     = "application/json",
                            Viewable     = false,
                            UploadedByID = _workflow.Identity.ID,
                            Length       = System.Text.UTF8Encoding.UTF8.GetCharCount(documentContent)
                        });

                        await db.SaveChangesAsync();

                        trustMatrixDoc.SetData(db, documentContent);
                    }
                    else
                    {
                        using (var ms = new MemoryStream())
                            using (var sw = new StreamWriter(ms))
                            {
                                sw.Write(JsonConvert.SerializeObject(matrixDoc));
                                sw.Flush();
                                ms.Position = 0;

                                await db.SaveChangesAsync();

                                using (var docStream = existingDocument.GetStream(db))
                                {
                                    await docStream.WriteStreamAsync(ms);
                                }
                            }
                    }
                }
                else
                {
                    await db.SaveChangesAsync();
                }

                //Do nothing, it was already saved.
                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }
            else if (activityResultID == SubmitResultID)
            {
                await db.LoadCollection(_entity, (r) => r.DataMarts);

                if (!_entity.DataMarts.Any())
                {
                    throw new Exception("At least one routing needs to be specified when submitting a requests.");
                }

                JObject incoming = JObject.Parse(data);

                IList <Guid> documentRevisionSets = incoming["Documents"].ToObject <List <Guid> >();

                var matrixDoc = incoming["TrustMatrix"].ToObject <TrustMatrix[]>();


                IEnumerable <Document> documents = await(from d in db.Documents.AsNoTracking()
                                                         join x in (
                                                             db.Documents.Where(dd => documentRevisionSets.Contains(dd.RevisionSetID.Value))
                                                             .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 d.ID equals x
                                                         orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending
                                                         select d).ToArrayAsync();

                //reload the request since altering the routings triggers a change of the request status in the db by a trigger.
                await db.Entry(_entity).ReloadAsync();

                //update the request
                _entity.SubmittedByID         = _workflow.Identity.ID;
                _entity.SubmittedOn           = DateTime.UtcNow;
                _entity.AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion;
                _entity.RejectedByID          = null;
                _entity.RejectedOn            = null;
                _entity.Private = false;

                var originalStatus = _entity.Status;

                foreach (var dm in _entity.DataMarts.Where(dm => dm.Status == 0 || dm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval || dm.Status == DTO.Enums.RoutingStatus.Draft))
                {
                    if (dm.RoutingType != DTO.Enums.RoutingType.AnalysisCenter)
                    {
                        dm.Status = DTO.Enums.RoutingStatus.Submitted;
                    }
                    else
                    {
                        dm.Status = DTO.Enums.RoutingStatus.Draft;
                    }

                    var currentResponse = db.Responses.FirstOrDefault(r => r.RequestDataMartID == dm.ID && r.Count == r.RequestDataMart.Responses.Max(rr => rr.Count));
                    if (dm.RoutingType != DTO.Enums.RoutingType.AnalysisCenter)
                    {
                        if (currentResponse == null)
                        {
                            currentResponse = dm.AddResponse(_workflow.Identity.ID);
                        }

                        for (int i = 0; i < documentRevisionSets.Count; i++)
                        {
                            db.RequestDocuments.Add(new RequestDocument {
                                RevisionSetID = documentRevisionSets[i], ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input
                            });
                        }
                    }
                    else if (currentResponse != null && dm.RoutingType == DTO.Enums.RoutingType.AnalysisCenter)
                    {
                        //since not submitting to the AC, delete the response. A response will be created when it is submitted to.
                        await db.LoadCollection(dm, d => d.Responses);

                        dm.Responses.Remove(currentResponse);
                        db.Responses.Remove(currentResponse);
                    }
                }

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

                var qcRequestDTO = ParseRequestJSON();
                var modularTerm  = GetAllTerms(HorizontalDistributedRegressionConfiguration.ModularProgramTermID, qcRequestDTO).FirstOrDefault();
                var termValues   = Newtonsoft.Json.JsonConvert.DeserializeObject <ModularProgramTermValues>(modularTerm.Values["Values"].ToString());

                //update the request.json term value to include system generated documents revisionsetIDs
                termValues.Documents.Clear();

                for (int i = 0; i < documentRevisionSets.Count; i++)
                {
                    termValues.Documents.Add(new ModularProgramTermValues.Document {
                        RevisionSetID = documentRevisionSets[i]
                    });
                }

                modularTerm.Values["Values"] = termValues;
                _entity.Query = Newtonsoft.Json.JsonConvert.SerializeObject(qcRequestDTO);

                var submittedIDs = _entity.DataMarts.Select(x => x.DataMartID);

                matrixDoc = matrixDoc.Where(x => submittedIDs.Contains(x.DataPartner1ID) && submittedIDs.Contains(x.DataPartner2ID)).ToArray();

                Document existingDocument = await(from d in db.Documents.AsNoTracking()
                                                  where d.ItemID == _entity.ID &&
                                                  d.FileName == TrustMatrixFileAndExtension &&
                                                  d.Kind == TrustMatrixKind
                                                  select d).FirstOrDefaultAsync();

                if (existingDocument == null)
                {
                    byte[] documentContent = System.Text.UTF8Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(matrixDoc));

                    Document trustMatrixDoc = db.Documents.Add(new Document
                    {
                        Name         = TrustMatrixFile,
                        FileName     = TrustMatrixFileAndExtension,
                        ItemID       = _entity.ID,
                        Kind         = TrustMatrixKind,
                        MimeType     = "application/json",
                        Viewable     = false,
                        UploadedByID = _workflow.Identity.ID,
                        Length       = Encoding.UTF8.GetCharCount(documentContent)
                    });

                    await db.SaveChangesAsync();

                    trustMatrixDoc.SetData(db, documentContent);
                }
                else
                {
                    using (var ms = new MemoryStream())
                        using (var sw = new StreamWriter(ms))
                        {
                            sw.Write(JsonConvert.SerializeObject(matrixDoc));
                            sw.Flush();
                            ms.Position = 0;

                            await db.SaveChangesAsync();

                            using (var docStream = existingDocument.GetStream(db))
                            {
                                await docStream.WriteStreamAsync(ms);
                            }
                        }
                }

                await db.SaveChangesAsync();

                await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Submitted);

                await MarkTaskComplete(task);

                return(new CompletionResult
                {
                    ResultID = SubmitResultID
                });
            }
            else if (activityResultID == CopyResultID)
            {
                return(new CompletionResult
                {
                    ResultID = CopyResultID
                });
            }
            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);
            }
        }
        public override async Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            if (!activityResultID.HasValue)
            {
                throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired);
            }


            if (activityResultID.Value == SaveResultID)
            {
                return(new CompletionResult {
                    ResultID = SaveResultID
                });
            }
            else if (activityResultID.Value == RejectResultID)
            {
                _entity.Status = DTO.Enums.RequestStatuses.RequestRejected;

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

                var originalStatus = _entity.Status;
                await SetRequestStatus(DTO.Enums.RequestStatuses.RequestRejected);
                await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.RequestRejected);

                await MarkTaskComplete(task);

                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = RejectResultID
                });
            }
            else if (activityResultID.Value == ApproveResultID)
            {
                var filters = new ExtendedQuery
                {
                    Projects             = (a) => a.ProjectID == _entity.ProjectID,
                    ProjectOrganizations = a => a.ProjectID == _entity.ProjectID && a.OrganizationID == _entity.OrganizationID,
                    Organizations        = a => a.OrganizationID == _entity.OrganizationID,
                    Users = a => a.UserID == _entity.CreatedByID
                };

                var permissions = await db.HasGrantedPermissions <Request>(_workflow.Identity, _entity, filters, PermissionIdentifiers.Request.ApproveRejectSubmission);

                if (!permissions.Contains(PermissionIdentifiers.Request.ApproveRejectSubmission))
                {
                    throw new SecurityException(CommonMessages.RequirePermissionToApproveOrRejectRequestSubmission);
                }

                var originalStatus = _entity.Status;
                await SetRequestStatus(DTO.Enums.RequestStatuses.RequestPendingDistribution);

                await db.LoadCollection(_entity, (r) => r.DataMarts);

                await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.RequestPendingDistribution);

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

                return(new CompletionResult
                {
                    ResultID = ApproveResultID
                });
            }
            else
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }
        }
        public async Task <HttpResponseMessage> TerminateRequest([FromBody] Guid id)
        {
            var request = await DataContext.Requests.FindAsync(id);

            request.CancelledByID = Identity.ID;
            request.CancelledOn   = DateTime.UtcNow;

            var newStatus = (int)request.Status < 400 ? RequestStatuses.TerminatedPriorToDistribution : DTO.Enums.RequestStatuses.Cancelled;


            var completedRoutingStatuses = new[] { RoutingStatus.RequestRejected, RoutingStatus.Canceled, RoutingStatus.ResponseRejectedAfterUpload, RoutingStatus.ResponseRejectedBeforeUpload, RoutingStatus.Failed, RoutingStatus.Completed };
            var rdms = DataContext.RequestDataMarts.Where(s => s.RequestID == id);

            foreach (var rdm in rdms)
            {
                if (completedRoutingStatuses.Contains(rdm.Status) == false)
                {
                    rdm.Status = DTO.Enums.RoutingStatus.Canceled;
                }
            }

            try
            {
                await DataContext.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message, ex);
                return(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex));
            }

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

            request.Status = newStatus;
            await DataContext.SaveChangesAsync();

            //have to explicitly change the request status since the property is marked as computed for EF.
            await DataContext.Database.ExecuteSqlCommandAsync("UPDATE Requests SET Status = @status WHERE ID = @ID", new System.Data.SqlClient.SqlParameter("@status", (int)newStatus), new System.Data.SqlClient.SqlParameter("@ID", request.ID));

            //cancel any outstanding tasks associated with the request.
            var incompleteTaskStatuses            = new[] { TaskStatuses.Complete, TaskStatuses.Cancelled };
            IEnumerable <PmnTask> incompleteTasks = await DataContext.Actions.Where(t => t.References.Any(r => r.ItemID == id) && t.Status != TaskStatuses.Complete && t.Status != TaskStatuses.Cancelled).ToArrayAsync();

            foreach (var incompleteTask in incompleteTasks)
            {
                incompleteTask.Status          = DTO.Enums.TaskStatuses.Cancelled;
                incompleteTask.EndOn           = DateTime.UtcNow;
                incompleteTask.PercentComplete = 100d;
            }
            await DataContext.SaveChangesAsync();

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

            //This has to be down here or the task can't be found to update.
            request.WorkFlowActivityID = Guid.Parse("CC2E0001-9B99-4C67-8DED-A3B600E1C696");

            var ta = new PmnTask
            {
                CreatedOn          = DateTime.UtcNow,
                PercentComplete    = 100,
                Priority           = DTO.Enums.Priorities.High,
                StartOn            = DateTime.UtcNow,
                EndOn              = DateTime.UtcNow,
                Status             = DTO.Enums.TaskStatuses.Complete,
                Subject            = "Request Terminated",
                Type               = DTO.Enums.TaskTypes.Task,
                WorkflowActivityID = request.WorkFlowActivityID
            };

            DataContext.Actions.Add(ta);

            var reference = new TaskReference
            {
                ItemID = request.ID,
                TaskID = ta.ID,
                Type   = DTO.Enums.TaskItemTypes.Request
            };

            DataContext.ActionReferences.Add(reference);

            await DataContext.SaveChangesAsync();

            try
            {
                await DataContext.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message, ex);
                return(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex));
            }


            return(Request.CreateResponse(HttpStatusCode.OK));
        }
Beispiel #14
0
        public void CreateWFRequestWithTaskAndDocuments()
        {
            using (var db = new DataContext())
            {
                var user = db.Users.Where(u => u.UserName == "SystemAdministrator").Select(u => new { u.ID, u.UserName, u.FirstName, u.LastName, u.OrganizationID }).First();

                System.Threading.Thread.CurrentPrincipal = new System.Security.Principal.GenericPrincipal(new ApiIdentity(user.ID, user.UserName, (user.FirstName + " " + user.LastName).Trim(), user.OrganizationID), null);

                var request = new Request();
                db.Requests.Add(request);
                Console.WriteLine("Request ID: " + request.ID.ToString("D"));

                request.Name                  = "Test Workflow Request";
                request.RequestTypeID         = new Guid("A3044773-8387-4C1B-8139-92B281D0467C"); //new workflow query composer type
                request.ProjectID             = new Guid("17598FF8-7668-4C58-8225-A377011CD582"); //change to local project
                request.OrganizationID        = new Guid("7C5B0001-7635-4AC4-8961-A2F9013FFC50"); //change to applicable organization
                request.CreatedByID           = user.ID;
                request.CreatedOn             = DateTime.UtcNow;
                request.UpdatedByID           = user.ID;
                request.UpdatedOn             = DateTime.UtcNow;
                request.Status                = DTO.Enums.RequestStatuses.Draft;
                request.AdapterPackageVersion = "5.2.0.0";
                request.WorkFlowActivityID    = new Guid("C1380001-4524-49BA-B4B6-A3B5013A3343");//create request of default workflow
                request.Description           = string.Empty;

                PmnTask task = new PmnTask();
                db.Actions.Add(task);
                Console.WriteLine("Task ID: " + task.ID.ToString("D"));

                task.Status             = DTO.Enums.TaskStatuses.InProgress;
                task.Type               = DTO.Enums.TaskTypes.Task;
                task.StartOn            = DateTime.UtcNow;
                task.Subject            = "Design request";
                task.WorkflowActivityID = request.WorkFlowActivityID.Value;

                task.References.Add(
                    new TaskReference {
                    TaskID = task.ID,
                    ItemID = request.ID,
                    Type   = DTO.Enums.TaskItemTypes.User
                }
                    );

                byte[] documentContent = System.Text.Encoding.UTF8.GetBytes("This is test document content.");

                Document d1 = new Document
                {
                    FileName     = "test.txt",
                    Name         = "test.txt",
                    Description  = "A test document.",
                    Length       = documentContent.Length,
                    MimeType     = "text/plain",
                    ItemID       = task.ID,
                    UploadedByID = request.CreatedByID
                };

                Document d2 = new Document
                {
                    FileName     = "test2.txt",
                    Name         = "test2.txt",
                    Description  = "A test document.",
                    Length       = documentContent.Length,
                    MimeType     = "text/plain",
                    ItemID       = task.ID,
                    UploadedByID = request.CreatedByID
                };

                Document d3 = new Document
                {
                    FileName     = "test3.txt",
                    Name         = "test3.txt",
                    Description  = "A test document.",
                    Length       = documentContent.Length,
                    MimeType     = "text/plain",
                    ItemID       = task.ID,
                    UploadedByID = request.CreatedByID
                };

                Document d4 = new Document
                {
                    FileName     = "test4.txt",
                    Name         = "test4.txt",
                    Description  = "A test document.",
                    Length       = documentContent.Length,
                    MimeType     = "text/plain",
                    ItemID       = task.ID,
                    UploadedByID = request.CreatedByID
                };

                d1.RevisionSetID = d1.ID;
                d2.RevisionSetID = d1.ID;
                d3.RevisionSetID = d1.ID;
                d4.RevisionSetID = d1.ID;
                Console.WriteLine("Document revision set ID: " + d1.ID.ToString("D"));

                db.Documents.AddRange(new[] { d1, d2, d3, d4 });

                db.SaveChanges();

                d1.SetData(db, documentContent);
                d2.SetData(db, documentContent);
                d3.SetData(db, documentContent);
                d4.SetData(db, documentContent);
            }
        }
Beispiel #15
0
 void CompleteTask(PmnTask task)
 {
     task.Status          = DTO.Enums.TaskStatuses.Complete;
     task.EndOn           = DateTime.UtcNow;
     task.PercentComplete = 100d;
 }
Beispiel #16
0
        public async Task Delete([FromBody] IEnumerable <RequestUserDTO> requestUsers)
        {
            try
            {
                var dbSet = DataContext.Set <RequestUser>();

                var requestID = requestUsers.Select(u => u.RequestID).First();

                if (!requestUsers.All(v => v.RequestID == requestID))
                {
                    throw new ArgumentException("The request ID must be the same for all values being deleted.");
                }

                if (!await DataContext.HasPermissions <Request>(Identity, requestID, PermissionIdentifiers.Request.Edit))
                {
                    throw new SecurityException("Insufficient permission to edit the request by deleting request users.");
                }

                var or = PredicateBuilder.False <RequestUser>();
                foreach (var user in requestUsers)
                {
                    or = or.Or(ru => ru.WorkflowRoleID == user.WorkflowRoleID && ru.UserID == user.UserID);
                }


                var logger = new Lpp.Dns.Data.RequestUserLogConfiguration();

                var objs = DataContext.RequestUsers.Where(ru => ru.RequestID == requestID);
                objs = objs.Where(or.Expand());

                foreach (var obj in objs)
                {
                    //by default the datacontext does not log deletes, manually call the logger for RequestUser to add the log entry.
                    logger.CreateLogItem(obj, EntityState.Deleted, Identity, DataContext, true);

                    dbSet.Remove(obj);
                }

                await DataContext.SaveChangesAsync();

                //check if there is a current task for the request, if so remove any of the deleted request users.
                var requestWorkflowActivityID = await DataContext.Requests.Where(r => r.ID == requestID).Select(r => r.WorkFlowActivityID).FirstOrDefaultAsync();

                if (requestWorkflowActivityID.HasValue)
                {
                    PmnTask workflowTask = await PmnTask.GetActiveTaskForRequestActivityAsync(requestID, requestWorkflowActivityID.Value, DataContext);

                    if (workflowTask != null)
                    {
                        var userID = requestUsers.Select(u => u.UserID).ToArray();
                        DataContext.ActionUsers.RemoveRange(DataContext.ActionUsers.Where(a => a.TaskID == workflowTask.ID && userID.Contains(a.UserID) && !DataContext.RequestUsers.Any(ru => ru.RequestID == requestID && ru.UserID == a.UserID)));

                        await DataContext.SaveChangesAsync();
                    }
                }
            }
            catch (System.Security.SecurityException se)
            {
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Forbidden, se));
            }
            catch (DbUpdateException dbe)
            {
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, dbe.UnwindException()));
            }
            catch (Exception e)
            {
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, e));
            }
        }
        public override async Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            if (!activityResultID.HasValue)
            {
                throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired);
            }

            if (activityResultID.Value != TerminateResultID &&
                activityResultID.Value != SubmitResultID &&
                activityResultID.Value != SaveResultID)
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }

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

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

            if (activityResultID.Value == TerminateResultID)
            {
                _entity.CancelledByID = _workflow.Identity.ID;
                _entity.CancelledOn   = DateTime.UtcNow;

                task.Status = DTO.Enums.TaskStatuses.Cancelled;
                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = TerminateResultID
                });
            }


            if (activityResultID.Value == SubmitResultID)
            {
                await db.LoadCollection(_entity, (r) => r.DataMarts);

                if (!_entity.DataMarts.Any())
                {
                    throw new Exception("At least one routing needs to be specified when submitting a requests.");
                }

                //prepare the request documents, save created documents same as legacy
                IList <Guid> documentRevisionSets = Newtonsoft.Json.JsonConvert.DeserializeObject <IList <Guid> >(data);

                IEnumerable <Document> documents = await(from d in db.Documents.AsNoTracking()
                                                         join x in (
                                                             db.Documents.Where(dd => documentRevisionSets.Contains(dd.RevisionSetID.Value))
                                                             .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 d.ID equals x
                                                         orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending
                                                         select d).ToArrayAsync();

                await db.Entry(_entity).Reference(r => r.Activity).LoadAsync();

                await db.Entry(_entity).Reference(r => r.RequestType).LoadAsync();

                string submitterEmail = await db.Users.Where(u => u.ID == _workflow.Identity.ID).Select(u => u.Email).SingleAsync();

                string xmlContent  = SerializeModularProgramsToXML(documents, submitterEmail);
                string htmlContent = SerializeModularProgramsToHTML(documents, submitterEmail);

                Document existingDocument = await(from d in db.Documents.AsNoTracking()
                                                  join x in (
                                                      db.Documents.Where(dd => dd.ItemID == task.ID && dd.FileName == "ModularProgramRequest.xml")
                                                      .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 d.ID equals x
                                                  orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending
                                                  select d).FirstOrDefaultAsync();

                Document xmlRequestDoc = db.Documents.Add(new Document
                {
                    Name         = "ModularProgramRequest.xml",
                    FileName     = "ModularProgramRequest.xml",
                    ItemID       = task.ID,
                    Kind         = DTO.Enums.DocumentKind.SystemGeneratedNoLog,
                    MimeType     = "application/xml",
                    Viewable     = false,
                    UploadedByID = _workflow.Identity.ID,
                    Length       = System.Text.UTF8Encoding.UTF8.GetByteCount(xmlContent)
                });

                db.ActionReferences.Add(new TaskReference {
                    TaskID = task.ID, ItemID = xmlRequestDoc.ID, Type = DTO.Enums.TaskItemTypes.ActivityDataDocument
                });

                if (existingDocument == null)
                {
                    xmlRequestDoc.RevisionSetID = xmlRequestDoc.ID;
                }
                else
                {
                    xmlRequestDoc.ParentDocumentID = existingDocument.ID;
                    xmlRequestDoc.Name             = existingDocument.Name;
                    xmlRequestDoc.Description      = existingDocument.Description;
                    xmlRequestDoc.RevisionSetID    = existingDocument.RevisionSetID;
                    xmlRequestDoc.MajorVersion     = existingDocument.MajorVersion;
                    xmlRequestDoc.MinorVersion     = existingDocument.MinorVersion;
                    xmlRequestDoc.BuildVersion     = existingDocument.BuildVersion;
                    xmlRequestDoc.RevisionVersion  = existingDocument.RevisionVersion + 1;
                }

                existingDocument = await(from d in db.Documents.AsNoTracking()
                                         join x in (
                                             db.Documents.Where(dd => dd.ItemID == task.ID && dd.FileName == "ModularProgramRequest.html")
                                             .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 d.ID equals x
                                         orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending
                                         select d).FirstOrDefaultAsync();

                Document htmlRequestDoc = db.Documents.Add(new Document
                {
                    Name         = "ModularProgramRequest.html",
                    FileName     = "ModularProgramRequest.html",
                    ItemID       = task.ID,
                    Kind         = DTO.Enums.DocumentKind.SystemGeneratedNoLog,
                    MimeType     = "text/html",
                    Viewable     = true,
                    UploadedByID = _workflow.Identity.ID,
                    Length       = System.Text.UTF8Encoding.UTF8.GetByteCount(htmlContent)
                });

                db.ActionReferences.Add(new TaskReference {
                    TaskID = task.ID, ItemID = htmlRequestDoc.ID, Type = DTO.Enums.TaskItemTypes.ActivityDataDocument
                });

                if (existingDocument == null)
                {
                    htmlRequestDoc.RevisionSetID = htmlRequestDoc.ID;
                }
                else
                {
                    htmlRequestDoc.ParentDocumentID = existingDocument.ID;
                    htmlRequestDoc.Name             = existingDocument.Name;
                    htmlRequestDoc.Description      = existingDocument.Description;
                    htmlRequestDoc.RevisionSetID    = existingDocument.RevisionSetID;
                    htmlRequestDoc.MajorVersion     = existingDocument.MajorVersion;
                    htmlRequestDoc.MinorVersion     = existingDocument.MinorVersion;
                    htmlRequestDoc.BuildVersion     = existingDocument.BuildVersion;
                    htmlRequestDoc.RevisionVersion  = existingDocument.RevisionVersion + 1;
                }

                //save the document metadata
                await db.SaveChangesAsync();

                //push the document bytes
                xmlRequestDoc.SetData(db, System.Text.Encoding.UTF8.GetBytes(xmlContent));
                htmlRequestDoc.SetData(db, System.Text.Encoding.UTF8.GetBytes(htmlContent));

                //add the system generated documents revisionsetIDs to the collection of request documents to be submitted to the data partners.
                documentRevisionSets.Add(xmlRequestDoc.RevisionSetID.Value);
                documentRevisionSets.Add(htmlRequestDoc.RevisionSetID.Value);

                //update the request
                _entity.SubmittedByID         = _workflow.Identity.ID;
                _entity.SubmittedOn           = DateTime.UtcNow;
                _entity.AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion;
                _entity.RejectedByID          = null;
                _entity.RejectedOn            = null;
                _entity.Private = false;

                //save the changes to the request now since the trigger for routings will change the status invalidating the object before save
                await db.SaveChangesAsync();

                var originalStatus = _entity.Status;
                await SetRequestStatus(DTO.Enums.RequestStatuses.Submitted, false);

                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 dm in _entity.DataMarts.Where(dm => dm.Status == 0 || dm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval || dm.Status == DTO.Enums.RoutingStatus.Draft))
                {
                    dm.Status = DTO.Enums.RoutingStatus.Submitted;

                    var currentResponse = db.Responses.Include(rsp => rsp.RequestDocument).FirstOrDefault(r => r.RequestDataMartID == dm.ID && r.Count == r.RequestDataMart.Responses.Max(rr => rr.Count));
                    if (currentResponse == null)
                    {
                        currentResponse = dm.AddResponse(_workflow.Identity.ID);
                    }

                    currentResponse.SubmittedByID = _workflow.Identity.ID;
                    currentResponse.SubmittedOn   = DateTime.UtcNow;

                    //add the request document associations
                    for (int i = 0; i < documentRevisionSets.Count; i++)
                    {
                        if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == documentRevisionSets[i]))
                        {
                            db.RequestDocuments.Add(new RequestDocument {
                                RevisionSetID = documentRevisionSets[i], ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input
                            });
                        }
                    }

                    foreach (var attachment in attachments)
                    {
                        if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == attachment.RevisionSetID.Value))
                        {
                            db.RequestDocuments.Add(new RequestDocument {
                                RevisionSetID = attachment.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput
                            });
                        }
                    }
                }

                await db.SaveChangesAsync();

                //reload the request since altering the routings triggers a change of the request status in the db by a trigger.
                await db.Entry(_entity).ReloadAsync();

                var qcRequestDTO = ParseRequestJSON();
                var modularTerm  = GetAllTerms(SimpleModularProgramWorkflowConfiguration.ModularProgramTermID, qcRequestDTO).FirstOrDefault();
                var termValues   = Newtonsoft.Json.JsonConvert.DeserializeObject <ModularProgramTermValues>(modularTerm.Values["Values"].ToString());

                //update the request.json term value to include system generated documents revisionsetIDs
                termValues.Documents.Clear();

                for (int i = 0; i < documentRevisionSets.Count; i++)
                {
                    termValues.Documents.Add(new ModularProgramTermValues.Document {
                        RevisionSetID = documentRevisionSets[i]
                    });
                }

                modularTerm.Values["Values"] = termValues;
                _entity.Query = Newtonsoft.Json.JsonConvert.SerializeObject(qcRequestDTO);

                await db.SaveChangesAsync();

                await MarkTaskComplete(task);
            }

            return(new CompletionResult
            {
                ResultID = activityResultID.Value
            });
        }
        /// <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.Entry(_entity).ReloadAsync();

                _entity.Private = false;
                await db.SaveChangesAsync();

                //Do nothing, it was already saved.
                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }
            else if (activityResultID == SubmitResultID)
            {
                await db.LoadCollection(_entity, (r) => r.DataMarts);

                if (!_entity.DataMarts.Any())
                {
                    throw new Exception("At least one routing needs to be specified when submitting a requests.");
                }

                IList <Guid> documentRevisionSets = Newtonsoft.Json.JsonConvert.DeserializeObject <IList <Guid> >(data);

                IEnumerable <Document> documents = await(from d in db.Documents.AsNoTracking()
                                                         join x in (
                                                             db.Documents.Where(dd => documentRevisionSets.Contains(dd.RevisionSetID.Value))
                                                             .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 d.ID equals x
                                                         orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending
                                                         select d).ToArrayAsync();

                //reload the request since altering the routings triggers a change of the request status in the db by a trigger.
                await db.Entry(_entity).ReloadAsync();

                //update the request
                _entity.SubmittedByID         = _workflow.Identity.ID;
                _entity.SubmittedOn           = DateTime.UtcNow;
                _entity.AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion;
                _entity.RejectedByID          = null;
                _entity.RejectedOn            = null;
                _entity.Private = false;

                //save the changes to the request now since the trigger for routings will change the status invalidating the object before save
                await db.SaveChangesAsync();

                var originalStatus = _entity.Status;
                await SetRequestStatus(DTO.Enums.RequestStatuses.Submitted, false);

                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 dm in _entity.DataMarts.Where(dm => dm.Status == 0 || dm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval || dm.Status == DTO.Enums.RoutingStatus.Draft))
                {
                    if (dm.RoutingType != DTO.Enums.RoutingType.AnalysisCenter)
                    {
                        dm.Status = DTO.Enums.RoutingStatus.Submitted;
                    }
                    else
                    {
                        dm.Status = DTO.Enums.RoutingStatus.Draft;
                    }

                    var currentResponse = db.Responses.Include(rsp => rsp.RequestDocument).FirstOrDefault(r => r.RequestDataMartID == dm.ID && r.Count == r.RequestDataMart.Responses.Max(rr => rr.Count));
                    if (currentResponse == null && dm.RoutingType != DTO.Enums.RoutingType.AnalysisCenter)
                    {
                        currentResponse = db.Responses.Add(new Response {
                            RequestDataMartID = dm.ID
                        });
                    }

                    if (dm.RoutingType != DTO.Enums.RoutingType.AnalysisCenter)
                    {
                        currentResponse.SubmittedByID = _workflow.Identity.ID;
                        currentResponse.SubmittedOn   = DateTime.UtcNow;

                        //add the request document associations
                        for (int i = 0; i < documentRevisionSets.Count; i++)
                        {
                            if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == documentRevisionSets[i]))
                            {
                                db.RequestDocuments.Add(new RequestDocument {
                                    RevisionSetID = documentRevisionSets[i], ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input
                                });
                            }
                        }

                        foreach (var attachment in attachments)
                        {
                            if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == attachment.RevisionSetID.Value))
                            {
                                db.RequestDocuments.Add(new RequestDocument {
                                    RevisionSetID = attachment.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput
                                });
                            }
                        }
                    }
                }

                await db.SaveChangesAsync();

                //reload the request since altering the routings triggers a change of the request status in the db by a trigger.
                await db.Entry(_entity).ReloadAsync();

                DTO.QueryComposer.QueryComposerRequestDTO qcRequestDTO = Newtonsoft.Json.JsonConvert.DeserializeObject <DTO.QueryComposer.QueryComposerRequestDTO>(_entity.Query);
                var modularTerm = qcRequestDTO.Where.Criteria.SelectMany(c => c.Terms.Where(t => t.Type == DistributedRegressionConfiguration.ModularProgramTermID)).FirstOrDefault();
                var termValues  = Newtonsoft.Json.JsonConvert.DeserializeObject <ModularProgramTermValues>(modularTerm.Values["Values"].ToString());

                //update the request.json term value to include system generated documents revisionsetIDs
                termValues.Documents.Clear();

                for (int i = 0; i < documentRevisionSets.Count; i++)
                {
                    termValues.Documents.Add(new ModularProgramTermValues.Document {
                        RevisionSetID = documentRevisionSets[i]
                    });
                }

                modularTerm.Values["Values"] = termValues;
                _entity.Query = Newtonsoft.Json.JsonConvert.SerializeObject(qcRequestDTO);

                await db.SaveChangesAsync();

                await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Submitted);

                await MarkTaskComplete(task);

                return(new CompletionResult
                {
                    ResultID = SubmitResultID
                });
            }
            else if (activityResultID == CopyResultID)
            {
                return(new CompletionResult
                {
                    ResultID = CopyResultID
                });
            }
            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);
            }
        }
        public override async Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            if (!activityResultID.HasValue)
            {
                throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired);
            }

            if (//activityResultID.Value != CompleteResultID &&
                activityResultID.Value != ReopenSubmitDraftReportResultID &&
                activityResultID.Value != SubmitReportForReviewResultID &&
                activityResultID.Value != SaveResultID &&
                activityResultID.Value != CompleteWithoutReportResultID)
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }

            if (activityResultID.Value == SaveResultID)
            {
                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }

            Guid destinationActivityID = Guid.Empty;

            DTO.Enums.RequestStatuses destinationRequestStatus = DTO.Enums.RequestStatuses.Complete;
            var originalStatus = _entity.Status;

            if (activityResultID.Value == CompleteWithoutReportResultID)
            {
                await SetRequestStatus(DTO.Enums.RequestStatuses.Complete);

                destinationActivityID = SummaryQueryWorkflowConfiguration.CompletedID;
            }
            else if (activityResultID.Value == SubmitReportForReviewResultID)
            {
                await SetRequestStatus(DTO.Enums.RequestStatuses.FinalReportPendingReview);

                destinationActivityID    = SummaryQueryWorkflowConfiguration.ReviewFinalReportID;
                destinationRequestStatus = DTO.Enums.RequestStatuses.FinalReportPendingReview;
            }
            else if (activityResultID.Value == ReopenSubmitDraftReportResultID)
            {
                await SetRequestStatus(DTO.Enums.RequestStatuses.PendingDraftReport);

                destinationActivityID    = SummaryQueryWorkflowConfiguration.SubmitDraftReportID;
                destinationRequestStatus = DTO.Enums.RequestStatuses.PendingDraftReport;
            }

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

            await MarkTaskComplete(task);

            await NotifyRequestStatusChanged(originalStatus, destinationRequestStatus);

            return(new CompletionResult
            {
                ResultID = activityResultID.Value
            });
        }
        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.Value == SaveResultID)
            {
                await task.LogAsModifiedAsync(_workflow.Identity, db);

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

                _entity.Private = false;
                await db.SaveChangesAsync();

                //Do nothing, it was already saved.
                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }
            else if (activityResultID.Value == SubmitResultID)
            {
                await db.Entry(_entity).ReloadAsync();

                _entity.Private       = false;
                _entity.SubmittedByID = _workflow.Identity.ID;

                //Reset reject for resubmit.
                _entity.RejectedByID = null;
                _entity.RejectedOn   = null;

                bool hasFileUploadTerm = GetAllTerms(QueryComposer.ModelTermsFactory.FileUploadID, ParseRequestJSON()).Any();

                if (hasFileUploadTerm)
                {
                    var originalStatus = _entity.Status;
                    //file distribution never requires review before submission, So go right to Distribute.
                    await SetRequestStatus(DTO.Enums.RequestStatuses.RequestPendingDistribution);

                    await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.RequestPendingDistribution);

                    await MarkTaskComplete(task);

                    return(new CompletionResult
                    {
                        ResultID = SubmitToDistributionID
                    });
                }
                else
                {
                    await db.SaveChangesAsync();

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

                    await NotifyRequestStatusChanged(DTO.Enums.RequestStatuses.Draft, DTO.Enums.RequestStatuses.DraftReview);

                    await MarkTaskComplete(task);

                    return(new CompletionResult
                    {
                        ResultID = SubmitResultID
                    });
                }
            }
            else if (activityResultID.Value == DeleteResultID)
            {
                db.Requests.Remove(_entity);

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

                await db.SaveChangesAsync();

                return(null);
            }
            else
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }
        }
        public async override Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            await db.LoadCollection(_entity, (r) => r.DataMarts);

            if (activityResultID.Value == SaveResultID)
            {
                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }

            if (activityResultID.Value == ApproveResultID)
            {
                var responses = await db.RequestDataMarts.Where(rdm => rdm.RequestID == _entity.ID && rdm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval).SelectMany(rdm => rdm.Responses.Where(rsp => rsp.Count == rdm.Responses.Max(rr => rr.Count))).ToArrayAsync();

                var previousTask = await(from a in db.Actions
                                         join ar in db.ActionReferences on a.ID equals ar.TaskID
                                         where ar.ItemID == _entity.ID && a.Status == DTO.Enums.TaskStatuses.Complete
                                         select a).FirstOrDefaultAsync();

                var document = await(from d in db.Documents.AsNoTracking()
                                     join x in (
                                         db.Documents.Where(dd => dd.ItemID == previousTask.ID && dd.FileName == "request.json" && dd.Kind == Dns.DTO.Enums.DocumentKind.Request)
                                         .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 d.ID equals x
                                     orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending
                                     select d).FirstOrDefaultAsync();


                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 dm in _entity.DataMarts.Where(dm => dm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval))
                {
                    dm.Status = DTO.Enums.RoutingStatus.Submitted;

                    _entity.SubmittedByID = _workflow.Identity.ID;
                    _entity.SubmittedOn   = DateTime.UtcNow;

                    //var currentResponse = db.Responses.FirstOrDefault(r => r.RequestDataMartID == dm.ID && r.Count == r.RequestDataMart.Responses.Max(rr => rr.Count));
                    var currentResponse = responses.Where(rsp => rsp.RequestDataMartID == dm.ID).FirstOrDefault();
                    if (currentResponse == null)
                    {
                        currentResponse = db.Responses.Add(new Response {
                            RequestDataMartID = dm.ID
                        });
                    }
                    currentResponse.SubmittedByID = _workflow.Identity.ID;
                    currentResponse.SubmittedOn   = DateTime.UtcNow;

                    var existingRequestDocuments = await db.RequestDocuments.Where(rd => rd.ResponseID == currentResponse.ID).ToArrayAsync();

                    if (!existingRequestDocuments.Any(rd => rd.RevisionSetID == document.RevisionSetID.Value))
                    {
                        db.RequestDocuments.Add(new RequestDocument {
                            RevisionSetID = document.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input
                        });
                    }

                    foreach (var attachment in attachments)
                    {
                        if (!existingRequestDocuments.Any(rd => rd.RevisionSetID == attachment.RevisionSetID.Value))
                        {
                            db.RequestDocuments.Add(new RequestDocument {
                                RevisionSetID = attachment.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput
                            });
                        }
                    }
                }

                var task = PmnTask.GetActiveTaskForRequestActivity(_entity.ID, ID, db);
                if (task != null)
                {
                    task.Status = DTO.Enums.TaskStatuses.Complete;
                    task.EndOn  = DateTime.UtcNow;
                }

                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = ApproveResultID
                });
            }
            else if (activityResultID.Value == RejectResultID)
            {
                foreach (var dm in _entity.DataMarts.Where(dm => dm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval))
                {
                    dm.Status = DTO.Enums.RoutingStatus.RequestRejected;
                }

                _entity.Status       = DTO.Enums.RequestStatuses.RequestRejected;
                _entity.RejectedByID = _workflow.Identity.ID;
                _entity.RejectedOn   = DateTime.UtcNow;

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

                var originalStatus = _entity.Status;
                await SetRequestStatus(DTO.Enums.RequestStatuses.RequestRejected);

                await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.RequestRejected);

                await MarkTaskComplete(task);

                await db.SaveChangesAsync();

                return(new CompletionResult
                {
                    ResultID = RejectResultID
                });
            }
            else
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }
        }
        public override async Task <Lpp.Workflow.Engine.CompletionResult> Complete(string data, Guid?activityResultID)
        {
            //Ad params that come through using Json and deserialize on each activity result and handle the logic.
            if (!activityResultID.HasValue)
            {
                throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired);
            }

            if (activityResultID.Value == SaveResultID)
            {
                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }

            if (activityResultID.Value == GroupResultID)
            {
                GroupingRequestModel model = Newtonsoft.Json.JsonConvert.DeserializeObject <GroupingRequestModel>(data);

                var responses = await db.Responses.Include(r => r.RequestDataMart).Where(r => model.Responses.Any(x => x == r.ID)).ToArrayAsync();

                if (responses.Select(r => r.RequestDataMart.RequestID).Distinct().Count() > 1)
                {
                    throw new ArgumentException("Cannot group responses that come from different requests.");
                }

                Guid[] requestDataMartIDs = responses.Select(rsp => rsp.RequestDataMartID).Distinct().ToArray();
                var    pq = (from rdm in db.RequestDataMarts
                             let permissionID = PermissionIdentifiers.DataMartInProject.GroupResponses.ID
                                                let identityID = _workflow.Identity.ID
                                                                 let acls = db.GlobalAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID)).Select(a => a.Allowed)
                                                                            .Concat(db.ProjectAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Project.Requests.Any(r => r.ID == rdm.RequestID)).Select(a => a.Allowed))
                                                                            .Concat(db.DataMartAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.DataMartID == rdm.DataMartID).Select(a => a.Allowed))
                                                                            .Concat(db.ProjectDataMartAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Project.Requests.Any(r => r.ID == rdm.RequestID) && a.DataMartID == rdm.DataMartID).Select(a => a.Allowed))
                                                                            .Concat(db.OrganizationAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Organization.Requests.Any(r => r.ID == rdm.RequestID)).Select(a => a.Allowed))
                                                                            where requestDataMartIDs.Contains(rdm.ID) &&
                                                                            acls.Any() && acls.All(a => a == true)
                                                                            select rdm.ID);

                var allowedResponses = await pq.ToArrayAsync();


                if (allowedResponses.Length != requestDataMartIDs.Length)
                {
                    throw new SecurityException("Insufficient permission to group one or more of the specified responses.");
                }

                if (string.IsNullOrWhiteSpace(model.GroupName))
                {
                    model.GroupName = string.Join(", ", db.Responses.Where(r => model.Responses.Any(x => x == r.ID)).Select(r => r.RequestDataMart.DataMart.Name).Distinct());
                }

                ResponseGroup grouping = db.ResponseGroups.Add(new ResponseGroup(model.GroupName));
                foreach (var response in responses)
                {
                    grouping.Responses.Add(response);
                    response.RequestDataMart.ResultsGrouped = true;
                }

                //log the save against the current task
                await LogTaskModified();

                await db.SaveChangesAsync();
            }
            else if (activityResultID.Value == UngroupResultID)
            {
                IEnumerable <Guid> groupID = (from r in data.Split(',')
                                              where !string.IsNullOrWhiteSpace(r)
                                              select Guid.Parse(r.Trim())).ToArray();

                List <Guid> requestDataMartIDs = await db.ResponseGroups.Include(g => g.Responses).Where(g => groupID.Contains(g.ID)).SelectMany(g => g.Responses.Select(r => r.RequestDataMartID)).ToListAsync();

                var pq = (from rdm in db.RequestDataMarts
                          let permissionID = PermissionIdentifiers.DataMartInProject.GroupResponses.ID
                                             let identityID = _workflow.Identity.ID
                                                              let acls = db.GlobalAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID)).Select(a => a.Allowed)
                                                                         .Concat(db.ProjectAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Project.Requests.Any(r => r.ID == rdm.RequestID)).Select(a => a.Allowed))
                                                                         .Concat(db.DataMartAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.DataMartID == rdm.DataMartID).Select(a => a.Allowed))
                                                                         .Concat(db.ProjectDataMartAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Project.Requests.Any(r => r.ID == rdm.RequestID) && a.DataMartID == rdm.DataMartID).Select(a => a.Allowed))
                                                                         .Concat(db.OrganizationAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Organization.Requests.Any(r => r.ID == rdm.RequestID)).Select(a => a.Allowed))
                                                                         where requestDataMartIDs.Contains(rdm.ID) &&
                                                                         acls.Any() && acls.All(a => a == true)
                                                                         select rdm.ID);

                var allowedResponses = await pq.ToArrayAsync();


                if (allowedResponses.Length != requestDataMartIDs.Count)
                {
                    throw new SecurityException("Insufficient permission to ungroup routings for the specified request.");
                }

                var groups = await db.ResponseGroups.Include(g => g.Responses).Where(g => groupID.Contains(g.ID)).ToArrayAsync();

                foreach (var group in groups)
                {
                    group.Responses.Clear();
                    db.ResponseGroups.Remove(group);
                }

                var routings = await db.RequestDataMarts.Where(dm => requestDataMartIDs.Contains(dm.ID)).ToArrayAsync();

                foreach (var routing in routings)
                {
                    routing.ResultsGrouped = false;
                }

                await LogTaskModified();

                await db.SaveChangesAsync();
            }
            else if (activityResultID.Value == AddDataMartsResultID)
            {
                string[] guids = data.Split(',');

                var revisionSetIDs = await(from req in db.Requests
                                           join rdm in db.RequestDataMarts on req.ID equals rdm.RequestID
                                           join res in db.Responses on rdm.ID equals res.RequestDataMartID
                                           join reqDoc in db.RequestDocuments on res.ID equals reqDoc.ResponseID
                                           where req.ID == _entity.ID && reqDoc.DocumentType == DTO.Enums.RequestDocumentType.Input
                                           select reqDoc.RevisionSetID).Distinct().ToArrayAsync();

                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 guids)
                {
                    Guid dmGuid = new Guid(guid);
                    var  dm     = RequestDataMart.Create(_entity.ID, dmGuid, _workflow.Identity.ID);
                    dm.Status   = DTO.Enums.RoutingStatus.Submitted;
                    dm.Priority = _entity.Priority;
                    dm.DueDate  = _entity.DueDate;
                    _entity.DataMarts.Add(dm);
                    foreach (var revset in revisionSetIDs)
                    {
                        db.RequestDocuments.Add(new RequestDocument {
                            RevisionSetID = revset, ResponseID = dm.Responses.FirstOrDefault().ID, DocumentType = DTO.Enums.RequestDocumentType.Input
                        });
                    }

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

                await db.SaveChangesAsync();
            }
            else if (activityResultID.Value == 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 LogTaskModified();

                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);
                }
            }
            else if (activityResultID.Value == EditRoutingStatusResultID)
            {
                var dataMarts = Newtonsoft.Json.JsonConvert.DeserializeObject <IEnumerable <RoutingChangeRequestModel> >(data);
                await UpdateDataMartRoutingStatus(dataMarts);

                return(new CompletionResult
                {
                    ResultID = EditRoutingStatusResultID
                });
            }
            else if (activityResultID.Value == RoutingsBulkEditID)
            {
                return(new CompletionResult
                {
                    ResultID = RoutingsBulkEditID
                });
            }
            else if (activityResultID.Value == ResubmitResultID)
            {
                //data will contain a list of routings to resubmit, the ID may also be for a group
                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();

                var revisions = await(from rdm in db.RequestDataMarts
                                      join rdmr in db.Responses on rdm.ID equals rdmr.RequestDataMartID
                                      join rdoc in db.RequestDocuments on rdmr.ID equals rdoc.ResponseID
                                      where rdoc.DocumentType == DTO.Enums.RequestDocumentType.Input && rdm.RequestID == _entity.ID
                                      select new
                {
                    DataMartID    = rdm.ID,
                    RevisionSetID = rdoc.RevisionSetID,
                    ResponseID    = rdoc.ResponseID
                }).ToArrayAsync();

                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();

                //attachments are associated to the task they were uploaded on, any existing attachment should be included with the routing
                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();


                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 revset in revisions.Where(x => x.DataMartID == dm.ID).Distinct())
                    {
                        db.RequestDocuments.Add(new RequestDocument {
                            RevisionSetID = revset.RevisionSetID, ResponseID = response.ID, DocumentType = DTO.Enums.RequestDocumentType.Input
                        });
                    }

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

                _entity.Status = DTO.Enums.RequestStatuses.Submitted;
                var task = await PmnTask.GetActiveTaskForRequestActivityAsync(_entity.ID, ID, db);

                await LogTaskModified();

                if (task != null)
                {
                    task.EndOn           = DateTime.UtcNow;
                    task.Status          = DTO.Enums.TaskStatuses.Complete;
                    task.PercentComplete = 100;
                    await db.SaveChangesAsync();
                }

                await db.SaveChangesAsync();
            }
            else if (activityResultID.Value == CompleteResultID)
            {
                var originalStatus = _entity.Status;
                if (originalStatus != DTO.Enums.RequestStatuses.Complete && originalStatus != DTO.Enums.RequestStatuses.CompleteWithReport)
                {
                    await SetRequestStatus(DTO.Enums.RequestStatuses.Complete);

                    await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Complete);
                }

                var task = await PmnTask.GetActiveTaskForRequestActivityAsync(_entity.ID, ID, db);
                await MarkTaskComplete(task);
            }
            else
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }

            return(new CompletionResult
            {
                ResultID = activityResultID.Value
            });
        }
Beispiel #23
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task Process(RequestDataMart reqDM)
        {
            //wait a small random amount of time before processing to try to avoid collision with webfarm containing multiple API
            System.Threading.Thread.Sleep(TimeSpan.FromMilliseconds(RandomGenerator.NextDouble() * 1500));


            var ifAdvaceStatuses = new[] {
                RoutingStatus.Completed,
                RoutingStatus.ResultsModified,
                RoutingStatus.RequestRejected,
                RoutingStatus.ResponseRejectedBeforeUpload,
                RoutingStatus.ResponseRejectedAfterUpload,
                RoutingStatus.AwaitingResponseApproval,
                RoutingStatus.Draft
            };

            var routes = await DB.RequestDataMarts.Where(x => x.RequestID == reqDM.RequestID).ToArrayAsync();

            if (routes.All(x => ifAdvaceStatuses.Contains(x.Status)))
            {
                if (ActiveProcessingRequests.ContainsKey(reqDM.RequestID))
                {
                    return;
                }


                ActiveProcessingRequests.TryAdd(reqDM.RequestID, DateTime.UtcNow);

                try
                {
                    var matrixDoc = await(from d in DB.Documents.AsNoTracking()
                                          where d.ItemID == reqDM.RequestID &&
                                          d.FileName == TrustMatrixFileAndExtension &&
                                          d.Kind == TrustMatrixKind
                                          select new { d.ID }).FirstOrDefaultAsync();

                    if (matrixDoc != null)
                    {
                        using (var docDB = new DataContext())
                            using (var sr = new StreamReader(LocalDiskCache.Instance.GetStream(DB, matrixDoc.ID)))
                            {
                                TrustMatrix = JsonConvert.DeserializeObject <TrustMatrix[]>(sr.ReadToEnd());
                                sr.Close();
                            }
                    }

                    int incrementedCount = (from res in DB.Responses
                                            join rdm in DB.RequestDataMarts on res.RequestDataMartID equals rdm.ID
                                            where rdm.RequestID == reqDM.RequestID
                                            select res.Count).Max() + 1;

                    var routeIDs = routes.Select(x => x.ID);

                    var currentTask = await PmnTask.GetActiveTaskForRequestActivityAsync(reqDM.Request.ID, reqDM.Request.WorkFlowActivityID.Value, DB);

                    List <DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem> manifestItems = new List <DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem>();

                    var q = from rd in DB.RequestDocuments
                            join rsp in DB.Responses on rd.ResponseID equals rsp.ID
                            join rdm in DB.RequestDataMarts on rsp.RequestDataMartID equals rdm.ID
                            join dm in DB.DataMarts on rdm.DataMartID equals dm.ID
                            join doc in DB.Documents on rd.RevisionSetID equals doc.RevisionSetID
                            where rsp.Count == (incrementedCount - 1) &&
                            rdm.RequestID == reqDM.Request.ID &&
                            routeIDs.Contains(reqDM.ID) &&
                            rd.DocumentType == RequestDocumentType.Output &&
                            doc.ItemID == rsp.ID &&
                            doc.ID == DB.Documents.Where(dd => dd.RevisionSetID == doc.RevisionSetID && doc.ItemID == rsp.ID).OrderByDescending(dd => dd.MajorVersion).ThenByDescending(dd => dd.MinorVersion).ThenByDescending(dd => dd.BuildVersion).ThenByDescending(dd => dd.RevisionVersion).Select(dd => dd.ID).FirstOrDefault()
                            select new
                    {
                        DocumentID            = doc.ID,
                        DocumentKind          = doc.Kind,
                        DocumentFileName      = doc.FileName,
                        ResponseID            = rd.ResponseID,
                        RevisionSetID         = rd.RevisionSetID,
                        RequestDataMartID     = rsp.RequestDataMartID,
                        DataMartID            = rdm.DataMartID,
                        DataPartnerIdentifier = dm.DataPartnerIdentifier,
                        DataMart = dm.Name
                    };

                    var documents = await(q).ToArrayAsync();

                    if (documents.Any(d => d.DocumentKind == StopProcessingTriggerDocumentKind))
                    {
                        var openRoutes = await DB.RequestDataMarts.Where(x => x.RequestID == reqDM.RequestID &&
                                                                         (x.Status == RoutingStatus.Submitted || x.Status == RoutingStatus.Resubmitted || x.Status == RoutingStatus.Draft)
                                                                         ).ToArrayAsync();

                        foreach (var route in openRoutes)
                        {
                            route.Status = RoutingStatus.Canceled;
                        }

                        currentTask.Status          = TaskStatuses.Complete;
                        currentTask.EndOn           = DateTime.UtcNow;
                        currentTask.PercentComplete = 100d;

                        reqDM.Request.WorkFlowActivityID = CompletedActivityID;

                        await DB.SaveChangesAsync();
                    }
                    else
                    {
                        List <KeyValuePair <string, Guid> > docsToSend = new List <KeyValuePair <string, Guid> >();

                        var fileListFiles = documents.Where(d => !string.IsNullOrEmpty(d.DocumentKind) && string.Equals("DistributedRegression.FileList", d.DocumentKind, StringComparison.OrdinalIgnoreCase));

                        var requestDataMarts = await(from dm in DB.DataMarts
                                                     join rdm in DB.RequestDataMarts on dm.ID equals rdm.DataMartID
                                                     where rdm.RequestID == reqDM.Request.ID
                                                     select new DTO.QueryComposer.DistributedRegressionManifestDataPartner
                        {
                            DataMartID         = dm.ID,
                            DataMartIdentifier = dm.DataPartnerIdentifier,
                            DataMartCode       = dm.DataPartnerCode,
                            RouteType          = rdm.RoutingType.Value
                        }).ToArrayAsync();

                        foreach (var fileListFile in fileListFiles)
                        {
                            //only include the files indicated in the filelist document
                            using (var stream = LocalDiskCache.Instance.GetStream(DB, fileListFile.DocumentID))
                                using (var reader = new System.IO.StreamReader(stream))
                                {
                                    //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 = documents.Where(d => string.Equals(d.DocumentFileName, filename, StringComparison.OrdinalIgnoreCase) && d.DataMartID == fileListFile.DataMartID).Select(d => d.RevisionSetID).FirstOrDefault();
                                                if (revisionSetID.HasValue)
                                                {
                                                    foreach (var dp in split[2].Trim().Split(' '))
                                                    {
                                                        List <Guid> dmIDs = new List <Guid>();
                                                        dmIDs.Add(fileListFile.DataMartID);
                                                        dmIDs.Add(requestDataMarts.Where(x => x.DataMartCode == dp).Select(x => x.DataMartID).FirstOrDefault());

                                                        var isAllowed = TrustMatrix.Where(x => dmIDs.Contains(x.DataPartner1ID) && dmIDs.Contains(x.DataPartner2ID)).Select(x => x.Trusted).FirstOrDefault();

                                                        if (TrustMatrix.Length == 0 || isAllowed)
                                                        {
                                                            docsToSend.Add(new KeyValuePair <string, Guid>(dp, revisionSetID.Value));
                                                            manifestItems.AddRange(documents.Where(d => d.RevisionSetID == revisionSetID.Value).Select(d => new DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem
                                                            {
                                                                DocumentID            = d.DocumentID,
                                                                DataMart              = d.DataMart,
                                                                DataMartID            = d.DataMartID,
                                                                DataPartnerIdentifier = d.DataPartnerIdentifier,
                                                                RequestDataMartID     = d.RequestDataMartID,
                                                                ResponseID            = d.ResponseID,
                                                                RevisionSetID         = d.RevisionSetID
                                                            }).ToArray());
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }

                                    reader.Close();
                                }
                        }



                        foreach (var dp in docsToSend.GroupBy(x => x.Key))
                        {
                            var dataMart = await(from dm in DB.DataMarts
                                                 join rdm in DB.RequestDataMarts on dm.ID equals rdm.DataMartID
                                                 where rdm.RequestID == reqDM.Request.ID &&
                                                 rdm.Status != RoutingStatus.Canceled &&
                                                 dm.DataPartnerCode == dp.Key
                                                 select rdm).Include(rdm => rdm.Responses).FirstOrDefaultAsync();

                            if (dataMart != null)
                            {
                                var response = dataMart.AddResponse(IdentityID, incrementedCount);

                                await DB.SaveChangesAsync();

                                await DB.Entry(dataMart).ReloadAsync();

                                List <DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem> filteredManifestItems = new List <DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem>();

                                foreach (var revisionSet in dp)
                                {
                                    DB.RequestDocuments.Add(new RequestDocument {
                                        DocumentType = RequestDocumentType.Input, ResponseID = response.ID, RevisionSetID = revisionSet.Value
                                    });
                                    filteredManifestItems.Add(manifestItems.Where(x => x.RevisionSetID == revisionSet.Value).FirstOrDefault());
                                }

                                byte[] buffer;
                                using (var ms = new System.IO.MemoryStream())
                                    using (var sw = new System.IO.StreamWriter(ms))
                                        using (var jw = new Newtonsoft.Json.JsonTextWriter(sw))
                                        {
                                            Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer();
                                            serializer.Serialize(jw, new DTO.QueryComposer.DistributedRegressionManifestFile {
                                                Items = filteredManifestItems, DataPartners = requestDataMarts
                                            });
                                            jw.Flush();

                                            buffer = ms.ToArray();
                                        }

                                Document analysisCenterManifest = DB.Documents.Add(new Document
                                {
                                    Description  = "Contains information about the input documents and the datamart they came from.",
                                    Name         = "Internal: Routing Manifest",
                                    FileName     = "manifest.json",
                                    ItemID       = currentTask.ID,
                                    Kind         = DocumentKind.SystemGeneratedNoLog,
                                    UploadedByID = IdentityID,
                                    Viewable     = false,
                                    MimeType     = "application/json",
                                    Length       = buffer.Length
                                });

                                analysisCenterManifest.RevisionSetID = analysisCenterManifest.ID;

                                DB.RequestDocuments.Add(new RequestDocument {
                                    DocumentType = RequestDocumentType.Input, ResponseID = response.ID, RevisionSetID = analysisCenterManifest.RevisionSetID.Value
                                });

                                await DB.SaveChangesAsync();

                                analysisCenterManifest.SetData(DB, buffer);

                                dataMart.Status = dataMart.Responses.Count > 1 ? RoutingStatus.Resubmitted : RoutingStatus.Submitted;
                                await DB.SaveChangesAsync();
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error($"Error processing DEC switch for requestID:{reqDM.RequestID}", ex);
                    throw;
                }
                finally
                {
                    DateTime startTime;
                    ActiveProcessingRequests.TryRemove(reqDM.RequestID, out startTime);
                }
            }
        }
Beispiel #24
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);
            }
        }
Beispiel #25
0
        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.Value == SaveResultID)
            {
                await task.LogAsModifiedAsync(_workflow.Identity, db);

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

                _entity.Private = false;
                await db.SaveChangesAsync();

                //Do nothing, it was already saved.
                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }
            else if (activityResultID.Value == SubmitResultID)
            {
                await db.Entry(_entity).ReloadAsync();

                _entity.Private       = false;
                _entity.SubmittedByID = _workflow.Identity.ID;

                //Reset reject for resubmit.
                _entity.RejectedByID = null;
                _entity.RejectedOn   = null;
                if (Newtonsoft.Json.JsonConvert.DeserializeObject <Lpp.Dns.DTO.QueryComposer.QueryComposerRequestDTO>(_entity.Query).Where.Criteria.Any(c => c.Terms.Any(t => t.Type.ToString().ToUpper() == "2F60504D-9B2F-4DB1-A961-6390117D3CAC") || c.Criteria.Any(ic => ic.Terms.Any(t => t.Type.ToString().ToUpper() == "2F60504D-9B2F-4DB1-A961-6390117D3CAC"))))
                {
                    var originalStatus = _entity.Status;
                    //file distribution never requires review before submission, So go right to Distribute.
                    await SetRequestStatus(DTO.Enums.RequestStatuses.RequestPendingDistribution);

                    await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.RequestPendingDistribution);

                    await MarkTaskComplete(task);

                    return(new CompletionResult
                    {
                        ResultID = SubmitToDistributionID
                    });
                }
                else
                {
                    await db.SaveChangesAsync();

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

                    await NotifyRequestStatusChanged(DTO.Enums.RequestStatuses.Draft, DTO.Enums.RequestStatuses.DraftReview);

                    await MarkTaskComplete(task);

                    return(new CompletionResult
                    {
                        ResultID = SubmitResultID
                    });
                }
            }
            else if (activityResultID.Value == DeleteResultID)
            {
                db.Requests.Remove(_entity);

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

                await db.SaveChangesAsync();

                return(null);
            }
            else
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }
        }
        public async Task <HttpResponseMessage> Register(CNDSRegisterRequestDTO dto)
        {
            await ConfirmProxyUser(dto);

            var requestTypeDetails = await DataContext.RequestTypes.Where(rt => rt.ID == dto.RequestTypeID)
                                     .Select(rt => new
            {
                rt.ID,
                rt.WorkflowID,
                StartActivityID     = rt.Workflow.RequestReviewWorkflowActivityID ?? DataContext.WorkflowActivityCompletionMaps.Where(wa => wa.WorkflowID == rt.WorkflowID && wa.SourceWorkflowActivity.Start == true).Select(wa => wa.SourceWorkflowActivityID).FirstOrDefault(),
                SubmittedActivityID = rt.Workflow.CompleteDistributionWorkflowActivityID,
                WorkflowRoleID      = rt.Workflow.Roles.Where(wr => wr.IsRequestCreator == true).Select(wr => wr.ID).FirstOrDefault()
            }
                                             ).FirstOrDefaultAsync();

            DTO.RequestDTO sourceRequest = Newtonsoft.Json.JsonConvert.DeserializeObject <DTO.RequestDTO>(dto.RequestDetails);

            //register the request, routes, responses, documents
            var request = DataContext.Requests.Add(new Data.Request
            {
                ID                 = dto.ParticipantID,
                ProjectID          = dto.ProjectID,
                RequestTypeID      = dto.RequestTypeID,
                WorkflowID         = requestTypeDetails.WorkflowID,
                WorkFlowActivityID = requestTypeDetails.StartActivityID,
                CreatedByID        = dto.SourceNetworkID,
                UpdatedByID        = dto.SourceNetworkID,
                SubmittedOn        = DateTime.UtcNow,
                SubmittedByID      = dto.SourceNetworkID,
                Description        = sourceRequest.Description,
                //TODO: figure out the naming format of the request
                Name                  = sourceRequest.Project + ": " + sourceRequest.Name,
                OrganizationID        = Requests.RequestsController.CNDSOrganizationRouteProxyID,
                Priority              = sourceRequest.Priority,
                Query                 = sourceRequest.Query,
                DataMarts             = new List <RequestDataMart>(),
                AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion,
                RejectedByID          = null,
                RejectedOn            = null,
                Private               = false
            });

            if (sourceRequest.DueDate.HasValue)
            {
                request.DueDate = sourceRequest.DueDate.Value.DateTime;
            }

            request.Users.Add(new RequestUser
            {
                RequestID      = request.ID,
                UserID         = dto.SourceNetworkID,
                WorkflowRoleID = requestTypeDetails.WorkflowRoleID
            });

            var workflowTask = DataContext.Actions.Add(PmnTask.CreateForWorkflowActivity(request.ID, request.WorkFlowActivityID.Value, request.WorkflowID.Value, DataContext));

            //register the documents
            List <Document> documents = new List <Document>();

            foreach (var doc in dto.Documents)
            {
                var document = DataContext.Documents.Add(new Document
                {
                    ID            = doc.DocumentID,
                    RevisionSetID = doc.RevisionSetID,
                    ItemID        = workflowTask.ID,
                    Name          = doc.Name,
                    FileName      = doc.FileName,
                    Kind          = doc.Kind,
                    Length        = doc.Length,
                    Description   = doc.Description,
                    MimeType      = doc.MimeType,
                    UploadedByID  = dto.SourceNetworkID
                });

                DataContext.ActionReferences.Add(new TaskReference {
                    TaskID = workflowTask.ID, ItemID = document.ID, Type = DTO.Enums.TaskItemTypes.ActivityDataDocument
                });
                documents.Add(document);
            }

            foreach (var datamart in dto.Routes)
            {
                var route = new RequestDataMart
                {
                    ID          = datamart.RouteID,
                    DataMartID  = datamart.DataMartID,
                    DueDate     = datamart.DueDate,
                    Priority    = datamart.Priority,
                    RequestID   = request.ID,
                    RoutingType = DTO.Enums.RoutingType.ExternalCNDS,
                    //default status is awaiting request approval, if the proxy user has permission to skip will be updated and notification sent to source request
                    Status    = DTO.Enums.RoutingStatus.AwaitingRequestApproval,
                    Responses = new HashSet <Response>()
                };

                var response = route.AddResponse(request.CreatedByID);
                response.ID = datamart.ResponseID;

                var responseDocuments = datamart.DocumentIDs.Select(docID => {
                    var dd = documents.First(d => d.ID == docID);
                    return(new RequestDocument {
                        DocumentType = DTO.Enums.RequestDocumentType.Input, ResponseID = response.ID, RevisionSetID = dd.RevisionSetID.Value
                    });
                });

                DataContext.RequestDocuments.AddRange(responseDocuments);

                request.DataMarts.Add(DataContext.RequestDataMarts.Add(route));
            }

            //Parse the query and fix the document references in the fileupload and modular program terms
            DTO.QueryComposer.QueryComposerRequestDTO queryDTO = Newtonsoft.Json.JsonConvert.DeserializeObject <DTO.QueryComposer.QueryComposerRequestDTO>(request.Query);
            var fileUploadTerms = queryDTO.Where.Criteria.SelectMany(c => c.Terms.Where(t => t.Type == Lpp.QueryComposer.ModelTermsFactory.FileUploadID || t.Type == QueryComposer.ModelTermsFactory.ModularProgramID)).ToArray();

            if (fileUploadTerms.Length > 0)
            {
                foreach (var term in fileUploadTerms)
                {
                    var termValue = Newtonsoft.Json.JsonConvert.DeserializeObject <FileUploadValues>(term.Values["Values"].ToString());
                    foreach (var termDoc in termValue.Documents)
                    {
                        var docDTO = dto.Documents.Where(d => d.SourceRevisionSetID == termDoc.RevisionSetID).FirstOrDefault();
                        if (docDTO != null)
                        {
                            termDoc.RevisionSetID = docDTO.RevisionSetID;
                        }
                    }

                    term.Values["Values"] = termValue;
                }

                request.Query = Newtonsoft.Json.JsonConvert.SerializeObject(queryDTO);
            }

            try
            {
                await DataContext.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                Logger.Error("Error saving request: " + request.ID, ex);
                System.Diagnostics.Debugger.Break();
                return(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex));
            }

            if (documents.Count > 0)
            {
                //var tasks = dto.Documents.Select(async doc => await GetDocumentContent(doc.DocumentID));
                //await Task.WhenAll(tasks);

                foreach (var doc in documents)
                {
                    await GetDocumentContent(doc.ID);
                }
            }

            //Submit the request if the proxy user has permission to skip request approval
            var permissionFilter = new ExtendedQuery
            {
                Projects             = (a) => a.ProjectID == request.ProjectID,
                ProjectOrganizations = (a) => a.ProjectID == request.ProjectID && a.OrganizationID == request.OrganizationID,
                Organizations        = (a) => a.OrganizationID == request.OrganizationID,
                Users = (a) => a.UserID == request.CreatedByID
            };

            var apiIdentity = new Utilities.Security.ApiIdentity(dto.SourceNetworkID, dto.SourceNetworkName.Replace(" ", "_"), dto.SourceNetworkName, Requests.RequestsController.CNDSOrganizationRouteProxyID);
            var permissions = await DataContext.HasGrantedPermissions <Request>(apiIdentity, request.ID, permissionFilter, Dns.DTO.Security.PermissionIdentifiers.Request.SkipSubmissionApproval);

            if (permissions.Contains(DTO.Security.PermissionIdentifiers.Request.SkipSubmissionApproval))
            {
                await DataContext.Entry(request).ReloadAsync();

                await DataContext.Entry(request).Collection(r => r.DataMarts).LoadAsync();

                var responses = (await DataContext.RequestDataMarts.Where(rdm => rdm.RequestID == request.ID && rdm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval).SelectMany(rdm => rdm.Responses.Where(rsp => rsp.Count == rdm.Responses.Max(rr => rr.Count))).ToArrayAsync()).ToDictionary(r => r.RequestDataMartID);

                //update the routings to Submitted
                foreach (var dm in request.DataMarts)
                {
                    await DataContext.Entry(dm).ReloadAsync();

                    Response response = null;
                    if (responses.TryGetValue(dm.ID, out response))
                    {
                        response.SubmittedByID = dto.SourceNetworkID;
                        response.SubmittedOn   = DateTime.UtcNow;
                    }

                    dm.Status = DTO.Enums.RoutingStatus.Submitted;
                }
                try
                {
                    await DataContext.SaveChangesAsync();
                }
                catch (Exception ex) {
                    Logger.Error(ex.Message, ex);
                    return(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex));
                }

                //update the request to submitted
                //manually override the request status using sql direct, EF does not allow update of computed
                await DataContext.Database.ExecuteSqlCommandAsync("UPDATE Requests SET Status = @status WHERE ID = @ID", new System.Data.SqlClient.SqlParameter("@status", (int)DTO.Enums.RequestStatuses.Submitted), new System.Data.SqlClient.SqlParameter("@ID", request.ID));

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

                //close the review task
                workflowTask.Status          = DTO.Enums.TaskStatuses.Complete;
                workflowTask.EndOn           = DateTime.UtcNow;
                workflowTask.PercentComplete = 100d;

                //create a new task for the next activity, and set the activity on the request
                request.WorkFlowActivityID = requestTypeDetails.SubmittedActivityID;
                var submitTask = DataContext.Actions.Add(PmnTask.CreateForWorkflowActivity(request.ID, request.WorkFlowActivityID.Value, request.WorkflowID.Value, DataContext));
                try
                {
                    await DataContext.SaveChangesAsync();
                }
                catch (Exception ex)
                {
                    Logger.Error(ex.Message, ex);
                    return(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex));
                }

                //notify CNDS of request status change, which will in turn notify the source network to update the status of the route
                System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken =>
                {
                    using (var helper = new Lpp.CNDS.ApiClient.NetworkRequestDispatcher())
                    {
                        foreach (var responseID in dto.Routes.Select(rt => rt.ResponseID))
                        {
                            await helper.UpdateSourceRoutingStatus(new[] { new DTO.CNDSUpdateRoutingStatusDTO {
                                                                               ResponseID = responseID, Message = string.Empty, RoutingStatus = DTO.Enums.RoutingStatus.Submitted
                                                                           } });
                        }
                    }
                });
            }


            return(Request.CreateResponse(HttpStatusCode.OK));;
        }
Beispiel #27
0
        public override async Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            //default to SaveResultID if resultID not specified
            if (!activityResultID.HasValue)
            {
                activityResultID = SaveResultID;
            }

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

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

            if (activityResultID.Value == SubmitResultID) //Submit
            {
                await db.LoadCollection(_entity, (r) => r.DataMarts);

                var filters = new ExtendedQuery
                {
                    Projects             = (a) => a.ProjectID == _entity.ProjectID,
                    ProjectOrganizations = a => a.ProjectID == _entity.ProjectID && a.OrganizationID == _entity.OrganizationID,
                    Organizations        = a => a.OrganizationID == _entity.OrganizationID,
                    Users = a => a.UserID == _entity.CreatedByID
                };

                var permissions = await db.HasGrantedPermissions <Request>(_workflow.Identity, _entity, filters, PermissionIdentifiers.Request.SkipSubmissionApproval);

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

                if (Newtonsoft.Json.JsonConvert.DeserializeObject <Lpp.Dns.DTO.QueryComposer.QueryComposerRequestDTO>(_entity.Query).Where.Criteria.Any(c => c.Terms.Any(t => t.Type.ToString().ToUpper() == "2F60504D-9B2F-4DB1-A961-6390117D3CAC") || c.Criteria.Any(ic => ic.Terms.Any(t => t.Type.ToString().ToUpper() == "2F60504D-9B2F-4DB1-A961-6390117D3CAC"))))
                {
                    if (!permissions.Contains(PermissionIdentifiers.Request.SkipSubmissionApproval))
                    {
                        //file distribution never requires review before submission, add the permission if the user does not have it.
                        permissions = new[] { PermissionIdentifiers.Request.SkipSubmissionApproval };
                    }

                    await db.LoadCollection(_entity, (r) => r.DataMarts);

                    if (!_entity.DataMarts.Any())
                    {
                        throw new Exception("At least one routing needs to be specified when submitting a requests.");
                    }

                    //prepare the request documents, save created documents same as legacy
                    IList <Guid> documentRevisionSets = Newtonsoft.Json.JsonConvert.DeserializeObject <IList <Guid> >(data);

                    IEnumerable <Document> documents = await(from d in db.Documents.AsNoTracking()
                                                             join x in (
                                                                 db.Documents.Where(dd => documentRevisionSets.Contains(dd.RevisionSetID.Value))
                                                                 .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 d.ID equals x
                                                             orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending
                                                             select d).ToArrayAsync();

                    await db.Entry(_entity).Reference(r => r.Activity).LoadAsync();

                    await db.Entry(_entity).Reference(r => r.RequestType).LoadAsync();

                    string submitterEmail = await db.Users.Where(u => u.ID == _workflow.Identity.ID).Select(u => u.Email).SingleAsync();

                    //update the request
                    _entity.SubmittedByID         = _workflow.Identity.ID;
                    _entity.SubmittedOn           = DateTime.UtcNow;
                    _entity.AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion;
                    _entity.RejectedByID          = null;
                    _entity.RejectedOn            = null;
                    _entity.Private = false;


                    //save the changes to the request now since the trigger for routings will change the status invalidating the object before save
                    await db.SaveChangesAsync();

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

                    var originalStatus = _entity.Status;
                    await SetRequestStatus(DTO.Enums.RequestStatuses.Submitted, false);

                    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 dm in _entity.DataMarts.Where(dm => dm.Status == 0 || dm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval || dm.Status == DTO.Enums.RoutingStatus.Draft))
                    {
                        dm.Status = DTO.Enums.RoutingStatus.Submitted;

                        var currentResponse = db.Responses.Include(rsp => rsp.RequestDocument).FirstOrDefault(r => r.RequestDataMartID == dm.ID && r.Count == r.RequestDataMart.Responses.Max(rr => rr.Count));
                        if (currentResponse == null)
                        {
                            currentResponse = db.Responses.Add(new Response {
                                RequestDataMartID = dm.ID
                            });
                        }
                        currentResponse.SubmittedByID = _workflow.Identity.ID;
                        currentResponse.SubmittedOn   = DateTime.UtcNow;

                        //add the request document associations
                        for (int i = 0; i < documentRevisionSets.Count; i++)
                        {
                            if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == documentRevisionSets[i]))
                            {
                                db.RequestDocuments.Add(new RequestDocument {
                                    RevisionSetID = documentRevisionSets[i], ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input
                                });
                            }
                        }

                        foreach (var attachment in attachments)
                        {
                            if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == attachment.RevisionSetID.Value))
                            {
                                db.RequestDocuments.Add(new RequestDocument {
                                    RevisionSetID = attachment.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput
                                });
                            }
                        }
                    }

                    await db.SaveChangesAsync();

                    //reload the request since altering the routings triggers a change of the request status in the db by a trigger.
                    await db.Entry(_entity).ReloadAsync();

                    DTO.QueryComposer.QueryComposerRequestDTO qcRequestDTO = Newtonsoft.Json.JsonConvert.DeserializeObject <DTO.QueryComposer.QueryComposerRequestDTO>(_entity.Query);
                    var fileUploadTerm = qcRequestDTO.Where.Criteria.SelectMany(c => c.Terms.Where(t => t.Type == FileUploadTermID)).FirstOrDefault();
                    var termValues     = Newtonsoft.Json.JsonConvert.DeserializeObject <FileUploadValues>(fileUploadTerm.Values["Values"].ToString());

                    //update the request.json term value to include system generated documents revisionsetIDs
                    termValues.Documents.Clear();

                    for (int i = 0; i < documentRevisionSets.Count; i++)
                    {
                        termValues.Documents.Add(new FileUploadValues.Document {
                            RevisionSetID = documentRevisionSets[i]
                        });
                    }

                    fileUploadTerm.Values["Values"] = termValues;
                    _entity.Query = Newtonsoft.Json.JsonConvert.SerializeObject(qcRequestDTO);

                    await db.SaveChangesAsync();

                    await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Submitted);
                }
                else
                {
                    await db.LoadCollection(_entity, (r) => r.DataMarts);

                    var parentDocument = db.Documents.FirstOrDefault(d => d.ItemID == _entity.ID && d.Kind == DocumentKind && d.ParentDocumentID == null);

                    byte[] documentContent = System.Text.UTF8Encoding.UTF8.GetBytes(_entity.Query ?? string.Empty);
                    var    document        = new Document
                    {
                        Name             = "Request Criteria",
                        MajorVersion     = parentDocument == null ? 1 : parentDocument.MajorVersion,
                        MinorVersion     = parentDocument == null ? 0 : parentDocument.MinorVersion,
                        RevisionVersion  = parentDocument == null ? 0 : parentDocument.RevisionVersion,
                        MimeType         = "application/json",
                        Viewable         = false,
                        UploadedByID     = _workflow.Identity.ID,
                        FileName         = "request.json",
                        CreatedOn        = DateTime.UtcNow,
                        BuildVersion     = parentDocument == null ? 0 : parentDocument.BuildVersion,
                        ParentDocumentID = parentDocument == null ? (Guid?)null : parentDocument.ID,
                        ItemID           = task.ID,
                        Length           = documentContent.LongLength,
                        Kind             = Dns.DTO.Enums.DocumentKind.Request
                    };

                    db.Documents.Add(document);
                    document.RevisionSetID = document.ID;
                    await db.SaveChangesAsync();

                    document.SetData(db, documentContent);


                    _entity.AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion;
                    //Reset reject for resubmit.
                    _entity.RejectedByID = null;
                    _entity.RejectedOn   = null;
                    _entity.Private      = false;

                    await db.SaveChangesAsync();

                    DTO.Enums.RequestStatuses newRequestStatus = DTO.Enums.RequestStatuses.AwaitingRequestApproval;

                    if (permissions.Contains(PermissionIdentifiers.Request.SkipSubmissionApproval))
                    {
                        _entity.SubmittedByID = _workflow.Identity.ID;
                        _entity.SubmittedOn   = DateTime.UtcNow;

                        await db.SaveChangesAsync();

                        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();

                        _entity.Status = DTO.Enums.RequestStatuses.Submitted;
                        foreach (var dm in _entity.DataMarts)
                        {
                            dm.Status = DTO.Enums.RoutingStatus.Submitted;

                            var currentResponse = db.Responses.Include(rsp => rsp.RequestDocument).FirstOrDefault(r => r.RequestDataMartID == dm.ID && r.Count == r.RequestDataMart.Responses.Max(rr => rr.Count));
                            if (currentResponse == null)
                            {
                                currentResponse = db.Responses.Add(new Response {
                                    RequestDataMartID = dm.ID
                                });
                            }
                            currentResponse.SubmittedByID = _workflow.Identity.ID;
                            currentResponse.SubmittedOn   = DateTime.UtcNow;

                            if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == document.RevisionSetID.Value))
                            {
                                db.RequestDocuments.Add(new RequestDocument {
                                    RevisionSetID = document.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input
                                });
                            }

                            foreach (var attachment in attachments)
                            {
                                if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == attachment.RevisionSetID.Value))
                                {
                                    db.RequestDocuments.Add(new RequestDocument {
                                        RevisionSetID = attachment.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput
                                    });
                                }
                            }
                        }
                    }
                    else
                    {
                        _entity.Status = DTO.Enums.RequestStatuses.AwaitingRequestApproval;
                        foreach (var dm in _entity.DataMarts)
                        {
                            dm.Status = DTO.Enums.RoutingStatus.AwaitingRequestApproval;
                        }
                    }

                    await db.SaveChangesAsync();

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


                    await MarkTaskComplete(task);
                }

                return(new CompletionResult
                {
                    ResultID = permissions.Contains(PermissionIdentifiers.Request.SkipSubmissionApproval) ? SubmitResultID : ReviewResultID
                });
            }
            else if (activityResultID.Value == SaveResultID) //Save
            {
                if (_entity.Private)
                {
                    await db.Entry(_entity).ReloadAsync();

                    _entity.Private = false;

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

                    await db.SaveChangesAsync();
                }

                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }
            else if (activityResultID.Value == DeleteResultID) //Delete
            {
                _workflow.DataContext.Requests.Remove(_workflow.Entity);

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

                await _workflow.DataContext.SaveChangesAsync();

                return(null);
            }
            else
            {
                throw new ArgumentOutOfRangeException(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);
            }
        }
        public async override Task <CompletionResult> Complete(string data, Guid?activityResultID)
        {
            if (activityResultID.Value == SaveResultID)
            {
                return(new CompletionResult
                {
                    ResultID = SaveResultID
                });
            }

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

            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();

            await db.LoadCollection(_entity, (r) => r.DataMarts);

            if (activityResultID.Value == ApproveResultID)
            {
                _entity.SubmittedByID = _workflow.Identity.ID;
                _entity.SubmittedOn   = DateTime.UtcNow;

                var responses = await db.RequestDataMarts.Where(rdm => rdm.RequestID == _entity.ID && rdm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval).SelectMany(rdm => rdm.Responses.Where(rsp => rsp.Count == rdm.Responses.Max(rr => rr.Count))).ToArrayAsync();

                var previousTask = await(from a in db.Actions
                                         join ar in db.ActionReferences on a.ID equals ar.TaskID
                                         where ar.ItemID == _entity.ID && a.Status == DTO.Enums.TaskStatuses.Complete select a).OrderByDescending(p => p.CreatedOn).FirstOrDefaultAsync();

                var document = await(from d in db.Documents.AsNoTracking()
                                     join x in (
                                         db.Documents.Where(dd => dd.ItemID == previousTask.ID && dd.FileName == "request.json" && dd.Kind == Dns.DTO.Enums.DocumentKind.Request)
                                         .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 d.ID equals x
                                     orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending
                                     select d).FirstOrDefaultAsync();

                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 dm in _entity.DataMarts.Where(dm => dm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval))
                {
                    dm.Status = DTO.Enums.RoutingStatus.Submitted;

                    var currentResponse = responses.Where(rsp => rsp.RequestDataMartID == dm.ID).FirstOrDefault();
                    if (currentResponse == null)
                    {
                        currentResponse = db.Responses.Add(new Response {
                            RequestDataMartID = dm.ID
                        });
                    }
                    currentResponse.SubmittedByID = _workflow.Identity.ID;
                    currentResponse.SubmittedOn   = DateTime.UtcNow;

                    //get existing request documents associated to the response, add only missing documents
                    var existingRequestDocuments = await db.RequestDocuments.Where(rd => rd.ResponseID == currentResponse.ID).ToArrayAsync();

                    if (!existingRequestDocuments.Any(ed => ed.RevisionSetID == document.RevisionSetID.Value))
                    {
                        db.RequestDocuments.Add(new RequestDocument {
                            RevisionSetID = document.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input
                        });
                    }

                    foreach (var attachment in attachments.Where(att => !existingRequestDocuments.Any(ed => ed.RevisionSetID == att.RevisionSetID.Value)))
                    {
                        db.RequestDocuments.Add(new RequestDocument {
                            RevisionSetID = attachment.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput
                        });
                    }
                }

                _entity.Status = DTO.Enums.RequestStatuses.Submitted;

                await db.SaveChangesAsync();

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

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

                await MarkTaskComplete(task);

                await NotifyRequestStatusChanged(DTO.Enums.RequestStatuses.AwaitingRequestApproval, DTO.Enums.RequestStatuses.Submitted);

                return(new CompletionResult
                {
                    ResultID = ApproveResultID
                });
            }
            else if (activityResultID.Value == RejectResultID)
            {
                //rejecting prior to submission terminates the request.

                foreach (var dm in _entity.DataMarts.Where(dm => dm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval))
                {
                    dm.Status = DTO.Enums.RoutingStatus.RequestRejected;
                }

                await db.SaveChangesAsync();

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

                _entity.RejectedByID = _workflow.Identity.ID;
                _entity.RejectedOn   = DateTime.UtcNow;
                //Update the workflow activity to request composition
                _entity.WorkFlowActivityID = DefaultWorkflowConfiguration.NewRequestActivityID;

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

                //create a completed task to show the request was rejected.
                PmnTask rejectedTask = db.Actions.Add(PmnTask.CreateForWorkflowActivity(_entity.ID, DefaultWorkflowConfiguration.NewRequestActivityID, _workflow.ID, db));
                rejectedTask.Subject = "Request Rejected Prior to Submission";
                rejectedTask.Status  = DTO.Enums.TaskStatuses.InProgress;

                if (!data.IsNullOrEmpty())
                {
                    rejectedTask.Body = data.ToStringEx();

                    var cmt = db.Comments.Add(new Comment
                    {
                        CreatedByID = _workflow.Identity.ID,
                        ItemID      = _entity.ID,
                        Text        = data.ToStringEx()
                    });

                    db.CommentReferences.Add(new CommentReference {
                        CommentID = cmt.ID,
                        Type      = DTO.Enums.CommentItemTypes.Task,
                        ItemTitle = rejectedTask.Subject,
                        ItemID    = rejectedTask.ID
                    });
                }

                await MarkTaskComplete(task);

                await NotifyRequestStatusChanged(DTO.Enums.RequestStatuses.AwaitingRequestApproval, DTO.Enums.RequestStatuses.RequestRejected);

                return(null);
            }
            else
            {
                throw new NotSupportedException(CommonMessages.ActivityResultNotSupported);
            }
        }
Beispiel #30
0
        public override async Task Start(string comment)
        {
            var task = await PmnTask.GetActiveTaskForRequestActivityAsync(_entity.ID, ID, db);

            if (task == null)
            {
                task = db.Actions.Add(PmnTask.CreateForWorkflowActivity(_entity.ID, ID, _workflow.ID, db, CustomTaskSubject));
                await db.SaveChangesAsync();

                var analysisCenterRouting = await db.RequestDataMarts.Include(rdm => rdm.Responses).Where(rdm => rdm.RequestID == _entity.ID && rdm.RoutingType == RoutingType.AnalysisCenter).FirstOrDefaultAsync();

                Lpp.Dns.Data.Response analysisCenterResponse = null;
                if (analysisCenterRouting.Status == RoutingStatus.Draft && analysisCenterRouting.Responses.Count == 1 && analysisCenterRouting.Responses.Where(rsp => rsp.ResponseTime.HasValue == false).Any())
                {
                    //if the initial status of the routing is draft, and there is only a single response assume this is the first time hitting the analysis center.
                    //use the existing response to submit to the analysis center
                    analysisCenterResponse = analysisCenterRouting.Responses.First();
                }
                else if (analysisCenterRouting.Status != RoutingStatus.Draft)
                {
                    analysisCenterRouting.Status = RoutingStatus.Draft;
                }

                if (analysisCenterResponse == null)
                {
                    analysisCenterResponse = analysisCenterRouting.AddResponse(_workflow.Identity.ID);
                }

                if (db.Entry(task).Collection(t => t.References).IsLoaded == false)
                {
                    await db.Entry(task).Collection(t => t.References).LoadAsync();
                }

                if (task.References.Any(tr => tr.ItemID == analysisCenterResponse.ID) == false)
                {
                    //add a reference to the response to be able to link task to iteration
                    task.References.Add(new TaskReference {
                        ItemID = analysisCenterResponse.ID, TaskID = task.ID, Type = TaskItemTypes.Response
                    });
                }

                //use all the dp output documents to be the input documents for the AC routing
                //build a manifest for where the documents are coming from
                List <Lpp.Dns.DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem> manifestItems = new List <DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem>();
                var documents = await(from rd in db.RequestDocuments
                                      join rsp in db.Responses on rd.ResponseID equals rsp.ID
                                      join rdm in db.RequestDataMarts on rsp.RequestDataMartID equals rdm.ID
                                      join dm in db.DataMarts on rdm.DataMartID equals dm.ID
                                      join doc in db.Documents on rd.RevisionSetID equals doc.RevisionSetID
                                      where rsp.Count == rsp.RequestDataMart.Responses.Max(r => r.Count) &&
                                      rdm.RequestID == _entity.ID &&
                                      rd.DocumentType == RequestDocumentType.Output &&
                                      rdm.RoutingType == RoutingType.DataPartner &&
                                      doc.ID == db.Documents.Where(dd => dd.RevisionSetID == doc.RevisionSetID).OrderByDescending(dd => dd.MajorVersion).ThenByDescending(dd => dd.MinorVersion).ThenByDescending(dd => dd.BuildVersion).ThenByDescending(dd => dd.RevisionVersion).Select(dd => dd.ID).FirstOrDefault()
                                      select new
                {
                    DocumentID            = doc.ID,
                    DocumentKind          = doc.Kind,
                    DocumentFileName      = doc.FileName,
                    ResponseID            = rd.ResponseID,
                    RevisionSetID         = rd.RevisionSetID,
                    RequestDataMartID     = rsp.RequestDataMartID,
                    DataMartID            = rdm.DataMartID,
                    DataPartnerIdentifier = dm.DataPartnerIdentifier,
                    DataMart = dm.Name
                }).ToArrayAsync();

                // further filtering based on if a output filelist document was included needs to be done. Only the files indicated should be passed on to the analysis center
                foreach (var dpDocuments in documents.GroupBy(k => k.RequestDataMartID))
                {
                    var filelistDocument = dpDocuments.Where(d => !string.IsNullOrEmpty(d.DocumentKind) && string.Equals("DistributedRegression.FileList", d.DocumentKind, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                    if (filelistDocument != null)
                    {
                        //only include the files indicated in the filelist document
                        using (var ds = new Lpp.Dns.Data.Documents.DocumentStream(db, filelistDocument.DocumentID))
                            using (var reader = new System.IO.StreamReader(ds))
                            {
                                //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 = dpDocuments.Where(d => string.Equals(d.DocumentFileName, filename, StringComparison.OrdinalIgnoreCase)).Select(d => d.RevisionSetID).FirstOrDefault();
                                            if (revisionSetID.HasValue)
                                            {
                                                db.RequestDocuments.AddRange(dpDocuments.Where(d => d.RevisionSetID == revisionSetID.Value).Select(d => new RequestDocument {
                                                    DocumentType = RequestDocumentType.Input, ResponseID = analysisCenterResponse.ID, RevisionSetID = d.RevisionSetID
                                                }).ToArray());
                                                manifestItems.AddRange(dpDocuments.Where(d => d.RevisionSetID == revisionSetID.Value).Select(d => new DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem
                                                {
                                                    DocumentID            = d.DocumentID,
                                                    DataMart              = d.DataMart,
                                                    DataMartID            = d.DataMartID,
                                                    DataPartnerIdentifier = d.DataPartnerIdentifier,
                                                    RequestDataMartID     = d.RequestDataMartID,
                                                    ResponseID            = d.ResponseID,
                                                    RevisionSetID         = d.RevisionSetID
                                                }).ToArray());
                                            }
                                        }
                                    }
                                }

                                reader.Close();
                            }
                    }
                    else
                    {
                        db.RequestDocuments.AddRange(dpDocuments.Select(d => new RequestDocument {
                            DocumentType = RequestDocumentType.Input, ResponseID = analysisCenterResponse.ID, RevisionSetID = d.RevisionSetID
                        }).ToArray());
                        manifestItems.AddRange(dpDocuments.Select(d => new DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem
                        {
                            DocumentID            = d.DocumentID,
                            DataMart              = d.DataMart,
                            DataMartID            = d.DataMartID,
                            DataPartnerIdentifier = d.DataPartnerIdentifier,
                            RequestDataMartID     = d.RequestDataMartID,
                            ResponseID            = d.ResponseID,
                            RevisionSetID         = d.RevisionSetID
                        }).ToArray());
                    }
                }

                //serialize the manifest of dataparter documents to the analysis center
                byte[] buffer;
                using (var ms = new System.IO.MemoryStream())
                    using (var sw = new System.IO.StreamWriter(ms))
                        using (var jw = new Newtonsoft.Json.JsonTextWriter(sw))
                        {
                            Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer();
                            serializer.Serialize(jw, manifestItems);
                            jw.Flush();

                            buffer = ms.ToArray();
                        }

                //create and add the manifest file
                Document analysisCenterManifest = db.Documents.Add(new Document
                {
                    Description  = "Contains information about the input documents and the datamart they came from.",
                    Name         = "Internal: Analysis Center Manifest",
                    FileName     = "manifest.json",
                    ItemID       = task.ID,
                    Kind         = DocumentKind.SystemGeneratedNoLog,
                    UploadedByID = _workflow.Identity.ID,
                    Viewable     = false,
                    MimeType     = "application/json",
                    Length       = buffer.Length
                });

                analysisCenterManifest.RevisionSetID = analysisCenterManifest.ID;

                db.RequestDocuments.Add(new RequestDocument {
                    DocumentType = RequestDocumentType.Input, ResponseID = analysisCenterResponse.ID, RevisionSetID = analysisCenterManifest.RevisionSetID.Value
                });

                await db.SaveChangesAsync();

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

                //post the manifest content
                analysisCenterManifest.SetData(db, buffer);

                //submit the routing
                analysisCenterRouting.Status = analysisCenterResponse.Count > 1 ? RoutingStatus.Resubmitted : RoutingStatus.Submitted;
                await db.SaveChangesAsync();

                //change the status of the request to conducting analysis
                //manually override the request status using sql direct, EF does not allow update of computed
                await db.Database.ExecuteSqlCommandAsync("UPDATE Requests SET Status = @status WHERE ID = @ID", new System.Data.SqlClient.SqlParameter("@status", (int)RequestStatuses.ConductingAnalysis), new System.Data.SqlClient.SqlParameter("@ID", _entity.ID));

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

            if (!string.IsNullOrWhiteSpace(comment))
            {
                var cmt = db.Comments.Add(new Comment
                {
                    CreatedByID = _workflow.Identity.ID,
                    ItemID      = _entity.ID,
                    Text        = comment
                });

                db.CommentReferences.Add(new CommentReference
                {
                    CommentID = cmt.ID,
                    Type      = DTO.Enums.CommentItemTypes.Task,
                    ItemTitle = task.Subject,
                    ItemID    = task.ID
                });

                await db.SaveChangesAsync();
            }
        }