Esempio n. 1
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="request"></param>
 /// <returns></returns>
 public async Task Process(RequestDataMart reqDM)
 {
     if (reqDM.Request.WorkFlowActivityID.Value == CompleteDistributionActivityID)
     {
         //Complete Distribution step: Data Partners => Analysis Center
         await FromDataPartner(reqDM);
     }
     else if (reqDM.Request.WorkFlowActivityID.Value == ConductAnalysisActivityID)
     {
         //Conduct Analysis step: Analysis Center => Data Partners or Stop
         await FromAnalysisCenter(reqDM);
     }
 }
Esempio n. 2
0
        public void PostResponseDocuments()
        {
            DataContext db       = new DataContext();
            Response    response = null;

            try
            {
                RequestDataMart routing = db.RequestDataMarts.Include(dm => dm.Responses).Where(dm => dm.Status == DTO.Enums.RoutingStatus.Submitted && dm.Responses.Count > 0).OrderByDescending(dm => dm.RequestTime).FirstOrDefault();
                response = routing.AddResponse(db.Users.Where(u => u.UserName == TestDMCController.TestUserName).Select(u => u.ID).Single());
                db.SaveChanges();

                Guid[] result = null;
                using (var controller = new TestDMCController())
                {
                    var postData = new Lpp.Dns.DTO.DataMartClient.Criteria.PostResponseDocumentsData
                    {
                        RequestID  = routing.RequestID,
                        DataMartID = routing.DataMartID,
                        Documents  = new[] { new DTO.DataMartClient.Document {
                                                 Name = "test-document.txt", IsViewable = false, MimeType = "text/plain", Size = 0
                                             } }
                    };
                    result = AsyncHelpers.RunSync <Guid[]>(() => controller.PostResponseDocuments(postData));
                }

                Assert.IsNotNull(result);
                Assert.IsTrue(result.Count() > 0);

                Guid     documentID = result.ToArray().First();
                Document doc        = db.Documents.FirstOrDefault(d => d.ID == documentID);
                Assert.IsNotNull(doc);
            }
            finally
            {
                if (response != null)
                {
                    db.Documents.RemoveRange(db.Documents.Where(d => d.ItemID == response.ID));
                    db.Responses.Remove(response);
                    db.SaveChanges();
                }
                db.Dispose();
            }
        }
