예제 #1
0
        /// <summary>
        /// Prepare paged affiliate list model
        /// </summary>
        /// <param name="searchModel">Affiliate search model</param>
        /// <returns>Affiliate list model</returns>
        public virtual async Task <AffiliateListModel> PrepareAffiliateListModelAsync(AffiliateSearchModel searchModel)
        {
            if (searchModel == null)
            {
                throw new ArgumentNullException(nameof(searchModel));
            }

            //get affiliates
            var affiliates = await _affiliateService.GetAllAffiliatesAsync(searchModel.SearchFriendlyUrlName,
                                                                           searchModel.SearchFirstName,
                                                                           searchModel.SearchLastName,
                                                                           searchModel.LoadOnlyWithOrders,
                                                                           searchModel.OrdersCreatedFromUtc,
                                                                           searchModel.OrdersCreatedToUtc,
                                                                           searchModel.Page - 1, searchModel.PageSize, true);

            //prepare list model
            var model = await new AffiliateListModel().PrepareToGridAsync(searchModel, affiliates, () =>
            {
                //fill in model values from the entity
                return(affiliates.SelectAwait(async affiliate =>
                {
                    var address = await _addressService.GetAddressByIdAsync(affiliate.AddressId);

                    var affiliateModel = affiliate.ToModel <AffiliateModel>();
                    affiliateModel.Address = address.ToModel <AddressModel>();
                    affiliateModel.Address.CountryName = (await _countryService.GetCountryByAddressAsync(address))?.Name;
                    affiliateModel.Address.StateProvinceName = (await _stateProvinceService.GetStateProvinceByAddressAsync(address))?.Name;

                    return affiliateModel;
                }));
            });

            return(model);
        }
