public void Calculate_SingleOrderItem_ShouldAddCorrectCharge() { // Arrange var orderItem = _orderItemBuilder.Build(); var order = _orderBuilder.WithOrderItems(new List <OrderItem> { orderItem }).Build(); var expectedChargeName = ChargeName.FromBaseChargeName(_chargeName, ChargeNames.Item); var sut = new FixedChargeCalculator(_chargeName, new Price(CurrencyFakes.EUR, 10)); // Act sut.Calculate(order); // Assert orderItem.Charges.Should() .HaveCount(3).And .ContainSingle(c => c.ChargeName.Value == expectedChargeName && c.ChargeAmount.Value == 10); }
/// <summary> /// Creates the specified range. /// </summary> /// <param name="range">The range.</param> /// <param name="includeFixedCalculators">if set to <c>true</c> [include fixed calculators]. Should not be included when forward calculator is running /// as part of the reverse calculator as the fixed charge will have already been added by the reverse calculator.</param> /// <returns></returns> /// <exception cref="InvalidChargeConfigurationException">Unknown charge configuration - can't create calculator delegate.</exception> public static Calculator?Create(CalculationRange range, bool includeFixedCalculators = true) { Calculator?calculatorDelegate = null; // Loop through each charge configuration (which are in order of execution) - and add the required // calculator to the delegate. foreach (var config in range.ChargeConfigurations) { IChargeCalculator?calculator = default; switch (config) { // FIXED RATE CONFIGURATIONS case FixedRateChargeConfiguration fixedChargeConfig when config is FixedRateChargeConfiguration: { if (includeFixedCalculators) { calculator = new FixedChargeCalculator(fixedChargeConfig.ChargeName, fixedChargeConfig.FixedChargeAmount); } break; } // WEIGHT BASED CONFIGURATIONS case WeightBasedChargeConfiguration weightBasedChargeConfig when config is WeightBasedChargeConfiguration && weightBasedChargeConfig.Rate != null: { calculator = new WeightBasedChargeCalculator(weightBasedChargeConfig.ChargeName, (oi) => weightBasedChargeConfig.Rate); break; } case WeightBasedChargeConfiguration weightBasedChargeConfig when config is WeightBasedChargeConfiguration && config.ChargeName.Value is ChargeNames.Duty: { calculator = new WeightBasedChargeCalculator(weightBasedChargeConfig.ChargeName, (oi) => oi.DutyRate); break; } case WeightBasedChargeConfiguration weightBasedChargeConfig when config is WeightBasedChargeConfiguration && config.ChargeName.Value is ChargeNames.Vat: { calculator = new WeightBasedChargeCalculator(weightBasedChargeConfig.ChargeName, (oi) => oi.VatRate); break; } // RATE BASED CONFIGURATIONS case RateBasedChargeConfiguration rateBasedChargeConfig when config is RateBasedChargeConfiguration && rateBasedChargeConfig.Rate != null: { calculator = new RateBasedChargeCalculator(rateBasedChargeConfig.ChargeName, (oi) => rateBasedChargeConfig.Rate, rateBasedChargeConfig.BaseCharges); break; } case RateBasedChargeConfiguration rateBasedChargeConfig when config is RateBasedChargeConfiguration && rateBasedChargeConfig.ChargeName.Value is ChargeNames.Duty: { calculator = new RateBasedChargeCalculator(rateBasedChargeConfig.ChargeName, (oi) => oi.DutyRate, rateBasedChargeConfig.BaseCharges); break; } case RateBasedChargeConfiguration rateBasedChargeConfig when config is RateBasedChargeConfiguration && rateBasedChargeConfig.ChargeName.Value is ChargeNames.Vat: { calculator = new RateBasedChargeCalculator(rateBasedChargeConfig.ChargeName, (oi) => oi.VatRate, rateBasedChargeConfig.BaseCharges); break; } default: throw new InvalidChargeConfigurationException("Unknown charge configuration - can't create calculator delegate."); } if (calculator != null) { // Add constraints if (config.MinimumPayable != null) { calculator = new MinimumPayableConstraint(calculator, config.ChargeName, config.MinimumPayable); } if (config.MinimumCollectible != null) { calculator = new MinimumCollectibleConstraint(calculator, config.ChargeName, config.MinimumCollectible); } // Add created calculator to delegate calculatorDelegate += calculator.Calculate; } } return(calculatorDelegate); }
public static Calculator?Create(CalculationRange range, IEnumerable <ChargeName> deminimisBaseCharges) { Calculator?calculatorDelegate = null; foreach (var config in range.ChargeConfigurations) { IChargeCalculator calculator; switch (config) { // FIXED RATE CONFIGURATIONS case FixedRateChargeConfiguration fixedChargeConfig when config is FixedRateChargeConfiguration: { calculator = new FixedChargeCalculator(fixedChargeConfig.ChargeName, fixedChargeConfig.FixedChargeAmount); break; } // WEIGHT BASED CONFIGURATIONS case WeightBasedChargeConfiguration weightBasedChargeConfig when config is WeightBasedChargeConfiguration && weightBasedChargeConfig.Rate != null: { calculator = new WeightBasedChargeCalculator(weightBasedChargeConfig.ChargeName, (oi) => weightBasedChargeConfig.Rate); break; } case WeightBasedChargeConfiguration weightBasedChargeConfig when config is WeightBasedChargeConfiguration && config.ChargeName.Value is ChargeNames.Duty: { calculator = new WeightBasedChargeCalculator(weightBasedChargeConfig.ChargeName, (oi) => oi.DutyRate); break; } case WeightBasedChargeConfiguration weightBasedChargeConfig when config is WeightBasedChargeConfiguration && config.ChargeName.Value is ChargeNames.Vat: { calculator = new WeightBasedChargeCalculator(weightBasedChargeConfig.ChargeName, (oi) => oi.VatRate); break; } // RATE BASED CONFIGURATIONS case RateBasedChargeConfiguration rateBasedChargeConfig when config is RateBasedChargeConfiguration && rateBasedChargeConfig.Rate != null: { calculator = new ReverseRateCalculator(rateBasedChargeConfig.ChargeName, (oi) => rateBasedChargeConfig.Rate, rateBasedChargeConfig.BaseCharges); break; } case RateBasedChargeConfiguration rateBasedChargeConfig when config is RateBasedChargeConfiguration && rateBasedChargeConfig.ChargeName.Value is ChargeNames.Duty: { calculator = new ReverseRateCalculator(rateBasedChargeConfig.ChargeName, (oi) => oi.DutyRate, rateBasedChargeConfig.BaseCharges); break; } case RateBasedChargeConfiguration rateBasedChargeConfig when config is RateBasedChargeConfiguration && rateBasedChargeConfig.ChargeName.Value is ChargeNames.Vat: { calculator = new ReverseRateCalculator(rateBasedChargeConfig.ChargeName, (oi) => oi.VatRate, rateBasedChargeConfig.BaseCharges); break; } default: throw new InvalidChargeConfigurationException("Unknown charge configuration - can't create calculator delegate."); } // Add created calculator to delegate calculatorDelegate += calculator.Calculate; } foreach (var deminimisBaseCharge in deminimisBaseCharges) { // Add the item price calculator last calculatorDelegate += new ReversePriceCalculator(deminimisBaseCharge, $"Input{deminimisBaseCharge}").Calculate; } return(calculatorDelegate); }