Esempio n. 3
0
        private void LogStatusChange <T>(Lpp.Security.SecurityTarget st, RoutingStatus newStatus, RequestDataMart datamart) where T : Events.RequestStatusChangeBase, new()
        {
            throw new Lpp.Utilities.CodeToBeUpdatedException();

            //Audit.CreateEvent(st, new T
            //{
            //    ActingUser = Auth.CurrentUser.Id,
            //    Request = dm.RequestId,
            //    Project = (dm.Request.Project ?? VirtualSecObjects.AllProjects).SID,
            //    RequestType = dm.Request.RequestTypeId,
            //    Name = dm.Request.Name,
            //    DataMart = dm.DataMartId,
            //    OldStatus = RoutingStatuses.AwaitingRequestApproval.ToString(),
            //    NewStatus = newStatus.ToString(),
            //})
            //.Log();
        }
        /// <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);
            }
        }
        /// <summary>
        /// Initiates the Document object to be saved in the database
        /// </summary>
        /// <returns></returns>
        public async Task SetUpDocumentInDatabase()
        {
            Response response = await _dataContext.Responses
                                .Where(rsp => rsp.RequestDataMart.DataMartID == DocumentMetadata.DataMartID && rsp.RequestDataMart.RequestID == DocumentMetadata.RequestID)
                                .OrderByDescending(rsp => rsp.Count)
                                .FirstOrDefaultAsync();

            if (response == null)
            {
                RequestDataMart datamart = await _dataContext.RequestDataMarts.FirstOrDefaultAsync(dm => dm.DataMartID == DocumentMetadata.DataMartID && dm.RequestID == DocumentMetadata.RequestID);

                if (datamart == null)
                {
                    throw new Exception($"Unable to determine the routing for the specified request and datamart. RequestID: { DocumentMetadata.RequestID }, DataMartID: {DocumentMetadata.DataMartID}");
                }

                //create the response
                response             = datamart.AddResponse(_identity.ID);
                response.SubmittedOn = DateTime.UtcNow;
            }

            if (_dataContext.Documents.Any(d => d.ItemID == response.ID && d.FileName == DocumentMetadata.Name))
            {
                //Get existing documents with revision
                var existingDocuments = await _dataContext.Documents.AsNoTracking().Where(d => d.ItemID == response.ID && d.FileName == DocumentMetadata.Name).Select(d => new { d.FileName, d.MajorVersion, d.MinorVersion, d.BuildVersion, d.RevisionVersion, d.ID, d.RevisionSetID }).ToArrayAsync();

                var existingRequestDocuments = await _dataContext.RequestDocuments.AsNoTracking().Where(rd => rd.ResponseID == response.ID).ToListAsync();

                //get the most recent parent document
                var pDoc = existingDocuments.Where(ed => ed.FileName == DocumentMetadata.Name).OrderByDescending(ed => ed.MajorVersion).ThenByDescending(ed => ed.MinorVersion).ThenByDescending(ed => ed.BuildVersion).ThenByDescending(ed => ed.RevisionVersion).First();

                Doc = new Document
                {
                    ID               = DocumentMetadata.ID,
                    ItemID           = response.ID,
                    FileName         = DocumentMetadata.Name,
                    Name             = DocumentMetadata.Name,
                    Description      = string.Empty,
                    UploadedByID     = _identity.ID,
                    MimeType         = DocumentMetadata.MimeType,
                    Length           = DocumentMetadata.Size,
                    Viewable         = DocumentMetadata.IsViewable,
                    Kind             = DocumentMetadata.Kind,
                    RevisionSetID    = pDoc.RevisionSetID,
                    ParentDocumentID = pDoc.ID,
                    MajorVersion     = pDoc.MajorVersion,
                    MinorVersion     = pDoc.MinorVersion,
                    BuildVersion     = pDoc.BuildVersion,
                    RevisionVersion  = pDoc.RevisionVersion + 1
                };
            }
            else
            {
                Doc = new Document
                {
                    ID               = DocumentMetadata.ID,
                    ItemID           = response.ID,
                    FileName         = DocumentMetadata.Name,
                    Name             = DocumentMetadata.Name,
                    ParentDocumentID = null,
                    MimeType         = DocumentMetadata.MimeType,
                    Length           = DocumentMetadata.Size,
                    Viewable         = DocumentMetadata.IsViewable,
                    Kind             = DocumentMetadata.Kind,
                    Description      = string.Empty,
                    UploadedByID     = _identity.ID,
                    RevisionSetID    = DocumentMetadata.ID
                };
            }

            _dataContext.Documents.Add(Doc);

            //If workflow add to RequestDocuments
            var requestWorkflowActivityID = await _dataContext.Requests.Where(r => r.ID == DocumentMetadata.RequestID).Select(x => x.WorkFlowActivityID).FirstOrDefaultAsync();

            if (requestWorkflowActivityID.HasValue)
            {
                if (!_dataContext.RequestDocuments.Any(rd => rd.ResponseID == Doc.ItemID && rd.RevisionSetID == Doc.RevisionSetID && rd.DocumentType == DTO.Enums.RequestDocumentType.Output))
                {
                    _dataContext.RequestDocuments.Add(new RequestDocument {
                        ResponseID = Doc.ItemID, RevisionSetID = Doc.RevisionSetID.Value, DocumentType = DTO.Enums.RequestDocumentType.Output
                    });
                }
            }

            await _dataContext.SaveChangesAsync();
        }
 public UnapprovedResultsReminder(RequestDataMart r) : base(r)
 {
 }
