public async Task <decimal> Calculate(TrolleyTotalRequest trolleyTotalRequest)
        {
            return(await Task.Run(() =>
            {
                var scenarios = Scenario.CreateScenarioListFromValidSpecials(trolleyTotalRequest);
                var products = trolleyTotalRequest.Products;

                foreach (var scenario in scenarios)
                {
                    //Apply Special to Scenario
                    scenario.Total += scenario.Special?.Total ?? 0;
                    if (scenario.Special != null)
                    {
                        foreach (var specialInventory in scenario.Special.Inventory)
                        {
                            var matchedItem =
                                scenario.RequestedItems.FirstOrDefault(_ => _.Name.Equals(specialInventory.Name));
                            if (matchedItem != null)
                            {
                                matchedItem.QuantityFilled += specialInventory.Quantity;
                            }
                        }
                    }

                    //Fill remaining
                    Scenario.FillScenarioFromProducts(scenario, products);
                }

                var returnData = scenarios.Where(m => !m.RequestedItems.Any(n => n.Incomplete));

                return returnData.OrderBy(_ => _.Total).First().Total;
            }));
        }
        public async void TrolleyCalculator_Serialize_Deserialize()
        {
            // Arrange
            var expectedResult      = new decimal(1);
            var httpClient          = FakeHttpClient.Create_WithContent(expectedResult.ToString(CultureInfo.InvariantCulture));
            var trolleyTotalRequest = new TrolleyTotalRequest()
            {
                RequestedItems = new List <RequestedItem>()
                {
                    new RequestedItem()
                },
                Specials = new List <Special>()
                {
                    new Special()
                    {
                        Inventory = new List <SpecialInventory>()
                        {
                            new SpecialInventory()
                        }
                    }
                },
                Products = new List <Product>()
                {
                    new Product()
                }
            };
            var sut = new ResourceServiceHttpHttpClient(httpClient, _mockOptions);

            // Act
            var result = await sut.TrolleyCalculator(trolleyTotalRequest);

            //Assert
            Assert.Equal(expectedResult, result);
        }
        public decimal CalculateTrolleyTotal(TrolleyTotalRequest trolleyTotalRequest)
        {
            var priceLookup = GetProductPriceLookup(trolleyTotalRequest);

            var quantitiesLookup = GetOrderedQuantitiesInLookupFormat(trolleyTotalRequest).ToImmutableDictionary();

            return(GetLowestTotal(priceLookup, trolleyTotalRequest.Specials.ToImmutableList(), quantitiesLookup, 0));
        }
        public void should_have_error_when_quantities_is_null()
        {
            var request = new TrolleyTotalRequest
            {
                Products = new List <BaseProduct>(),
                Specials = new List <ProductSpecial>()
            };

            _sut.ShouldHaveValidationErrorFor(r => r.Quantities, request);
        }
Beispiel #5
0
        public async Task <IActionResult> CalculateTrolleyTotal(TrolleyTotalRequest trolleyTotalRequest)
        {
            if (trolleyTotalRequest == null)
            {
                return(BadRequest("Please provide valid trolley total request."));
            }

            var trolleyTotal = await _woolworthsResourceProvider.CalculateTrolleyTotal(trolleyTotalRequest);

            return(Ok(trolleyTotal));
        }
        private static Dictionary <string, ProductPrice> GetProductPriceLookup(TrolleyTotalRequest trolleyTotalRequest)
        {
            var priceLookup = new Dictionary <string, ProductPrice>();

            foreach (var product in trolleyTotalRequest.Products)
            {
                priceLookup.Add(product.Name, product);
            }

            return(priceLookup);
        }
Beispiel #7
0
        public static List <Scenario> CreateScenarioListFromValidSpecials(TrolleyTotalRequest trolleyTotalRequest)
        {
            var scenarios = trolleyTotalRequest.Specials
                            .Where(_ => _.IsValidForTrolleyTotalRequest(trolleyTotalRequest)).Select(special => new Scenario()
            {
                Special        = special,
                RequestedItems = trolleyTotalRequest.RequestedItems.Select(RequestedItem.Copy).ToList()
            }).ToList();

            scenarios.Add(new Scenario()
            {
                RequestedItems = trolleyTotalRequest.RequestedItems.Select(RequestedItem.Copy).ToList()
            });
            return(scenarios);
        }
