private async Task GetProceduresByOrderIDs(IEnumerable <string> orderIDs, WorklistSearchResultDto result) { var procedureGroupsTask = (from o in _dbContext.Set <Order>() join pro in _dbContext.Set <Procedure>() on o.UniqueID equals pro.OrderID join r in _dbContext.Set <Report>() on pro.ReportID equals r.UniqueID into subReport from s in subReport.DefaultIfEmpty() where orderIDs.Contains(o.UniqueID) select new { pro.OrderID, pro.UniqueID, pro.Status, pro.ModalityType, pro.Modality, pro.RPDesc, pro.CreateTime, pro.RegisterTime, pro.ExamineTime, pro.ReportID, pro.IsExistImage, s.IsPrint, pro.ExamSystem }).GroupBy(p => p.OrderID).ToListAsync(); var procedureGroups = await procedureGroupsTask; foreach (var o in result.OrderItems) { var procedures = procedureGroups.FirstOrDefault(g => g.Key.Equals(o.OrderID, StringComparison.OrdinalIgnoreCase)); if (procedures != null) { o.Procedures = procedures.Select(p => new ProcedureItemDto { ProcedureID = p.UniqueID, Status = p.Status, ModalityType = p.ModalityType, RPDesc = p.RPDesc, Modality = p.Modality, ReportID = p.ReportID, IsPrint = p.IsPrint, IsExistImage = p.IsExistImage, OrderId = p.OrderID, ExamSystem = p.ExamSystem }).ToList(); } } }
public async Task <WorklistSearchResultDto> SearchWorklist(WorklistSearchCriteriaDto criteria, string userID, string site, string role) { if (criteria == null || criteria.Pagination == null) { return(null); } criteria.AccessSites = await GetAccessSites(userID, site, role); // prepare date range by criteria var createStartDay = criteria.CreateStartDate.HasValue ? (DateTime?)criteria.CreateStartDate.Value.Date : null; var createEndDay = criteria.CreateEndDate.HasValue ? (DateTime?)criteria.CreateEndDate.Value.Date.AddDays(1) : null; var examineStartDay = criteria.ExamineStartDate.HasValue ? (DateTime?)criteria.ExamineStartDate.Value.Date : null; var examineEndDay = criteria.ExamineEndDate.HasValue ? (DateTime?)criteria.ExamineEndDate.Value.Date.AddDays(1) : null; // filter result by all criteria except time ranges var orderQuery = from o in _dbContext.Set <Order>() join p in _dbContext.Set <Patient>() on o.PatientID equals p.UniqueID join pro in _dbContext.Set <Procedure>() on o.UniqueID equals pro.OrderID where (criteria.AccessSites.Count == 0 || criteria.AccessSites.Contains(o.CurrentSite) || criteria.AccessSites.Contains(o.Assign2Site)) && pro.Status > 0 select new WorklistSearchQueryResult { o = o, p = p, pro = pro }; #region Build Query var isFuzzySearch = false; if (!String.IsNullOrEmpty(criteria.PatientNo)) { string actualSearchValue = criteria.PatientNo; var searchingType = SearchingUtil.ProcessSearchValue(criteria.PatientNo, out actualSearchValue); if (searchingType == SearchingType.Exact) { orderQuery = orderQuery.Where(q => q.p.PatientNo.Equals(actualSearchValue)); } else { isFuzzySearch = true; orderQuery = orderQuery.Where(q => q.p.PatientNo.Contains(actualSearchValue)); } } if (!String.IsNullOrEmpty(criteria.PatientName)) { string actualSearchValue = criteria.PatientName; var searchingType = SearchingUtil.ProcessSearchValue(criteria.PatientName, out actualSearchValue); if (searchingType == SearchingType.Exact) { orderQuery = orderQuery.Where(q => q.p.LocalName.Equals(actualSearchValue)); } else { isFuzzySearch = true; orderQuery = orderQuery.Where(q => q.p.LocalName.Contains(actualSearchValue)); } } if (!String.IsNullOrEmpty(criteria.AccNo)) { string actualSearchValue = criteria.AccNo; var searchingType = SearchingUtil.ProcessSearchValue(criteria.AccNo, out actualSearchValue); if (searchingType == SearchingType.Exact) { orderQuery = orderQuery.Where(q => q.o.AccNo.Equals(actualSearchValue)); } else { isFuzzySearch = true; orderQuery = orderQuery.Where(q => q.o.AccNo.Contains(actualSearchValue)); } } if (criteria.AccessSites.Count > 0) { orderQuery = orderQuery.Where(q => criteria.AccessSites.Contains(q.o.CurrentSite)); } if (criteria.PatientTypes.Count > 0) { orderQuery = orderQuery.Where(q => criteria.PatientTypes.Contains(q.o.PatientType)); } if (criteria.Statuses.Count > 0) { orderQuery = orderQuery.Where(q => criteria.Statuses.Contains(q.pro.Status)); } if (criteria.ModalityTypes.Count > 0) { orderQuery = orderQuery.Where(q => criteria.ModalityTypes.Contains(q.pro.ModalityType)); } if (criteria.Modalities.Count > 0) { orderQuery = orderQuery.Where(q => criteria.Modalities.Contains(q.pro.Modality)); } // limit to search one month data for fuzzy search // Case 1: start(N), end(N) // Case 2: start(Y), end(N) // Case 3: strat(Y), end(Y) -> Case 3.1: end - start > 30 days, Case 3.2: end - start <= 30 days // Case 4: start(N), end(Y) if (createStartDay.HasValue) { orderQuery = orderQuery.Where(q => q.o.CreateTime.HasValue && q.o.CreateTime.Value >= createStartDay.Value); // limit to search one month data for fuzzy search if (isFuzzySearch) { if (!createEndDay.HasValue || (createEndDay.Value - createStartDay) > TimeSpan.FromDays(30)) { createEndDay = createStartDay.Value.AddDays(30); } } } else { // limit to search one month data for fuzzy search if (isFuzzySearch) { DateTime startDate = DateTime.Today.AddDays(-30); if (createEndDay.HasValue) { startDate = createEndDay.Value.AddDays(-30); } orderQuery = orderQuery.Where(q => q.o.CreateTime > startDate); } } if (createEndDay.HasValue) { orderQuery = orderQuery.Where(q => q.o.CreateTime.HasValue && q.o.CreateTime.Value < createEndDay.Value); } if (examineStartDay.HasValue) { orderQuery = orderQuery.Where(q => q.pro.ExamineTime.HasValue && q.pro.ExamineTime.Value >= examineStartDay.Value); } if (examineEndDay.HasValue) { orderQuery = orderQuery.Where(q => q.pro.ExamineTime.HasValue && q.pro.ExamineTime.Value < examineEndDay.Value); } // filter create time ranges if (criteria.CreateTimeRanges != null && criteria.CreateTimeRanges.Count > 0) { var predicate = BuildWithInOrderCreateTimeRangesPredicate(criteria.CreateTimeRanges); orderQuery = orderQuery.AsExpandable().Where(predicate); } // filter examine time ranges if (criteria.ExamineTimeRanges != null && criteria.ExamineTimeRanges.Count > 0) { var predicate = BuildWithInExamineTimeRangesPredicate(criteria.ExamineTimeRanges); orderQuery = orderQuery.AsExpandable().Where(predicate); } #endregion // theoretically, the result should be distinct by order and patient info var finalQuery = orderQuery.Select(q => new { PatientID = q.p.UniqueID, q.p.Birthday, q.p.LocalName, q.p.PatientNo, OrderID = q.o.UniqueID, q.o.AccNo, q.o.PatientType, q.o.CurrentSite, q.o.ExamSite, q.o.CreateTime, q.o.CurrentAge, q.o.AgeInDays, q.o.IsScan, q.o.ReferralID, q.pro.ExamineTime }).Distinct().AsNoTracking(); // pagination orders by create time // get two pages items every time, to see if there is items in next page var getTwoPagesItemsTask = !criteria.Pagination.NeedNoPagination ? finalQuery.OrderByDescending(q => q.CreateTime).Skip(criteria.Pagination.PageSize * (criteria.Pagination.PageIndex - 1)).Take(criteria.Pagination.PageSize * 2).ToListAsync() : finalQuery.OrderByDescending(q => q.CreateTime).ToListAsync(); var twoPagesItems = await getTwoPagesItemsTask; var firstPageItems = twoPagesItems.Take(criteria.Pagination.PageSize); // assemble result with no procedure info var result = new WorklistSearchResultDto { Pagination = new PaginationDto { PageIndex = criteria.Pagination.PageIndex, PageSize = criteria.Pagination.PageSize, HasNextPage = twoPagesItems.Count > criteria.Pagination.PageSize }, OrderItems = firstPageItems.Select(item => new OrderItemDto { PatientID = item.PatientID, Birthday = item.Birthday, PatientName = item.LocalName, PatientNo = item.PatientNo, OrderID = item.OrderID, AccNo = item.AccNo, PatientType = item.PatientType, CurrentSite = item.CurrentSite, ExamSite = item.ExamSite, CreatedTime = item.CreateTime.HasValue ? item.CreateTime.Value : DateTime.MinValue, CurrentAge = item.CurrentAge, AgeInDays = item.AgeInDays, IsScan = item.IsScan.HasValue ? item.IsScan.Value.Equals(1) : false, ReferralID = item.ReferralID, ExamineTime = item.ExamineTime }).ToList(), }; var orderIDs = firstPageItems.Select(i => i.OrderID).ToList(); // fetch all procedures associated with those orders await GetProceduresByOrderIDs(orderIDs, result); return(result); }