コード例 #1
0
        /// <summary>
        /// Install the plugin
        /// </summary>
        /// <returns>A task that represents the asynchronous operation</returns>
        public override async Task InstallAsync()
        {
            //sample pickup point
            var country = await _countryService.GetCountryByThreeLetterIsoCodeAsync("USA");

            var state = await _stateProvinceService.GetStateProvinceByAbbreviationAsync("NY", country?.Id);

            var address = new Address
            {
                Address1        = "21 West 52nd Street",
                City            = "New York",
                CountryId       = country?.Id,
                StateProvinceId = state?.Id,
                ZipPostalCode   = "10021",
                CreatedOnUtc    = DateTime.UtcNow
            };
            await _addressService.InsertAddressAsync(address);

            var pickupPoint = new StorePickupPoint
            {
                Name         = "New York store",
                AddressId    = address.Id,
                OpeningHours = "10.00 - 19.00",
                PickupFee    = 1.99m
            };
            await _storePickupPointService.InsertStorePickupPointAsync(pickupPoint);

            //locales
            await _localizationService.AddOrUpdateLocaleResourceAsync(new Dictionary <string, string>
            {
                ["Plugins.Pickup.PickupInStore.AddNew"]                                      = "Add a new pickup point",
                ["Plugins.Pickup.PickupInStore.Fields.Description"]                          = "Description",
                ["Plugins.Pickup.PickupInStore.Fields.Description.Hint"]                     = "Specify a description of the pickup point.",
                ["Plugins.Pickup.PickupInStore.Fields.DisplayOrder"]                         = "Display order",
                ["Plugins.Pickup.PickupInStore.Fields.DisplayOrder.Hint"]                    = "Specify the pickup point display order.",
                ["Plugins.Pickup.PickupInStore.Fields.Latitude"]                             = "Latitude",
                ["Plugins.Pickup.PickupInStore.Fields.Latitude.Hint"]                        = "Specify a latitude (DD.dddddddd°).",
                ["Plugins.Pickup.PickupInStore.Fields.Latitude.InvalidPrecision"]            = "Precision should be less then 8",
                ["Plugins.Pickup.PickupInStore.Fields.Latitude.InvalidRange"]                = "Latitude should be in range -90 to 90",
                ["Plugins.Pickup.PickupInStore.Fields.Latitude.IsNullWhenLongitudeHasValue"] = "Latitude and Longitude should be specify together",
                ["Plugins.Pickup.PickupInStore.Fields.Longitude"]                            = "Longitude",
                ["Plugins.Pickup.PickupInStore.Fields.Longitude.Hint"]                       = "Specify a longitude (DD.dddddddd°).",
                ["Plugins.Pickup.PickupInStore.Fields.Longitude.InvalidPrecision"]           = "Precision should be less then 8",
                ["Plugins.Pickup.PickupInStore.Fields.Longitude.InvalidRange"]               = "Longitude should be in range -180 to 180",
                ["Plugins.Pickup.PickupInStore.Fields.Longitude.IsNullWhenLatitudeHasValue"] = "Latitude and Longitude should be specify together",
                ["Plugins.Pickup.PickupInStore.Fields.Name"]                                 = "Name",
                ["Plugins.Pickup.PickupInStore.Fields.Name.Hint"]                            = "Specify a name of the pickup point.",
                ["Plugins.Pickup.PickupInStore.Fields.OpeningHours"]                         = "Opening hours",
                ["Plugins.Pickup.PickupInStore.Fields.OpeningHours.Hint"]                    = "Specify opening hours of the pickup point (Monday - Friday: 09:00 - 19:00 for example).",
                ["Plugins.Pickup.PickupInStore.Fields.PickupFee"]                            = "Pickup fee",
                ["Plugins.Pickup.PickupInStore.Fields.PickupFee.Hint"]                       = "Specify a fee for the shipping to the pickup point.",
                ["Plugins.Pickup.PickupInStore.Fields.Store"]                                = "Store",
                ["Plugins.Pickup.PickupInStore.Fields.Store.Hint"]                           = "A store name for which this pickup point will be available.",
                ["Plugins.Pickup.PickupInStore.Fields.TransitDays"]                          = "Transit days",
                ["Plugins.Pickup.PickupInStore.Fields.TransitDays.Hint"]                     = "The number of days of delivery of the goods to pickup point.",
                ["Plugins.Pickup.PickupInStore.NoPickupPoints"]                              = "No pickup points are available"
            });

            await base.InstallAsync();
        }
コード例 #2
0
        /// <summary>
        /// Gets or sets a pickup point address for tax calculation
        /// </summary>
        /// <param name="pickupPoint">Pickup point</param>
        /// <returns>
        /// A task that represents the asynchronous operation
        /// The task result contains the address
        /// </returns>
        protected virtual async Task <Address> LoadPickupPointTaxAddressAsync(PickupPoint pickupPoint)
        {
            if (pickupPoint == null)
            {
                throw new ArgumentNullException(nameof(pickupPoint));
            }

            var country = await _countryService.GetCountryByTwoLetterIsoCodeAsync(pickupPoint.CountryCode);

            var state = await _stateProvinceService.GetStateProvinceByAbbreviationAsync(pickupPoint.StateAbbreviation, country?.Id);

            return(new Address
            {
                CountryId = country?.Id ?? 0,
                StateProvinceId = state?.Id ?? 0,
                County = pickupPoint.County,
                City = pickupPoint.City,
                Address1 = pickupPoint.Address,
                ZipPostalCode = pickupPoint.ZipPostalCode
            });
        }