Beispiel #8
0
        public async Task <decimal> CalculateMinTrolleyTotal(TrolleyTotalRequest request)
        {
            var response = await _httpClient.PostAsJsonAsync($"{_resourceApiSettings.Url}/trolleyCalculator?token={_apiSettings.Token}", request);

            if (!response.IsSuccessStatusCode)
            {
                _logger.Warning("Call to Calculate trolley total failed with status code: {StatusCode}", response.StatusCode);
                response.EnsureSuccessStatusCode();
            }

            _logger.Information("Call to Calculate trolley total succeeded");
            var total = await response.Content.ReadAsAsync <decimal>();

            return(total);
        }
Beispiel #9
0
        public bool IsValidForTrolleyTotalRequest(TrolleyTotalRequest trolleyTotalRequest)
        {
            var anyTooLarge = false;

            // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator - Foreach more readable than LINQ in this case
            foreach (var requestedItem in trolleyTotalRequest.RequestedItems)
            {
                if (!Inventory.Any(_ => _.Name.Equals(requestedItem.Name) && (_.Quantity > requestedItem.Quantity)))
                {
                    continue;
                }
                anyTooLarge = true;
                break;
            }
            return(!anyTooLarge);
        }
        public async Task <decimal> TrolleyCalculator(TrolleyTotalRequest trolleyTotalRequest)
        {
            var jsonString         = JsonSerializer.Serialize(trolleyTotalRequest);
            var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, $"{_options.TrolleyCalculatorPath}?token={_options.Token}")
            {
                Content = new StringContent(jsonString, Encoding.UTF8, "application/json")
            };
            var httpResponseMessage = await _httpClient.SendAsync(httpRequestMessage);

            httpResponseMessage.EnsureSuccessStatusCode();
            var responseStream = await httpResponseMessage.Content.ReadAsStreamAsync();

            var total = await JsonSerializer.DeserializeAsync <decimal>(responseStream);

            return(total);
        }
        public async Task <string> CalculateTrolleyTotal(TrolleyTotalRequest trolleyTotalRequest)
        {
            /*
             * //sample request which is useless in Mock setup for now
             * string testRequest = @"{
             * ""products"": [
             * {
             * ""name"": ""Test Product A"",
             * ""price"": 99.99
             * },
             * {
             * ""name"": ""Test Product B"",
             * ""price"": 29.99
             * }
             * ],
             * ""specials"": [
             * {
             * ""quantities"": [
             * {
             * ""name"": ""Test Product A"",
             * ""quantity"": 3
             * },
             * {
             * ""name"": ""Test Product B"",
             * ""quantity"": 3
             * }
             * ],
             * ""total"": 6
             * }
             * ],
             * ""quantities"": [
             * {
             * ""name"": ""Test Product A"",
             * ""quantity"": 3
             * },
             * {
             * ""name"": ""Test Product B"",
             * ""quantity"": 3
             * }
             * ]
             * }";
             */

            return("6");
        }
        private static Dictionary <string, int> GetOrderedQuantitiesInLookupFormat(TrolleyTotalRequest trolleyTotalRequest)
        {
            var quantitiesLookup = new Dictionary <string, int>();

            foreach (var quantity in trolleyTotalRequest.Quantities)
            {
                if (quantitiesLookup.ContainsKey(quantity.Name))
                {
                    quantitiesLookup[quantity.Name] += quantity.Number;
                }
                else
                {
                    quantitiesLookup.Add(quantity.Name, quantity.Number);
                }
            }

            return(quantitiesLookup);
        }
        public async Task <decimal> GetTrollyTotalAsync(TrolleyTotalRequest request)
        {
            HttpContent httpContent = new StringContent(JsonSerializer.Serialize(request),
                                                        Encoding.UTF8, MediaTypeNames.Application.Json);

            using var responseMessage =
                      await _httpClient.PostAsync(
                          $"trolleyCalculator?token={_productServiceConfig.Token}", httpContent);

            try
            {
                var response = await responseMessage.Content.ReadAsStreamAsync();

                responseMessage.EnsureSuccessStatusCode();
                var serializerOptions = JsonSerializerExtensions.GetDefaultJsonSerializerOptions();
                return(await JsonSerializer.DeserializeAsync <decimal>(response, serializerOptions));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "ProductServiceException.GetTrollyTotalAsync");
                throw new ProductServiceException(
                          $"ProductServiceException, {ex.Message} {responseMessage.StatusCode}");
            }
        }
 public async Task <string> CalculateTrolleyTotal(TrolleyTotalRequest trolleyTotalRequest)
 {
     return(await postToUri(TrolleyCalculatorUri, trolleyTotalRequest));
 }
