コード例 #1
0
 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);
 }
コード例 #2
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));
        }
コード例 #3
0
        /// <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));
        }
コード例 #4
0
        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);
        }
コード例 #5
0
 public virtual async Task <Money> GetUnitPriceAsync(OrganizedShoppingCartItem shoppingCartItem, bool includeDiscounts)
 {
     return(_primaryCurrency.AsMoney(await GetUnitPriceAmountAsync(shoppingCartItem, includeDiscounts)));
 }