コード例 #3
0
        /// <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));
        }
コード例 #4
0
        /// <summary>
        /// Prepares the checkout pickup points model
        /// </summary>
        /// <param name="cart">Cart</param>
        /// <returns>
        /// A task that represents the asynchronous operation
        /// The task result contains the checkout pickup points model
        /// </returns>
        protected virtual async Task <CheckoutPickupPointsModel> PrepareCheckoutPickupPointsModelAsync(IList <ShoppingCartItem> cart)
        {
            var model = new CheckoutPickupPointsModel
            {
                AllowPickupInStore = _shippingSettings.AllowPickupInStore
            };

            if (!model.AllowPickupInStore)
            {
                return(model);
            }

            model.DisplayPickupPointsOnMap = _shippingSettings.DisplayPickupPointsOnMap;
            model.GoogleMapsApiKey         = _shippingSettings.GoogleMapsApiKey;
            var pickupPointProviders = await _pickupPluginManager.LoadActivePluginsAsync(await _workContext.GetCurrentCustomerAsync(), (await _storeContext.GetCurrentStoreAsync()).Id);

            if (pickupPointProviders.Any())
            {
                var languageId           = (await _workContext.GetWorkingLanguageAsync()).Id;
                var pickupPointsResponse = await _shippingService.GetPickupPointsAsync((await _workContext.GetCurrentCustomerAsync()).BillingAddressId ?? 0,
                                                                                       await _workContext.GetCurrentCustomerAsync(), storeId : (await _storeContext.GetCurrentStoreAsync()).Id);

                if (pickupPointsResponse.Success)
                {
                    model.PickupPoints = await pickupPointsResponse.PickupPoints.SelectAwait(async point =>
                    {
                        var country = await _countryService.GetCountryByTwoLetterIsoCodeAsync(point.CountryCode);
                        var state   = await _stateProvinceService.GetStateProvinceByAbbreviationAsync(point.StateAbbreviation, country?.Id);

                        var pickupPointModel = new CheckoutPickupPointModel
                        {
                            Id                 = point.Id,
                            Name               = point.Name,
                            Description        = point.Description,
                            ProviderSystemName = point.ProviderSystemName,
                            Address            = point.Address,
                            City               = point.City,
                            County             = point.County,
                            StateName          = state != null ? await _localizationService.GetLocalizedAsync(state, x => x.Name, languageId) : string.Empty,
                            CountryName        = country != null ? await _localizationService.GetLocalizedAsync(country, x => x.Name, languageId) : string.Empty,
                            ZipPostalCode      = point.ZipPostalCode,
                            Latitude           = point.Latitude,
                            Longitude          = point.Longitude,
                            OpeningHours       = point.OpeningHours
                        };

                        var cart   = await _shoppingCartService.GetShoppingCartAsync(await _workContext.GetCurrentCustomerAsync(), ShoppingCartType.ShoppingCart, (await _storeContext.GetCurrentStoreAsync()).Id);
                        var amount = await _orderTotalCalculationService.IsFreeShippingAsync(cart) ? 0 : point.PickupFee;

                        if (amount > 0)
                        {
                            (amount, _) = await _taxService.GetShippingPriceAsync(amount, await _workContext.GetCurrentCustomerAsync());
                            amount      = await _currencyService.ConvertFromPrimaryStoreCurrencyAsync(amount, await _workContext.GetWorkingCurrencyAsync());
                            pickupPointModel.PickupFee = await _priceFormatter.FormatShippingPriceAsync(amount, true);
                        }

                        //adjust rate
                        var(shippingTotal, _) = await _orderTotalCalculationService.AdjustShippingRateAsync(point.PickupFee, cart, true);
                        var(rateBase, _)      = await _taxService.GetShippingPriceAsync(shippingTotal, await _workContext.GetCurrentCustomerAsync());
                        var rate = await _currencyService.ConvertFromPrimaryStoreCurrencyAsync(rateBase, await _workContext.GetWorkingCurrencyAsync());
                        pickupPointModel.PickupFee = await _priceFormatter.FormatShippingPriceAsync(rate, true);

                        return(pickupPointModel);
                    }).ToListAsync();
                }
                else
                {
                    foreach (var error in pickupPointsResponse.Errors)
                    {
                        model.Warnings.Add(error);
                    }
                }
            }

            //only available pickup points
            var shippingProviders = await _shippingPluginManager.LoadActivePluginsAsync(await _workContext.GetCurrentCustomerAsync(), (await _storeContext.GetCurrentStoreAsync()).Id);

            if (!shippingProviders.Any())
            {
                if (!pickupPointProviders.Any())
                {
                    model.Warnings.Add(await _localizationService.GetResourceAsync("Checkout.ShippingIsNotAllowed"));
                    model.Warnings.Add(await _localizationService.GetResourceAsync("Checkout.PickupPoints.NotAvailable"));
                }
                model.PickupInStoreOnly = true;
                model.PickupInStore     = true;
                return(model);
            }

            return(model);
        }