public async Task NotChangeRequestOrder_WhenOptimizeRouteResultIsNotSuccess()
        {
            var optimizeRouteService = new Mock <IOptimizeRouteService>();

            optimizeRouteService.Setup(x => x.OptimizeRoute(It.IsAny <OptimizeRouteCriteria>()))
            .ReturnsAsync(OptimizeRouteResult.FailedOptimizeRouteResult("failure"));

            var sut = new OptimizeRouteCommandHandler(Context, optimizeRouteService.Object, Mock.Of <IMemoryCache>());

            await sut.Handle(new OptimizeRouteCommand { ItineraryId = 1 });

            var requests = Context.ItineraryRequests.Where(x => x.ItineraryId == 1).OrderBy(x => x.OrderIndex).ToList();

            requests[0].Request.Name.ShouldBe("Request 1");
            requests[1].Request.Name.ShouldBe("Request 4");
        }
        /// <summary>
        /// Reorders requests based on an optimized route from a 3rd party service. The new order will be persisted to the database
        /// </summary>
        /// <param name="message"></param>
        protected override async Task HandleCore(OptimizeRouteCommand message)
        {
            var requests = await GetRequests(message.ItineraryId);

            if (!requests.Any())
            {
                return;
            }

            var itinerary = requests.First().Itinerary;

            if (itinerary.HasAddresses)
            {
                var waypoints = requests.Select(req => new OptimizeRouteWaypoint(req.Request.Latitude, req.Request.Longitude, req.RequestId)).ToList();

                var optimizeResult = await _optimizeRouteService.OptimizeRoute(new OptimizeRouteCriteria(itinerary.StartAddress, itinerary.EndAddress, waypoints));

                if (!optimizeResult.Status.IsSuccess)
                {
                    SetOptimizeCache(message.UserId, message.ItineraryId, optimizeResult.Status);
                }
                else if (ValidateOptimizedRequests(waypoints, optimizeResult.RequestIds))
                {
                    var originalRequestIds = waypoints.Select(x => x.RequestId);

                    if (originalRequestIds.SequenceEqual(optimizeResult.RequestIds))
                    {
                        SetOptimizeCache(message.UserId, message.ItineraryId, new OptimizeRouteResultStatus {
                            StatusMessage = OptimizeRouteStatusMessages.AlreadyOptimized
                        });
                    }
                    else
                    {
                        await ReOrderRequests(waypoints, requests, optimizeResult);

                        SetOptimizeCache(message.UserId, message.ItineraryId, new OptimizeRouteResultStatus {
                            StatusMessage = OptimizeRouteStatusMessages.OptimizeSucess
                        });
                    }
                }
                else
                {
                    SetOptimizeCache(message.UserId, message.ItineraryId, OptimizeRouteResult.FailedOptimizeRouteResult(OptimizeRouteStatusMessages.GeneralOptimizeFailure).Status);
                }
            }
        }
        public async Task SetsCorrectCacheEntry_WhenOptimizeRouteResultIsNotSuccess()
        {
            const string statusMsg = "failure";

            var optimizeRouteService = new Mock <IOptimizeRouteService>();

            optimizeRouteService.Setup(x => x.OptimizeRoute(It.IsAny <OptimizeRouteCriteria>()))
            .ReturnsAsync(OptimizeRouteResult.FailedOptimizeRouteResult(statusMsg));

            var cache = new MemoryCache(new MemoryCacheOptions());

            var sut = new OptimizeRouteCommandHandler(Context, optimizeRouteService.Object, cache);

            await sut.Handle(new OptimizeRouteCommand { ItineraryId = 1, UserId = "123" });

            var expectedCacheKey = CacheKeyBuilder.BuildOptimizeRouteCacheKey("123", 1);

            OptimizeRouteResultStatus cachedStatus = null;
            var keyExists = cache.TryGetValue(expectedCacheKey, out cachedStatus);

            keyExists.ShouldBeTrue();
            cachedStatus.IsSuccess.ShouldBeFalse();
            cachedStatus.StatusMessage.ShouldBe(statusMsg);
        }
        private async Task ReOrderRequests(List <OptimizeRouteWaypoint> waypoints, List <ItineraryRequest> requests, OptimizeRouteResult optimizeResult)
        {
            for (var i = 0; i < waypoints.Count; i++)
            {
                var itineraryRequest = requests.SingleOrDefault(r => r.RequestId == optimizeResult.RequestIds[i]);

                if (itineraryRequest != null)
                {
                    itineraryRequest.OrderIndex = i + 1;
                }
            }

            await _context.SaveChangesAsync();
        }