예제 #2
0
        public virtual async Task <CustomerAddressListModel> PrepareCompanyCustomerAddressListModelAsync(CustomerAddressSearchModel searchModel, Company company)
        {
            if (searchModel == null)
            {
                throw new ArgumentNullException(nameof(searchModel));
            }

            if (company == null)
            {
                throw new ArgumentNullException(nameof(company));
            }

            var model = new CustomerAddressListModel();
            var getCompanyCustomers = await _companyService.GetCompanyCustomersByCompanyIdAsync(company.Id);

            IPagedList <Address> addressesList = new PagedList <Address>(new List <Address>(), 0, 1);

            foreach (var getCompanyCustomer in getCompanyCustomers)
            {
                var customer = await _customerService.GetCustomerByIdAsync(getCompanyCustomer.CustomerId);

                //get customer addresses
                var addresses = (await _customerService.GetAddressesByCustomerIdAsync(customer.Id))
                                .OrderByDescending(address => address.CreatedOnUtc).ThenByDescending(address => address.Id).ToList()
                                .ToPagedList(searchModel);

                foreach (var address in addresses)
                {
                    if (!addressesList.Where(x => x.Id == address.Id).Any())
                    {
                        addressesList.Add(address);
                    }
                }
                searchModel.CustomerId = customer.Id;
            }

            //prepare list model
            model = await new CustomerAddressListModel().PrepareToGridAsync(searchModel, addressesList, () =>
            {
                return(addressesList.SelectAwait(async address =>
                {
                    //fill in model values from the entity
                    var addressModel = address.ToModel <AddressModel>();

                    var customerAddressMapping = await _customerService.GetCustomerAddressesByAddressIdAsync(address.Id);
                    addressModel.CustomerId = customerAddressMapping.Any() ? customerAddressMapping.FirstOrDefault().CustomerId : 0;
                    addressModel.CountryName = (await _countryService.GetCountryByAddressAsync(address))?.Name;
                    addressModel.StateProvinceName = (await _stateProvinceService.GetStateProvinceByAddressAsync(address))?.Name;

                    //fill in additional values (not existing in the entity)
                    await PrepareModelAddressHtmlAsync(addressModel, address);

                    return addressModel;
                }));
            });
            return(model);
        }
        /// <summary>
        /// Create common query parameters for the request
        /// </summary>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        /// <returns>Created query parameters</returns>
        private async Task <IDictionary <string, string> > CreateQueryParametersAsync(PostProcessPaymentRequest postProcessPaymentRequest)
        {
            //get store location
            var storeLocation = _webHelper.GetStoreLocation();

            //choosing correct order address
            var orderAddress = await _addressService.GetAddressByIdAsync(
                (postProcessPaymentRequest.Order.PickupInStore ? postProcessPaymentRequest.Order.PickupAddressId : postProcessPaymentRequest.Order.ShippingAddressId) ?? 0);

            //create query parameters
            return(new Dictionary <string, string>
            {
                //PayPal ID or an email address associated with your PayPal account
                ["business"] = _payPalStandardPaymentSettings.BusinessEmail,

                //the character set and character encoding
                ["charset"] = "utf-8",

                //set return method to "2" (the customer redirected to the return URL by using the POST method, and all payment variables are included)
                ["rm"] = "2",

                ["bn"] = PayPalHelper.NopCommercePartnerCode,
                ["currency_code"] = (await _currencyService.GetCurrencyByIdAsync(_currencySettings.PrimaryStoreCurrencyId))?.CurrencyCode,

                //order identifier
                ["invoice"] = postProcessPaymentRequest.Order.CustomOrderNumber,
                ["custom"] = postProcessPaymentRequest.Order.OrderGuid.ToString(),

                //PDT, IPN and cancel URL
                ["return"] = $"{storeLocation}Plugins/PaymentPayPalStandard/PDTHandler",
                ["notify_url"] = $"{storeLocation}Plugins/PaymentPayPalStandard/IPNHandler",
                ["cancel_return"] = $"{storeLocation}Plugins/PaymentPayPalStandard/CancelOrder",

                //shipping address, if exists
                ["no_shipping"] = postProcessPaymentRequest.Order.ShippingStatus == ShippingStatus.ShippingNotRequired ? "1" : "2",
                ["address_override"] = postProcessPaymentRequest.Order.ShippingStatus == ShippingStatus.ShippingNotRequired ? "0" : "1",
                ["first_name"] = orderAddress?.FirstName,
                ["last_name"] = orderAddress?.LastName,
                ["address1"] = orderAddress?.Address1,
                ["address2"] = orderAddress?.Address2,
                ["city"] = orderAddress?.City,
                ["state"] = (await _stateProvinceService.GetStateProvinceByAddressAsync(orderAddress))?.Abbreviation,
                ["country"] = (await _countryService.GetCountryByAddressAsync(orderAddress))?.TwoLetterIsoCode,
                ["zip"] = orderAddress?.ZipPostalCode,
                ["email"] = orderAddress?.Email
            });
        }
        /// <summary>
        /// Get pickup points for the address
        /// </summary>
        /// <param name="address">Address</param>
        /// <returns>
        /// A task that represents the asynchronous operation
        /// The task result contains the represents a response of getting pickup points
        /// </returns>
        public async Task <GetPickupPointsResponse> GetPickupPointsAsync(Address address)
        {
            var result = new GetPickupPointsResponse();
            var store  = await _storeContext.GetCurrentStoreAsync();

            foreach (var point in await _storePickupPointService.GetAllStorePickupPointsAsync(store.Id))
            {
                var pointAddress = await _addressService.GetAddressByIdAsync(point.AddressId);

                if (pointAddress == null)
                {
                    continue;
                }

                result.PickupPoints.Add(new PickupPoint
                {
                    Id                 = point.Id.ToString(),
                    Name               = point.Name,
                    Description        = point.Description,
                    Address            = pointAddress.Address1,
                    City               = pointAddress.City,
                    County             = pointAddress.County,
                    StateAbbreviation  = (await _stateProvinceService.GetStateProvinceByAddressAsync(pointAddress))?.Abbreviation ?? string.Empty,
                    CountryCode        = (await _countryService.GetCountryByAddressAsync(pointAddress))?.TwoLetterIsoCode ?? string.Empty,
                    ZipPostalCode      = pointAddress.ZipPostalCode,
                    OpeningHours       = point.OpeningHours,
                    PickupFee          = point.PickupFee,
                    DisplayOrder       = point.DisplayOrder,
                    ProviderSystemName = PluginDescriptor.SystemName,
                    Latitude           = point.Latitude,
                    Longitude          = point.Longitude,
                    TransitDays        = point.TransitDays
                });
            }

            if (!result.PickupPoints.Any())
            {
                result.AddError(await _localizationService.GetResourceAsync("Plugins.Pickup.PickupInStore.NoPickupPoints"));
            }

            return(result);
        }
        /// <summary>
        /// Post process payment (used by payment gateways that require redirecting to a third-party URL)
        /// </summary>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        public async Task PostProcessPaymentAsync(PostProcessPaymentRequest postProcessPaymentRequest)
        {
            //choosing correct order address
            var orderAddress = await _addressService.GetAddressByIdAsync(
                (postProcessPaymentRequest.Order.PickupInStore ? postProcessPaymentRequest.Order.PickupAddressId : postProcessPaymentRequest.Order.ShippingAddressId) ?? 0);

            var orderShippingAddress = await _addressService.GetAddressByIdAsync((int)postProcessPaymentRequest.Order.ShippingAddressId);

            var myUtility = new PayuHelper();
            var orderId   = postProcessPaymentRequest.Order.Id;

            var remotePostHelper = new RemotePost();

            remotePostHelper.FormName = "PayuForm";
            remotePostHelper.Url      = _PayuPaymentSettings.PayUri;
            remotePostHelper.Add("key", _PayuPaymentSettings.MerchantId.ToString());
            remotePostHelper.Add("amount", postProcessPaymentRequest.Order.OrderTotal.ToString(new CultureInfo("en-US", false).NumberFormat));
            remotePostHelper.Add("productinfo", "productinfo");
            remotePostHelper.Add("Currency", (await _currencyService.GetCurrencyByIdAsync(_currencySettings.PrimaryStoreCurrencyId)).CurrencyCode);
            remotePostHelper.Add("Order_Id", orderId.ToString());
            remotePostHelper.Add("txnid", orderId.ToString());
            remotePostHelper.Add("service_provider", "payu_paisa");
            remotePostHelper.Add("surl", _webHelper.GetStoreLocation(false) + "Plugins/PaymentPayu/Return");
            remotePostHelper.Add("furl", _webHelper.GetStoreLocation(false) + "Plugins/PaymentPayu/Return");
            remotePostHelper.Add("hash", myUtility.getchecksum(_PayuPaymentSettings.MerchantId.ToString(),
                                                               postProcessPaymentRequest.Order.Id.ToString(), postProcessPaymentRequest.Order.OrderTotal.ToString(new CultureInfo("en-US", false).NumberFormat),
                                                               "productinfo", orderAddress?.FirstName,
                                                               orderAddress?.Email.ToString(), _PayuPaymentSettings.Key));


            //Billing details
            remotePostHelper.Add("firstname", orderAddress?.FirstName.ToString());
            remotePostHelper.Add("billing_cust_address", orderAddress?.Address1);
            remotePostHelper.Add("phone", orderAddress?.PhoneNumber);
            remotePostHelper.Add("email", orderAddress?.Email.ToString());
            remotePostHelper.Add("billing_cust_city", orderAddress?.City);
            var billingStateProvince = (await _stateProvinceService.GetStateProvinceByAddressAsync(orderAddress))?.Abbreviation;

            if (billingStateProvince != null)
            {
                remotePostHelper.Add("billing_cust_state", (await _stateProvinceService.GetStateProvinceByAddressAsync(orderAddress))?.Abbreviation);
            }
            else
            {
                remotePostHelper.Add("billing_cust_state", "");
            }
            remotePostHelper.Add("billing_zip_code", orderAddress?.ZipPostalCode);
            var billingCountry = (await _countryService.GetCountryByAddressAsync(orderAddress))?.TwoLetterIsoCode;

            if (billingCountry != null)
            {
                remotePostHelper.Add("billing_cust_country", (await _countryService.GetCountryByAddressAsync(orderAddress))?.TwoLetterIsoCode);
            }
            else
            {
                remotePostHelper.Add("billing_cust_country", "");
            }

            //Delivery details

            if (postProcessPaymentRequest.Order.ShippingStatus != ShippingStatus.ShippingNotRequired)
            {
                remotePostHelper.Add("delivery_cust_name", orderShippingAddress.FirstName);
                remotePostHelper.Add("delivery_cust_address", orderShippingAddress.Address1);
                remotePostHelper.Add("delivery_cust_notes", string.Empty);
                remotePostHelper.Add("delivery_cust_tel", orderShippingAddress.PhoneNumber);
                remotePostHelper.Add("delivery_cust_city", orderShippingAddress.City);
                var deliveryStateProvince = await _stateProvinceService.GetStateProvinceByAddressAsync(orderShippingAddress);

                if (deliveryStateProvince != null)
                {
                    remotePostHelper.Add("delivery_cust_state", deliveryStateProvince.Abbreviation);
                }
                else
                {
                    remotePostHelper.Add("delivery_cust_state", "");
                }
                remotePostHelper.Add("delivery_zip_code", orderShippingAddress.ZipPostalCode);
                var deliveryCountry = await _countryService.GetCountryByAddressAsync(orderShippingAddress); // postProcessPaymentRequest.Order.ShippingAddress.Country;

                if (deliveryCountry != null)
                {
                    remotePostHelper.Add("delivery_cust_country", deliveryCountry.ThreeLetterIsoCode);
                }
                else
                {
                    remotePostHelper.Add("delivery_cust_country", "");
                }
            }

            //  remotePostHelper.Add("Merchant_Param", _PayuPaymentSettings.MerchantParam);
            remotePostHelper.Post();
        }
        /// <summary>
        /// Invoke the widget view component
        /// </summary>
        /// <param name="widgetZone">Widget zone</param>
        /// <param name="additionalData">Additional parameters</param>
        /// <returns>
        /// A task that represents the asynchronous operation
        /// The task result contains the view component result
        /// </returns>
        public async Task <IViewComponentResult> InvokeAsync(string widgetZone, object additionalData)
        {
            //ensure that Avalara tax provider is active
            var customer = await _workContext.GetCurrentCustomerAsync();

            if (!await _taxPluginManager.IsPluginActiveAsync(AvalaraTaxDefaults.SystemName, customer))
            {
                return(Content(string.Empty));
            }

            //ensure that it's a proper widget zone
            if (!widgetZone.Equals(PublicWidgetZones.CheckoutConfirmTop) && !widgetZone.Equals(PublicWidgetZones.OpCheckoutConfirmTop))
            {
                return(Content(string.Empty));
            }

            //ensure thet address validation is enabled
            if (!_avalaraTaxSettings.ValidateAddress)
            {
                return(Content(string.Empty));
            }

            //validate entered by customer addresses only
            var addressId = _taxSettings.TaxBasedOn == TaxBasedOn.BillingAddress
                ? customer.BillingAddressId
                : _taxSettings.TaxBasedOn == TaxBasedOn.ShippingAddress
                ? customer.ShippingAddressId
                : null;

            var address = await _addressService.GetAddressByIdAsync(addressId ?? 0);

            if (address == null)
            {
                return(Content(string.Empty));
            }

            //validate address
            var validationResult = await _avalaraTaxManager.ValidateAddressAsync(address);

            //whether there are errors in validation result
            var errorDetails = validationResult?.messages?
                               .Where(message => message.severity.Equals("Error", StringComparison.InvariantCultureIgnoreCase))
                               .Select(message => message.details)
                               ?? new List <string>();

            if (errorDetails.Any())
            {
                //display error message to customer
                return(View("~/Plugins/Tax.Avalara/Views/Checkout/AddressValidation.cshtml", new AddressValidationModel
                {
                    Message = string.Format(await _localizationService.GetResourceAsync("Plugins.Tax.Avalara.AddressValidation.Error"),
                                            WebUtility.HtmlEncode(string.Join("; ", errorDetails))),
                    IsError = true
                }));
            }

            //if there are no errors and no validated addresses, nothing to display
            if (!validationResult?.validatedAddresses?.Any() ?? true)
            {
                return(Content(string.Empty));
            }

            //get validated address info
            var validatedAddressInfo = validationResult.validatedAddresses.FirstOrDefault();

            //create new address as a copy of address to validate and with details of the validated one
            var validatedAddress = _addressService.CloneAddress(address);

            validatedAddress.City            = validatedAddressInfo.city;
            validatedAddress.CountryId       = (await _countryService.GetCountryByTwoLetterIsoCodeAsync(validatedAddressInfo.country))?.Id;
            validatedAddress.Address1        = validatedAddressInfo.line1;
            validatedAddress.Address2        = validatedAddressInfo.line2;
            validatedAddress.ZipPostalCode   = validatedAddressInfo.postalCode;
            validatedAddress.StateProvinceId = (await _stateProvinceService.GetStateProvinceByAbbreviationAsync(validatedAddressInfo.region))?.Id;

            //try to find an existing address with the same values
            var existingAddress = _addressService.FindAddress((await _customerService.GetAddressesByCustomerIdAsync(customer.Id)).ToList(),
                                                              validatedAddress.FirstName, validatedAddress.LastName, validatedAddress.PhoneNumber,
                                                              validatedAddress.Email, validatedAddress.FaxNumber, validatedAddress.Company,
                                                              validatedAddress.Address1, validatedAddress.Address2, validatedAddress.City,
                                                              validatedAddress.County, validatedAddress.StateProvinceId, validatedAddress.ZipPostalCode,
                                                              validatedAddress.CountryId, validatedAddress.CustomAttributes);

            //if the found address is the same as address to validate, nothing to display
            if (address.Id == existingAddress?.Id)
            {
                return(Content(string.Empty));
            }

            //otherwise display to customer a confirmation dialog about address updating
            var model = new AddressValidationModel();

            if (existingAddress == null)
            {
                await _addressService.InsertAddressAsync(validatedAddress);

                model.AddressId    = validatedAddress.Id;
                model.IsNewAddress = true;
            }
            else
            {
                model.AddressId = existingAddress.Id;
            }

            async Task <string> getAddressLineAsync(Address address) =>
            WebUtility.HtmlEncode($"{(!string.IsNullOrEmpty(address.Address1) ? $"{address.Address1}, " : string.Empty)}" +
                                  $"{(!string.IsNullOrEmpty(address.Address2) ? $"{address.Address2}, " : string.Empty)}" +
                                  $"{(!string.IsNullOrEmpty(address.City) ? $"{address.City}, " : string.Empty)}" +
                                  $"{(await _stateProvinceService.GetStateProvinceByAddressAsync(address) is StateProvince stateProvince ? $"{stateProvince.Name}, " : string.Empty)}" +
                                  $"{(await _countryService.GetCountryByAddressAsync(address) is Country country ? $"{country.Name}, " : string.Empty)}" +
                                  $"{(!string.IsNullOrEmpty(address.ZipPostalCode) ? $"{address.ZipPostalCode}, " : string.Empty)}"
                                  .TrimEnd(' ').TrimEnd(','));

            model.Message = string.Format(await _localizationService.GetResourceAsync("Plugins.Tax.Avalara.AddressValidation.Confirm"),
                                          await getAddressLineAsync(address), await getAddressLineAsync(existingAddress ?? validatedAddress));

            return(View("~/Plugins/Tax.Avalara/Views/Checkout/AddressValidation.cshtml", model));
        }