Esempio n. 7
0
        public void PostResponseDocumentsWithContent()
        {
            const string string1 = "This is a test document.";
            const string string2 = " This is the second sentence.";

            byte[] string1Data = Encoding.Default.GetBytes(string1);
            byte[] string2Data = Encoding.Default.GetBytes(string2);

            DataContext db       = new DataContext();
            Response    response = null;

            try
            {
                RequestDataMart routing = db.RequestDataMarts.Include(dm => dm.Responses).Where(dm => dm.Status == DTO.Enums.RoutingStatus.Submitted && dm.Responses.Count > 0).OrderByDescending(dm => dm.RequestTime).FirstOrDefault();
                response             = routing.AddResponse(db.Users.Where(u => u.UserName == TestDMCController.TestUserName).Select(u => u.ID).Single());
                response.SubmittedOn = DateTime.Now;
                db.SaveChanges();

                Guid[] result = null;
                Guid   documentID;
                using (var controller = new TestDMCController())
                {
                    var postData = new Lpp.Dns.DTO.DataMartClient.Criteria.PostResponseDocumentsData {
                        RequestID  = routing.RequestID,
                        DataMartID = routing.DataMartID,
                        Documents  = new[] { new DTO.DataMartClient.Document {
                                                 Name = "test-document.txt", IsViewable = false, MimeType = "text/plain", Size = 0
                                             } }
                    };
                    result = AsyncHelpers.RunSync <Guid[]>(() => controller.PostResponseDocuments(postData));

                    documentID = result.ToArray()[0];
                    System.Net.Http.HttpResponseMessage postResponse = AsyncHelpers.RunSync <System.Net.Http.HttpResponseMessage>(() => controller.PostResponseDocumentChunk(documentID, string1Data));
                    Assert.IsTrue(postResponse.StatusCode == System.Net.HttpStatusCode.OK);
                    postResponse = AsyncHelpers.RunSync <System.Net.Http.HttpResponseMessage>(() => controller.PostResponseDocumentChunk(documentID, string2Data));
                    Assert.IsTrue(postResponse.StatusCode == System.Net.HttpStatusCode.OK);
                }

                Assert.IsNotNull(result);
                Assert.IsTrue(result.Count() > 0);

                Document doc = db.Documents.FirstOrDefault(d => d.ID == documentID);
                Assert.IsNotNull(doc);

                byte[] docData = doc.GetData(db);

                Assert.AreEqual(string1Data.Length + string2Data.Length, docData.Length);
                string savedString = Encoding.Default.GetString(docData);
                Console.WriteLine(savedString);
            }
            finally
            {
                if (response != null)
                {
                    db.Database.ExecuteSqlCommand("DELETE FROM Documents WHERE ItemID = @p0", response.ID);
                    db.Database.ExecuteSqlCommand("DELETE FROM RequestDataMartResponses WHERE ID = @p0", response.ID);
                    db.SaveChanges();
                }
                db.Dispose();
            }
        }
