Exemple #1
0
 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;
 }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        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);
            }
        }