예제 #7
0
파일: Events.cs 프로젝트: Sakchai/eStore
        private async Task ProcessOrderEventAsync(Order order, bool add)
        {
            try
            {
                //settings per store
                var store = await _storeService.GetStoreByIdAsync(order.StoreId) ?? await _storeContext.GetCurrentStoreAsync();

                var googleAnalyticsSettings = await _settingService.LoadSettingAsync <GoogleAnalyticsSettings>(store.Id);

                var request = new GoogleRequest
                {
                    AccountCode = googleAnalyticsSettings.GoogleId,
                    Culture     = "en-US",
                    HostName    = new Uri(_webHelper.GetThisPageUrl(false)).Host,
                    PageTitle   = add ? "AddTransaction" : "CancelTransaction"
                };

                var orderId       = order.CustomOrderNumber;
                var orderShipping = googleAnalyticsSettings.IncludingTax ? order.OrderShippingInclTax : order.OrderShippingExclTax;
                var orderTax      = order.OrderTax;
                var orderTotal    = order.OrderTotal;
                if (!add)
                {
                    orderShipping = -orderShipping;
                    orderTax      = -orderTax;
                    orderTotal    = -orderTotal;
                }

                var billingAddress = await _addressService.GetAddressByIdAsync(order.BillingAddressId);

                var trans = new Transaction(FixIllegalJavaScriptChars(orderId),
                                            FixIllegalJavaScriptChars(billingAddress.City),
                                            await _countryService.GetCountryByAddressAsync(billingAddress) is Country country ? FixIllegalJavaScriptChars(country.Name) : string.Empty,
                                            await _stateProvinceService.GetStateProvinceByAddressAsync(billingAddress) is StateProvince stateProvince ? FixIllegalJavaScriptChars(stateProvince.Name) : string.Empty,
                                            store.Name,
                                            orderShipping,
                                            orderTax,
                                            orderTotal);

                foreach (var item in await _orderService.GetOrderItemsAsync(order.Id))
                {
                    var product = await _productService.GetProductByIdAsync(item.ProductId);

                    //get category
                    var category  = (await _categoryService.GetCategoryByIdAsync((await _categoryService.GetProductCategoriesByProductIdAsync(product.Id)).FirstOrDefault()?.CategoryId ?? 0))?.Name;
                    var unitPrice = googleAnalyticsSettings.IncludingTax ? item.UnitPriceInclTax : item.UnitPriceExclTax;
                    var qty       = item.Quantity;
                    if (!add)
                    {
                        qty = -qty;
                    }

                    var sku = await _productService.FormatSkuAsync(product, item.AttributesXml);

                    if (string.IsNullOrEmpty(sku))
                    {
                        sku = product.Id.ToString();
                    }

                    var productItem = new TransactionItem(FixIllegalJavaScriptChars(orderId),
                                                          FixIllegalJavaScriptChars(sku),
                                                          FixIllegalJavaScriptChars(product.Name),
                                                          unitPrice,
                                                          qty,
                                                          FixIllegalJavaScriptChars(category));

                    trans.Items.Add(productItem);
                }

                await request.SendRequest(trans, _httpClientFactory.CreateClient(NopHttpDefaults.DefaultHttpClient));
            }
            catch (Exception ex)
            {
                await _logger.InsertLogAsync(LogLevel.Error, "Google Analytics. Error canceling transaction from server side", ex.ToString());
            }
        }
예제 #8
0
        /// <summary>
        /// Create shipment packages (requests) from shopping cart
        /// </summary>
        /// <param name="cart">Shopping cart</param>
        /// <param name="shippingAddress">Shipping address</param>
        /// <param name="storeId">Load records allowed only in a specified store; pass 0 to load all records</param>
        /// <returns>Shipment packages (requests). Value indicating whether shipping is done from multiple locations (warehouses)</returns>
        public virtual async Task <(IList <GetShippingOptionRequest> shipmentPackages, bool shippingFromMultipleLocations)> CreateShippingOptionRequestsAsync(IList <ShoppingCartItem> cart,
                                                                                                                                                              Address shippingAddress, int storeId)
        {
            //if we always ship from the default shipping origin, then there's only one request
            //if we ship from warehouses ("ShippingSettings.UseWarehouseLocation" enabled),
            //then there could be several requests

            //key - warehouse identifier (0 - default shipping origin)
            //value - request
            var requests = new Dictionary <int, GetShippingOptionRequest>();

            //a list of requests with products which should be shipped separately
            var separateRequests = new List <GetShippingOptionRequest>();

            foreach (var sci in cart)
            {
                if (!await IsShipEnabledAsync(sci))
                {
                    continue;
                }

                var product = await _productService.GetProductByIdAsync(sci.ProductId);

                if (product == null || !product.IsShipEnabled)
                {
                    var associatedProducts = await(await _productAttributeParser.ParseProductAttributeValuesAsync(sci.AttributesXml))
                                             .Where(attributeValue => attributeValue.AttributeValueType == AttributeValueType.AssociatedToProduct)
                                             .SelectAwait(async attributeValue => await _productService.GetProductByIdAsync(attributeValue.AssociatedProductId)).ToListAsync();
                    product = associatedProducts.FirstOrDefault(associatedProduct => associatedProduct != null && associatedProduct.IsShipEnabled);
                }

                if (product == null)
                {
                    continue;
                }

                //warehouses
                Warehouse warehouse = null;
                if (_shippingSettings.UseWarehouseLocation)
                {
                    if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock &&
                        product.UseMultipleWarehouses)
                    {
                        var allWarehouses = new List <Warehouse>();
                        //multiple warehouses supported
                        foreach (var pwi in await _productService.GetAllProductWarehouseInventoryRecordsAsync(product.Id))
                        {
                            var tmpWarehouse = await GetWarehouseByIdAsync(pwi.WarehouseId);

                            if (tmpWarehouse != null)
                            {
                                allWarehouses.Add(tmpWarehouse);
                            }
                        }

                        warehouse = await GetNearestWarehouseAsync(shippingAddress, allWarehouses);
                    }
                    else
                    {
                        //multiple warehouses are not supported
                        warehouse = await GetWarehouseByIdAsync(product.WarehouseId);
                    }
                }

                var warehouseId = warehouse?.Id ?? 0;

                if (requests.ContainsKey(warehouseId) && !product.ShipSeparately)
                {
                    //add item to existing request
                    requests[warehouseId].Items.Add(new GetShippingOptionRequest.PackageItem(sci, product));
                }
                else
                {
                    //create a new request
                    var request = new GetShippingOptionRequest
                    {
                        //store
                        StoreId = storeId
                    };
                    //customer
                    request.Customer = await _customerService.GetShoppingCartCustomerAsync(cart);

                    //ship to
                    request.ShippingAddress = shippingAddress;
                    //ship from
                    Address originAddress = null;
                    if (warehouse != null)
                    {
                        //warehouse address
                        originAddress = await _addressService.GetAddressByIdAsync(warehouse.AddressId);

                        request.WarehouseFrom = warehouse;
                    }

                    if (originAddress == null)
                    {
                        //no warehouse address. in this case use the default shipping origin
                        originAddress = await _addressService.GetAddressByIdAsync(_shippingSettings.ShippingOriginAddressId);
                    }

                    if (originAddress != null)
                    {
                        request.CountryFrom = await _countryService.GetCountryByAddressAsync(originAddress);

                        request.StateProvinceFrom = await _stateProvinceService.GetStateProvinceByAddressAsync(originAddress);

                        request.ZipPostalCodeFrom = originAddress.ZipPostalCode;
                        request.CountyFrom        = originAddress.County;
                        request.CityFrom          = originAddress.City;
                        request.AddressFrom       = originAddress.Address1;
                    }

                    //whether this product should be shipped separately from other ones
                    if (product.ShipSeparately)
                    {
                        //whether product items should be shipped separately
                        if (_shippingSettings.ShipSeparatelyOneItemEach)
                        {
                            //add item with overridden quantity 1
                            request.Items.Add(new GetShippingOptionRequest.PackageItem(sci, product, 1));

                            //create separate requests for all product quantity
                            for (var i = 0; i < sci.Quantity; i++)
                            {
                                separateRequests.Add(request);
                            }
                        }
                        else
                        {
                            //all of product items should be shipped in a single box, so create the single separate request
                            request.Items.Add(new GetShippingOptionRequest.PackageItem(sci, product));
                            separateRequests.Add(request);
                        }
                    }
                    else
                    {
                        //usual request
                        request.Items.Add(new GetShippingOptionRequest.PackageItem(sci, product));
                        requests.Add(warehouseId, request);
                    }
                }
            }

            //multiple locations?
            //currently we just compare warehouses
            //but we should also consider cases when several warehouses are located in the same address
            var shippingFromMultipleLocations = requests.Select(x => x.Key).Distinct().Count() > 1;

            var result = requests.Values.ToList();

            result.AddRange(separateRequests);

            return(result, shippingFromMultipleLocations);
        }
        /// <summary>
        /// Handle order completed event
        /// </summary>
        /// <param name="order">Order</param>
        /// <returns>A task that represents the asynchronous operation</returns>
        public async Task HandleOrderCompletedEventAsync(Order order)
        {
            //whether marketing automation is enabled
            if (!_sendinblueSettings.UseMarketingAutomation)
            {
                return;
            }

            if (order is null)
            {
                throw new ArgumentNullException(nameof(order));
            }

            var customer = await _customerService.GetCustomerByIdAsync(order.CustomerId);

            try
            {
                //create API client
                var client = CreateMarketingAutomationClient();

                //first, try to identify current customer
                await client.IdentifyAsync(new Identify(customer.Email));

                //get URL helper
                var urlHelper = _urlHelperFactory.GetUrlHelper(_actionContextAccessor.ActionContext);

                //get products data by order items
                var itemsData = await(await _orderService.GetOrderItemsAsync(order.Id)).SelectAwait(async item =>
                {
                    var product = await _productService.GetProductByIdAsync(item.ProductId);

                    //try to get product attribute combination
                    var combination = await _productAttributeParser.FindProductAttributeCombinationAsync(product, item.AttributesXml);

                    //get default product picture
                    var picture = await _pictureService.GetProductPictureAsync(product, item.AttributesXml);

                    //get product SEO slug name
                    var seName = await _urlRecordService.GetSeNameAsync(product);

                    //create product data
                    return(new
                    {
                        id = product.Id,
                        name = product.Name,
                        variant_id = combination?.Id ?? product.Id,
                        variant_name = combination?.Sku ?? product.Name,
                        sku = combination?.Sku ?? product.Sku,
                        category = await(await _categoryService.GetProductCategoriesByProductIdAsync(item.ProductId)).AggregateAwaitAsync(",", async(all, pc) =>
                        {
                            var res = (await _categoryService.GetCategoryByIdAsync(pc.CategoryId)).Name;
                            res = all == "," ? res : all + ", " + res;
                            return res;
                        }),
                        url = urlHelper.RouteUrl("Product", new { SeName = seName }, _webHelper.GetCurrentRequestProtocol()),
                        image = (await _pictureService.GetPictureUrlAsync(picture)).Url,
                        quantity = item.Quantity,
                        price = item.PriceInclTax,
                    });
                }).ToArrayAsync();

                var shippingAddress = await _addressService.GetAddressByIdAsync(order.ShippingAddressId ?? 0);

                var billingAddress = await _addressService.GetAddressByIdAsync(order.BillingAddressId);

                var shippingAddressData = new
                {
                    firstname = shippingAddress?.FirstName,
                    lastname  = shippingAddress?.LastName,
                    company   = shippingAddress?.Company,
                    phone     = shippingAddress?.PhoneNumber,
                    address1  = shippingAddress?.Address1,
                    address2  = shippingAddress?.Address2,
                    city      = shippingAddress?.City,
                    country   = (await _countryService.GetCountryByAddressAsync(shippingAddress))?.Name,
                    state     = (await _stateProvinceService.GetStateProvinceByAddressAsync(shippingAddress))?.Name,
                    zipcode   = shippingAddress?.ZipPostalCode
                };

                var billingAddressData = new
                {
                    firstname = billingAddress?.FirstName,
                    lastname  = billingAddress?.LastName,
                    company   = billingAddress?.Company,
                    phone     = billingAddress?.PhoneNumber,
                    address1  = billingAddress?.Address1,
                    address2  = billingAddress?.Address2,
                    city      = billingAddress?.City,
                    country   = (await _countryService.GetCountryByAddressAsync(billingAddress))?.Name,
                    state     = (await _stateProvinceService.GetStateProvinceByAddressAsync(billingAddress))?.Name,
                    zipcode   = billingAddress?.ZipPostalCode
                };

                var store = await _storeContext.GetCurrentStoreAsync();

                //prepare cart data
                var cartData = new
                {
                    id               = order.Id,
                    affiliation      = customer.AffiliateId > 0 ? customer.AffiliateId.ToString() : store.Name,
                    date             = order.PaidDateUtc?.ToString("yyyy-MM-dd"),
                    subtotal         = order.OrderSubtotalInclTax,
                    shipping         = order.OrderShippingInclTax,
                    total_before_tax = order.OrderSubtotalInclTax + order.OrderShippingInclTax,
                    tax              = order.OrderTax,
                    discount         = order.OrderDiscount,
                    revenue          = order.OrderTotal,
                    url              = urlHelper.RouteUrl("OrderDetails", new { orderId = order.Id }, _webHelper.GetCurrentRequestProtocol()),
                    currency         = order.CustomerCurrencyCode,
                    //gift_wrapping = string.Empty, //currently we can't get this value
                    items            = itemsData,
                    shipping_address = shippingAddressData,
                    billing_address  = billingAddressData
                };

                //get shopping cart GUID
                var shoppingCartGuid = await _genericAttributeService.GetAttributeAsync <Guid?>(order,
                                                                                                SendinblueDefaults.ShoppingCartGuidAttribute) ?? Guid.NewGuid();

                //create track event object
                var trackEvent = new TrackEvent(customer.Email, SendinblueDefaults.OrderCompletedEventName,
                                                eventData: new { id = $"cart:{shoppingCartGuid}", data = cartData });

                //track event
                client.TrackEvent(trackEvent);

                //update GUID for the current customer's shopping cart
                await _genericAttributeService.SaveAttributeAsync <Guid?>(order, SendinblueDefaults.ShoppingCartGuidAttribute, null);
            }
            catch (Exception exception)
            {
                //log full error
                await _logger.ErrorAsync($"Sendinblue Marketing Automation error: {exception.Message}.", exception, customer);
            }
        }
