///<summary>Gets time availalbility for appointment searching. Moved to business layer for unit tests. ///Returns the first available time slots for each of the next 10 available days. This means there will only be one time slot per day and ///that time slot will always be the first available time slot within that day regardless of additional time slots being available. ///resultCount defaults to preserve old functionality, the UI only holds 10 but this could be changed.</summary> public static List <ScheduleOpening> GetSearchResults(long aptNum, DateTime dateStart, DateTime dateEnd, List <long> listProvNums, List <long> listOpNums , List <long> listClinicNums, TimeSpan beforeTime, TimeSpan afterTime, long blockoutType = 0, bool hasProvAndBlockout = false, int resultCount = 10) { if (RemotingClient.RemotingRole == RemotingRole.ClientWeb) //No call to db but designed to save middle tier trips. { return(Meth.GetObject <List <ScheduleOpening> >(MethodBase.GetCurrentMethod(), aptNum, dateStart, dateEnd, listProvNums, listOpNums, listClinicNums , beforeTime, afterTime, blockoutType, hasProvAndBlockout, resultCount)); } //if they didn't set a before time, set it to a large timespan so that we can use the same logic for checking appointment times. if (beforeTime == TimeSpan.FromSeconds(0)) { beforeTime = TimeSpan.FromHours(25); //bigger than any time of day. } ApptSearchData data = GetDataForSearch(aptNum, dateStart, dateEnd, listProvNums, listOpNums, listClinicNums, blockoutType); List <ScheduleOpening> retVal = new List <ScheduleOpening>(); if (data.AppointmentToAdd == null) //appointment was deleted after clicking search. { return(retVal); } DateTime dateEvaluating = data.DateEvaluating; SearchBehaviorCriteria searchType = (SearchBehaviorCriteria)PrefC.GetInt(PrefName.AppointmentSearchBehavior); if (hasProvAndBlockout) //searching for intersection of providers and blockouts get as many results as possible. { while (dateEvaluating < dateEnd) { List <ScheduleOpening> listPotentialTimeAvailable = GetProvAndOpAvailabilityHelper(listProvNums, dateEvaluating, data, searchType, listOpNums , blockoutType); //At this point listPotentialTimeAvailable is already filtered and only contains appt times that match both provider time and operatory time. List <ScheduleOpening> listOpeningsForEntireDay = AddTimesToSearchResultsHelper(listPotentialTimeAvailable, beforeTime, afterTime); retVal.AddRange(listOpeningsForEntireDay); dateEvaluating = dateEvaluating.AddDays(1); } } else { while (retVal.Count < resultCount && dateEvaluating < dateEnd) { List <ScheduleOpening> listPotentialTimeAvailable = GetProvAndOpAvailabilityHelper(listProvNums, dateEvaluating, data, searchType, listOpNums , blockoutType); //At this point listPotentialTimeAvailable is already filtered and only contains appt times that match both provider time and operatory time. ScheduleOpening firstOpeningForDay = AddTimeToSearchResultsHelper(listPotentialTimeAvailable, beforeTime, afterTime); if (firstOpeningForDay != null) { retVal.Add(firstOpeningForDay); } dateEvaluating = dateEvaluating.AddDays(1); } } return(retVal); }
private static List <ScheduleOpening> GetProvAndOpAvailabilityHelper(List <long> listProvNums, DateTime dateEvaluating, ApptSearchData data, SearchBehaviorCriteria searchType, List <long> listOpNums, long blockoutType) { //No need to check RemotingRole; no call to db. List <ScheduleOpening> listPotentialTimeAvailable = new List <ScheduleOpening>(); //create or clear //Providers--------------------------------------------------------------------------------------------------------------- List <ApptSearchProviderSchedule> listProvScheds = new List <ApptSearchProviderSchedule>(); //Provider Bar, ProviderSched Bar, Date and Provider listProvScheds = Appointments.GetProviderScheduleForProvidersAndDate(listProvNums, dateEvaluating, data.ListSchedules, data.ListAppointments); if (searchType == SearchBehaviorCriteria.ProviderTime) //Fill the time the provider is available { listPotentialTimeAvailable = FillProviderTimeHelper(listProvScheds, data.AppointmentToAdd, dateEvaluating, blockoutType); } //Handle Operatories ----------------------------------------------------------------------------------------------------- if (searchType == SearchBehaviorCriteria.ProviderTimeOperatory) //Fill the time the prov and op are available { List <ApptSearchOperatorySchedule> listOpScheds = new List <ApptSearchOperatorySchedule>(); //filtered based on SearchType listOpScheds = GetAllForDate(dateEvaluating, data.ListSchedules, data.ListAppointments, data.ListSchedOps, listOpNums, listProvNums, blockoutType); listPotentialTimeAvailable = FillOperatoryTime(listOpScheds, listProvScheds, data.AppointmentToAdd, dateEvaluating, listProvNums, blockoutType , data.ListSchedOps, data.ListSchedules); } return(listPotentialTimeAvailable); }
///<summary></summary> public static List <DateTime> GetSearchResults(long aptNum, DateTime afterDate, List <long> providerNums, int resultCount, TimeSpan beforeTime, TimeSpan afterTime) { if (beforeTime == TimeSpan.FromSeconds(0)) //if they didn't set a before time, set it to a large timespan so that we can use the same logic for checking appointment times. { beforeTime = TimeSpan.FromHours(25); //bigger than any time of day. } SearchBehaviorCriteria SearchType = (SearchBehaviorCriteria)PrefC.GetInt(PrefName.AppointmentSearchBehavior); List <DateTime> retVal = new List <DateTime>(); DateTime dayEvaluating = afterDate.AddDays(1); Appointment appointmentToAdd = Appointments.GetOneApt(aptNum); List <DateTime> potentialProvAppointmentTime; List <DateTime> potentialOpAppointmentTime; List <Operatory> opsListAll = Operatories.GetDeepCopy(); //all operatory Numbers List <Schedule> scheduleListAll = Schedules.GetTwoYearPeriod(dayEvaluating); // Schedules for the given day. List <Appointment> appointmentListAll = Appointments.GetForPeriodList(dayEvaluating, dayEvaluating.AddYears(2)); List <ScheduleOp> schedOpListAll = ScheduleOps.GetForSchedList(scheduleListAll); List <ApptSearchProviderSchedule> provScheds = new List <ApptSearchProviderSchedule>(); //Provider Bar, ProviderSched Bar, Date and Provider List <ApptSearchOperatorySchedule> operatrorySchedules = new List <ApptSearchOperatorySchedule>(); //filtered based on SearchType List <long> operatoryNums = new List <long>(); //more usefull than a list of operatories. for (int i = 0; i < opsListAll.Count; i++) { operatoryNums.Add(opsListAll[i].OperatoryNum); } while (retVal.Count < resultCount && dayEvaluating < afterDate.AddYears(2)) { potentialOpAppointmentTime = new List <DateTime>(); //clear or create //Providers------------------------------------------------------------------------------------------------------------------------------------- potentialProvAppointmentTime = new List <DateTime>(); //clear or create provScheds = Appointments.GetApptSearchProviderScheduleForProvidersAndDate(providerNums, dayEvaluating, scheduleListAll, appointmentListAll); for (int i = 0; i < provScheds.Count; i++) { for (int j = 0; j < 288; j++) //search every 5 minute increment per day { if (j + appointmentToAdd.Pattern.Length > 288) { break; } if (potentialProvAppointmentTime.Contains(dayEvaluating.AddMinutes(j * 5))) { continue; } bool addDateTime = true; for (int k = 0; k < appointmentToAdd.Pattern.Length; k++) { if ((provScheds[i].ProvBar[j + k] == false && appointmentToAdd.Pattern[k] == 'X') || provScheds[i].ProvSchedule[j + k] == false) { addDateTime = false; break; } } if (addDateTime) { potentialProvAppointmentTime.Add(dayEvaluating.AddMinutes(j * 5)); } } } if (SearchType == SearchBehaviorCriteria.ProviderTimeOperatory) //Handle Operatories here---------------------------------------------------------------------------- { operatrorySchedules = GetAllForDate(dayEvaluating, scheduleListAll, appointmentListAll, schedOpListAll, operatoryNums, providerNums); potentialOpAppointmentTime = new List <DateTime>(); //create or clear //for(int j=0;j<operatrorySchedules.Count;j++) {//for each operatory for (int i = 0; i < 288; i++) //search every 5 minute increment per day { if (i + appointmentToAdd.Pattern.Length > 288) //skip if appointment would span across midnight { break; } for (int j = 0; j < operatrorySchedules.Count; j++) //for each operatory //if(potentialOpAppointmentTime.Contains(dayEvaluating.AddMinutes(i*5))) {//skip if we already have this dateTime // break; //} { bool addDateTime = true; for (int k = 0; k < appointmentToAdd.Pattern.Length; k++) //check appointment against operatories { if (operatrorySchedules[j].OperatorySched[i + k] == false) { addDateTime = false; break; } } if (!addDateTime) { continue; } if (addDateTime) // && SearchType==SearchBehaviorCriteria.ProviderTimeOperatory) {//check appointment against providers available for the given operatory { bool provAvail = false; for (int k = 0; k < providerNums.Count; k++) { if (!operatrorySchedules[j].ProviderNums.Contains(providerNums[k])) { continue; } provAvail = true; for (int m = 0; m < appointmentToAdd.Pattern.Length; m++) { if ((provScheds[k].ProvBar[i + m] == false && appointmentToAdd.Pattern[m] == 'X') || provScheds[k].ProvSchedule[i + m] == false) //if provider bar time slot { provAvail = false; break; } } if (provAvail) //found a provider with an available operatory { break; } } if (provAvail && addDateTime) //operatory and provider are available { potentialOpAppointmentTime.Add(dayEvaluating.AddMinutes(i * 5)); } } else //not using SearchBehaviorCriteria.ProviderTimeOperatory { if (addDateTime) { potentialOpAppointmentTime.Add(dayEvaluating.AddMinutes(i * 5)); } } } } } //At this point the potentialOpAppointmentTime is already filtered and only contains appointment times that match both provider time and operatory time. switch (SearchType) { case SearchBehaviorCriteria.ProviderTime: //Add based on provider bars for (int i = 0; i < potentialProvAppointmentTime.Count; i++) { if (potentialProvAppointmentTime[i].TimeOfDay > beforeTime || potentialProvAppointmentTime[i].TimeOfDay < afterTime) { continue; } retVal.Add(potentialProvAppointmentTime[i]); //add one for this day break; //stop looking through potential times for today. } break; case SearchBehaviorCriteria.ProviderTimeOperatory: //add based on provider bar and operatory bar for (int i = 0; i < potentialOpAppointmentTime.Count; i++) { if (potentialOpAppointmentTime[i].TimeOfDay > beforeTime || potentialOpAppointmentTime[i].TimeOfDay < afterTime) { continue; } retVal.Add(potentialOpAppointmentTime[i]); //add one for this day break; //stop looking through potential times for today. } break; } dayEvaluating = dayEvaluating.AddDays(1); } return(retVal); }