// TODO: Create abstraction private void DetectGreyZones(CalculatorConfiguration configuration, Order order) { var boundaries = new List <Tuple <Price, CalculationRange> >(); foreach (var range in configuration.CalculationRanges.Where(x => x.DeminimisThreshold.Value != 0)) { boundaries.Add(new Tuple <Price, CalculationRange>(new Price(order.Currency, range.DeminimisThreshold.Value - .01m), range)); boundaries.Add(new Tuple <Price, CalculationRange>(new Price(order.Currency, range.DeminimisThreshold.Value), range)); } var greyZonePrices = new List <Tuple <Price, CalculationRange> >(); foreach (var boundary in boundaries) { // Create forward calc var range = configuration.GetRangeForBasePrice(boundary.Item1); var forwardCalculator = ForwardCalculatorFactory.Create(range); var orderItems = order.OrderItems.Select(oi => new OrderItem(oi.Quantity, oi.Weight, oi.VatRate, oi.DutyRate, new Price(order.Currency, order.RelativeOrderItemValue(oi) * boundary.Item1.Value))).ToList(); orderItems.ForEach(oi => { var c = oi.GetChargeAmount(ChargeNames.InputItem, order.Currency); oi.AddCharge(new OrderCharge(ChargeNames.Item, c, ChargeNames.Item)); }); var detectionOrder = new Order(order.Country, order.Currency, orderItems, new Price(order.Currency, 0)); forwardCalculator?.Invoke(detectionOrder); var greyZonePrice = detectionOrder.Charges .Where(x => !x.InputCharge) .Where(x => x.ChargeName.Value.EndsWith(ChargeNames.Item)) .Select(x => x.ChargeAmount.Value) .Sum(); greyZonePrices.Add(new Tuple <Price, CalculationRange>(new Price(order.Currency, greyZonePrice), boundary.Item2)); } if (greyZonePrices.Count % 2 != 0) { throw new ArgumentException("Invalid grey zones, should be in pairs!"); } for (int x = 0; x < greyZonePrices.Count; x++) { configuration.AddGreyZone(new GreyZone(greyZonePrices[x].Item1, greyZonePrices[x + 1].Item1, greyZonePrices[x].Item2)); x++; } }
public void GetCalculationRange_MultipleRanges_ShouldReturnCorrectRegions(string price, string expectedThreshold) { // Arrange var deminimisBaseCharges = new List <ChargeName> { "Item" }; var chargeConfigurations = new List <ChargeConfiguration> { new FixedRateChargeConfiguration("Duty", "EUR0", "EUR10"), new FixedRateChargeConfiguration("Duty", "EUR100", "EUR20"), new FixedRateChargeConfiguration("Duty", "EUR200", "EUR30") }; var calculationRanges = new CalculatorConfiguration(chargeConfigurations, deminimisBaseCharges); // Act var range = calculationRanges.GetRangeForBasePrice(new Price(price)); // Assert range.DeminimisThreshold.Should().Be(new Price(expectedThreshold)); }