예제 #10
0
        /// <summary>
        /// Prepare the order details model
        /// </summary>
        /// <param name="order">Order</param>
        /// <returns>
        /// A task that represents the asynchronous operation
        /// The task result contains the order details model
        /// </returns>
        public virtual async Task <OrderDetailsModel> PrepareOrderDetailsModelAsync(Order order)
        {
            if (order == null)
            {
                throw new ArgumentNullException(nameof(order));
            }
            var model = new OrderDetailsModel
            {
                Id                     = order.Id,
                CreatedOn              = await _dateTimeHelper.ConvertToUserTimeAsync(order.CreatedOnUtc, DateTimeKind.Utc),
                OrderStatus            = await _localizationService.GetLocalizedEnumAsync(order.OrderStatus),
                IsReOrderAllowed       = _orderSettings.IsReOrderAllowed,
                IsReturnRequestAllowed = await _orderProcessingService.IsReturnRequestAllowedAsync(order),
                PdfInvoiceDisabled     = _pdfSettings.DisablePdfInvoicesForPendingOrders && order.OrderStatus == OrderStatus.Pending,
                CustomOrderNumber      = order.CustomOrderNumber,

                //shipping info
                ShippingStatus = await _localizationService.GetLocalizedEnumAsync(order.ShippingStatus)
            };

            if (order.ShippingStatus != ShippingStatus.ShippingNotRequired)
            {
                model.IsShippable   = true;
                model.PickupInStore = order.PickupInStore;
                if (!order.PickupInStore)
                {
                    var shippingAddress = await _addressService.GetAddressByIdAsync(order.ShippingAddressId ?? 0);

                    await _addressModelFactory.PrepareAddressModelAsync(model.ShippingAddress,
                                                                        address : shippingAddress,
                                                                        excludeProperties : false,
                                                                        addressSettings : _addressSettings);
                }
                else if (order.PickupAddressId.HasValue && await _addressService.GetAddressByIdAsync(order.PickupAddressId.Value) is Address pickupAddress)
                {
                    model.PickupAddress = new AddressModel
                    {
                        Address1          = pickupAddress.Address1,
                        City              = pickupAddress.City,
                        County            = pickupAddress.County,
                        StateProvinceName = await _stateProvinceService.GetStateProvinceByAddressAsync(pickupAddress) is StateProvince stateProvince
                            ? await _localizationService.GetLocalizedAsync(stateProvince, entity => entity.Name)
                            : string.Empty,
                        CountryName = await _countryService.GetCountryByAddressAsync(pickupAddress) is Country country
                            ? await _localizationService.GetLocalizedAsync(country, entity => entity.Name)
                            : string.Empty,
                        ZipPostalCode = pickupAddress.ZipPostalCode
                    };
                }

                model.ShippingMethod = order.ShippingMethod;

                //shipments (only already shipped or ready for pickup)
                var shipments = (await _shipmentService.GetShipmentsByOrderIdAsync(order.Id, !order.PickupInStore, order.PickupInStore)).OrderBy(x => x.CreatedOnUtc).ToList();
                foreach (var shipment in shipments)
                {
                    var shipmentModel = new OrderDetailsModel.ShipmentBriefModel
                    {
                        Id             = shipment.Id,
                        TrackingNumber = shipment.TrackingNumber,
                    };
                    if (shipment.ShippedDateUtc.HasValue)
                    {
                        shipmentModel.ShippedDate = await _dateTimeHelper.ConvertToUserTimeAsync(shipment.ShippedDateUtc.Value, DateTimeKind.Utc);
                    }
                    if (shipment.ReadyForPickupDateUtc.HasValue)
                    {
                        shipmentModel.ReadyForPickupDate = await _dateTimeHelper.ConvertToUserTimeAsync(shipment.ReadyForPickupDateUtc.Value, DateTimeKind.Utc);
                    }
                    if (shipment.DeliveryDateUtc.HasValue)
                    {
                        shipmentModel.DeliveryDate = await _dateTimeHelper.ConvertToUserTimeAsync(shipment.DeliveryDateUtc.Value, DateTimeKind.Utc);
                    }
                    model.Shipments.Add(shipmentModel);
                }
            }

            var billingAddress = await _addressService.GetAddressByIdAsync(order.BillingAddressId);

            //billing info
            await _addressModelFactory.PrepareAddressModelAsync(model.BillingAddress,
                                                                address : billingAddress,
                                                                excludeProperties : false,
                                                                addressSettings : _addressSettings);

            //VAT number
            model.VatNumber = order.VatNumber;

            var languageId = (await _workContext.GetWorkingLanguageAsync()).Id;

            //payment method
            var customer = await _customerService.GetCustomerByIdAsync(order.CustomerId);

            var paymentMethod = await _paymentPluginManager
                                .LoadPluginBySystemNameAsync(order.PaymentMethodSystemName, customer, order.StoreId);

            model.PaymentMethod = paymentMethod != null ? await _localizationService.GetLocalizedFriendlyNameAsync(paymentMethod, languageId) : order.PaymentMethodSystemName;

            model.PaymentMethodStatus = await _localizationService.GetLocalizedEnumAsync(order.PaymentStatus);

            model.CanRePostProcessPayment = await _paymentService.CanRePostProcessPaymentAsync(order);

            //custom values
            model.CustomValues = _paymentService.DeserializeCustomValues(order);

            //order subtotal
            if (order.CustomerTaxDisplayType == TaxDisplayType.IncludingTax && !_taxSettings.ForceTaxExclusionFromOrderSubtotal)
            {
                //including tax

                //order subtotal
                var orderSubtotalInclTaxInCustomerCurrency = _currencyService.ConvertCurrency(order.OrderSubtotalInclTax, order.CurrencyRate);
                model.OrderSubtotal = await _priceFormatter.FormatPriceAsync(orderSubtotalInclTaxInCustomerCurrency, true, order.CustomerCurrencyCode, languageId, true);

                model.OrderSubtotalValue = orderSubtotalInclTaxInCustomerCurrency;
                //discount (applied to order subtotal)
                var orderSubTotalDiscountInclTaxInCustomerCurrency = _currencyService.ConvertCurrency(order.OrderSubTotalDiscountInclTax, order.CurrencyRate);
                if (orderSubTotalDiscountInclTaxInCustomerCurrency > decimal.Zero)
                {
                    model.OrderSubTotalDiscount = await _priceFormatter.FormatPriceAsync(-orderSubTotalDiscountInclTaxInCustomerCurrency, true, order.CustomerCurrencyCode, languageId, true);

                    model.OrderSubTotalDiscountValue = orderSubTotalDiscountInclTaxInCustomerCurrency;
                }
            }
            else
            {
                //excluding tax

                //order subtotal
                var orderSubtotalExclTaxInCustomerCurrency = _currencyService.ConvertCurrency(order.OrderSubtotalExclTax, order.CurrencyRate);
                model.OrderSubtotal = await _priceFormatter.FormatPriceAsync(orderSubtotalExclTaxInCustomerCurrency, true, order.CustomerCurrencyCode, languageId, false);

                model.OrderSubtotalValue = orderSubtotalExclTaxInCustomerCurrency;
                //discount (applied to order subtotal)
                var orderSubTotalDiscountExclTaxInCustomerCurrency = _currencyService.ConvertCurrency(order.OrderSubTotalDiscountExclTax, order.CurrencyRate);
                if (orderSubTotalDiscountExclTaxInCustomerCurrency > decimal.Zero)
                {
                    model.OrderSubTotalDiscount = await _priceFormatter.FormatPriceAsync(-orderSubTotalDiscountExclTaxInCustomerCurrency, true, order.CustomerCurrencyCode, languageId, false);

                    model.OrderSubTotalDiscountValue = orderSubTotalDiscountExclTaxInCustomerCurrency;
                }
            }

            if (order.CustomerTaxDisplayType == TaxDisplayType.IncludingTax)
            {
                //including tax

                //order shipping
                var orderShippingInclTaxInCustomerCurrency = _currencyService.ConvertCurrency(order.OrderShippingInclTax, order.CurrencyRate);
                model.OrderShipping = await _priceFormatter.FormatShippingPriceAsync(orderShippingInclTaxInCustomerCurrency, true, order.CustomerCurrencyCode, languageId, true);

                model.OrderShippingValue = orderShippingInclTaxInCustomerCurrency;
                //payment method additional fee
                var paymentMethodAdditionalFeeInclTaxInCustomerCurrency = _currencyService.ConvertCurrency(order.PaymentMethodAdditionalFeeInclTax, order.CurrencyRate);
                if (paymentMethodAdditionalFeeInclTaxInCustomerCurrency > decimal.Zero)
                {
                    model.PaymentMethodAdditionalFee = await _priceFormatter.FormatPaymentMethodAdditionalFeeAsync(paymentMethodAdditionalFeeInclTaxInCustomerCurrency, true, order.CustomerCurrencyCode, languageId, true);

                    model.PaymentMethodAdditionalFeeValue = paymentMethodAdditionalFeeInclTaxInCustomerCurrency;
                }
            }
            else
            {
                //excluding tax

                //order shipping
                var orderShippingExclTaxInCustomerCurrency = _currencyService.ConvertCurrency(order.OrderShippingExclTax, order.CurrencyRate);
                model.OrderShipping = await _priceFormatter.FormatShippingPriceAsync(orderShippingExclTaxInCustomerCurrency, true, order.CustomerCurrencyCode, languageId, false);

                model.OrderShippingValue = orderShippingExclTaxInCustomerCurrency;
                //payment method additional fee
                var paymentMethodAdditionalFeeExclTaxInCustomerCurrency = _currencyService.ConvertCurrency(order.PaymentMethodAdditionalFeeExclTax, order.CurrencyRate);
                if (paymentMethodAdditionalFeeExclTaxInCustomerCurrency > decimal.Zero)
                {
                    model.PaymentMethodAdditionalFee = await _priceFormatter.FormatPaymentMethodAdditionalFeeAsync(paymentMethodAdditionalFeeExclTaxInCustomerCurrency, true, order.CustomerCurrencyCode, languageId, false);

                    model.PaymentMethodAdditionalFeeValue = paymentMethodAdditionalFeeExclTaxInCustomerCurrency;
                }
            }

            //tax
            var displayTax      = true;
            var displayTaxRates = true;

            if (_taxSettings.HideTaxInOrderSummary && order.CustomerTaxDisplayType == TaxDisplayType.IncludingTax)
            {
                displayTax      = false;
                displayTaxRates = false;
            }
            else
            {
                if (order.OrderTax == 0 && _taxSettings.HideZeroTax)
                {
                    displayTax      = false;
                    displayTaxRates = false;
                }
                else
                {
                    var taxRates = _orderService.ParseTaxRates(order, order.TaxRates);
                    displayTaxRates = _taxSettings.DisplayTaxRates && taxRates.Any();
                    displayTax      = !displayTaxRates;

                    var orderTaxInCustomerCurrency = _currencyService.ConvertCurrency(order.OrderTax, order.CurrencyRate);
                    model.Tax = await _priceFormatter.FormatPriceAsync(orderTaxInCustomerCurrency, true, order.CustomerCurrencyCode, false, languageId);

                    foreach (var tr in taxRates)
                    {
                        model.TaxRates.Add(new OrderDetailsModel.TaxRate
                        {
                            Rate  = _priceFormatter.FormatTaxRate(tr.Key),
                            Value = await _priceFormatter.FormatPriceAsync(_currencyService.ConvertCurrency(tr.Value, order.CurrencyRate), true, order.CustomerCurrencyCode, false, languageId),
                        });
                    }
                }
            }
            model.DisplayTaxRates        = displayTaxRates;
            model.DisplayTax             = displayTax;
            model.DisplayTaxShippingInfo = _catalogSettings.DisplayTaxShippingInfoOrderDetailsPage;
            model.PricesIncludeTax       = order.CustomerTaxDisplayType == TaxDisplayType.IncludingTax;

            //discount (applied to order total)
            var orderDiscountInCustomerCurrency = _currencyService.ConvertCurrency(order.OrderDiscount, order.CurrencyRate);

            if (orderDiscountInCustomerCurrency > decimal.Zero)
            {
                model.OrderTotalDiscount = await _priceFormatter.FormatPriceAsync(-orderDiscountInCustomerCurrency, true, order.CustomerCurrencyCode, false, languageId);

                model.OrderTotalDiscountValue = orderDiscountInCustomerCurrency;
            }

            //gift cards
            foreach (var gcuh in await _giftCardService.GetGiftCardUsageHistoryAsync(order))
            {
                model.GiftCards.Add(new OrderDetailsModel.GiftCard
                {
                    CouponCode = (await _giftCardService.GetGiftCardByIdAsync(gcuh.GiftCardId)).GiftCardCouponCode,
                    Amount     = await _priceFormatter.FormatPriceAsync(-(_currencyService.ConvertCurrency(gcuh.UsedValue, order.CurrencyRate)), true, order.CustomerCurrencyCode, false, languageId),
                });
            }

            //reward points
            if (order.RedeemedRewardPointsEntryId.HasValue && await _rewardPointService.GetRewardPointsHistoryEntryByIdAsync(order.RedeemedRewardPointsEntryId.Value) is RewardPointsHistory redeemedRewardPointsEntry)
            {
                model.RedeemedRewardPoints       = -redeemedRewardPointsEntry.Points;
                model.RedeemedRewardPointsAmount = await _priceFormatter.FormatPriceAsync(-(_currencyService.ConvertCurrency(redeemedRewardPointsEntry.UsedAmount, order.CurrencyRate)), true, order.CustomerCurrencyCode, false, languageId);
            }

            //total
            var orderTotalInCustomerCurrency = _currencyService.ConvertCurrency(order.OrderTotal, order.CurrencyRate);

            model.OrderTotal = await _priceFormatter.FormatPriceAsync(orderTotalInCustomerCurrency, true, order.CustomerCurrencyCode, false, languageId);

            model.OrderTotalValue = orderTotalInCustomerCurrency;

            //checkout attributes
            model.CheckoutAttributeInfo = order.CheckoutAttributeDescription;

            //order notes
            foreach (var orderNote in (await _orderService.GetOrderNotesByOrderIdAsync(order.Id, true))
                     .OrderByDescending(on => on.CreatedOnUtc)
                     .ToList())
            {
                model.OrderNotes.Add(new OrderDetailsModel.OrderNote
                {
                    Id          = orderNote.Id,
                    HasDownload = orderNote.DownloadId > 0,
                    Note        = _orderService.FormatOrderNoteText(orderNote),
                    CreatedOn   = await _dateTimeHelper.ConvertToUserTimeAsync(orderNote.CreatedOnUtc, DateTimeKind.Utc)
                });
            }

            //purchased products
            model.ShowSku        = _catalogSettings.ShowSkuOnProductDetailsPage;
            model.ShowVendorName = _vendorSettings.ShowVendorOnOrderDetailsPage;

            var orderItems = await _orderService.GetOrderItemsAsync(order.Id);

            foreach (var orderItem in orderItems)
            {
                var product = await _productService.GetProductByIdAsync(orderItem.ProductId);

                var orderItemModel = new OrderDetailsModel.OrderItemModel
                {
                    Id            = orderItem.Id,
                    OrderItemGuid = orderItem.OrderItemGuid,
                    Sku           = await _productService.FormatSkuAsync(product, orderItem.AttributesXml),
                    VendorName    = (await _vendorService.GetVendorByIdAsync(product.VendorId))?.Name ?? string.Empty,
                    ProductId     = product.Id,
                    ProductName   = await _localizationService.GetLocalizedAsync(product, x => x.Name),
                    ProductSeName = await _urlRecordService.GetSeNameAsync(product),
                    Quantity      = orderItem.Quantity,
                    AttributeInfo = orderItem.AttributeDescription,
                };
                //rental info
                if (product.IsRental)
                {
                    var rentalStartDate = orderItem.RentalStartDateUtc.HasValue
                        ? _productService.FormatRentalDate(product, orderItem.RentalStartDateUtc.Value) : "";
                    var rentalEndDate = orderItem.RentalEndDateUtc.HasValue
                        ? _productService.FormatRentalDate(product, orderItem.RentalEndDateUtc.Value) : "";
                    orderItemModel.RentalInfo = string.Format(await _localizationService.GetResourceAsync("Order.Rental.FormattedDate"),
                                                              rentalStartDate, rentalEndDate);
                }
                model.Items.Add(orderItemModel);

                //unit price, subtotal
                if (order.CustomerTaxDisplayType == TaxDisplayType.IncludingTax)
                {
                    //including tax
                    var unitPriceInclTaxInCustomerCurrency = _currencyService.ConvertCurrency(orderItem.UnitPriceInclTax, order.CurrencyRate);
                    orderItemModel.UnitPrice = await _priceFormatter.FormatPriceAsync(unitPriceInclTaxInCustomerCurrency, true, order.CustomerCurrencyCode, languageId, true);

                    orderItemModel.UnitPriceValue = unitPriceInclTaxInCustomerCurrency;

                    var priceInclTaxInCustomerCurrency = _currencyService.ConvertCurrency(orderItem.PriceInclTax, order.CurrencyRate);
                    orderItemModel.SubTotal = await _priceFormatter.FormatPriceAsync(priceInclTaxInCustomerCurrency, true, order.CustomerCurrencyCode, languageId, true);

                    orderItemModel.SubTotalValue = priceInclTaxInCustomerCurrency;
                }
                else
                {
                    //excluding tax
                    var unitPriceExclTaxInCustomerCurrency = _currencyService.ConvertCurrency(orderItem.UnitPriceExclTax, order.CurrencyRate);
                    orderItemModel.UnitPrice = await _priceFormatter.FormatPriceAsync(unitPriceExclTaxInCustomerCurrency, true, order.CustomerCurrencyCode, languageId, false);

                    orderItemModel.UnitPriceValue = unitPriceExclTaxInCustomerCurrency;

                    var priceExclTaxInCustomerCurrency = _currencyService.ConvertCurrency(orderItem.PriceExclTax, order.CurrencyRate);
                    orderItemModel.SubTotal = await _priceFormatter.FormatPriceAsync(priceExclTaxInCustomerCurrency, true, order.CustomerCurrencyCode, languageId, false);

                    orderItemModel.SubTotalValue = priceExclTaxInCustomerCurrency;
                }

                //downloadable products
                if (await _orderService.IsDownloadAllowedAsync(orderItem))
                {
                    orderItemModel.DownloadId = product.DownloadId;
                }
                if (await _orderService.IsLicenseDownloadAllowedAsync(orderItem))
                {
                    orderItemModel.LicenseId = orderItem.LicenseDownloadId ?? 0;
                }
            }

            return(model);
        }
