public void Can_convert_currency_1() { currencyUSD.AsMoney(10.1M).Exchange(1.5M).Amount.ShouldEqual(15.15M); currencyUSD.AsMoney(10.1M).Exchange(1).Amount.ShouldEqual(10.1M); currencyUSD.AsMoney(10.1M).Exchange(0).Amount.ShouldEqual(0); currencyUSD.AsMoney(0).Exchange(5).Amount.ShouldEqual(0); }
/// <summary> /// Gets orders total async. /// </summary> /// <param name="query">Order query.</param> /// <param name="currency">Currency for <see cref="Money"/>.</param> /// <returns>Orders total money.</returns> public static async Task <Money> GetOrdersTotalAsync(this IQueryable <Order> query, Currency currency) { Guard.NotNull(query, nameof(query)); var sumTotal = await query.SumAsync(x => (decimal?)x.OrderTotal ?? decimal.Zero); return(currency.AsMoney(sumTotal)); }
/// <summary> /// Gets orders product costs async. /// </summary> /// <param name="query">Order query.</param> /// <param name="currency">Currency for <see cref="Money"/>.</param> /// <returns>Product cost as <see cref="Money"/></returns> public static async Task <Money> GetOrdersProductCostsAsync(this IQueryable <Order> query, Currency currency) { Guard.NotNull(query, nameof(query)); var db = query.GetDbContext <SmartDbContext>(); var productCost = await db.OrderItems .Join(query, orderItem => orderItem.OrderId, order => order.Id, (orderItem, order) => orderItem) .SumAsync(x => ((decimal?)x.ProductCost ?? decimal.Zero) * x.Quantity); return(currency.AsMoney(productCost)); }
public virtual async Task <ShoppingCartTotal> GetShoppingCartTotalAsync( IList <OrganizedShoppingCartItem> cart, bool includeRewardPoints = true, bool includePaymentAdditionalFee = true, bool includeCreditBalance = true) { Guard.NotNull(cart, nameof(cart)); var store = _storeContext.CurrentStore; var customer = cart.GetCustomer(); var paymentMethodSystemName = customer != null ? customer.GenericAttributes.SelectedPaymentMethod : string.Empty; var subTotal = await GetShoppingCartSubTotalAsync(cart, false); // Subtotal with discount. var subtotalBase = subTotal.SubTotalWithDiscount; // Shipping without tax. Money?shoppingCartShipping = await GetShoppingCartShippingTotalAsync(cart, false); // Payment method additional fee without tax. var paymentFeeWithoutTax = new Money(_primaryCurrency); if (includePaymentAdditionalFee && paymentMethodSystemName.HasValue()) { var provider = _providerManager.GetProvider <IPaymentMethod>(paymentMethodSystemName); var paymentFee = await provider?.Value?.GetAdditionalHandlingFeeAsync(cart); (paymentFeeWithoutTax, _) = await _taxService.GetPaymentMethodAdditionalFeeAsync(paymentFee, false, customer : customer); } // Tax. var(shoppingCartTax, _) = await GetTaxTotalAsync(cart, includePaymentAdditionalFee); // Order total. var resultTemp = subtotalBase; if (shoppingCartShipping.HasValue) { resultTemp += shoppingCartShipping.Value; } resultTemp += paymentFeeWithoutTax; resultTemp += shoppingCartTax; // Round: resultTemp = _primaryCurrency.AsMoney(resultTemp.Amount); // Order total discount. var(discountAmount, appliedDiscount) = await GetDiscountAmountAsync(resultTemp, DiscountType.AssignedToOrderTotal, customer); // Subtotal with discount. if (resultTemp < discountAmount) { discountAmount = resultTemp; } // Reduce subtotal. resultTemp = _primaryCurrency.AsMoney((resultTemp - discountAmount).Amount, true, true); // Applied gift cards. var appliedGiftCards = new List <AppliedGiftCard>(); if (!cart.IncludesMatchingItems(x => x.IsRecurring)) { // TODO: (ms) (core) Gift card usage in OrderCalculationService needs to be tested extensively as the gift card code has been fundamentally changed. var giftCards = await _giftCardService.GetValidGiftCardsAsync(store.Id, customer); foreach (var gc in giftCards) { if (resultTemp > decimal.Zero) { var usableAmount = resultTemp > gc.UsableAmount ? gc.UsableAmount : resultTemp; // Reduce subtotal. resultTemp -= usableAmount; appliedGiftCards.Add(new() { GiftCard = gc.GiftCard, UsableAmount = usableAmount }); } } } // Reward points. var redeemedRewardPoints = 0; var redeemedRewardPointsAmount = new Money(_primaryCurrency); if (_rewardPointsSettings.Enabled && includeRewardPoints && resultTemp > decimal.Zero && customer != null && customer.GenericAttributes.UseRewardPointsDuringCheckout) { var rewardPointsBalance = customer.GetRewardPointsBalance(); var rewardPointsBalanceAmount = ConvertRewardPointsToAmount(rewardPointsBalance); if (resultTemp > rewardPointsBalanceAmount) { redeemedRewardPointsAmount = rewardPointsBalanceAmount; redeemedRewardPoints = rewardPointsBalance; } else { redeemedRewardPointsAmount = resultTemp; redeemedRewardPoints = ConvertAmountToRewardPoints(redeemedRewardPointsAmount); } } resultTemp = _primaryCurrency.AsMoney(resultTemp.Amount, true, true); // Return null if we have errors: Money?orderTotal = shoppingCartShipping.HasValue ? resultTemp : null; var orderTotalConverted = orderTotal; var appliedCreditBalance = new Money(_primaryCurrency); var toNearestRounding = new Money(_primaryCurrency); var toNearestRoundingConverted = new Money(_primaryCurrency); if (orderTotal.HasValue) { orderTotal = orderTotal.Value - redeemedRewardPointsAmount; // Credit balance. if (includeCreditBalance && customer != null && orderTotal > decimal.Zero) { var creditBalance = _primaryCurrency.AsMoney(customer.GenericAttributes.UseCreditBalanceDuringCheckout, false); if (creditBalance > decimal.Zero) { if (creditBalance > orderTotal) { // Normalize used amount. appliedCreditBalance = orderTotal.Value; customer.GenericAttributes.UseCreditBalanceDuringCheckout = orderTotal.Value.Amount; await _db.SaveChangesAsync(); } else { appliedCreditBalance = creditBalance; } } } orderTotal = _primaryCurrency.AsMoney(orderTotal.Value.Amount - appliedCreditBalance.Amount); orderTotalConverted = _currencyService.ConvertFromPrimaryStoreCurrency(orderTotal.Value, store); // Round order total to nearest (cash rounding). if (_primaryCurrency.RoundOrderTotalEnabled && paymentMethodSystemName.HasValue()) { var paymentMethod = await _db.PaymentMethods.AsNoTracking().FirstOrDefaultAsync(x => x.PaymentMethodSystemName == paymentMethodSystemName); if (paymentMethod?.RoundOrderTotalEnabled ?? false) { orderTotal = _primaryCurrency.RoundToNearest(orderTotal.Value, out toNearestRounding); orderTotalConverted = _primaryCurrency.RoundToNearest(orderTotalConverted.Value, out toNearestRoundingConverted); } } } var result = new ShoppingCartTotal(orderTotal) { ToNearestRounding = toNearestRounding, DiscountAmount = discountAmount, AppliedDiscount = appliedDiscount, RedeemedRewardPoints = redeemedRewardPoints, RedeemedRewardPointsAmount = redeemedRewardPointsAmount, CreditBalance = appliedCreditBalance, AppliedGiftCards = appliedGiftCards, ConvertedAmount = new ShoppingCartTotal.ConvertedAmounts { Total = orderTotalConverted, ToNearestRounding = toNearestRoundingConverted } }; return(result); }
public virtual async Task <Money> GetUnitPriceAsync(OrganizedShoppingCartItem shoppingCartItem, bool includeDiscounts) { return(_primaryCurrency.AsMoney(await GetUnitPriceAmountAsync(shoppingCartItem, includeDiscounts))); }