/// <summary> /// Performs tasks associated to the start of the activity. By default confirms that an active PmnTask has been created for the current activity, and also records any comment entered when leaving the previous activity. /// </summary> /// <param name="comment"></param> /// <returns></returns> public virtual async Task Start(string comment) { var task = await PmnTask.GetActiveTaskForRequestActivityAsync(_entity.ID, ID, db); if (task == null) { task = db.Actions.Add(PmnTask.CreateForWorkflowActivity(_entity.ID, ID, _workflow.ID, db, CustomTaskSubject)); await db.SaveChangesAsync(); } if (!string.IsNullOrWhiteSpace(comment)) { var cmt = db.Comments.Add(new Comment { CreatedByID = _workflow.Identity.ID, ItemID = _entity.ID, Text = comment }); db.CommentReferences.Add(new CommentReference { CommentID = cmt.ID, Type = DTO.Enums.CommentItemTypes.Task, ItemTitle = task.Subject, ItemID = task.ID }); await db.SaveChangesAsync(); } }
/// <summary> /// Marks the current activity's task as modified. /// </summary> /// <param name="optionalMessage"></param> /// <returns></returns> protected async Task LogTaskModified(string optionalMessage = null) { var task = await PmnTask.GetActiveTaskForRequestActivityAsync(_entity.ID, ID, db); if (task == null) { task = db.Actions.Add(PmnTask.CreateForWorkflowActivity(_entity.ID, ID, _workflow.ID, db)); return; } await task.LogAsModifiedAsync(_workflow.Identity, db, optionalMessage); }
public async Task <CompletionResult> Complete(string data, Guid?activityResultID) { if (!activityResultID.HasValue) { throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired); } var task = await PmnTask.GetActiveTaskForRequestActivityAsync(Request.ID, ID, db); if (activityResultID.Value == SaveResultID || activityResultID.Value == SubmitResultID) { if (activityResultID.Value == SubmitResultID) { task.Status = DTO.Enums.TaskStatuses.Complete; task.EndOn = DateTime.UtcNow; } else { await task.LogAsModifiedAsync(Workflow.Identity, db); } await db.SaveChangesAsync(); return(new CompletionResult { ResultID = activityResultID.Value }); } else if (activityResultID.Value == DeleteResultID) { Request.CancelledByID = Workflow.Identity.ID; Request.CancelledOn = DateTime.UtcNow; task.Status = DTO.Enums.TaskStatuses.Cancelled; await db.SaveChangesAsync(); return(new CompletionResult { ResultID = DeleteResultID }); } else { throw new NotSupportedException(CommonMessages.ActivityResultNotSupported); } }
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 }); }
/// <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 async Task Delete([FromBody] IEnumerable <RequestUserDTO> requestUsers) { try { var dbSet = DataContext.Set <RequestUser>(); var requestID = requestUsers.Select(u => u.RequestID).First(); if (!requestUsers.All(v => v.RequestID == requestID)) { throw new ArgumentException("The request ID must be the same for all values being deleted."); } if (!await DataContext.HasPermissions <Request>(Identity, requestID, PermissionIdentifiers.Request.Edit)) { throw new SecurityException("Insufficient permission to edit the request by deleting request users."); } var or = PredicateBuilder.False <RequestUser>(); foreach (var user in requestUsers) { or = or.Or(ru => ru.WorkflowRoleID == user.WorkflowRoleID && ru.UserID == user.UserID); } var logger = new Lpp.Dns.Data.RequestUserLogConfiguration(); var objs = DataContext.RequestUsers.Where(ru => ru.RequestID == requestID); objs = objs.Where(or.Expand()); foreach (var obj in objs) { //by default the datacontext does not log deletes, manually call the logger for RequestUser to add the log entry. logger.CreateLogItem(obj, EntityState.Deleted, Identity, DataContext, true); dbSet.Remove(obj); } await DataContext.SaveChangesAsync(); //check if there is a current task for the request, if so remove any of the deleted request users. var requestWorkflowActivityID = await DataContext.Requests.Where(r => r.ID == requestID).Select(r => r.WorkFlowActivityID).FirstOrDefaultAsync(); if (requestWorkflowActivityID.HasValue) { PmnTask workflowTask = await PmnTask.GetActiveTaskForRequestActivityAsync(requestID, requestWorkflowActivityID.Value, DataContext); if (workflowTask != null) { var userID = requestUsers.Select(u => u.UserID).ToArray(); DataContext.ActionUsers.RemoveRange(DataContext.ActionUsers.Where(a => a.TaskID == workflowTask.ID && userID.Contains(a.UserID) && !DataContext.RequestUsers.Any(ru => ru.RequestID == requestID && ru.UserID == a.UserID))); await DataContext.SaveChangesAsync(); } } } catch (System.Security.SecurityException se) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Forbidden, se)); } catch (DbUpdateException dbe) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, dbe.UnwindException())); } catch (Exception e) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, e)); } }
public override async Task <CompletionResult> Complete(string data, Guid?activityResultID) { if (!activityResultID.HasValue) { throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired); } var task = await PmnTask.GetActiveTaskForRequestActivityAsync(_workflow.Entity.ID, ID, db); if (task == null) { task = db.Actions.Add(PmnTask.CreateForWorkflowActivity(_workflow.Entity.ID, ID, _workflow.ID, db)); } if (activityResultID.Value == SaveResultID) { return(new CompletionResult { ResultID = SaveResultID }); } if (activityResultID.Value == EditRoutingStatusResultID) { var dataMarts = Newtonsoft.Json.JsonConvert.DeserializeObject <IEnumerable <RoutingChangeRequestModel> >(data); await UpdateDataMartRoutingStatus(dataMarts); return(new CompletionResult { ResultID = EditRoutingStatusResultID }); } else if (activityResultID.Value == RoutingsBulkEditID) { return(new CompletionResult { ResultID = RoutingsBulkEditID }); } else if (activityResultID.Value == RemoveDataMartsResultID) { Guid[] guids = data.Split(',').Select(s => Guid.Parse(s)).ToArray(); var routings = await db.RequestDataMarts.Where(dm => guids.Contains(dm.ID)).ToArrayAsync(); foreach (var routing in routings) { routing.Status = DTO.Enums.RoutingStatus.Canceled; } await LogTaskModified(); await db.SaveChangesAsync(); var originalStatus = _entity.Status; await db.SaveChangesAsync(); await db.Entry(_entity).ReloadAsync(); if (originalStatus != DTO.Enums.RequestStatuses.Complete && _entity.Status == DTO.Enums.RequestStatuses.Complete) { await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Complete); } } else if (activityResultID.Value == AddDataMartsResultID) { DTO.QueryComposer.QueryComposerRequestDTO requestDTO = Newtonsoft.Json.JsonConvert.DeserializeObject <DTO.QueryComposer.QueryComposerRequestDTO>(_entity.Query); var modularTerm = requestDTO.Where.Criteria.SelectMany(c => c.Terms.Where(t => t.Type == SimpleModularProgramWorkflowConfiguration.ModularProgramTermID)).FirstOrDefault(); var termValues = Newtonsoft.Json.JsonConvert.DeserializeObject <ModularProgramTermValues>(modularTerm.Values["Values"].ToString()); string[] datamartIDs = data.Split(','); var allTasks = await db.ActionReferences.Where(tr => tr.ItemID == _entity.ID && tr.Type == DTO.Enums.TaskItemTypes.Request && tr.Task.Type == DTO.Enums.TaskTypes.Task ) .Select(tr => tr.Task.ID).ToArrayAsync(); var attachments = await(from doc in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => allTasks.Contains(dd.ItemID)) .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on doc.ID equals x where allTasks.Contains(doc.ItemID) && doc.Kind == "Attachment.Input" orderby doc.ItemID descending, doc.RevisionSetID descending, doc.CreatedOn descending select doc).ToArrayAsync(); foreach (var guid in datamartIDs) { Guid dmGuid = new Guid(guid); var dm = RequestDataMart.Create(_entity.ID, dmGuid, _workflow.Identity.ID); dm.Status = DTO.Enums.RoutingStatus.Submitted; dm.DueDate = _entity.DueDate; dm.Priority = _entity.Priority; _entity.DataMarts.Add(dm); Response rsp = dm.Responses.OrderByDescending(r => r.Count).FirstOrDefault(); //add the request document associations foreach (var revisionSetID in termValues.Documents.Select(d => d.RevisionSetID)) { db.RequestDocuments.Add(new RequestDocument { DocumentType = DTO.Enums.RequestDocumentType.Input, ResponseID = rsp.ID, RevisionSetID = revisionSetID }); } foreach (var attachment in attachments) { db.RequestDocuments.Add(new RequestDocument { RevisionSetID = attachment.RevisionSetID.Value, ResponseID = rsp.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput }); } } await LogTaskModified(); await db.SaveChangesAsync(); } //Grouping if (activityResultID.Value == GroupResultID) { GroupingRequestModel model = Newtonsoft.Json.JsonConvert.DeserializeObject <GroupingRequestModel>(data); var responses = await db.Responses.Include(r => r.RequestDataMart).Where(r => model.Responses.Any(x => x == r.ID)).ToArrayAsync(); if (responses.Select(r => r.RequestDataMart.RequestID).Distinct().Count() > 1) { throw new ArgumentException("Cannot group responses that come from different requests."); } Guid[] requestDataMartIDs = responses.Select(rsp => rsp.RequestDataMartID).Distinct().ToArray(); var pq = (from rdm in db.RequestDataMarts let permissionID = PermissionIdentifiers.DataMartInProject.GroupResponses.ID let identityID = _workflow.Identity.ID let acls = db.GlobalAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID)).Select(a => a.Allowed) .Concat(db.ProjectAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Project.Requests.Any(r => r.ID == rdm.RequestID)).Select(a => a.Allowed)) .Concat(db.DataMartAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.DataMartID == rdm.DataMartID).Select(a => a.Allowed)) .Concat(db.ProjectDataMartAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Project.Requests.Any(r => r.ID == rdm.RequestID) && a.DataMartID == rdm.DataMartID).Select(a => a.Allowed)) .Concat(db.OrganizationAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Organization.Requests.Any(r => r.ID == rdm.RequestID)).Select(a => a.Allowed)) where requestDataMartIDs.Contains(rdm.ID) && acls.Any() && acls.All(a => a == true) select rdm.ID); var allowedResponses = await pq.ToArrayAsync(); if (allowedResponses.Length != requestDataMartIDs.Length) { throw new SecurityException("Insufficient permission to group one or more of the specified responses."); } if (string.IsNullOrWhiteSpace(model.GroupName)) { model.GroupName = string.Join(", ", db.Responses.Where(r => model.Responses.Any(x => x == r.ID)).Select(r => r.RequestDataMart.DataMart.Name).Distinct()); } ResponseGroup grouping = db.ResponseGroups.Add(new ResponseGroup(model.GroupName)); foreach (var response in responses) { grouping.Responses.Add(response); response.RequestDataMart.ResultsGrouped = true; } await LogTaskModified("Grouped results."); await db.SaveChangesAsync(); } //Un-grouping if (activityResultID.Value == UngroupResultID) { IEnumerable <Guid> groupID = (from r in data.Split(',') where !string.IsNullOrWhiteSpace(r) select Guid.Parse(r.Trim())).ToArray(); List <Guid> requestDataMartIDs = await db.ResponseGroups.Include(g => g.Responses).Where(g => groupID.Contains(g.ID)).SelectMany(g => g.Responses.Select(r => r.RequestDataMartID)).ToListAsync(); var pq = (from rdm in db.RequestDataMarts let permissionID = PermissionIdentifiers.DataMartInProject.GroupResponses.ID let identityID = _workflow.Identity.ID let acls = db.GlobalAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID)).Select(a => a.Allowed) .Concat(db.ProjectAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Project.Requests.Any(r => r.ID == rdm.RequestID)).Select(a => a.Allowed)) .Concat(db.DataMartAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.DataMartID == rdm.DataMartID).Select(a => a.Allowed)) .Concat(db.ProjectDataMartAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Project.Requests.Any(r => r.ID == rdm.RequestID) && a.DataMartID == rdm.DataMartID).Select(a => a.Allowed)) .Concat(db.OrganizationAcls.Where(a => a.PermissionID == permissionID && a.SecurityGroup.Users.Any(sgu => sgu.UserID == identityID) && a.Organization.Requests.Any(r => r.ID == rdm.RequestID)).Select(a => a.Allowed)) where requestDataMartIDs.Contains(rdm.ID) && acls.Any() && acls.All(a => a == true) select rdm.ID); var allowedResponses = await pq.ToArrayAsync(); if (allowedResponses.Length != requestDataMartIDs.Count) { throw new SecurityException("Insufficient permission to ungroup routings for the specified request."); } var groups = await db.ResponseGroups.Include(g => g.Responses).Where(g => groupID.Contains(g.ID)).ToArrayAsync(); foreach (var group in groups) { requestDataMartIDs.AddRange(group.Responses.Select(r => r.RequestDataMartID)); group.Responses.Clear(); db.ResponseGroups.Remove(group); } var routings = await db.RequestDataMarts.Where(dm => requestDataMartIDs.Contains(dm.ID)).ToArrayAsync(); foreach (var routing in routings) { routing.ResultsGrouped = false; } await LogTaskModified("Ungrouped results."); await db.SaveChangesAsync(); } if (activityResultID.Value == TerminateResultID) { _workflow.Entity.CancelledByID = _workflow.Identity.ID; _workflow.Entity.CancelledOn = DateTime.UtcNow; task.Status = DTO.Enums.TaskStatuses.Cancelled; await db.SaveChangesAsync(); return(new CompletionResult { ResultID = TerminateResultID }); } if (activityResultID.Value == RedistributeResultID) { if (!await db.HasPermissions <Project>(_workflow.Identity, _entity.ProjectID, Lpp.Dns.DTO.Security.PermissionIdentifiers.Project.ResubmitRequests)) { throw new System.Security.SecurityException(CommonMessages.RequirePermissionToResubmitRequest, Lpp.Dns.DTO.Security.PermissionIdentifiers.Project.ResubmitRequests.GetType()); } //TODO: is this applicable in workflow? //bool canSkipSubmissionApproval = await db.HasPermissions<Request>(Workflow.Identity, Request.ID, Lpp.Dns.DTO.Security.PermissionIdentifiers.Request.SkipSubmissionApproval); //data will contain a list of routings to resubmit, the ID may also be for a group ResubmitRoutingsModel resubmitModel = Newtonsoft.Json.JsonConvert.DeserializeObject <ResubmitRoutingsModel>(data); var datamarts = await( from dm in db.RequestDataMarts.Include(dm => dm.Responses) where dm.RequestID == _entity.ID && dm.Responses.Any(r => resubmitModel.Responses.Contains(r.ID) || (r.ResponseGroupID.HasValue && resubmitModel.Responses.Contains(r.ResponseGroupID.Value))) select dm ).ToArrayAsync(); //get the previously submitted input RequestDocument links var previousInputRequestDocuments = await(from rd in db.RequestDocuments where rd.DocumentType == DTO.Enums.RequestDocumentType.Input && resubmitModel.Responses.Contains(rd.ResponseID) select new { RequestDataMartID = rd.Response.RequestDataMartID, RevisionSetID = rd.RevisionSetID }).ToArrayAsync(); var allTasks = await db.ActionReferences.Where(tr => tr.ItemID == _entity.ID && tr.Type == DTO.Enums.TaskItemTypes.Request && tr.Task.Type == DTO.Enums.TaskTypes.Task ) .Select(tr => tr.Task.ID).ToArrayAsync(); //attachments are associated to the task they were uploaded on, any existing attachment should be included with the routing var attachments = await(from doc in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => allTasks.Contains(dd.ItemID)) .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on doc.ID equals x where allTasks.Contains(doc.ItemID) && doc.Kind == "Attachment.Input" orderby doc.ItemID descending, doc.RevisionSetID descending, doc.CreatedOn descending select doc).ToArrayAsync(); DateTime reSubmittedOn = DateTime.UtcNow; foreach (var dm in datamarts) { var response = dm.AddResponse(_workflow.Identity.ID); response.SubmittedOn = reSubmittedOn; response.SubmitMessage = resubmitModel.ResubmissionMessage; dm.Status = DTO.Enums.RoutingStatus.Resubmitted; foreach (var requestDoc in previousInputRequestDocuments.Where(rd => rd.RequestDataMartID == dm.ID)) { db.RequestDocuments.Add(new RequestDocument { ResponseID = response.ID, RevisionSetID = requestDoc.RevisionSetID, DocumentType = DTO.Enums.RequestDocumentType.Input }); } foreach (var attachment in attachments) { db.RequestDocuments.Add(new RequestDocument { RevisionSetID = attachment.RevisionSetID.Value, ResponseID = response.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput }); } } await SetRequestStatus(DTO.Enums.RequestStatuses.Submitted); await LogTaskModified(); await MarkTaskComplete(task); } else if (activityResultID.Value == CompleteResultID) { var originalStatus = _entity.Status; await SetRequestStatus(DTO.Enums.RequestStatuses.PendingDraftReport); await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.PendingDraftReport); await MarkTaskComplete(task); } else if (activityResultID.Value == CompleteWorkflowResultID) { var originalStatus = _entity.Status; if (originalStatus != DTO.Enums.RequestStatuses.Complete && originalStatus != DTO.Enums.RequestStatuses.CompleteWithReport) { await SetRequestStatus(DTO.Enums.RequestStatuses.Complete); await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Complete); } await MarkTaskComplete(task); } return(new CompletionResult { ResultID = activityResultID.Value }); }
public override async Task <CompletionResult> Complete(string data, Guid?activityResultID) { //default to SaveResultID if resultID not specified if (!activityResultID.HasValue) { activityResultID = SaveResultID; } var task = await PmnTask.GetActiveTaskForRequestActivityAsync(_entity.ID, ID, db); if (activityResultID.Value == SubmitResultID) //Submit { var filters = new ExtendedQuery { Projects = (a) => a.ProjectID == _entity.ProjectID, ProjectOrganizations = a => a.ProjectID == _entity.ProjectID && a.OrganizationID == _entity.OrganizationID, Organizations = a => a.OrganizationID == _entity.OrganizationID, Users = a => a.UserID == _entity.CreatedByID }; var permissions = await db.HasGrantedPermissions <Request>(_workflow.Identity, _entity, filters, PermissionIdentifiers.Request.SkipSubmissionApproval); await db.Entry(_entity).ReloadAsync(); var requestJSON = ParseRequestJSON(); //bool hasFileUploadTerm = HasTermInAnyCriteria(QueryComposer.ModelTermsFactory.FileUploadID, requestJSON); var fileUploadTerm = GetAllTerms(QueryComposer.ModelTermsFactory.FileUploadID, requestJSON).FirstOrDefault(); var originalStatus = _entity.Status; if (fileUploadTerm != null) { if (!permissions.Contains(PermissionIdentifiers.Request.SkipSubmissionApproval)) { //file distribution never requires review before submission, add the permission if the user does not have it. permissions = new[] { PermissionIdentifiers.Request.SkipSubmissionApproval }; } await db.LoadCollection(_entity, (r) => r.DataMarts); if (!_entity.DataMarts.Any()) { throw new Exception("At least one routing needs to be specified when submitting a requests."); } var termValues = Newtonsoft.Json.JsonConvert.DeserializeObject <FileUploadValues>(fileUploadTerm.Values["Values"].ToString()); IList <Guid> documentRevisionSets = termValues.Documents.Select(d => d.RevisionSetID).ToArray(); IEnumerable <Document> documents = await(from d in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => documentRevisionSets.Contains(dd.RevisionSetID.Value)) .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on d.ID equals x orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending select d).ToArrayAsync(); await db.Entry(_entity).Reference(r => r.Activity).LoadAsync(); await db.Entry(_entity).Reference(r => r.RequestType).LoadAsync(); string submitterEmail = await db.Users.Where(u => u.ID == _workflow.Identity.ID).Select(u => u.Email).SingleAsync(); //update the request _entity.SubmittedByID = _workflow.Identity.ID; _entity.SubmittedOn = DateTime.UtcNow; _entity.AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion; _entity.RejectedByID = null; _entity.RejectedOn = null; _entity.Private = false; //save the changes to the request now since the trigger for routings will change the status invalidating the object before save await db.SaveChangesAsync(); await db.Entry(_entity).ReloadAsync(); await SetRequestStatus(DTO.Enums.RequestStatuses.Submitted, false); var allTasks = await db.ActionReferences.Where(tr => tr.ItemID == _entity.ID && tr.Type == DTO.Enums.TaskItemTypes.Request && tr.Task.Type == DTO.Enums.TaskTypes.Task ) .Select(tr => tr.Task.ID).ToArrayAsync(); var attachments = await(from doc in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => allTasks.Contains(dd.ItemID)) .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on doc.ID equals x where allTasks.Contains(doc.ItemID) && doc.Kind == "Attachment.Input" orderby doc.ItemID descending, doc.RevisionSetID descending, doc.CreatedOn descending select doc).ToArrayAsync(); foreach (var dm in _entity.DataMarts.Where(dm => dm.Status == 0 || dm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval || dm.Status == DTO.Enums.RoutingStatus.Draft)) { dm.Status = DTO.Enums.RoutingStatus.Submitted; var currentResponse = db.Responses.FirstOrDefault(r => r.RequestDataMartID == dm.ID && r.Count == r.RequestDataMart.Responses.Max(rr => rr.Count)); if (currentResponse == null) { currentResponse = dm.AddResponse(_workflow.Identity.ID); } currentResponse.SubmittedByID = _workflow.Identity.ID; currentResponse.SubmittedOn = DateTime.UtcNow; //get existing request documents associated to the response, add only missing documents var existingRequestDocuments = await db.RequestDocuments.Where(rd => rd.ResponseID == currentResponse.ID).ToArrayAsync(); //add the request document associations for (int i = 0; i < documentRevisionSets.Count; i++) { if (!existingRequestDocuments.Any(ed => ed.RevisionSetID == documentRevisionSets[i])) { db.RequestDocuments.Add(new RequestDocument { RevisionSetID = documentRevisionSets[i], ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input }); } } foreach (var attachment in attachments.Where(att => !existingRequestDocuments.Any(ed => ed.RevisionSetID == att.RevisionSetID.Value))) { db.RequestDocuments.Add(new RequestDocument { RevisionSetID = attachment.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput }); } } await db.SaveChangesAsync(); //reload the request since altering the routings triggers a change of the request status in the db by a trigger. await db.Entry(_entity).ReloadAsync(); //update the request.json term value to include system generated documents revisionsetIDs termValues.Documents.Clear(); for (int i = 0; i < documentRevisionSets.Count; i++) { termValues.Documents.Add(new FileUploadValues.Document { RevisionSetID = documentRevisionSets[i] }); } fileUploadTerm.Values["Values"] = termValues; _entity.Query = Newtonsoft.Json.JsonConvert.SerializeObject(requestJSON); await db.SaveChangesAsync(); await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Submitted); } else { //var parentDocument = db.Documents.FirstOrDefault(d => d.ItemID == task.ID && d.Kind == DocumentKind && d.ParentDocumentID == null); Document parentDocument = await(from d in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => dd.ItemID == task.ID && dd.FileName == "request.json") .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on d.ID equals x orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending select d).FirstOrDefaultAsync(); byte[] documentContent = System.Text.UTF8Encoding.UTF8.GetBytes(_entity.Query ?? string.Empty); var document = new Document { Name = "Request Criteria", MajorVersion = parentDocument == null ? 1 : parentDocument.MajorVersion, MinorVersion = parentDocument == null ? 0 : parentDocument.MinorVersion, RevisionVersion = parentDocument == null ? 0 : parentDocument.RevisionVersion, MimeType = "application/json", Viewable = false, UploadedByID = _workflow.Identity.ID, FileName = "request.json", CreatedOn = DateTime.UtcNow, BuildVersion = parentDocument == null ? 0 : parentDocument.BuildVersion, ParentDocumentID = parentDocument == null ? (Guid?)null : parentDocument.ID, ItemID = task.ID, Length = documentContent.LongLength, Kind = Dns.DTO.Enums.DocumentKind.Request }; db.Documents.Add(document); document.RevisionSetID = parentDocument == null ? document.ID : parentDocument.RevisionSetID; await db.SaveChangesAsync(); document.SetData(db, documentContent); _entity.AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion; //Reset reject for resubmit. _entity.RejectedByID = null; _entity.RejectedOn = null; _entity.Private = false; await db.SaveChangesAsync(); DTO.Enums.RequestStatuses newRequestStatus = DTO.Enums.RequestStatuses.AwaitingRequestApproval; await db.LoadCollection(_entity, (r) => r.DataMarts); //set the request status, but do not refresh the entity yet await SetRequestStatus(newRequestStatus, false); if (permissions.Contains(PermissionIdentifiers.Request.SkipSubmissionApproval)) { await db.Entry(_entity).ReloadAsync(); newRequestStatus = DTO.Enums.RequestStatuses.Submitted; _entity.SubmittedByID = _workflow.Identity.ID; _entity.SubmittedOn = DateTime.UtcNow; var attachments = await(from doc in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => dd.ItemID == task.ID) .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 doc.ItemID == task.ID && doc.Kind == "Attachment.Input" orderby doc.ItemID descending, doc.RevisionSetID descending, doc.CreatedOn descending select doc).ToArrayAsync(); foreach (var dm in _entity.DataMarts) { dm.Status = DTO.Enums.RoutingStatus.Submitted; var currentResponse = db.Responses.FirstOrDefault(r => r.RequestDataMartID == dm.ID && r.Count == r.RequestDataMart.Responses.Max(rr => rr.Count)); if (currentResponse == null) { currentResponse = dm.AddResponse(_workflow.Identity.ID); } currentResponse.SubmittedByID = _workflow.Identity.ID; currentResponse.SubmittedOn = DateTime.UtcNow; //get existing request documents associated to the response, add only missing documents var existingRequestDocuments = await db.RequestDocuments.Where(rd => rd.ResponseID == currentResponse.ID).ToArrayAsync(); if (!existingRequestDocuments.Any(ed => ed.RevisionSetID == document.RevisionSetID.Value)) { db.RequestDocuments.Add(new RequestDocument { RevisionSetID = document.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input }); } foreach (var attachment in attachments.Where(att => !existingRequestDocuments.Any(ed => ed.RevisionSetID == att.RevisionSetID.Value))) { db.RequestDocuments.Add(new RequestDocument { RevisionSetID = attachment.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput }); } } } else { foreach (var dm in _entity.DataMarts) { dm.Status = DTO.Enums.RoutingStatus.AwaitingRequestApproval; } } await db.SaveChangesAsync(); await db.Entry(_entity).ReloadAsync(); await NotifyRequestStatusChanged(originalStatus, newRequestStatus); } await MarkTaskComplete(task); return(new CompletionResult { ResultID = permissions.Contains(PermissionIdentifiers.Request.SkipSubmissionApproval) ? SubmitResultID : ReviewResultID }); } else if (activityResultID.Value == SaveResultID) //Save { if (_entity.Private) { await db.Entry(_entity).ReloadAsync(); _entity.Private = false; await task.LogAsModifiedAsync(_workflow.Identity, db); await db.SaveChangesAsync(); } return(new CompletionResult { ResultID = SaveResultID }); } else if (activityResultID.Value == DeleteResultID) //Delete { db.Requests.Remove(_entity); if (task != null) { db.Actions.Remove(task); } await db.SaveChangesAsync(); return(null); } else { throw new ArgumentOutOfRangeException(CommonMessages.ActivityResultNotSupported); } }
public override async Task <CompletionResult> Complete(string data, Guid?activityResultID) { if (!activityResultID.HasValue) { throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired); } if (activityResultID.Value != TerminateResultID && activityResultID.Value != SubmitResultID && activityResultID.Value != SaveResultID) { throw new NotSupportedException(CommonMessages.ActivityResultNotSupported); } var task = await PmnTask.GetActiveTaskForRequestActivityAsync(_entity.ID, ID, db); await db.Entry(_entity).ReloadAsync(); if (activityResultID.Value == TerminateResultID) { _entity.CancelledByID = _workflow.Identity.ID; _entity.CancelledOn = DateTime.UtcNow; task.Status = DTO.Enums.TaskStatuses.Cancelled; await db.SaveChangesAsync(); return(new CompletionResult { ResultID = TerminateResultID }); } if (activityResultID.Value == SubmitResultID) { await db.LoadCollection(_entity, (r) => r.DataMarts); if (!_entity.DataMarts.Any()) { throw new Exception("At least one routing needs to be specified when submitting a requests."); } //prepare the request documents, save created documents same as legacy IList <Guid> documentRevisionSets = Newtonsoft.Json.JsonConvert.DeserializeObject <IList <Guid> >(data); IEnumerable <Document> documents = await(from d in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => documentRevisionSets.Contains(dd.RevisionSetID.Value)) .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on d.ID equals x orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending select d).ToArrayAsync(); await db.Entry(_entity).Reference(r => r.Activity).LoadAsync(); await db.Entry(_entity).Reference(r => r.RequestType).LoadAsync(); string submitterEmail = await db.Users.Where(u => u.ID == _workflow.Identity.ID).Select(u => u.Email).SingleAsync(); string xmlContent = SerializeModularProgramsToXML(documents, submitterEmail); string htmlContent = SerializeModularProgramsToHTML(documents, submitterEmail); Document existingDocument = await(from d in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => dd.ItemID == task.ID && dd.FileName == "ModularProgramRequest.xml") .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on d.ID equals x orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending select d).FirstOrDefaultAsync(); Document xmlRequestDoc = db.Documents.Add(new Document { Name = "ModularProgramRequest.xml", FileName = "ModularProgramRequest.xml", ItemID = task.ID, Kind = DTO.Enums.DocumentKind.SystemGeneratedNoLog, MimeType = "application/xml", Viewable = false, UploadedByID = _workflow.Identity.ID, Length = System.Text.UTF8Encoding.UTF8.GetByteCount(xmlContent) }); db.ActionReferences.Add(new TaskReference { TaskID = task.ID, ItemID = xmlRequestDoc.ID, Type = DTO.Enums.TaskItemTypes.ActivityDataDocument }); if (existingDocument == null) { xmlRequestDoc.RevisionSetID = xmlRequestDoc.ID; } else { xmlRequestDoc.ParentDocumentID = existingDocument.ID; xmlRequestDoc.Name = existingDocument.Name; xmlRequestDoc.Description = existingDocument.Description; xmlRequestDoc.RevisionSetID = existingDocument.RevisionSetID; xmlRequestDoc.MajorVersion = existingDocument.MajorVersion; xmlRequestDoc.MinorVersion = existingDocument.MinorVersion; xmlRequestDoc.BuildVersion = existingDocument.BuildVersion; xmlRequestDoc.RevisionVersion = existingDocument.RevisionVersion + 1; } existingDocument = await(from d in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => dd.ItemID == task.ID && dd.FileName == "ModularProgramRequest.html") .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on d.ID equals x orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending select d).FirstOrDefaultAsync(); Document htmlRequestDoc = db.Documents.Add(new Document { Name = "ModularProgramRequest.html", FileName = "ModularProgramRequest.html", ItemID = task.ID, Kind = DTO.Enums.DocumentKind.SystemGeneratedNoLog, MimeType = "text/html", Viewable = true, UploadedByID = _workflow.Identity.ID, Length = System.Text.UTF8Encoding.UTF8.GetByteCount(htmlContent) }); db.ActionReferences.Add(new TaskReference { TaskID = task.ID, ItemID = htmlRequestDoc.ID, Type = DTO.Enums.TaskItemTypes.ActivityDataDocument }); if (existingDocument == null) { htmlRequestDoc.RevisionSetID = htmlRequestDoc.ID; } else { htmlRequestDoc.ParentDocumentID = existingDocument.ID; htmlRequestDoc.Name = existingDocument.Name; htmlRequestDoc.Description = existingDocument.Description; htmlRequestDoc.RevisionSetID = existingDocument.RevisionSetID; htmlRequestDoc.MajorVersion = existingDocument.MajorVersion; htmlRequestDoc.MinorVersion = existingDocument.MinorVersion; htmlRequestDoc.BuildVersion = existingDocument.BuildVersion; htmlRequestDoc.RevisionVersion = existingDocument.RevisionVersion + 1; } //save the document metadata await db.SaveChangesAsync(); //push the document bytes xmlRequestDoc.SetData(db, System.Text.Encoding.UTF8.GetBytes(xmlContent)); htmlRequestDoc.SetData(db, System.Text.Encoding.UTF8.GetBytes(htmlContent)); //add the system generated documents revisionsetIDs to the collection of request documents to be submitted to the data partners. documentRevisionSets.Add(xmlRequestDoc.RevisionSetID.Value); documentRevisionSets.Add(htmlRequestDoc.RevisionSetID.Value); //update the request _entity.SubmittedByID = _workflow.Identity.ID; _entity.SubmittedOn = DateTime.UtcNow; _entity.AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion; _entity.RejectedByID = null; _entity.RejectedOn = null; _entity.Private = false; //save the changes to the request now since the trigger for routings will change the status invalidating the object before save await db.SaveChangesAsync(); var originalStatus = _entity.Status; await SetRequestStatus(DTO.Enums.RequestStatuses.Submitted, false); var allTasks = await db.ActionReferences.Where(tr => tr.ItemID == _entity.ID && tr.Type == DTO.Enums.TaskItemTypes.Request && tr.Task.Type == DTO.Enums.TaskTypes.Task ) .Select(tr => tr.Task.ID).ToArrayAsync(); var attachments = await(from doc in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => allTasks.Contains(dd.ItemID)) .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on doc.ID equals x where allTasks.Contains(doc.ItemID) && doc.Kind == "Attachment.Input" orderby doc.ItemID descending, doc.RevisionSetID descending, doc.CreatedOn descending select doc).ToArrayAsync(); foreach (var dm in _entity.DataMarts.Where(dm => dm.Status == 0 || dm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval || dm.Status == DTO.Enums.RoutingStatus.Draft)) { dm.Status = DTO.Enums.RoutingStatus.Submitted; var currentResponse = db.Responses.Include(rsp => rsp.RequestDocument).FirstOrDefault(r => r.RequestDataMartID == dm.ID && r.Count == r.RequestDataMart.Responses.Max(rr => rr.Count)); if (currentResponse == null) { currentResponse = dm.AddResponse(_workflow.Identity.ID); } currentResponse.SubmittedByID = _workflow.Identity.ID; currentResponse.SubmittedOn = DateTime.UtcNow; //add the request document associations for (int i = 0; i < documentRevisionSets.Count; i++) { if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == documentRevisionSets[i])) { db.RequestDocuments.Add(new RequestDocument { RevisionSetID = documentRevisionSets[i], ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input }); } } foreach (var attachment in attachments) { if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == attachment.RevisionSetID.Value)) { db.RequestDocuments.Add(new RequestDocument { RevisionSetID = attachment.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput }); } } } await db.SaveChangesAsync(); //reload the request since altering the routings triggers a change of the request status in the db by a trigger. await db.Entry(_entity).ReloadAsync(); var qcRequestDTO = ParseRequestJSON(); var modularTerm = GetAllTerms(SimpleModularProgramWorkflowConfiguration.ModularProgramTermID, qcRequestDTO).FirstOrDefault(); var termValues = Newtonsoft.Json.JsonConvert.DeserializeObject <ModularProgramTermValues>(modularTerm.Values["Values"].ToString()); //update the request.json term value to include system generated documents revisionsetIDs termValues.Documents.Clear(); for (int i = 0; i < documentRevisionSets.Count; i++) { termValues.Documents.Add(new ModularProgramTermValues.Document { RevisionSetID = documentRevisionSets[i] }); } modularTerm.Values["Values"] = termValues; _entity.Query = Newtonsoft.Json.JsonConvert.SerializeObject(qcRequestDTO); await db.SaveChangesAsync(); await MarkTaskComplete(task); } return(new CompletionResult { ResultID = activityResultID.Value }); }
public override async Task Start(string comment) { var task = await PmnTask.GetActiveTaskForRequestActivityAsync(_entity.ID, ID, db); if (task == null) { task = db.Actions.Add(PmnTask.CreateForWorkflowActivity(_entity.ID, ID, _workflow.ID, db, CustomTaskSubject)); await db.SaveChangesAsync(); var analysisCenterRouting = await db.RequestDataMarts.Include(rdm => rdm.Responses).Where(rdm => rdm.RequestID == _entity.ID && rdm.RoutingType == RoutingType.AnalysisCenter).FirstOrDefaultAsync(); Lpp.Dns.Data.Response analysisCenterResponse = null; if (analysisCenterRouting.Status == RoutingStatus.Draft && analysisCenterRouting.Responses.Count == 1 && analysisCenterRouting.Responses.Where(rsp => rsp.ResponseTime.HasValue == false).Any()) { //if the initial status of the routing is draft, and there is only a single response assume this is the first time hitting the analysis center. //use the existing response to submit to the analysis center analysisCenterResponse = analysisCenterRouting.Responses.First(); } else if (analysisCenterRouting.Status != RoutingStatus.Draft) { analysisCenterRouting.Status = RoutingStatus.Draft; } if (analysisCenterResponse == null) { analysisCenterResponse = analysisCenterRouting.AddResponse(_workflow.Identity.ID); } if (db.Entry(task).Collection(t => t.References).IsLoaded == false) { await db.Entry(task).Collection(t => t.References).LoadAsync(); } if (task.References.Any(tr => tr.ItemID == analysisCenterResponse.ID) == false) { //add a reference to the response to be able to link task to iteration task.References.Add(new TaskReference { ItemID = analysisCenterResponse.ID, TaskID = task.ID, Type = TaskItemTypes.Response }); } //use all the dp output documents to be the input documents for the AC routing //build a manifest for where the documents are coming from List <Lpp.Dns.DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem> manifestItems = new List <DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem>(); var documents = await(from rd in db.RequestDocuments join rsp in db.Responses on rd.ResponseID equals rsp.ID join rdm in db.RequestDataMarts on rsp.RequestDataMartID equals rdm.ID join dm in db.DataMarts on rdm.DataMartID equals dm.ID join doc in db.Documents on rd.RevisionSetID equals doc.RevisionSetID where rsp.Count == rsp.RequestDataMart.Responses.Max(r => r.Count) && rdm.RequestID == _entity.ID && rd.DocumentType == RequestDocumentType.Output && rdm.RoutingType == RoutingType.DataPartner && doc.ID == db.Documents.Where(dd => dd.RevisionSetID == doc.RevisionSetID).OrderByDescending(dd => dd.MajorVersion).ThenByDescending(dd => dd.MinorVersion).ThenByDescending(dd => dd.BuildVersion).ThenByDescending(dd => dd.RevisionVersion).Select(dd => dd.ID).FirstOrDefault() select new { DocumentID = doc.ID, DocumentKind = doc.Kind, DocumentFileName = doc.FileName, ResponseID = rd.ResponseID, RevisionSetID = rd.RevisionSetID, RequestDataMartID = rsp.RequestDataMartID, DataMartID = rdm.DataMartID, DataPartnerIdentifier = dm.DataPartnerIdentifier, DataMart = dm.Name }).ToArrayAsync(); // further filtering based on if a output filelist document was included needs to be done. Only the files indicated should be passed on to the analysis center foreach (var dpDocuments in documents.GroupBy(k => k.RequestDataMartID)) { var filelistDocument = dpDocuments.Where(d => !string.IsNullOrEmpty(d.DocumentKind) && string.Equals("DistributedRegression.FileList", d.DocumentKind, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); if (filelistDocument != null) { //only include the files indicated in the filelist document using (var ds = new Lpp.Dns.Data.Documents.DocumentStream(db, filelistDocument.DocumentID)) using (var reader = new System.IO.StreamReader(ds)) { //read the header line reader.ReadLine(); string line, filename; bool includeInDistribution = false; while (!reader.EndOfStream) { line = reader.ReadLine(); string[] split = line.Split(','); if (split.Length > 0) { filename = split[0].Trim(); if (split.Length > 1) { includeInDistribution = string.Equals(split[1].Trim(), "1"); } else { includeInDistribution = false; } if (includeInDistribution == false) { continue; } if (!string.IsNullOrEmpty(filename)) { Guid?revisionSetID = dpDocuments.Where(d => string.Equals(d.DocumentFileName, filename, StringComparison.OrdinalIgnoreCase)).Select(d => d.RevisionSetID).FirstOrDefault(); if (revisionSetID.HasValue) { db.RequestDocuments.AddRange(dpDocuments.Where(d => d.RevisionSetID == revisionSetID.Value).Select(d => new RequestDocument { DocumentType = RequestDocumentType.Input, ResponseID = analysisCenterResponse.ID, RevisionSetID = d.RevisionSetID }).ToArray()); manifestItems.AddRange(dpDocuments.Where(d => d.RevisionSetID == revisionSetID.Value).Select(d => new DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem { DocumentID = d.DocumentID, DataMart = d.DataMart, DataMartID = d.DataMartID, DataPartnerIdentifier = d.DataPartnerIdentifier, RequestDataMartID = d.RequestDataMartID, ResponseID = d.ResponseID, RevisionSetID = d.RevisionSetID }).ToArray()); } } } } reader.Close(); } } else { db.RequestDocuments.AddRange(dpDocuments.Select(d => new RequestDocument { DocumentType = RequestDocumentType.Input, ResponseID = analysisCenterResponse.ID, RevisionSetID = d.RevisionSetID }).ToArray()); manifestItems.AddRange(dpDocuments.Select(d => new DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem { DocumentID = d.DocumentID, DataMart = d.DataMart, DataMartID = d.DataMartID, DataPartnerIdentifier = d.DataPartnerIdentifier, RequestDataMartID = d.RequestDataMartID, ResponseID = d.ResponseID, RevisionSetID = d.RevisionSetID }).ToArray()); } } //serialize the manifest of dataparter documents to the analysis center byte[] buffer; using (var ms = new System.IO.MemoryStream()) using (var sw = new System.IO.StreamWriter(ms)) using (var jw = new Newtonsoft.Json.JsonTextWriter(sw)) { Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer(); serializer.Serialize(jw, manifestItems); jw.Flush(); buffer = ms.ToArray(); } //create and add the manifest file Document analysisCenterManifest = db.Documents.Add(new Document { Description = "Contains information about the input documents and the datamart they came from.", Name = "Internal: Analysis Center Manifest", FileName = "manifest.json", ItemID = task.ID, Kind = DocumentKind.SystemGeneratedNoLog, UploadedByID = _workflow.Identity.ID, Viewable = false, MimeType = "application/json", Length = buffer.Length }); analysisCenterManifest.RevisionSetID = analysisCenterManifest.ID; db.RequestDocuments.Add(new RequestDocument { DocumentType = RequestDocumentType.Input, ResponseID = analysisCenterResponse.ID, RevisionSetID = analysisCenterManifest.RevisionSetID.Value }); await db.SaveChangesAsync(); await db.Entry(analysisCenterRouting).ReloadAsync(); //post the manifest content analysisCenterManifest.SetData(db, buffer); //submit the routing analysisCenterRouting.Status = analysisCenterResponse.Count > 1 ? RoutingStatus.Resubmitted : RoutingStatus.Submitted; await db.SaveChangesAsync(); //change the status of the request to conducting analysis //manually override the request status using sql direct, EF does not allow update of computed await db.Database.ExecuteSqlCommandAsync("UPDATE Requests SET Status = @status WHERE ID = @ID", new System.Data.SqlClient.SqlParameter("@status", (int)RequestStatuses.ConductingAnalysis), new System.Data.SqlClient.SqlParameter("@ID", _entity.ID)); await db.Entry(_entity).ReloadAsync(); } if (!string.IsNullOrWhiteSpace(comment)) { var cmt = db.Comments.Add(new Comment { CreatedByID = _workflow.Identity.ID, ItemID = _entity.ID, Text = comment }); db.CommentReferences.Add(new CommentReference { CommentID = cmt.ID, Type = DTO.Enums.CommentItemTypes.Task, ItemTitle = task.Subject, ItemID = task.ID }); await db.SaveChangesAsync(); } }