예제 #11
0
        /// <returns>A task that represents the asynchronous operation</returns>
        protected virtual async Task <IList <ShipStationServiceRate> > GetRatesAsync(GetShippingOptionRequest getShippingOptionRequest, string carrierCode)
        {
            var usedWeight = await _measureService.GetMeasureWeightBySystemKeywordAsync(Weight.Units);

            if (usedWeight == null)
            {
                throw new NopException("ShipStatio shipping service. Could not load \"{0}\" measure weight", Weight.Units);
            }

            var usedMeasureDimension = await _measureService.GetMeasureDimensionBySystemKeywordAsync(Dimensions.Units);

            if (usedMeasureDimension == null)
            {
                throw new NopException("ShipStatio shipping service. Could not load \"{0}\" measure dimension", Dimensions.Units);
            }

            var weight = Convert.ToInt32(Math.Ceiling(await _measureService.ConvertFromPrimaryMeasureWeightAsync(await _shippingService.GetTotalWeightAsync(getShippingOptionRequest), usedWeight)));

            var postData = new RatesRequest
            {
                CarrierCode    = carrierCode,
                FromPostalCode = getShippingOptionRequest.ZipPostalCodeFrom ?? getShippingOptionRequest.ShippingAddress.ZipPostalCode,
                ToState        = (await _stateProvinceService.GetStateProvinceByAddressAsync(getShippingOptionRequest.ShippingAddress)).Abbreviation,
                ToCountry      = (await _countryService.GetCountryByAddressAsync(getShippingOptionRequest.ShippingAddress)).TwoLetterIsoCode,
                ToPostalCode   = getShippingOptionRequest.ShippingAddress.ZipPostalCode,
                ToCity         = getShippingOptionRequest.ShippingAddress.City,
                Weight         = new Weight {
                    Value = weight
                }
            };

            if (_shipStationSettings.PassDimensions)
            {
                int length, height, width;

                decimal lengthTmp, widthTmp, heightTmp;

                switch (_shipStationSettings.PackingType)
                {
                case PackingType.PackByDimensions:
                    (widthTmp, lengthTmp, heightTmp) = await _shippingService.GetDimensionsAsync(getShippingOptionRequest.Items);

                    length = await ConvertFromPrimaryMeasureDimensionAsync(lengthTmp, usedMeasureDimension);

                    height = await ConvertFromPrimaryMeasureDimensionAsync(heightTmp, usedMeasureDimension);

                    width = await ConvertFromPrimaryMeasureDimensionAsync(widthTmp, usedMeasureDimension);

                    break;

                case PackingType.PackByVolume:
                    if (getShippingOptionRequest.Items.Count == 1 &&
                        getShippingOptionRequest.Items[0].GetQuantity() == 1)
                    {
                        var sci     = getShippingOptionRequest.Items[0].ShoppingCartItem;
                        var product = getShippingOptionRequest.Items[0].Product;

                        (widthTmp, lengthTmp, heightTmp) = await _shippingService.GetDimensionsAsync(new List <GetShippingOptionRequest.PackageItem>
                        {
                            new GetShippingOptionRequest.PackageItem(sci, product, 1)
                        });

                        length = await ConvertFromPrimaryMeasureDimensionAsync(lengthTmp, usedMeasureDimension);

                        height = await ConvertFromPrimaryMeasureDimensionAsync(lengthTmp, usedMeasureDimension);

                        width = await ConvertFromPrimaryMeasureDimensionAsync(widthTmp, usedMeasureDimension);
                    }
                    else
                    {
                        decimal totalVolume = 0;
                        foreach (var item in getShippingOptionRequest.Items)
                        {
                            var sci     = item.ShoppingCartItem;
                            var product = item.Product;

                            (widthTmp, lengthTmp, heightTmp) = await _shippingService.GetDimensionsAsync(new List <GetShippingOptionRequest.PackageItem>
                            {
                                new GetShippingOptionRequest.PackageItem(sci, product, 1)
                            });

                            var productLength = await ConvertFromPrimaryMeasureDimensionAsync(lengthTmp, usedMeasureDimension);

                            var productHeight = await ConvertFromPrimaryMeasureDimensionAsync(heightTmp, usedMeasureDimension);

                            var productWidth = await ConvertFromPrimaryMeasureDimensionAsync(widthTmp, usedMeasureDimension);

                            totalVolume += item.GetQuantity() * (productHeight * productWidth * productLength);
                        }

                        int dimension;
                        if (totalVolume == 0)
                        {
                            dimension = 0;
                        }
                        else
                        {
                            // cubic inches
                            var packageVolume = _shipStationSettings.PackingPackageVolume;
                            if (packageVolume <= 0)
                            {
                                packageVolume = 5184;
                            }

                            // cube root (floor)
                            dimension = Convert.ToInt32(Math.Floor(Math.Pow(Convert.ToDouble(packageVolume),
                                                                            1.0 / 3.0)));
                        }

                        length = width = height = dimension;
                    }

                    break;

                default:
                    length = height = width = 1;
                    break;
                }

                if (length < 1)
                {
                    length = 1;
                }
                if (height < 1)
                {
                    height = 1;
                }
                if (width < 1)
                {
                    width = 1;
                }

                postData.Dimensions = new Dimensions
                {
                    Length = length,
                    Height = height,
                    Width  = width
                };
            }

            using var client = new WebClient
                  {
                      Credentials = new NetworkCredential(_shipStationSettings.ApiKey, _shipStationSettings.ApiSecret)
                  };

            client.Headers.Add("Content-Type", CONTENT_TYPE);

            var data = client.UploadString($"{API_URL}{LIST_RATES_CMD}", JsonConvert.SerializeObject(postData));

            return((await TryGetError(data)) ? new List <ShipStationServiceRate>() : JsonConvert.DeserializeObject <List <ShipStationServiceRate> >(data));
        }