Esempio n. 8
0
        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));;
        }
        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
            });
        }
        public static Lpp.Security.SecurityTarget AsEventTarget(this RequestDataMart r)
        {
            throw new Lpp.Utilities.CodeToBeUpdatedException();

            //return Sec.Target( r.Request.Project ?? VirtualSecObjects.AllProjects, r.DataMart.Organization, r.DataMart, r.Request );
        }
        private Request CreateRequest(Project project, RequestType requestType, ApiIdentity userIdentity)
        {
            Guid?projectID = project == null ? new Nullable <Guid>() : project.ID;

            var requestTypeIDs = DataContext.Secure <RequestType>(userIdentity)
                                 .If(projectID.HasValue, q => q.Where(r =>
                                                                      DataContext.ProjectRequestTypeAcls.Any(a => a.RequestTypeID == r.ID && a.ProjectID == projectID.Value && a.Permission > 0) ||
                                                                      DataContext.ProjectDataMartRequestTypeAcls.Any(a => a.RequestTypeID == r.ID && a.ProjectID == projectID.Value && a.Permission > 0) ||
                                                                      DataContext.ProjectDataMarts.Where(pd => pd.ProjectID == projectID.Value).Any(dm => dm.DataMart.DataMartRequestTypeAcls.Any(a => a.RequestTypeID == r.ID && a.Permission > 0))
                                                                      ))
                                 .Where(r => r.ProcessorID.HasValue && DataContext.Projects.Where(p => !p.Deleted).Any())
                                 .Select(r => r.ID)
                                 .ToSet();

            if (!requestTypeIDs.Contains(requestType.ID))
            {
                throw new UnauthorizedAccessException();
            }

            if (project == null)
            {
                /**
                 * BMS: When saving or submitting the request, edit rules prevent the project from being null, however if the user navigates away w/o saving the request,
                 * the request is effectively lost from any view.  To prevent this, always initialize the view with a "default" project which in this case is the first one
                 * in the list.  Better would be to designate a "Default" project and choose it when it doubt, or use the project chosen on the last request saved/submitted.
                 **/

                project = DataContext.Secure <Project>(userIdentity)
                          .Where(p => !p.Deleted &&
                                 !p.Group.Deleted &&
                                 !p.Deleted &&
                                 (p.ProjectDataMartRequestTypeAcls.Any(a => a.RequestTypeID == requestType.ID && a.Permission > 0 && a.SecurityGroup.Users.Any(u => u.UserID == userIdentity.ID)) ||
                                  p.ProjectRequestTypeAcls.Any(a => a.RequestTypeID == requestType.ID && a.Permission > 0 && a.SecurityGroup.Users.Any(u => u.UserID == userIdentity.ID)))
                                 ).FirstOrDefault();

                if (project == null)
                {
                    //final fallback to use the project chosen on the last request saved/submitted
                    project = DataContext.Requests.Where(r => r.SubmittedByID == userIdentity.ID && !r.Deleted && r.Project.Active && !r.Project.Deleted).Select(r => r.Project).FirstOrDefault();
                }
            }

            if (project == null)
            {
                throw new UnauthorizedAccessException("A Project was not specified and is required to create a request; could not determine a default project to assign based on the current security permissions. Please make sure permission has been granted for the desired request type to at least one Project.");
            }

            string requestName = requestType.Name + " - " + DataContext.Requests.Count(r => r.RequestTypeID == requestType.ID);
            var    request     = DataContext.Requests.Add(new Request
            {
                Name                   = requestName.Substring(0, Math.Min(requestName.Length, MaxRequestNameLength)),
                Description            = "",
                AdditionalInstructions = "",
                Project                = project,
                RequestTypeID          = requestType.ID,
                CreatedByID            = userIdentity.ID,
                UpdatedByID            = userIdentity.ID,
                OrganizationID         = userIdentity.EmployerID.HasValue ? userIdentity.EmployerID.Value : Guid.Empty,
                Priority               = Priorities.Medium,
                DataMarts              = new List <RequestDataMart>()
            });

            foreach (var dm in GetGrantedDataMarts(project, requestType.ID, userIdentity))
            {
                var datamart        = dm;
                var requestDataMart = new RequestDataMart {
                    DataMart = datamart, Responses = new HashSet <Response>()
                };
                requestDataMart.Responses.Add(new Response {
                    RequestDataMart = requestDataMart, SubmittedByID = userIdentity.ID
                });
                requestDataMart.Priority = DTO.Enums.Priorities.Medium;
                requestDataMart.Status   = RoutingStatus.Draft;
                request.DataMarts.Add(requestDataMart);
            }

            //TODO: does default security need to be explicitly set or is it handled in triggers?
            //SecurityHierarchy.SetObjectInheritanceParent(res, VirtualSecObjects.AllRequests);

            return(request);
        }
        private Request CopyRequest(Request request, ApiIdentity userIdentity)
        {
            Project project    = DataContext.Projects.SingleOrDefault(p => p.ID == request.ProjectID);
            var     newRequest = CreateRequest(project, request.RequestType, userIdentity);

            newRequest.Name                     = request.Name;
            newRequest.Description              = request.Description ?? string.Empty;
            newRequest.AdditionalInstructions   = request.AdditionalInstructions ?? string.Empty;
            newRequest.PurposeOfUse             = request.PurposeOfUse;
            newRequest.PhiDisclosureLevel       = request.PhiDisclosureLevel;
            newRequest.Priority                 = request.Priority;
            newRequest.ActivityID               = request.ActivityID;
            newRequest.Activity                 = request.ActivityID == null ? null : DataContext.Activities.SingleOrDefault(a => a.ID == request.ActivityID);
            newRequest.ActivityDescription      = request.ActivityDescription ?? string.Empty;
            newRequest.SourceActivityID         = request.SourceActivityID;
            newRequest.SourceActivity           = request.SourceActivityID == null ? null : DataContext.Activities.SingleOrDefault(a => a.ID == request.SourceActivityID);
            newRequest.SourceActivityProjectID  = request.SourceActivityProjectID;
            newRequest.SourceActivityProject    = request.SourceActivityProjectID == null ? null : DataContext.Activities.SingleOrDefault(a => a.ID == request.SourceActivityProjectID);
            newRequest.SourceTaskOrderID        = request.SourceTaskOrderID;
            newRequest.SourceTaskOrder          = request.SourceTaskOrderID == null ? null : DataContext.Activities.SingleOrDefault(a => a.ID == request.SourceTaskOrderID);
            newRequest.DueDate                  = request.DueDate;
            newRequest.WorkplanTypeID           = request.WorkplanTypeID;
            newRequest.RequesterCenterID        = request.RequesterCenterID;
            newRequest.MirrorBudgetFields       = request.MirrorBudgetFields;
            newRequest.MSRequestID              = request.MSRequestID;
            newRequest.ReportAggregationLevelID = request.ReportAggregationLevelID;

            newRequest.Name =
                Enumerable.Range(2, int.MaxValue - 2)
                .Select(i => " " + i)
                .Select(suffix => " (Copy" + suffix + ")")
                .Select(suffix => newRequest.Name.Substring(0, Math.Min(newRequest.Name.Length, MaxRequestNameLength - suffix.Length)) + suffix)
                .Where(name => !DataContext.Requests.Any(r => r.Name == name))
                .FirstOrDefault();

            if (newRequest.Name == null)
            {
                newRequest.Name = newRequest.Name;
            }

            newRequest.MSRequestID =
                Enumerable.Range(2, int.MaxValue - 2)
                .Select(i => " " + i)
                .Select(suffix => " (Copy" + suffix + ")")
                .Select(suffix => newRequest.MSRequestID.Substring(0, Math.Min(newRequest.MSRequestID.Length, MaxRequestNameLength - suffix.Length)) + suffix)
                .Where(msId => !DataContext.Requests.Any(r => r.MSRequestID == msId))
                .FirstOrDefault();

            if (newRequest.MSRequestID == null)
            {
                newRequest.MSRequestID = "";
            }

            if (string.IsNullOrWhiteSpace(newRequest.Name))
            {
                throw new InvalidOperationException("Request name cannot be empty");
            }

            if (newRequest.MSRequestID != null && newRequest.MSRequestID != "" &&
                (DataContext.Requests.Any(req => req.MSRequestID == newRequest.MSRequestID && req.ID != newRequest.ID)))
            {
                throw new InvalidOperationException("The Request ID entered is not unique. Please enter in a different Request ID.");
            }

            if (newRequest.MSRequestID == null || newRequest.MSRequestID == "")
            {
                newRequest.MSRequestID = "Request " + newRequest.Identifier.ToString();
            }

            if (newRequest.DueDate.HasValue)
            {
                newRequest.DueDate = newRequest.DueDate.Value.AddHours(12);
            }

            newRequest.DataMarts.Clear();

            foreach (var dm in DataContext.RequestDataMarts.Where(rdm => rdm.RequestID == request.ID && rdm.Status != RoutingStatus.Canceled && DataContext.DataMarts.Any(dm => dm.ID == rdm.DataMartID)).ToArray())
            {
                var originalDataMart = dm;
                var requestDataMart  = new RequestDataMart
                {
                    DataMartID = originalDataMart.DataMartID,
                    RequestID  = newRequest.ID,
                    Status     = RoutingStatus.Draft,
                    Responses  = new HashSet <Response>()
                };

                newRequest.DataMarts.Add(requestDataMart);

                requestDataMart.Responses.Add(new Response
                {
                    RequestDataMartID = requestDataMart.ID,
                    RequestDataMart   = requestDataMart,
                    SubmittedByID     = userIdentity.ID
                });
            }

            var documents = DataContext.Documents.Where(d => d.ItemID == request.ID).ToArray();
            Dictionary <Guid, Document> newDocuments = new Dictionary <Guid, Document>();

            foreach (var document in documents)
            {
                var newDocument = new Document
                {
                    CreatedOn = DateTime.UtcNow,
                    FileName  = document.FileName,
                    ItemID    = newRequest.ID,
                    Kind      = document.Kind,
                    Length    = document.Length,
                    MimeType  = document.MimeType,
                    Name      = document.Name,
                    Viewable  = document.Viewable
                };

                newDocuments.Add(document.ID, newDocument);
                DataContext.Documents.Add(newDocument);
            }

            DataContext.SaveChanges();

            foreach (var document in newDocuments)
            {
                document.Value.CopyData(DataContext, document.Key);
            }

            DataContext.SaveChanges();

            return(newRequest);
        }