Beispiel #15
0
        public async Task <double> CalculateTrolleyTotal(TrolleyTotalRequest trolleyTotalRequest)
        {
            var result = await _woolworthsResourceClient.CalculateTrolleyTotal(trolleyTotalRequest);

            return(double.Parse(result));
        }
Beispiel #16
0
 public async Task <decimal> GetLowestTrolleyTotal(TrolleyTotalRequest trolleyRequest)
 {
     return(await _httpClientWrapper.PostAsync <decimal, TrolleyTotalRequest>(trolleyRequest,
                                                                              _connectionSettings.BaseUrl, $"/api/resource/trolleyCalculator?token={_connectionSettings.Token}"));
 }
Beispiel #17
0
 public Task <decimal> GetTrolleyCalculator(TrolleyTotalRequest request)
 {
     return(ExecuteRequest <decimal>(() => _httpClient.PostAsJsonAsync($"trolleyCalculator?token={_apiEndpointConfiguration.Token}", request)));
 }
Beispiel #18
0
 public async Task <ActionResult <decimal> > TrolleyTotal([Required] TrolleyTotalRequest request)
 {
     return(await _productsService.TrolleyTotal(request));
 }
Beispiel #19
0
 public TrolleyTotalControllerTests()
 {
     _trolleyTotalRequest = new TrolleyTotalRequest()
     {
         RequestedItems = new List <RequestedItem>()
         {
             new RequestedItem()
             {
                 Name = "1", Quantity = 3
             },
             new RequestedItem()
             {
                 Name = "2", Quantity = 2
             }
         },
         Products = new List <Product>()
         {
             new Product()
             {
                 Name = "1", Price = 2
             },
             new Product()
             {
                 Name = "2", Price = 5
             }
         },
         Specials = new List <Special>()
         {
             new Special()
             {
                 Inventory = new List <SpecialInventory>()
                 {
                     new SpecialInventory()
                     {
                         Name = "1", Quantity = 3
                     },
                     new SpecialInventory()
                     {
                         Name = "2", Quantity = 0
                     }
                 },
                 Total = 5
             },
             new Special()
             {
                 Inventory = new List <SpecialInventory>()
                 {
                     new SpecialInventory()
                     {
                         Name = "1", Quantity = 1
                     },
                     new SpecialInventory()
                     {
                         Name = "2", Quantity = 2
                     }
                 },
                 Total = 10
             }
         }
     };
 }
Beispiel #20
0
 public async Task <decimal> Post([FromBody] TrolleyTotalRequest trolleyTotalRequest)
 {
     return(await _trolleyCalculator.Calculate(trolleyTotalRequest));
 }
 public async Task <IActionResult> TrolleyTotal(TrolleyTotalRequest request)
 {
     return(Ok(await _trolleyService.GetLowestTrolleyTotal(request)));
 }
Beispiel #22
0
 public async Task <decimal> TrolleyTotal(TrolleyTotalRequest request)
 {
     return(await _apiResourceProxy.GetTrolleyCalculator(request));
 }