/// <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); }
/// <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); }