Esempio n. 13
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        async Task FromDataPartner(RequestDataMart reqDM)
        {
            //close the current task
            var currentTask = await PmnTask.GetActiveTaskForRequestActivityAsync(reqDM.Request.ID, reqDM.Request.WorkFlowActivityID.Value, DB);

            CompleteTask(currentTask);

            //open new task and set the request to the new activity
            var task = DB.Actions.Add(PmnTask.CreateForWorkflowActivity(reqDM.Request.ID, ConductAnalysisActivityID, WorkflowID, DB));

            reqDM.Request.WorkFlowActivityID = ConductAnalysisActivityID;

            //create new routing
            var analysisCenterRouting = await DB.RequestDataMarts.Include(rdm => rdm.Responses).Where(rdm => rdm.RequestID == reqDM.Request.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(IdentityID);
            }

            //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 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 == rsp.RequestDataMart.Responses.Max(r => r.Count) &&
                    rdm.RequestID == reqDM.Request.ID &&
                    rd.DocumentType == RequestDocumentType.Output &&
                    rdm.RoutingType == RoutingType.DataPartner &&
                    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();

            // 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
                {
                    var inputDocuments = dpDocuments.Where(d => d.DocumentKind != "DistributedRegression.AdapterEventLog" && d.DocumentKind != "DistributedRegression.TrackingTable");
                    if (inputDocuments.Count() > 0)
                    {
                        DB.RequestDocuments.AddRange(inputDocuments.Select(d => new RequestDocument {
                            DocumentType = RequestDocumentType.Input, ResponseID = analysisCenterResponse.ID, RevisionSetID = d.RevisionSetID
                        }).ToArray());
                        manifestItems.AddRange(inputDocuments.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 = IdentityID,
                Viewable     = false,
                MimeType     = "application/json",
                Length       = buffer.Length
            });

            analysisCenterManifest.RevisionSetID = analysisCenterManifest.ID;

            //TODO:determine if there is a parent document to make the manifest a revision of. If there is update the revisionset id, and version numbers
            //chances are there should not be unless this is a resubmit for the same task

            var allTasks = await DB.ActionReferences.Where(tr => tr.ItemID == reqDM.Request.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();

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

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

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

            //Check for Job Fail trigger, and update Data Partner Routing to Failed.
            //Request status will not be affected.
            if (documents.Any(d => d.DocumentKind == JobFailTriggerFileKind))
            {
                //Reload the entity before updating the status, else EF will report an exception.
                await DB.Entry(reqDM).ReloadAsync();

                reqDM.Status = RoutingStatus.Failed;
                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", reqDM.Request.ID));

            await DB.Entry(reqDM.Request).ReloadAsync();
        }
Esempio n. 14
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        async Task FromAnalysisCenter(RequestDataMart reqDM)
        {
            //close the current task
            var currentTask = await PmnTask.GetActiveTaskForRequestActivityAsync(reqDM.Request.ID, reqDM.Request.WorkFlowActivityID.Value, DB);

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

            //open new task and set the request to the new activity
            var task = DB.Actions.Add(PmnTask.CreateForWorkflowActivity(reqDM.Request.ID, CompleteDistributionActivityID, WorkflowID, DB));

            reqDM.Request.WorkFlowActivityID = CompleteDistributionActivityID;

            //get the documents uploaded by the analysis center
            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 rdm.RequestID == reqDM.Request.ID &&
                                  rdm.RoutingType == RoutingType.AnalysisCenter &&
                                  rd.DocumentType == RequestDocumentType.Output &&
                                  rsp.Count == rdm.Responses.Max(r => r.Count) &&
                                  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,
                RevisionSetID = rd.RevisionSetID,
                DocumentKind  = doc.Kind,
                FileName      = doc.FileName
            }).ToArrayAsync();

            if (documents.Any(d => d.DocumentKind == JobFailTriggerFileKind))
            {
                //stop file, end regression.
                CompleteTask(task);
                reqDM.Request.WorkFlowActivityID = CompletedActivityID;

                //Save changes and reload entity
                //If this is not done, EF throws an exception on updating the status of the Request DataMart.
                await DB.SaveChangesAsync();

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

                //Set the routing status to Failed.
                reqDM.Status = RoutingStatus.Failed;
                await DB.SaveChangesAsync();

                //change the status of the request to Failed
                //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.Failed), new System.Data.SqlClient.SqlParameter("@ID", reqDM.Request.ID));

                return;
            }

            if (documents.Any(d => d.DocumentKind == StopProcessingTriggerDocumentKind))
            {
                //stop file, end regression. All the routes should be complete now and the request status should be already in Completed. Just need to update the current activity.
                CompleteTask(task);
                reqDM.Request.WorkFlowActivityID = CompletedActivityID;

                //NOTE: notification of complete request will be handled outside of the helper
            }
            else
            {
                if (documents.Length > 0)
                {//ASPE-605: change the association of the document owner from the analysis center response to the complete distribution task (current task).
                 //This is to support showing the AC documents in the task documents tab.

                    //add a reference to the response to the current task so that we can track back to the source.
                    try
                    {
                        Guid currentResponseID = await DB.Responses.Where(rsp => rsp.RequestDataMartID == reqDM.ID && rsp == rsp.RequestDataMart.Responses.OrderByDescending(rrsp => rrsp.Count).FirstOrDefault()).Select(rsp => rsp.ID).FirstAsync();

                        if (DB.Entry(currentTask).Collection(t => t.References).IsLoaded == false)
                        {
                            await DB.Entry(currentTask).Collection(t => t.References).LoadAsync();
                        }
                        if (currentTask.References.Any(tr => tr.ItemID == currentResponseID) == false)
                        {
                            task.References.Add(new TaskReference {
                                TaskID = currentTask.ID, ItemID = currentResponseID, Type = TaskItemTypes.Response
                            });
                        }
                    }catch
                    {
                        //do not kill processing if this fails, eventlog builder has contingencies to handle if the task reference to the response is not set.
                    }

                    StringBuilder query = new StringBuilder();
                    query.Append("UPDATE Documents SET ItemID='" + currentTask.ID.ToString("D") + "'");
                    query.Append(" WHERE ID IN (");
                    query.Append(string.Join(",", documents.Select(d => string.Format("'{0:D}'", d.DocumentID))));
                    query.Append(")");
                    await DB.Database.ExecuteSqlCommandAsync(query.ToString());
                }

                //the output files from the analysis center will now become the input files for each active dataparter route
                List <Guid> responseIDs = new List <Guid>();

                var allTasks = await DB.ActionReferences.Where(tr => tr.ItemID == reqDM.Request.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();

                var dataPartnerRoutes = await DB.RequestDataMarts.Include(rdm => rdm.Responses).Where(rdm => rdm.RequestID == reqDM.Request.ID && rdm.Status != RoutingStatus.Canceled && rdm.RoutingType == RoutingType.DataPartner).ToArrayAsync();

                foreach (var route in dataPartnerRoutes)
                {
                    var response = route.AddResponse(IdentityID);
                    responseIDs.Add(response.ID);

                    route.Status = response.Count > 1 ? RoutingStatus.Resubmitted : RoutingStatus.Submitted;

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

                var filelistDocument = documents.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 = documents.Where(d => string.Equals(d.FileName, filename, StringComparison.OrdinalIgnoreCase)).Select(d => d.RevisionSetID).FirstOrDefault();
                                        if (revisionSetID.HasValue)
                                        {
                                            DB.RequestDocuments.AddRange(responseIDs.Select(rspID => new RequestDocument {
                                                DocumentType = RequestDocumentType.Input, ResponseID = rspID, RevisionSetID = revisionSetID.Value
                                            }).ToArray());
                                        }
                                    }
                                }
                            }

                            reader.Close();
                        }
                }
                else
                {
                    var requestDocuments = (from d in documents
                                            from responseID in responseIDs
                                            where d.DocumentKind != "DistributedRegression.AdapterEventLog" && d.DocumentKind != "DistributedRegression.TrackingTable"
                                            select new RequestDocument
                    {
                        DocumentType = RequestDocumentType.Input,
                        ResponseID = responseID,
                        RevisionSetID = d.RevisionSetID
                    }).ToArray();

                    if (requestDocuments.Length > 0)
                    {
                        DB.RequestDocuments.AddRange(requestDocuments);
                    }
                }
            }

            await DB.SaveChangesAsync();
        }
