/// <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); } }
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(); } }
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) { }
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(); } }
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); }
/// <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(); }
/// <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(); }
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 }); }
/// <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); } } }
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(); }
public class UnrespondedRequestReminder : RoutingEventBase { public UnrespondedRequestReminder(RequestDataMart r) : base(r) { }