public void Calculate(Order order) { foreach (var item in order.OrderItems) { // For each base charge that this charge should be calculated on top of (item, duty, vat etc.) foreach (var baseChargeName in _baseCharges) { // All of the charges that we need to calculate on top of // e.g if applying on top of item and vat, and vat was applied on item, the charges we need to calculate on are: // item, vatOnItem var baseCharges = item.Charges.Where(c => c.BaseChargeName == baseChargeName); foreach (var charge in baseCharges.ToList()) { if (charge.ChargeAmount.Value == 0) { continue; } var chargeAmount = charge.ChargeAmount * _getRate(item).AsDecimal; var chargeName = ChargeName.FromBaseChargeName(_chargeName, charge.ChargeName); item.AddCharge(new OrderCharge(chargeName, chargeAmount, _chargeName)); } } } }
public void Calculate(Order order) { foreach (var item in order.OrderItems) { var chargeAmount = _amount * order.RelativeOrderItemValue(item); var chargeName = ChargeName.FromBaseChargeName(_chargeName, ChargeNames.Item); item.AddCharge(new OrderCharge(chargeName, chargeAmount, _chargeName)); } }
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); }
public void Calculate(Order order) { foreach (var item in order.OrderItems) { // Loop through each of the charges that this charge type is to be calculated on top of. foreach (var baseChargeName in _baseCharges) { var baseChargeAmount = item.GetChargeAmount(baseChargeName, order.Currency); // Check to see if a charge has been calculated for this charge type. // If so, do a forward calculation - the calculated charges can be removed from the // inclusive price before applying the reverse rate as they are known. if (baseChargeAmount.Value != 0) { var chargeAmount = baseChargeAmount * _getRate(item).AsDecimal; var chargeName = ChargeName.FromBaseChargeName(_chargeName, baseChargeName); item.AddCharge(new OrderCharge(chargeName, chargeAmount, _chargeName)); } // If the charge that we need to calculate on top of has not already been calculated, // and is therefore unknown - we need to calculate the reverse rate. else { // If the base charge is item or delivery (not a calculated rate), just add the rate // for this item to the calculation rates collection. There might be a better way of // identifying these 'non calculated' rates types of charges that would be more flexible. if (baseChargeName.Value == "Item" || baseChargeName.Value == "Delivery") { item.AddReverseRate(new ReverseRate( name: ChargeName.FromBaseChargeName(_chargeName, baseChargeName), parentChargeName: _chargeName, rate: _getRate(item))); } // If the base charge is a calculated rate, we need to calculate a new rate and add it // to the calculated rates collection. All of these rates combined will be used to reverse // back to the item price. else { // Get the current list of rates var reverseRates = item.ReverseRates.ToList(); // Get all of the reverse rates related to the current base charge. For example, if we're // calculating a fee, which was calculated on top of duty and vat, we'll need the base // fee rate, the fee on duty rate and the fee on vat rate. This is done by querying the // rates collection by 'parent' charge. In this example, all rates would have a parent charge // of fee. foreach (var reverseRate in reverseRates.Where(x => x.BaseChargeName == baseChargeName)) { var rate = _getRate(item).AsDecimal *reverseRate.Rate.AsDecimal * 100; var calculatedRate = new ReverseRate( name: ChargeName.FromBaseChargeName(_chargeName, reverseRate.ChargeName), parentChargeName: _chargeName, rate: new Rate(rate)); item.AddReverseRate(calculatedRate); } } } } } }