예제 #12
0
        /// <summary>
        /// Create request details to get shipping rates
        /// </summary>
        /// <param name="shippingOptionRequest">Shipping option request</param>
        /// <param name="saturdayDelivery">Whether to get rates for Saturday Delivery</param>
        /// <returns>Rate request details</returns>
        private async Task <UPSRate.RateRequest> CreateRateRequestAsync(GetShippingOptionRequest shippingOptionRequest, bool saturdayDelivery = false)
        {
            //set request details
            var request = new UPSRate.RateRequest
            {
                Request = new UPSRate.RequestType
                {
                    //used to define the request type
                    //Shop - the server validates the shipment, and returns rates for all UPS products from the ShipFrom to the ShipTo addresses
                    RequestOption = new[] { "Shop" }
                }
            };

            //prepare addresses details
            var stateCodeTo     = (await _stateProvinceService.GetStateProvinceByAddressAsync(shippingOptionRequest.ShippingAddress))?.Abbreviation;
            var stateCodeFrom   = shippingOptionRequest.StateProvinceFrom?.Abbreviation;
            var countryCodeFrom = (shippingOptionRequest.CountryFrom ?? (await _countryService.GetAllCountriesAsync()).FirstOrDefault())?.TwoLetterIsoCode ?? string.Empty;

            var addressFromDetails = new UPSRate.ShipAddressType
            {
                AddressLine       = new[] { shippingOptionRequest.AddressFrom },
                City              = shippingOptionRequest.CityFrom,
                StateProvinceCode = stateCodeFrom,
                CountryCode       = countryCodeFrom,
                PostalCode        = shippingOptionRequest.ZipPostalCodeFrom
            };
            var addressToDetails = new UPSRate.ShipToAddressType
            {
                AddressLine                 = new[] { shippingOptionRequest.ShippingAddress.Address1, shippingOptionRequest.ShippingAddress.Address2 },
                City                        = shippingOptionRequest.ShippingAddress.City,
                StateProvinceCode           = stateCodeTo,
                CountryCode                 = (await _countryService.GetCountryByAddressAsync(shippingOptionRequest.ShippingAddress))?.TwoLetterIsoCode,
                PostalCode                  = shippingOptionRequest.ShippingAddress.ZipPostalCode,
                ResidentialAddressIndicator = string.Empty
            };

            //set shipment details
            request.Shipment = new UPSRate.ShipmentType
            {
                Shipper = new UPSRate.ShipperType
                {
                    ShipperNumber = _upsSettings.AccountNumber,
                    Address       = addressFromDetails
                },
                ShipFrom = new UPSRate.ShipFromType
                {
                    Address = addressFromDetails
                },
                ShipTo = new UPSRate.ShipToType
                {
                    Address = addressToDetails
                }
            };

            //set pickup options and customer classification for US shipments
            if (countryCodeFrom.Equals("US", StringComparison.InvariantCultureIgnoreCase))
            {
                request.PickupType = new UPSRate.CodeDescriptionType
                {
                    Code = GetUpsCode(_upsSettings.PickupType)
                };
                request.CustomerClassification = new UPSRate.CodeDescriptionType
                {
                    Code = GetUpsCode(_upsSettings.CustomerClassification)
                };
            }

            //set negotiated rates details
            if (!string.IsNullOrEmpty(_upsSettings.AccountNumber) && !string.IsNullOrEmpty(stateCodeFrom) && !string.IsNullOrEmpty(stateCodeTo))
            {
                request.Shipment.ShipmentRatingOptions = new UPSRate.ShipmentRatingOptionsType
                {
                    NegotiatedRatesIndicator   = string.Empty,
                    UserLevelDiscountIndicator = string.Empty
                };
            }

            //set Saturday delivery details
            if (saturdayDelivery)
            {
                request.Shipment.ShipmentServiceOptions = new UPSRate.ShipmentServiceOptionsType
                {
                    SaturdayDeliveryIndicator = string.Empty
                };
            }

            //set packages details
            request.Shipment.Package = _upsSettings.PackingType switch
            {
                PackingType.PackByOneItemPerPackage => (await GetPackagesForOneItemPerPackageAsync(shippingOptionRequest)).ToArray(),
                PackingType.PackByVolume => (await GetPackagesByCubicRootAsync(shippingOptionRequest)).ToArray(),
                _ => (await GetPackagesByDimensionsAsync(shippingOptionRequest)).ToArray()
            };
            return(request);
        }
