/// <summary> /// Create and send request status change notifications. /// </summary> /// <param name="currentStatus">The original status of the request.</param> /// <param name="newStatus">The new status of the request.</param> /// <returns></returns> protected async Task NotifyRequestStatusChanged(DTO.Enums.RequestStatuses currentStatus, DTO.Enums.RequestStatuses newStatus) { string[] emailText = await _requestLogger.GenerateRequestStatusChangedEmailContent(db, _entity.ID, _workflow.Identity.ID, currentStatus, newStatus); var logItems = _requestLogger.GenerateRequestStatusEvents(db, _workflow.Identity, false, currentStatus, newStatus, _entity.ID, emailText[1], emailText[0], "Request Status Changed"); await db.SaveChangesAsync(); await ProcessNotifications(logItems); }
/// <summary> /// Manually set the status of the request using a direct sql command, the status on the entity is also set and a save on the datacontext called. By default the entity is refreshed after the actions have been completed. /// </summary> /// <param name="newStatus">The status to set.</param> /// <param name="refreshEntity">If true the entity will be reloaded.</param> /// <returns></returns> protected async Task SetRequestStatus(DTO.Enums.RequestStatuses newStatus, bool refreshEntity = true) { //if we do not set and and save the status the entity logger will not fire based on status changes correctly _entity.Status = newStatus; await db.SaveChangesAsync(); //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)newStatus), new System.Data.SqlClient.SqlParameter("@ID", _entity.ID)); if (refreshEntity) { await db.Entry(_entity).ReloadAsync(); } }
public override async Task <CompletionResult> Complete(string data, Guid?activityResultID) { //default to SaveResultID if resultID not specified if (!activityResultID.HasValue) { activityResultID = SaveResultID; } await db.Entry(_entity).ReloadAsync(); var task = PmnTask.GetActiveTaskForRequestActivity(_entity.ID, ID, db); if (activityResultID.Value == SubmitResultID) //Submit { await db.LoadCollection(_entity, (r) => r.DataMarts); var filters = new ExtendedQuery { Projects = (a) => a.ProjectID == _entity.ProjectID, ProjectOrganizations = a => a.ProjectID == _entity.ProjectID && a.OrganizationID == _entity.OrganizationID, Organizations = a => a.OrganizationID == _entity.OrganizationID, Users = a => a.UserID == _entity.CreatedByID }; var permissions = await db.HasGrantedPermissions <Request>(_workflow.Identity, _entity, filters, PermissionIdentifiers.Request.SkipSubmissionApproval); await db.Entry(_entity).ReloadAsync(); if (Newtonsoft.Json.JsonConvert.DeserializeObject <Lpp.Dns.DTO.QueryComposer.QueryComposerRequestDTO>(_entity.Query).Where.Criteria.Any(c => c.Terms.Any(t => t.Type.ToString().ToUpper() == "2F60504D-9B2F-4DB1-A961-6390117D3CAC") || c.Criteria.Any(ic => ic.Terms.Any(t => t.Type.ToString().ToUpper() == "2F60504D-9B2F-4DB1-A961-6390117D3CAC")))) { if (!permissions.Contains(PermissionIdentifiers.Request.SkipSubmissionApproval)) { //file distribution never requires review before submission, add the permission if the user does not have it. permissions = new[] { PermissionIdentifiers.Request.SkipSubmissionApproval }; } await db.LoadCollection(_entity, (r) => r.DataMarts); if (!_entity.DataMarts.Any()) { throw new Exception("At least one routing needs to be specified when submitting a requests."); } //prepare the request documents, save created documents same as legacy IList <Guid> documentRevisionSets = Newtonsoft.Json.JsonConvert.DeserializeObject <IList <Guid> >(data); IEnumerable <Document> documents = await(from d in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => documentRevisionSets.Contains(dd.RevisionSetID.Value)) .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on d.ID equals x orderby d.ItemID descending, d.RevisionSetID descending, d.CreatedOn descending select d).ToArrayAsync(); await db.Entry(_entity).Reference(r => r.Activity).LoadAsync(); await db.Entry(_entity).Reference(r => r.RequestType).LoadAsync(); string submitterEmail = await db.Users.Where(u => u.ID == _workflow.Identity.ID).Select(u => u.Email).SingleAsync(); //update the request _entity.SubmittedByID = _workflow.Identity.ID; _entity.SubmittedOn = DateTime.UtcNow; _entity.AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion; _entity.RejectedByID = null; _entity.RejectedOn = null; _entity.Private = false; //save the changes to the request now since the trigger for routings will change the status invalidating the object before save await db.SaveChangesAsync(); await db.Entry(_entity).ReloadAsync(); var originalStatus = _entity.Status; await SetRequestStatus(DTO.Enums.RequestStatuses.Submitted, false); var allTasks = await db.ActionReferences.Where(tr => tr.ItemID == _entity.ID && tr.Type == DTO.Enums.TaskItemTypes.Request && tr.Task.Type == DTO.Enums.TaskTypes.Task ) .Select(tr => tr.Task.ID).ToArrayAsync(); var attachments = await(from doc in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => allTasks.Contains(dd.ItemID)) .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on doc.ID equals x where allTasks.Contains(doc.ItemID) && doc.Kind == "Attachment.Input" orderby doc.ItemID descending, doc.RevisionSetID descending, doc.CreatedOn descending select doc).ToArrayAsync(); foreach (var dm in _entity.DataMarts.Where(dm => dm.Status == 0 || dm.Status == DTO.Enums.RoutingStatus.AwaitingRequestApproval || dm.Status == DTO.Enums.RoutingStatus.Draft)) { dm.Status = DTO.Enums.RoutingStatus.Submitted; var currentResponse = db.Responses.Include(rsp => rsp.RequestDocument).FirstOrDefault(r => r.RequestDataMartID == dm.ID && r.Count == r.RequestDataMart.Responses.Max(rr => rr.Count)); if (currentResponse == null) { currentResponse = db.Responses.Add(new Response { RequestDataMartID = dm.ID }); } currentResponse.SubmittedByID = _workflow.Identity.ID; currentResponse.SubmittedOn = DateTime.UtcNow; //add the request document associations for (int i = 0; i < documentRevisionSets.Count; i++) { if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == documentRevisionSets[i])) { db.RequestDocuments.Add(new RequestDocument { RevisionSetID = documentRevisionSets[i], ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input }); } } foreach (var attachment in attachments) { if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == attachment.RevisionSetID.Value)) { db.RequestDocuments.Add(new RequestDocument { RevisionSetID = attachment.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput }); } } } await db.SaveChangesAsync(); //reload the request since altering the routings triggers a change of the request status in the db by a trigger. await db.Entry(_entity).ReloadAsync(); DTO.QueryComposer.QueryComposerRequestDTO qcRequestDTO = Newtonsoft.Json.JsonConvert.DeserializeObject <DTO.QueryComposer.QueryComposerRequestDTO>(_entity.Query); var fileUploadTerm = qcRequestDTO.Where.Criteria.SelectMany(c => c.Terms.Where(t => t.Type == FileUploadTermID)).FirstOrDefault(); var termValues = Newtonsoft.Json.JsonConvert.DeserializeObject <FileUploadValues>(fileUploadTerm.Values["Values"].ToString()); //update the request.json term value to include system generated documents revisionsetIDs termValues.Documents.Clear(); for (int i = 0; i < documentRevisionSets.Count; i++) { termValues.Documents.Add(new FileUploadValues.Document { RevisionSetID = documentRevisionSets[i] }); } fileUploadTerm.Values["Values"] = termValues; _entity.Query = Newtonsoft.Json.JsonConvert.SerializeObject(qcRequestDTO); await db.SaveChangesAsync(); await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Submitted); } else { await db.LoadCollection(_entity, (r) => r.DataMarts); var parentDocument = db.Documents.FirstOrDefault(d => d.ItemID == _entity.ID && d.Kind == DocumentKind && d.ParentDocumentID == null); byte[] documentContent = System.Text.UTF8Encoding.UTF8.GetBytes(_entity.Query ?? string.Empty); var document = new Document { Name = "Request Criteria", MajorVersion = parentDocument == null ? 1 : parentDocument.MajorVersion, MinorVersion = parentDocument == null ? 0 : parentDocument.MinorVersion, RevisionVersion = parentDocument == null ? 0 : parentDocument.RevisionVersion, MimeType = "application/json", Viewable = false, UploadedByID = _workflow.Identity.ID, FileName = "request.json", CreatedOn = DateTime.UtcNow, BuildVersion = parentDocument == null ? 0 : parentDocument.BuildVersion, ParentDocumentID = parentDocument == null ? (Guid?)null : parentDocument.ID, ItemID = task.ID, Length = documentContent.LongLength, Kind = Dns.DTO.Enums.DocumentKind.Request }; db.Documents.Add(document); document.RevisionSetID = document.ID; await db.SaveChangesAsync(); document.SetData(db, documentContent); _entity.AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion; //Reset reject for resubmit. _entity.RejectedByID = null; _entity.RejectedOn = null; _entity.Private = false; await db.SaveChangesAsync(); DTO.Enums.RequestStatuses newRequestStatus = DTO.Enums.RequestStatuses.AwaitingRequestApproval; if (permissions.Contains(PermissionIdentifiers.Request.SkipSubmissionApproval)) { _entity.SubmittedByID = _workflow.Identity.ID; _entity.SubmittedOn = DateTime.UtcNow; await db.SaveChangesAsync(); var allTasks = await db.ActionReferences.Where(tr => tr.ItemID == _entity.ID && tr.Type == DTO.Enums.TaskItemTypes.Request && tr.Task.Type == DTO.Enums.TaskTypes.Task ) .Select(tr => tr.Task.ID).ToArrayAsync(); var attachments = await(from doc in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => allTasks.Contains(dd.ItemID)) .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on doc.ID equals x where allTasks.Contains(doc.ItemID) && doc.Kind == "Attachment.Input" orderby doc.ItemID descending, doc.RevisionSetID descending, doc.CreatedOn descending select doc).ToArrayAsync(); _entity.Status = DTO.Enums.RequestStatuses.Submitted; foreach (var dm in _entity.DataMarts) { dm.Status = DTO.Enums.RoutingStatus.Submitted; var currentResponse = db.Responses.Include(rsp => rsp.RequestDocument).FirstOrDefault(r => r.RequestDataMartID == dm.ID && r.Count == r.RequestDataMart.Responses.Max(rr => rr.Count)); if (currentResponse == null) { currentResponse = db.Responses.Add(new Response { RequestDataMartID = dm.ID }); } currentResponse.SubmittedByID = _workflow.Identity.ID; currentResponse.SubmittedOn = DateTime.UtcNow; if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == document.RevisionSetID.Value)) { db.RequestDocuments.Add(new RequestDocument { RevisionSetID = document.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.Input }); } foreach (var attachment in attachments) { if (!currentResponse.RequestDocument.Any(rd => rd.RevisionSetID == attachment.RevisionSetID.Value)) { db.RequestDocuments.Add(new RequestDocument { RevisionSetID = attachment.RevisionSetID.Value, ResponseID = currentResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput }); } } } } else { _entity.Status = DTO.Enums.RequestStatuses.AwaitingRequestApproval; foreach (var dm in _entity.DataMarts) { dm.Status = DTO.Enums.RoutingStatus.AwaitingRequestApproval; } } await db.SaveChangesAsync(); await db.Entry(_entity).ReloadAsync(); await SetRequestStatus(newRequestStatus); await MarkTaskComplete(task); } return(new CompletionResult { ResultID = permissions.Contains(PermissionIdentifiers.Request.SkipSubmissionApproval) ? SubmitResultID : ReviewResultID }); } else if (activityResultID.Value == SaveResultID) //Save { if (_entity.Private) { await db.Entry(_entity).ReloadAsync(); _entity.Private = false; await task.LogAsModifiedAsync(_workflow.Identity, db); await db.SaveChangesAsync(); } return(new CompletionResult { ResultID = SaveResultID }); } else if (activityResultID.Value == DeleteResultID) //Delete { _workflow.DataContext.Requests.Remove(_workflow.Entity); if (task != null) { db.Actions.Remove(task); } await _workflow.DataContext.SaveChangesAsync(); return(null); } else { throw new ArgumentOutOfRangeException(CommonMessages.ActivityResultNotSupported); } }
public override async Task <CompletionResult> Complete(string data, Guid?activityResultID) { if (!activityResultID.HasValue) { throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired); } if (//activityResultID.Value != CompleteResultID && activityResultID.Value != ReopenSubmitDraftReportResultID && activityResultID.Value != SubmitReportForReviewResultID && activityResultID.Value != SaveResultID && activityResultID.Value != CompleteWithoutReportResultID) { throw new NotSupportedException(CommonMessages.ActivityResultNotSupported); } if (activityResultID.Value == SaveResultID) { return(new CompletionResult { ResultID = SaveResultID }); } Guid destinationActivityID = Guid.Empty; DTO.Enums.RequestStatuses destinationRequestStatus = DTO.Enums.RequestStatuses.Complete; var originalStatus = _entity.Status; if (activityResultID.Value == CompleteWithoutReportResultID) { await SetRequestStatus(DTO.Enums.RequestStatuses.Complete); destinationActivityID = SummaryQueryWorkflowConfiguration.CompletedID; } else if (activityResultID.Value == SubmitReportForReviewResultID) { await SetRequestStatus(DTO.Enums.RequestStatuses.FinalReportPendingReview); destinationActivityID = SummaryQueryWorkflowConfiguration.ReviewFinalReportID; destinationRequestStatus = DTO.Enums.RequestStatuses.FinalReportPendingReview; } else if (activityResultID.Value == ReopenSubmitDraftReportResultID) { await SetRequestStatus(DTO.Enums.RequestStatuses.PendingDraftReport); destinationActivityID = SummaryQueryWorkflowConfiguration.SubmitDraftReportID; destinationRequestStatus = DTO.Enums.RequestStatuses.PendingDraftReport; } var task = PmnTask.GetActiveTaskForRequestActivity(_entity.ID, ID, db); await MarkTaskComplete(task); await NotifyRequestStatusChanged(originalStatus, destinationRequestStatus); return(new CompletionResult { ResultID = activityResultID.Value }); }