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 <ValidationResult> Validate(Guid?activityResultID) { if (activityResultID == null) { return(new ValidationResult { Success = false, Errors = CommonMessages.ActivityResultIDRequired }); } var permissions = await db.GetGrantedWorkflowActivityPermissionsForRequestAsync(_workflow.Identity, _entity); if (!permissions.Contains(PermissionIdentifiers.ProjectRequestTypeWorkflowActivities.EditTask) && (activityResultID.Value == SaveResultID || activityResultID.Value == ModifyResultID)) { return(new ValidationResult { Success = false, Errors = CommonMessages.RequirePermissionToEditTask }); } if (!permissions.Contains(PermissionIdentifiers.ProjectRequestTypeWorkflowActivities.CloseTask) && (activityResultID.Value == SubmitResultID)) { return(new ValidationResult { Success = false, Errors = CommonMessages.RequirePermissionToCloseTask }); } if (!permissions.Contains(PermissionIdentifiers.ProjectRequestTypeWorkflowActivities.CloseTask) && (activityResultID.Value == TerminateResultID)) { return(new ValidationResult { Success = false, Errors = CommonMessages.RequirePermissionToTerminateWorkflow }); } var errors = new StringBuilder(); if (activityResultID.Value == SubmitResultID) { if (_entity.ProjectID == null) { errors.AppendHtmlLine("Please ensure that you have selected a project for the request."); } if (_entity.DueDate.HasValue && _entity.DueDate.Value < DateTime.UtcNow) { errors.AppendHtmlLine("The Request Due Date must be set in the future."); } var dataMartsDueDate = false; foreach (var dm in _entity.DataMarts) { if (dm.DueDate.HasValue && dm.DueDate.Value.Date < DateTime.UtcNow.Date) { dataMartsDueDate = true; } } if (dataMartsDueDate) { errors.AppendHtmlLine("The Request's DataMart Due Dates must be set in the future."); } if (_entity.SubmittedOn.HasValue) { errors.AppendHtmlLine("Cannot submit a request that has already been submitted"); } if (_entity.Template) { errors.AppendHtmlLine("Cannot submit a request template"); } if (_entity.Scheduled) { errors.AppendHtmlLine("Cannot submit a scheduled request"); } await db.LoadReference(_entity, (r) => r.Project); //If a project loaded successfully check it. if (_entity.Project != null) { if (!_entity.Project.Active || _entity.Project.Deleted) { errors.AppendHtmlLine("Cannot submit a request for an inactive or deleted project."); } if (_entity.Project.EndDate < DateTime.UtcNow) { errors.AppendHtmlLine("Cannot submit a request for a project that has ended."); } await db.LoadCollection(_entity.Project, (p) => p.DataMarts); if (_entity.DataMarts.Any(dm => !_entity.Project.DataMarts.Any(pdm => pdm.DataMartID == dm.DataMartID))) { errors.AppendHtmlLine("The request contains datamarts that are not part of the project specified and thus cannot be processed. Please remove these datamarts and try again."); } } await db.LoadCollection(_entity, (r) => r.DataMarts); var dataMarts = _entity.GetGrantedDataMarts(db, _workflow.Identity); if (_entity.DataMarts.Any(dm => !dataMarts.Any(gdm => gdm.ID == dm.DataMartID))) { errors.AppendHtmlLine("This request contains datamarts you are not permitted to submit to. Please remove them and try again."); } 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 }; if (_entity.DataMarts.Count < 2) { var skip2DataMartRulePerms = await db.HasGrantedPermissions <Request>(_workflow.Identity, _entity, filters, PermissionIdentifiers.Portal.SkipTwoDataMartRule); if (!skip2DataMartRulePerms.Contains(PermissionIdentifiers.Portal.SkipTwoDataMartRule)) { errors.AppendHtmlLine("Cannot submit a request with less than 2 datamarts"); } } } if (errors.Length > 0) { return(new ValidationResult { Success = false, Errors = errors.ToString() }); } else { return(new ValidationResult { Success = true }); } }
public override async Task <CompletionResult> Complete(string data, Guid?activityResultID) { if (!activityResultID.HasValue) { throw new ArgumentNullException(CommonMessages.ActivityResultIDRequired); } if (activityResultID.Value == SaveResultID) { return(new CompletionResult { ResultID = SaveResultID }); } else if (activityResultID.Value == RejectResultID) { _entity.Status = DTO.Enums.RequestStatuses.RequestRejected; var task = PmnTask.GetActiveTaskForRequestActivity(_entity.ID, ID, db); var originalStatus = _entity.Status; await SetRequestStatus(DTO.Enums.RequestStatuses.RequestRejected); await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.RequestRejected); await MarkTaskComplete(task); await db.SaveChangesAsync(); return(new CompletionResult { ResultID = RejectResultID }); } else if (activityResultID.Value == ApproveResultID) { var filters = new ExtendedQuery { Projects = (a) => a.ProjectID == _entity.ProjectID, ProjectOrganizations = a => a.ProjectID == _entity.ProjectID && a.OrganizationID == _entity.OrganizationID, Organizations = a => a.OrganizationID == _entity.OrganizationID, Users = a => a.UserID == _entity.CreatedByID }; var permissions = await db.HasGrantedPermissions <Request>(_workflow.Identity, _entity, filters, PermissionIdentifiers.Request.ApproveRejectSubmission); if (!permissions.Contains(PermissionIdentifiers.Request.ApproveRejectSubmission)) { throw new SecurityException(CommonMessages.RequirePermissionToApproveOrRejectRequestSubmission); } var originalStatus = _entity.Status; await SetRequestStatus(DTO.Enums.RequestStatuses.RequestPendingDistribution); await db.LoadCollection(_entity, (r) => r.DataMarts); await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.RequestPendingDistribution); var task = PmnTask.GetActiveTaskForRequestActivity(_entity.ID, ID, db); await MarkTaskComplete(task); return(new CompletionResult { ResultID = ApproveResultID }); } else { throw new NotSupportedException(CommonMessages.ActivityResultNotSupported); } }
/// <summary> /// Performs common submit validation of a request. /// </summary> /// <returns>Any error messages, empty if valid.</returns> protected async Task <string> PerformSubmitValidation() { var errors = new StringBuilder(); if (_entity.ProjectID == null) { errors.AppendHtmlLine("Please ensure that you have selected a project for the request."); } if (_entity.DueDate.HasValue && _entity.DueDate.Value < DateTime.UtcNow) { errors.AppendHtmlLine("The Request Due Date must be set in the future."); } var dataMartsDueDate = false; foreach (var dm in _entity.DataMarts) { if (dm.DueDate.HasValue && dm.DueDate.Value.Date < DateTime.UtcNow.Date) { dataMartsDueDate = true; } } if (dataMartsDueDate) { errors.AppendHtmlLine("The Request's DataMart Due Dates must be set in the future."); } if (_entity.SubmittedOn.HasValue && _entity.Status != Lpp.Dns.DTO.Enums.RequestStatuses.RequestRejected) //Rejected requests can be re-submitted. { errors.AppendHtmlLine("Cannot submit a request that has already been submitted"); } if (_entity.Template) { errors.AppendHtmlLine("Cannot submit a request template"); } if (_entity.Scheduled) { errors.AppendHtmlLine("Cannot submit a scheduled request"); } await db.LoadReference(_entity, (r) => r.Project); await db.LoadCollection(_entity, (r) => r.DataMarts); //If a project loaded successfully check it. if (_entity.Project != null) { if (!_entity.Project.Active || _entity.Project.Deleted) { errors.AppendHtmlLine("Cannot submit a request for an inactive or deleted project."); } if (_entity.Project.EndDate < DateTime.UtcNow) { errors.AppendHtmlLine("Cannot submit a request for a project that has ended."); } await db.LoadCollection(_entity.Project, (p) => p.DataMarts); if (_entity.DataMarts.Any(dm => !_entity.Project.DataMarts.Any(pdm => pdm.DataMartID == dm.DataMartID))) { errors.AppendHtmlLine("The request contains datamarts that are not part of the project specified and thus cannot be processed. Please remove these datamarts and try again."); } } var dataMarts = await GetAllAvailableDataMarts(); if (_entity.DataMarts.Any(dm => !dataMarts.Any(gdm => gdm == dm.DataMartID))) { errors.AppendHtmlLine("This request contains datamarts you are not permitted to submit to. Please remove them and try again."); } 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 }; if (_entity.DataMarts.Count < 2) { var skip2DataMartRulePerms = await db.HasGrantedPermissions <Request>(_workflow.Identity, _entity, filters, PermissionIdentifiers.Portal.SkipTwoDataMartRule); if (!skip2DataMartRulePerms.Contains(PermissionIdentifiers.Portal.SkipTwoDataMartRule)) { errors.AppendHtmlLine("Cannot submit a request with less than 2 datamarts"); } } return(errors.ToString()); }
private bool SubmitRequest(Guid requestID, ApiIdentity identity) { /** * Due to concurrency issues that are being created somehow by doing the update first * this operation is being done using a standalone datacontext and fresh data from db. * */ RoutingStatus targetStatus = RoutingStatus.AwaitingRequestApproval; using (var datacontext = new DataContext()) { var request = datacontext.Requests.Include(r => r.DataMarts.Select(rr => rr.Responses)).Include(r => r.RequestType).Single(r => r.ID == requestID); var project = datacontext.Projects.SingleOrDefault(p => p.ID == request.ProjectID); if (project == null) { /** * BMS: We used to allow a metadata request to be submitted w/o a project, however this causes the request to be lost from any view, * so now I force the request to a project until we figure out how to display requests w/o project assignments. **/ throw new Exception("Cannot submit a request outside of a Project context. Please select a Project."); } if (!project.Active || project.Deleted) { throw new Exception("Cannot submit requests for project " + project.Name + ", because the project is marked inactive."); } if (project.StartDate != null && project.StartDate > DateTime.UtcNow) { throw new Exception("Cannot submit requests for project " + project.Name + ", because the project has not started yet."); } if (project.EndDate != null && project.EndDate < DateTime.UtcNow) { throw new Exception("Cannot submit requests for project " + project.Name + ", because the project has already finished."); } var dueDate = request.DueDate; if (dueDate != null && dueDate < DateTime.UtcNow.Date) { throw new Exception("Due date must be set in the future."); } var pastDueDate = false; foreach (var dm in request.DataMarts) { if (dm.DueDate != null && dm.DueDate < DateTime.UtcNow.Date) { pastDueDate = true; } } if (pastDueDate) { throw new Exception("Request's DataMart Due dates must be set in the future."); } var grantedDataMarts = GetGrantedDataMarts(project, request.RequestTypeID, identity).ToArray(); var nonGrantedDataMartIDs = datacontext.RequestDataMarts.Where(dm => dm.RequestID == request.ID).Select(dm => dm.DataMartID).Except(grantedDataMarts.Select(d => d.ID)).ToArray(); if (nonGrantedDataMartIDs.Length > 0) { var nonGrantedDmNames = datacontext.DataMarts.Where(dm => nonGrantedDataMartIDs.Contains(dm.ID)).Select(dm => dm.Name); throw new Exception("You do not have permission to submit requests of type '" + request.RequestType.Name + "' to the following data marts: " + string.Join(", ", nonGrantedDmNames)); } // Remove datamarts that do not belong to the Project var invalidDataMarts = (from dm in datacontext.RequestDataMarts.Where(d => d.RequestID == request.ID) join pdm in datacontext.ProjectDataMarts.Where(p => p.ProjectID == request.ProjectID) on dm.DataMartID equals pdm.DataMartID into pdms where !pdms.Any() select dm).ToList(); if (invalidDataMarts.Count > 0) { datacontext.RequestDataMarts.RemoveRange(invalidDataMarts); } if (request.SubmittedOn.HasValue) { throw new Exception("Cannot submit a request that has already been submitted"); } if (request.Template) { throw new Exception("Cannot submit a request template"); } if (request.Scheduled) { throw new Exception("Cannot submit a scheduled request"); } var filters = 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 }; if (request.DataMarts.Count < 2) { var skip2DataMartRulePerms = AsyncHelpers.RunSync(() => datacontext.HasGrantedPermissions <Request>(identity, request, filters, PermissionIdentifiers.Portal.SkipTwoDataMartRule)); if (!skip2DataMartRulePerms.Contains(PermissionIdentifiers.Portal.SkipTwoDataMartRule)) { throw new Exception("Cannot submit a request with less than 2 datamarts."); } } var permissions = AsyncHelpers.RunSync(() => datacontext.HasGrantedPermissions <Request>(identity, request, filters, PermissionIdentifiers.Request.SkipSubmissionApproval)); if (permissions.Contains(PermissionIdentifiers.Request.SkipSubmissionApproval)) { targetStatus = RoutingStatus.Submitted; } request.Status = targetStatus == RoutingStatus.Submitted ? RequestStatuses.Submitted : RequestStatuses.AwaitingRequestApproval; request.SubmittedOn = DateTime.UtcNow; request.SubmittedByID = identity.ID; //set the version on the request request.AdapterPackageVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(this.GetType().Assembly.Location).FileVersion; foreach (var d in request.DataMarts) { if (grantedDataMarts.Any(dm => dm.ID == d.DataMartID)) { d.Status = targetStatus; foreach (var response in d.Responses) { response.SubmittedByID = identity.ID; response.SubmittedOn = request.SubmittedOn ?? DateTime.UtcNow; } } else { datacontext.RequestDataMarts.Remove(d); } } datacontext.SaveChanges(); //SALMAN - TODO //if (result.IsSuccess && targetStatus == RoutingStatus.Submitted) //{ // ExecuteIfLocalRequest(ctx, datacontext); //} //return result; return(true); } }
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));; }