예제 #13
0
        /// <summary>
        /// Prepare address model
        /// </summary>
        /// <param name="model">Address model</param>
        /// <param name="address">Address entity</param>
        /// <param name="excludeProperties">Whether to exclude populating of model properties from the entity</param>
        /// <param name="addressSettings">Address settings</param>
        /// <param name="loadCountries">Countries loading function; pass null if countries do not need to load</param>
        /// <param name="prePopulateWithCustomerFields">Whether to populate model properties with the customer fields (used with the customer entity)</param>
        /// <param name="customer">Customer entity; required if prePopulateWithCustomerFields is true</param>
        /// <param name="overrideAttributesXml">Overridden address attributes in XML format; pass null to use CustomAttributes of the address entity</param>
        /// <returns>A task that represents the asynchronous operation</returns>
        public virtual async Task PrepareAddressModelAsync(AddressModel model,
                                                           Address address, bool excludeProperties,
                                                           AddressSettings addressSettings,
                                                           Func <Task <IList <Country> > > loadCountries = null,
                                                           bool prePopulateWithCustomerFields            = false,
                                                           Customer customer            = null,
                                                           string overrideAttributesXml = "")
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            if (addressSettings == null)
            {
                throw new ArgumentNullException(nameof(addressSettings));
            }

            if (!excludeProperties && address != null)
            {
                model.Id          = address.Id;
                model.FirstName   = address.FirstName;
                model.LastName    = address.LastName;
                model.Email       = address.Email;
                model.Company     = address.Company;
                model.CountryId   = address.CountryId;
                model.CountryName = await _countryService.GetCountryByAddressAsync(address) is Country country ? await _localizationService.GetLocalizedAsync(country, x => x.Name) : null;

                model.StateProvinceId   = address.StateProvinceId;
                model.StateProvinceName = await _stateProvinceService.GetStateProvinceByAddressAsync(address) is StateProvince stateProvince ? await _localizationService.GetLocalizedAsync(stateProvince, x => x.Name) : null;

                model.County        = address.County;
                model.City          = address.City;
                model.Address1      = address.Address1;
                model.Address2      = address.Address2;
                model.ZipPostalCode = address.ZipPostalCode;
                model.PhoneNumber   = address.PhoneNumber;
                model.FaxNumber     = address.FaxNumber;
            }

            if (address == null && prePopulateWithCustomerFields)
            {
                if (customer == null)
                {
                    throw new Exception("Customer cannot be null when prepopulating an address");
                }
                model.Email     = customer.Email;
                model.FirstName = await _genericAttributeService.GetAttributeAsync <string>(customer, NopCustomerDefaults.FirstNameAttribute);

                model.LastName = await _genericAttributeService.GetAttributeAsync <string>(customer, NopCustomerDefaults.LastNameAttribute);

                model.Company = await _genericAttributeService.GetAttributeAsync <string>(customer, NopCustomerDefaults.CompanyAttribute);

                model.Address1 = await _genericAttributeService.GetAttributeAsync <string>(customer, NopCustomerDefaults.StreetAddressAttribute);

                model.Address2 = await _genericAttributeService.GetAttributeAsync <string>(customer, NopCustomerDefaults.StreetAddress2Attribute);

                model.ZipPostalCode = await _genericAttributeService.GetAttributeAsync <string>(customer, NopCustomerDefaults.ZipPostalCodeAttribute);

                model.City = await _genericAttributeService.GetAttributeAsync <string>(customer, NopCustomerDefaults.CityAttribute);

                model.County = await _genericAttributeService.GetAttributeAsync <string>(customer, NopCustomerDefaults.CountyAttribute);

                model.PhoneNumber = await _genericAttributeService.GetAttributeAsync <string>(customer, NopCustomerDefaults.PhoneAttribute);

                model.FaxNumber = await _genericAttributeService.GetAttributeAsync <string>(customer, NopCustomerDefaults.FaxAttribute);
            }

            //countries and states
            if (addressSettings.CountryEnabled && loadCountries != null)
            {
                var countries = await loadCountries();

                if (_addressSettings.PreselectCountryIfOnlyOne && countries.Count == 1)
                {
                    model.CountryId = countries[0].Id;
                }
                else
                {
                    model.AvailableCountries.Add(new SelectListItem {
                        Text = await _localizationService.GetResourceAsync("Address.SelectCountry"), Value = "0"
                    });
                }

                foreach (var c in countries)
                {
                    model.AvailableCountries.Add(new SelectListItem
                    {
                        Text     = await _localizationService.GetLocalizedAsync(c, x => x.Name),
                        Value    = c.Id.ToString(),
                        Selected = c.Id == model.CountryId
                    });
                }

                if (addressSettings.StateProvinceEnabled)
                {
                    var languageId = (await _workContext.GetWorkingLanguageAsync()).Id;
                    var states     = (await _stateProvinceService
                                      .GetStateProvincesByCountryIdAsync(model.CountryId ?? 0, languageId))
                                     .ToList();
                    if (states.Any())
                    {
                        model.AvailableStates.Add(new SelectListItem {
                            Text = await _localizationService.GetResourceAsync("Address.SelectState"), Value = "0"
                        });

                        foreach (var s in states)
                        {
                            model.AvailableStates.Add(new SelectListItem
                            {
                                Text     = await _localizationService.GetLocalizedAsync(s, x => x.Name),
                                Value    = s.Id.ToString(),
                                Selected = (s.Id == model.StateProvinceId)
                            });
                        }
                    }
                    else
                    {
                        var anyCountrySelected = model.AvailableCountries.Any(x => x.Selected);
                        model.AvailableStates.Add(new SelectListItem
                        {
                            Text  = await _localizationService.GetResourceAsync(anyCountrySelected ? "Address.Other" : "Address.SelectState"),
                            Value = "0"
                        });
                    }
                }
            }

            //form fields
            model.CompanyEnabled         = addressSettings.CompanyEnabled;
            model.CompanyRequired        = addressSettings.CompanyRequired;
            model.StreetAddressEnabled   = addressSettings.StreetAddressEnabled;
            model.StreetAddressRequired  = addressSettings.StreetAddressRequired;
            model.StreetAddress2Enabled  = addressSettings.StreetAddress2Enabled;
            model.StreetAddress2Required = addressSettings.StreetAddress2Required;
            model.ZipPostalCodeEnabled   = addressSettings.ZipPostalCodeEnabled;
            model.ZipPostalCodeRequired  = addressSettings.ZipPostalCodeRequired;
            model.CityEnabled            = addressSettings.CityEnabled;
            model.CityRequired           = addressSettings.CityRequired;
            model.CountyEnabled          = addressSettings.CountyEnabled;
            model.CountyRequired         = addressSettings.CountyRequired;
            model.CountryEnabled         = addressSettings.CountryEnabled;
            model.StateProvinceEnabled   = addressSettings.StateProvinceEnabled;
            model.PhoneEnabled           = addressSettings.PhoneEnabled;
            model.PhoneRequired          = addressSettings.PhoneRequired;
            model.FaxEnabled             = addressSettings.FaxEnabled;
            model.FaxRequired            = addressSettings.FaxRequired;

            //customer attribute services
            if (_addressAttributeService != null && _addressAttributeParser != null)
            {
                await PrepareCustomAddressAttributesAsync(model, address, overrideAttributesXml);
            }
            if (_addressAttributeFormatter != null && address != null)
            {
                model.FormattedCustomAddressAttributes = await _addressAttributeFormatter.FormatAttributesAsync(address.CustomAttributes);
            }
        }
