/// <summary> /// /// </summary> /// <param name="request"></param> /// <returns></returns> async Task FromDataPartner(RequestDataMart reqDM) { //close the current task var currentTask = await PmnTask.GetActiveTaskForRequestActivityAsync(reqDM.Request.ID, reqDM.Request.WorkFlowActivityID.Value, DB); CompleteTask(currentTask); //open new task and set the request to the new activity var task = DB.Actions.Add(PmnTask.CreateForWorkflowActivity(reqDM.Request.ID, ConductAnalysisActivityID, WorkflowID, DB)); reqDM.Request.WorkFlowActivityID = ConductAnalysisActivityID; //create new routing var analysisCenterRouting = await DB.RequestDataMarts.Include(rdm => rdm.Responses).Where(rdm => rdm.RequestID == reqDM.Request.ID && rdm.RoutingType == RoutingType.AnalysisCenter).FirstOrDefaultAsync(); Lpp.Dns.Data.Response analysisCenterResponse = null; if (analysisCenterRouting.Status == RoutingStatus.Draft && analysisCenterRouting.Responses.Count == 1 && analysisCenterRouting.Responses.Where(rsp => rsp.ResponseTime.HasValue == false).Any()) { //if the initial status of the routing is draft, and there is only a single response assume this is the first time hitting the analysis center. //use the existing response to submit to the analysis center analysisCenterResponse = analysisCenterRouting.Responses.First(); } else if (analysisCenterRouting.Status != RoutingStatus.Draft) { analysisCenterRouting.Status = RoutingStatus.Draft; } if (analysisCenterResponse == null) { analysisCenterResponse = analysisCenterRouting.AddResponse(IdentityID); } //use all the dp output documents to be the input documents for the AC routing //build a manifest for where the documents are coming from List <Lpp.Dns.DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem> manifestItems = new List <DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem>(); var q = from rd in DB.RequestDocuments join rsp in DB.Responses on rd.ResponseID equals rsp.ID join rdm in DB.RequestDataMarts on rsp.RequestDataMartID equals rdm.ID join dm in DB.DataMarts on rdm.DataMartID equals dm.ID join doc in DB.Documents on rd.RevisionSetID equals doc.RevisionSetID where rsp.Count == rsp.RequestDataMart.Responses.Max(r => r.Count) && rdm.RequestID == reqDM.Request.ID && rd.DocumentType == RequestDocumentType.Output && rdm.RoutingType == RoutingType.DataPartner && doc.ItemID == rsp.ID && doc.ID == DB.Documents.Where(dd => dd.RevisionSetID == doc.RevisionSetID && doc.ItemID == rsp.ID).OrderByDescending(dd => dd.MajorVersion).ThenByDescending(dd => dd.MinorVersion).ThenByDescending(dd => dd.BuildVersion).ThenByDescending(dd => dd.RevisionVersion).Select(dd => dd.ID).FirstOrDefault() select new { DocumentID = doc.ID, DocumentKind = doc.Kind, DocumentFileName = doc.FileName, ResponseID = rd.ResponseID, RevisionSetID = rd.RevisionSetID, RequestDataMartID = rsp.RequestDataMartID, DataMartID = rdm.DataMartID, DataPartnerIdentifier = dm.DataPartnerIdentifier, DataMart = dm.Name }; var documents = await(q).ToArrayAsync(); // further filtering based on if a output filelist document was included needs to be done. Only the files indicated should be passed on to the analysis center foreach (var dpDocuments in documents.GroupBy(k => k.RequestDataMartID)) { var filelistDocument = dpDocuments.Where(d => !string.IsNullOrEmpty(d.DocumentKind) && string.Equals("DistributedRegression.FileList", d.DocumentKind, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); if (filelistDocument != null) { //only include the files indicated in the filelist document using (var ds = new Lpp.Dns.Data.Documents.DocumentStream(DB, filelistDocument.DocumentID)) using (var reader = new System.IO.StreamReader(ds)) { //read the header line reader.ReadLine(); string line, filename; bool includeInDistribution = false; while (!reader.EndOfStream) { line = reader.ReadLine(); string[] split = line.Split(','); if (split.Length > 0) { filename = split[0].Trim(); if (split.Length > 1) { includeInDistribution = string.Equals(split[1].Trim(), "1"); } else { includeInDistribution = false; } if (includeInDistribution == false) { continue; } if (!string.IsNullOrEmpty(filename)) { Guid?revisionSetID = dpDocuments.Where(d => string.Equals(d.DocumentFileName, filename, StringComparison.OrdinalIgnoreCase)).Select(d => d.RevisionSetID).FirstOrDefault(); if (revisionSetID.HasValue) { DB.RequestDocuments.AddRange(dpDocuments.Where(d => d.RevisionSetID == revisionSetID.Value).Select(d => new RequestDocument { DocumentType = RequestDocumentType.Input, ResponseID = analysisCenterResponse.ID, RevisionSetID = d.RevisionSetID }).ToArray()); manifestItems.AddRange(dpDocuments.Where(d => d.RevisionSetID == revisionSetID.Value).Select(d => new DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem { DocumentID = d.DocumentID, DataMart = d.DataMart, DataMartID = d.DataMartID, DataPartnerIdentifier = d.DataPartnerIdentifier, RequestDataMartID = d.RequestDataMartID, ResponseID = d.ResponseID, RevisionSetID = d.RevisionSetID }).ToArray()); } } } } reader.Close(); } } else { var inputDocuments = dpDocuments.Where(d => d.DocumentKind != "DistributedRegression.AdapterEventLog" && d.DocumentKind != "DistributedRegression.TrackingTable"); if (inputDocuments.Count() > 0) { DB.RequestDocuments.AddRange(inputDocuments.Select(d => new RequestDocument { DocumentType = RequestDocumentType.Input, ResponseID = analysisCenterResponse.ID, RevisionSetID = d.RevisionSetID }).ToArray()); manifestItems.AddRange(inputDocuments.Select(d => new DTO.QueryComposer.DistributedRegressionAnalysisCenterManifestItem { DocumentID = d.DocumentID, DataMart = d.DataMart, DataMartID = d.DataMartID, DataPartnerIdentifier = d.DataPartnerIdentifier, RequestDataMartID = d.RequestDataMartID, ResponseID = d.ResponseID, RevisionSetID = d.RevisionSetID }).ToArray()); } } } //serialize the manifest of dataparter documents to the analysis center byte[] buffer; using (var ms = new System.IO.MemoryStream()) using (var sw = new System.IO.StreamWriter(ms)) using (var jw = new Newtonsoft.Json.JsonTextWriter(sw)) { Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer(); serializer.Serialize(jw, manifestItems); jw.Flush(); buffer = ms.ToArray(); } //create and add the manifest file Document analysisCenterManifest = DB.Documents.Add(new Document { Description = "Contains information about the input documents and the datamart they came from.", Name = "Internal: Analysis Center Manifest", FileName = "manifest.json", ItemID = task.ID, Kind = DocumentKind.SystemGeneratedNoLog, UploadedByID = IdentityID, Viewable = false, MimeType = "application/json", Length = buffer.Length }); analysisCenterManifest.RevisionSetID = analysisCenterManifest.ID; //TODO:determine if there is a parent document to make the manifest a revision of. If there is update the revisionset id, and version numbers //chances are there should not be unless this is a resubmit for the same task var allTasks = await DB.ActionReferences.Where(tr => tr.ItemID == reqDM.Request.ID && tr.Type == DTO.Enums.TaskItemTypes.Request && tr.Task.Type == DTO.Enums.TaskTypes.Task ) .Select(tr => tr.Task.ID).ToArrayAsync(); var attachments = await(from doc in DB.Documents.AsNoTracking() join x in ( DB.Documents.Where(dd => allTasks.Contains(dd.ItemID)) .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on doc.ID equals x where allTasks.Contains(doc.ItemID) && doc.Kind == "Attachment.Input" orderby doc.ItemID descending, doc.RevisionSetID descending, doc.CreatedOn descending select doc).ToArrayAsync(); DB.RequestDocuments.Add(new RequestDocument { DocumentType = RequestDocumentType.Input, ResponseID = analysisCenterResponse.ID, RevisionSetID = analysisCenterManifest.RevisionSetID.Value }); foreach (var attachment in attachments) { DB.RequestDocuments.Add(new RequestDocument { RevisionSetID = attachment.RevisionSetID.Value, ResponseID = analysisCenterResponse.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput }); } await DB.SaveChangesAsync(); await DB.Entry(analysisCenterRouting).ReloadAsync(); //post the manifest content analysisCenterManifest.SetData(DB, buffer); //submit the routing analysisCenterRouting.Status = analysisCenterResponse.Count > 1 ? RoutingStatus.Resubmitted : RoutingStatus.Submitted; await DB.SaveChangesAsync(); //Check for Job Fail trigger, and update Data Partner Routing to Failed. //Request status will not be affected. if (documents.Any(d => d.DocumentKind == JobFailTriggerFileKind)) { //Reload the entity before updating the status, else EF will report an exception. await DB.Entry(reqDM).ReloadAsync(); reqDM.Status = RoutingStatus.Failed; await DB.SaveChangesAsync(); } //change the status of the request to conducting analysis //manually override the request status using sql direct, EF does not allow update of computed await DB.Database.ExecuteSqlCommandAsync("UPDATE Requests SET Status = @status WHERE ID = @ID", new System.Data.SqlClient.SqlParameter("@status", (int)RequestStatuses.ConductingAnalysis), new System.Data.SqlClient.SqlParameter("@ID", reqDM.Request.ID)); await DB.Entry(reqDM.Request).ReloadAsync(); }
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(); } }