Esempio n. 15
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
            });
        }
Esempio n. 16
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);
                }
            }
        }
Esempio n. 17
0
 public RoutingEventBase(RequestDataMart r) : base(r.Request)
 {
     this.DataMart = r.DataMartID;
 }
        /// <summary>
        /// Initiates the Document object to be saved in the database
        /// </summary>
        /// <returns></returns>
        public async Task SetUpDocumentInDatabase()
        {
            Response response = await db.Responses
                                .Where(rsp => rsp.ID == DocumentMetadata.ResponseID)
                                .OrderByDescending(rsp => rsp.Count)
                                .FirstOrDefaultAsync();

            RequestDataMart datamart = await db.RequestDataMarts.FirstOrDefaultAsync(dm => dm.ID == response.RequestDataMartID);

            if (db.Documents.Any(d => d.ItemID == response.ID && d.FileName == DocumentMetadata.FileName))
            {
                //Get existing documents with revision
                var existingDocuments = await db.Documents.AsNoTracking().Where(d => d.ItemID == response.ID && d.FileName == DocumentMetadata.FileName).Select(d => new { d.FileName, d.MajorVersion, d.MinorVersion, d.BuildVersion, d.RevisionVersion, d.ID, d.RevisionSetID }).ToArrayAsync();

                var existingRequestDocuments = await db.RequestDocuments.AsNoTracking().Where(rd => rd.ResponseID == response.ID).ToListAsync();

                //get the most recent parent document
                var pDoc = existingDocuments.Where(ed => ed.FileName == DocumentMetadata.FileName).OrderByDescending(ed => ed.MajorVersion).ThenByDescending(ed => ed.MinorVersion).ThenByDescending(ed => ed.BuildVersion).ThenByDescending(ed => ed.RevisionVersion).First();

                Doc = new Document
                {
                    ID               = DocumentMetadata.DocumentID,
                    ItemID           = response.ID,
                    FileName         = DocumentMetadata.FileName,
                    Name             = DocumentMetadata.FileName,
                    Description      = string.Empty,
                    UploadedByID     = identity.ID,
                    MimeType         = DocumentMetadata.MimeType,
                    Length           = DocumentMetadata.Length,
                    Viewable         = true,
                    Kind             = "",
                    RevisionSetID    = pDoc.RevisionSetID,
                    ParentDocumentID = pDoc.ID,
                    MajorVersion     = pDoc.MajorVersion,
                    MinorVersion     = pDoc.MinorVersion,
                    BuildVersion     = pDoc.BuildVersion,
                    RevisionVersion  = pDoc.RevisionVersion + 1
                };
            }
            else
            {
                Doc = new Document
                {
                    ID               = DocumentMetadata.DocumentID,
                    ItemID           = response.ID,
                    FileName         = DocumentMetadata.FileName,
                    Name             = DocumentMetadata.FileName,
                    ParentDocumentID = null,
                    MimeType         = DocumentMetadata.MimeType,
                    Length           = DocumentMetadata.Length,
                    Viewable         = true,
                    Kind             = "",
                    Description      = string.Empty,
                    UploadedByID     = identity.ID,
                    RevisionSetID    = DocumentMetadata.DocumentID
                };
            }

            db.Documents.Add(Doc);

            //If workflow add to RequestDocuments
            var requestWorkflowActivityID = await db.Requests.Where(r => r.ID == datamart.RequestID).Select(x => x.WorkFlowActivityID).FirstOrDefaultAsync();

            if (requestWorkflowActivityID.HasValue)
            {
                if (!db.RequestDocuments.Any(rd => rd.ResponseID == Doc.ItemID && rd.RevisionSetID == Doc.RevisionSetID && rd.DocumentType == DTO.Enums.RequestDocumentType.Output))
                {
                    db.RequestDocuments.Add(new RequestDocument {
                        ResponseID = Doc.ItemID, RevisionSetID = Doc.RevisionSetID.Value, DocumentType = DTO.Enums.RequestDocumentType.Output
                    });
                }
            }

            await db.SaveChangesAsync();
        }
Esempio n. 19
0
 public class UnrespondedRequestReminder : RoutingEventBase { public UnrespondedRequestReminder(RequestDataMart r) : base(r)
                                                              {
                                                              }