예제 #14
0
        private async Task <AuthenticationTokenResponse> FindStatusCallAsync()
        {
            var storeScope = await _storeContext.GetActiveStoreScopeConfigurationAsync();

            var paySynchronyPaymentSettings = await _settingService.LoadSettingAsync <SynchronyPaymentSettings>(storeScope);

            var cart = await _shoppingCartService.GetShoppingCartAsync(
                await _workContext.GetCurrentCustomerAsync(),
                ShoppingCartType.ShoppingCart,
                (await _storeContext.GetCurrentStoreAsync()).Id);

            var orderTotalsModel = await _shoppingCartModelFactory.PrepareOrderTotalsModelAsync(cart, false);

            string authorizationRegionStatusURL = paySynchronyPaymentSettings.Integration
                ? SynchronyPaymentConstants.DemoInquiryEndpoint
                : SynchronyPaymentConstants.LiveInquiryEndpoint;
            var merchantId        = paySynchronyPaymentSettings.MerchantId;
            var merchantPassword  = paySynchronyPaymentSettings.MerchantPassword;
            var Integration       = paySynchronyPaymentSettings.Integration;
            var token             = HttpContext.Session.GetString("token").Replace("\"", "");
            var transactionAmount = Convert.ToDecimal(orderTotalsModel.OrderTotal.Replace("$", ""));
            var model             = new AuthenticationTokenResponse();
            // take reference from below link - Answer 1  by Seema As
            // https://stackoverflow.com/questions/39190018/how-to-get-object-using-httpclient-with-response-ok-in-web-api

            var response = new HttpResponseMessage();

            using (HttpClient client = new HttpClient())
            {
                client.BaseAddress = new Uri(authorizationRegionStatusURL);
                client.DefaultRequestHeaders.Clear();
                client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
                client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0");
                ServicePointManager.Expect100Continue = true;

                var requestBody = new
                {
                    merchantNumber = merchantId,
                    password       = merchantPassword,
                    userToken      = token
                };
                string json = JsonSerializer.Serialize(requestBody);

                if (_synchronyPaymentSettings.IsDebugMode)
                {
                    await _logger.InsertLogAsync(Core.Domain.Logging.LogLevel.Debug, $"FindStatusCallAsync request - {requestBody.ToString()}");
                }

                var content = new StringContent(json.ToString(), Encoding.UTF8, "application/json");
                ServicePointManager.SecurityProtocol =
                    SecurityProtocolType.Tls13 |
                    SecurityProtocolType.Tls12 |
                    SecurityProtocolType.Tls11 |
                    SecurityProtocolType.Tls;
                response = await client.PostAsync(authorizationRegionStatusURL, content);
            }

            var authResponseJsonAsString = await response.Content.ReadAsStringAsync();

            if (_synchronyPaymentSettings.IsDebugMode)
            {
                await _logger.InsertLogAsync(Core.Domain.Logging.LogLevel.Debug, $"FindStatusCallAsync response - {authResponseJsonAsString}");
            }

            if (authResponseJsonAsString.Contains("Unauthorized"))
            {
                await _logger.ErrorAsync($"Payments.Synchrony: Failed authenticating - {authResponseJsonAsString}");

                throw new HttpRequestException("There was an error, please select another payment method.");
            }

            var authResponse = JsonSerializer.Deserialize <AuthenticationTokenResponse>(
                authResponseJsonAsString
                );

            var customer = await _workContext.GetCurrentCustomerAsync();

            var billingAddress = await _addressService.GetAddressByIdAsync(customer.BillingAddressId.Value);

            model.Integration   = Integration;
            model.MerchantId    = merchantId;
            model.clientToken   = token;
            model.transactionId = authResponse.transactionId;
            model.responseCode  = authResponse.responseCode;
            model.responseDesc  = authResponse.responseDesc;
            model.ZipCode       = billingAddress.ZipPostalCode;
            model.State         = (await _stateProvinceService.GetStateProvinceByAddressAsync(
                                       billingAddress
                                       )).Abbreviation;
            model.FirstName         = billingAddress.FirstName;
            model.City              = billingAddress.City;
            model.Address1          = billingAddress.Address1;
            model.LastName          = billingAddress.LastName;
            model.StatusCode        = authResponse.StatusCode;
            model.AccountNumber     = authResponse.AccountNumber;
            model.StatusMessage     = authResponse.StatusMessage;
            model.TransactionAmount = transactionAmount.ToString();

            model.ClientTransactionID    = authResponse.ClientTransactionID;
            model.TransactionDate        = authResponse.TransactionDate;
            model.TransactionDescription = authResponse.TransactionDescription;
            model.AuthCode   = authResponse.AuthCode;
            model.PromoCode  = authResponse.PromoCode;
            model.PostbackId = authResponse.PostbackId;

            return(model);
        }
예제 #15
0
        public async Task <IList <YahooHeaderRow> > GetYahooHeaderRowsAsync(Order order)
        {
            var result = new List <YahooHeaderRow>();

            var orderItems = await _customOrderService.GetOrderItemsAsync(order.Id);

            if (!orderItems.Any())
            {
                return(result);
            }

            var splitItems = orderItems.SplitByPickupAndShipping();
            var address    = await _addressService.GetAddressByIdAsync(order.BillingAddressId);

            var stateAbbv    = (await _stateProvinceService.GetStateProvinceByAddressAsync(address)).Abbreviation;
            var country      = (await _countryService.GetCountryByAddressAsync(address)).Name;
            var cardName     = _encryptionService.DecryptText(order.CardName, _securitySettings.EncryptionKey);
            var cardNumber   = _encryptionService.DecryptText(order.CardNumber, _securitySettings.EncryptionKey);
            var cardMonth    = _encryptionService.DecryptText(order.CardExpirationMonth, _securitySettings.EncryptionKey);
            var cardYear     = _encryptionService.DecryptText(order.CardExpirationYear, _securitySettings.EncryptionKey);
            var cardCvv2     = _encryptionService.DecryptText(order.CardCvv2, _securitySettings.EncryptionKey);
            var customValues = _paymentService.DeserializeCustomValues(order);
            var ccRefNo      = customValues != null?
                               customValues.Where(cv => cv.Key == "CC_REFNO")
                               .Select(cv => cv.Value?.ToString())
                               .FirstOrDefault() :
                                   null;

            var pickupItems = splitItems.pickupItems;

            if (pickupItems.Any())
            {
                decimal backendOrderTax, backendOrderTotal;
                CalculateValues(pickupItems, out backendOrderTax, out backendOrderTotal);

                var giftCard = await CalculateGiftCardAsync(order, backendOrderTotal);

                result.Add(new YahooHeaderRow(
                               _settings.OrderIdPrefix,
                               order,
                               address,
                               stateAbbv,
                               country,
                               cardName,
                               cardNumber,
                               cardMonth,
                               cardYear,
                               cardCvv2,
                               await _priceCalculationService.RoundPriceAsync(backendOrderTax),
                               await _priceCalculationService.RoundPriceAsync(backendOrderTotal),
                               giftCard.GiftCardCode,
                               giftCard.GiftCardUsage,
                               ccRefNo
                               ));
            }

            var shippingItems = splitItems.shippingItems;

            if (shippingItems.Any())
            {
                decimal homeDeliveryCost = 0;
                decimal shippingCost     = 0;

                homeDeliveryCost = await _homeDeliveryCostService.GetHomeDeliveryCostAsync(shippingItems);

                shippingCost = order.OrderShippingExclTax - homeDeliveryCost;

                decimal backendOrderTax, backendOrderTotal;
                CalculateValues(shippingItems, out backendOrderTax, out backendOrderTotal);

                decimal shippingTax = order.OrderShippingInclTax - order.OrderShippingExclTax;
                backendOrderTax   += shippingTax;
                backendOrderTotal += order.OrderShippingInclTax;

                var giftCard = await CalculateGiftCardAsync(order, backendOrderTotal);

                result.Add(new YahooHeaderRowShipping(
                               _settings.OrderIdPrefix,
                               order,
                               address,
                               stateAbbv,
                               country,
                               cardName,
                               cardNumber,
                               cardMonth,
                               cardYear,
                               cardCvv2,
                               await _priceCalculationService.RoundPriceAsync(backendOrderTax),
                               await _priceCalculationService.RoundPriceAsync(shippingCost),
                               await _priceCalculationService.RoundPriceAsync(homeDeliveryCost),
                               await _priceCalculationService.RoundPriceAsync(backendOrderTotal),
                               giftCard.GiftCardCode,
                               giftCard.GiftCardUsage,
                               ccRefNo
                               ));
            }

            return(result);
        }