public void CopyFrom(AppointmentRequest request) { Shop = request.Shop; Barber = request.RequestedBarber; StartDateTime = request.StartDateTime; Service = request.Service; }
public void CopyFrom(AppointmentRequest suggestedAppointmentRequest) { Shop = suggestedAppointmentRequest.Shop; StartDateTime = suggestedAppointmentRequest.StartDateTime; RequestedBarber = suggestedAppointmentRequest.RequestedBarber; Service = suggestedAppointmentRequest.Service; }
public async Task <BarberAvailabilityResponse> AnyBarbersAvailableAsync(AppointmentRequest appointmentRequest) { var barbers = await LoadBarbersAsync(false); BarberAvailabilityResponse availabilityResponse = null; foreach (var barber in barbers) { availabilityResponse = await barber.IsAvailableAsync(appointmentRequest); if (availabilityResponse.IsAvailable) { return(availabilityResponse); } } availabilityResponse = new BarberAvailabilityResponse() { IsAvailable = false }; availabilityResponse.ValidationResults.Add(new ValidationResult() { Message = $"No barbers are available at {appointmentRequest.StartDateTime.ToString()}. " }); return(availabilityResponse); }
public async Task <AppointmentAvailabilityResponse> IsAvailableAsync(AppointmentRequest appointmentRequest) { AppointmentAvailabilityResponse response = new AppointmentAvailabilityResponse(); var dateTimeToCheck = appointmentRequest.StartDateTime.Add(minimumTimeBeforeClose); DateTime nowDateTime = DateTime.UtcNow.AddHours(ShopHours.UTC_to_PST_Hours); // convert to PST. await Hours.LoadAsync(this, nowDateTime.Date); // today's hours // check holidays // is it in the past? if (dateTimeToCheck < nowDateTime) { response.ValidationResults.Add(new ValidationResult() { Message = "Appointments can't be scheduled before right now. " }); return(response); } // is the store open? await Hours.LoadAsync(this, dateTimeToCheck); if (!Hours.Exists) { response.ValidationResults.Add(new ValidationResult() { Message = "The shop isn't open that day. " }); return(response); } // is it between hours bool isWithinHours = Hours.IsWithinHours(appointmentRequest.StartDateTime); // does it meet the minimum window? bool meetsMinimum = Hours.IsWithinHours(dateTimeToCheck); if (isWithinHours && meetsMinimum) { response.IsAvailable = true; } else if (!isWithinHours) { response.ValidationResults.Add(new ValidationResult() { Message = $"The appointment isn't between store hours of {Hours.FormattedDayHours()}. " }); } else if (!meetsMinimum) { response.ValidationResults.Add(new ValidationResult() { Message = $"The appointment needs to be at least {minimumTimeBeforeClose} minutes before closing. Hours are {Hours.FormattedDayHours()}. " }); } return(response); }
public async Task <AppointmentRequest> NextAvailableBarberAsync(AppointmentRequest appointmentRequest) { var barbers = await LoadBarbersAsync(false); Barber nextAvailable = null; AppointmentRequest nextRequest = new AppointmentRequest(this); nextRequest.CopyFrom(appointmentRequest); int attempts = 0; while (nextAvailable == null && attempts < ShopHours.SuggestionAttempts) { foreach (var barber in barbers) { BarberAvailabilityResponse availabilityResponse = await barber.IsAvailableAsync(nextRequest); if (availabilityResponse.IsAvailable) { nextAvailable = barber; break; } } if (nextAvailable == null) { DateTime nextDateTimeCheck = nextRequest.StartDateTime.Add(ShopHours.SuggestionAttemptIncrement); if (!await IsOpenAsync(nextDateTimeCheck)) { nextDateTimeCheck = nextDateTimeCheck.AddDays(1); await Hours.LoadAsync(this, nextDateTimeCheck); nextDateTimeCheck = Hours.OpeningDateTime(); } nextRequest = new AppointmentRequest(this); nextRequest.CopyFrom(appointmentRequest); attempts++; } } if (nextAvailable == null) { // if we can't find a barber this is not a valid request. nextRequest = null; } else { nextRequest.RequestedBarber = nextAvailable; } return(nextRequest); }
public async Task <AppointmentRequest> NextAvailableRequestAsync(AppointmentRequest appointmentRequest) { // special case for "Anyone" if (string.Equals(DisplayName, "Anyone", StringComparison.OrdinalIgnoreCase)) { return(await shop.NextAvailableBarberAsync(appointmentRequest)); } BarberAvailabilityResponse availableResponse = await IsAvailableAsync(appointmentRequest); // create a request based on the incoming request with the right datetime, shop, and barber. AppointmentRequest suggestedAppointment = new AppointmentRequest(shop); suggestedAppointment.CopyFrom(appointmentRequest); if (availableResponse.IsAvailable) { return(suggestedAppointment); } else { int attempts = 0; DateTime nextDateTimeCheck = suggestedAppointment.StartDateTime; while (!availableResponse.IsAvailable && attempts < BarberHours.SuggestionAttempts) { nextDateTimeCheck = suggestedAppointment.StartDateTime.Add(BarberHours.SuggestionAttemptIncrement); if (!await shop.IsOpenAsync(nextDateTimeCheck)) { nextDateTimeCheck = nextDateTimeCheck.AddDays(1); nextDateTimeCheck = await shop.OpeningDateTimeAsync(nextDateTimeCheck); } suggestedAppointment.StartDateTime = nextDateTimeCheck; availableResponse = await IsAvailableAsync(suggestedAppointment); attempts++; } if (attempts < BarberHours.SuggestionAttempts && availableResponse.IsAvailable) { suggestedAppointment.StartDateTime = nextDateTimeCheck; } else { suggestedAppointment = await shop.NextAvailableBarberAsync(appointmentRequest); } } return(suggestedAppointment); }
public async Task <BarberAvailabilityResponse> IsAvailableAsync(AppointmentRequest appointmentRequest) { if (string.Equals(DisplayName, "Anyone", StringComparison.OrdinalIgnoreCase)) { return(await shop.AnyBarbersAvailableAsync(appointmentRequest)); } // check working days / hours // check if already reserved bool startTimeAvailable = await Hours.IsAvailableAsync(this, appointmentRequest.StartDateTime); DateTime durationTime = appointmentRequest.StartDateTime.Add(appointmentRequest.Service.Duration); bool durationAvailable = await Hours.IsAvailableAsync(this, durationTime); Appointment appointment = new Appointment(appointmentRepository); appointment.CopyFrom(appointmentRequest); bool conflictingAppointments = await appointment.HasConflictingAppointmentsAsync(); bool barberAvailability = Hours.Exists && startTimeAvailable && !conflictingAppointments; // if not available get next available barber BarberAvailabilityResponse availabilityResponse = new BarberAvailabilityResponse() { IsAvailable = barberAvailability, IsConflictingAppointment = conflictingAppointments, Barber = this }; if (!barberAvailability) { availabilityResponse.ValidationResults.Add(new ValidationResult() { Message = $"{DisplayName} is not available on this date or time. " }); } return(availabilityResponse); }
public async Task <AppointmentAvailabilityResponse> IsAvailableAsync() { DateTime nowDateTime = DateTime.UtcNow.AddHours(ShopHours.UTC_to_PST_Hours); if (StartDateTime < nowDateTime) { var response = new AppointmentAvailabilityResponse() { IsAvailable = false }; response.ValidationResults.Add(new ValidationResult() { Message = "That date and time is in the past." }); return(response); } StartDateTime = await roundingRules.RoundDateTimeAsync(StartDateTime); TimeSpan difference = nowDateTime - StartDateTime; // we need to adjust the rounding for any rounding to a few minutes in the past. while (StartDateTime < nowDateTime && difference < TimeSpan.FromMinutes(1)) { StartDateTime = await roundingRules.RoundDateTimeAsync(StartDateTime.AddMinutes(5)); } var shopResponse = await Shop.IsAvailableAsync(this); BarberAvailabilityResponse barberResponse = await RequestedBarber.IsAvailableAsync(this); if (RequestedBarber != barberResponse.Barber) { // this happens if the user requests "Anyone" RequestedBarber = barberResponse.Barber; } if (shopResponse.IsAvailable && barberResponse.IsAvailable) { return(new AppointmentAvailabilityResponse() { IsAvailable = true, SuggestedRequest = this }); } else if (shopResponse.IsAvailable && !barberResponse.IsAvailable) { // barber is not available // we could either suggest the next available barber's time // and we could find when the barber is available next AppointmentRequest suggestedRequest = await RequestedBarber.NextAvailableRequestAsync(this); var response = new AppointmentAvailabilityResponse() { IsAvailable = false, SuggestedRequest = suggestedRequest }; response.ValidationResults.AddRange(barberResponse.ValidationResults); return(response); } else { // shop is not available // show the hours for the week and suggest the next available appointment AppointmentRequest nextRequest = null; AppointmentAvailabilityResponse response = new AppointmentAvailabilityResponse() { IsAvailable = false }; if (!shopResponse.IsAvailable) { nextRequest = new AppointmentRequest(Shop); nextRequest.CopyFrom(this); if (nextRequest.StartDateTime < nowDateTime) { int attempts = 0; while (!await Shop.CanAcceptCustomersAsync(nextRequest.StartDateTime) && attempts < 5) { nextRequest.StartDateTime = nextRequest.StartDateTime.AddDays(1); nextRequest.StartDateTime = await Shop.OpeningDateTimeAsync(nextRequest.StartDateTime); attempts++; } } nextRequest = await Shop.NextAvailableBarberAsync(nextRequest); response.ValidationResults.AddRange(shopResponse.ValidationResults); } else if (!barberResponse.IsAvailable) { nextRequest = new AppointmentRequest(Shop); nextRequest.CopyFrom(this); if (nextRequest.StartDateTime < nowDateTime) { int attempts = 0; nextRequest.StartDateTime = nextRequest.StartDateTime.AddDays(1); await RequestedBarber.Hours.LoadAsync(RequestedBarber, nextRequest.StartDateTime); while (!await Shop.IsOpenAsync(nextRequest.StartDateTime) && !RequestedBarber.Hours.IsWithinHours(nextRequest.StartDateTime) && attempts < 5) { nextRequest.StartDateTime = nextRequest.StartDateTime.AddDays(1); nextRequest.StartDateTime = await Shop.OpeningDateTimeAsync(nextRequest.StartDateTime); attempts++; } } nextRequest = await RequestedBarber.NextAvailableRequestAsync(nextRequest); response.ValidationResults.AddRange(barberResponse.ValidationResults); } response.SuggestedRequest = nextRequest; return(response); } }