/// <summary>
        /// Gets tax rate
        /// </summary>
        /// <param name="calculateTaxRequest">Tax calculation request</param>
        /// <returns>Tax</returns>
        public CalculateTaxResult GetTaxRate(CalculateTaxRequest calculateTaxRequest)
        {
            var result = new CalculateTaxResult();

            //choose the tax rate calculation method
            if (!_countryStateZipSettings.CountryStateZipEnabled)
            {
                //the tax rate calculation by fixed rate
                result = new CalculateTaxResult
                {
                    TaxRate = _settingService.GetSettingByKey <decimal>(string.Format("Tax.TaxProvider.FixedOrByCountryStateZip.TaxCategoryId{0}", calculateTaxRequest.TaxCategoryId))
                };
            }
            else
            {
                //the tax rate calculation by country & state & zip

                if (calculateTaxRequest.Address == null)
                {
                    result.Errors.Add("Address is not set");
                    return(result);
                }

                //first, load all tax rate records (cached) - loaded only once
                var allTaxRates = GetAllTaxRates()
                                  .Select(x => new TaxRateForCaching
                {
                    Id              = x.Id,
                    StoreId         = x.StoreId,
                    TaxCategoryId   = x.TaxCategoryId,
                    CountryId       = x.CountryId,
                    StateProvinceId = x.StateProvinceId,
                    Zip             = x.Zip,
                    Percentage      = x.Percentage
                }
                                          )
                                  .ToList();

                var storeId         = _storeContext.CurrentStore.Id;
                var taxCategoryId   = calculateTaxRequest.TaxCategoryId;
                var countryId       = calculateTaxRequest.Address.Country != null ? calculateTaxRequest.Address.Country.Id : 0;
                var stateProvinceId = calculateTaxRequest.Address.StateProvince != null
                    ? calculateTaxRequest.Address.StateProvince.Id
                    : 0;
                var zip = calculateTaxRequest.Address.ZipPostalCode;

                if (zip == null)
                {
                    zip = string.Empty;
                }
                zip = zip.Trim();

                var existingRates = allTaxRates.Where(taxRate => taxRate.CountryId == countryId && taxRate.TaxCategoryId == taxCategoryId).ToList();

                //filter by store
                //first, find by a store ID
                var matchedByStore = existingRates.Where(taxRate => storeId == taxRate.StoreId).ToList();

                //not found? use the default ones (ID == 0)
                if (!matchedByStore.Any())
                {
                    matchedByStore.AddRange(existingRates.Where(taxRate => taxRate.StoreId == 0));
                }

                //filter by state/province
                //first, find by a state ID
                var matchedByStateProvince = matchedByStore.Where(taxRate => stateProvinceId == taxRate.StateProvinceId).ToList();

                //not found? use the default ones (ID == 0)
                if (!matchedByStateProvince.Any())
                {
                    matchedByStateProvince.AddRange(matchedByStore.Where(taxRate => taxRate.StateProvinceId == 0));
                }

                //filter by zip
                var matchedByZip = matchedByStateProvince.Where(taxRate => (string.IsNullOrEmpty(zip) && string.IsNullOrEmpty(taxRate.Zip)) || zip.Equals(taxRate.Zip, StringComparison.InvariantCultureIgnoreCase)).ToList();
                if (!matchedByZip.Any())
                {
                    matchedByZip.AddRange(matchedByStateProvince.Where(taxRate => string.IsNullOrWhiteSpace(taxRate.Zip)));
                }

                if (matchedByZip.Any())
                {
                    result.TaxRate = matchedByZip[0].Percentage;
                }
            }
            return(result);
        }
예제 #2
0
        /// <summary>
        /// Create request for tax calculation
        /// </summary>
        /// <param name="product">Product</param>
        /// <param name="taxCategoryId">Tax category identifier</param>
        /// <param name="customer">Customer</param>
        /// <param name="price">Price</param>
        /// <returns>Package for tax calculation</returns>
        protected virtual CalculateTaxRequest CreateCalculateTaxRequest(Product product, int taxCategoryId, Customer customer, decimal price)
        {
            if (customer == null)
            {
                throw new ArgumentNullException("customer");
            }

            var calculateTaxRequest = new CalculateTaxRequest
            {
                Customer      = customer,
                Product       = product,
                Price         = price,
                TaxCategoryId = taxCategoryId > 0 ? taxCategoryId : (product != null ? product.TaxCategoryId : 0)
            };

            var basedOn = _taxSettings.TaxBasedOn;

            //new EU VAT rules starting January 1st 2015
            //find more info at http://ec.europa.eu/taxation_customs/taxation/vat/how_vat_works/telecom/index_en.htm#new_rules
            var overridenBasedOn = _taxSettings.EuVatEnabled &&                                                         //EU VAT enabled?
                                   product != null && product.IsTelecommunicationsOrBroadcastingOrElectronicServices && //telecommunications, broadcasting and electronic services?
                                   DateTime.UtcNow > new DateTime(2015, 1, 1, 0, 0, 0, DateTimeKind.Utc) &&             //January 1st 2015 passed?
                                   IsEuConsumer(customer);                                                              //Europe Union consumer?

            if (overridenBasedOn)
            {
                //We must charge VAT in the EU country where the customer belongs (not where the business is based)
                basedOn = TaxBasedOn.BillingAddress;
            }

            //tax is based on pickup point address
            if (!overridenBasedOn && _taxSettings.TaxBasedOnPickupPointAddress && _shippingSettings.AllowPickUpInStore)
            {
                var pickupPoint = customer.GetAttribute <PickupPoint>(SystemCustomerAttributeNames.SelectedPickupPoint, _genericAttributeService, _storeContext.CurrentStore.Id);
                if (pickupPoint != null)
                {
                    var country = _countryService.GetCountryByTwoLetterIsoCode(pickupPoint.CountryCode);
                    var state   = _stateProvinceService.GetStateProvinceByAbbreviation(pickupPoint.StateAbbreviation);

                    calculateTaxRequest.Address = new Address
                    {
                        Address1        = pickupPoint.Address,
                        City            = pickupPoint.City,
                        Country         = country,
                        CountryId       = country.Return(c => c.Id, 0),
                        StateProvince   = state,
                        StateProvinceId = state.Return(sp => sp.Id, 0),
                        ZipPostalCode   = pickupPoint.ZipPostalCode,
                        CreatedOnUtc    = DateTime.UtcNow
                    };

                    return(calculateTaxRequest);
                }
            }

            if (basedOn == TaxBasedOn.BillingAddress && customer.BillingAddress == null ||
                basedOn == TaxBasedOn.ShippingAddress && customer.ShippingAddress == null)
            {
                basedOn = TaxBasedOn.DefaultAddress;
            }

            switch (basedOn)
            {
            case TaxBasedOn.BillingAddress:
                calculateTaxRequest.Address = customer.BillingAddress;
                break;

            case TaxBasedOn.ShippingAddress:
                calculateTaxRequest.Address = customer.ShippingAddress;
                break;

            case TaxBasedOn.DefaultAddress:
            default:
                calculateTaxRequest.Address = _addressService.GetAddressById(_taxSettings.DefaultTaxAddressId);
                break;
            }

            return(calculateTaxRequest);
        }