All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.broadleafcommerce.core.pricing.service.tax.provider.SimpleTaxProvider Maven / Gradle / Ivy

There is a newer version: 3.1.15-GA
Show newest version
/*
 * #%L
 * BroadleafCommerce Framework
 * %%
 * Copyright (C) 2009 - 2013 Broadleaf Commerce
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package org.broadleafcommerce.core.pricing.service.tax.provider;

import org.broadleafcommerce.common.config.domain.ModuleConfiguration;
import org.broadleafcommerce.common.persistence.EntityConfiguration;
import org.broadleafcommerce.core.order.domain.FulfillmentGroup;
import org.broadleafcommerce.core.order.domain.FulfillmentGroupFee;
import org.broadleafcommerce.core.order.domain.FulfillmentGroupItem;
import org.broadleafcommerce.core.order.domain.Order;
import org.broadleafcommerce.core.order.domain.TaxDetail;
import org.broadleafcommerce.core.order.domain.TaxType;
import org.broadleafcommerce.core.pricing.service.exception.TaxException;
import org.broadleafcommerce.profile.core.domain.Address;
import org.broadleafcommerce.profile.core.domain.Country;
import org.broadleafcommerce.profile.core.domain.State;

import java.math.BigDecimal;
import java.util.Map;

import javax.annotation.Resource;

/**
 * 

* Simple factor-based tax module that can be configured by adding rates for * specific postalCodes, city, state, or country. * *

* Through configuration, this module can be used to set a specific tax rate for items and shipping for a given postal code, * city, state, or country. * *

* Utilizes the fulfillment group's address to determine the tax location. * *

* Useful for those with very simple tax needs that want to configure rates programmatically. * * @author jfischer, brian polster * @author Phillip Verheyden (phillipuniverse) */ public class SimpleTaxProvider implements TaxProvider { protected Map itemPostalCodeTaxRateMap; protected Map itemCityTaxRateMap; protected Map itemStateTaxRateMap; protected Map itemCountryTaxRateMap; protected Map fulfillmentGroupPostalCodeTaxRateMap; protected Map fulfillmentGroupCityTaxRateMap; protected Map fulfillmentGroupStateTaxRateMap; protected Map fulfillmentGroupCountryTaxRateMap; protected Double defaultItemTaxRate; protected Double defaultFulfillmentGroupTaxRate; protected boolean taxFees; @Resource(name = "blEntityConfiguration") protected EntityConfiguration entityConfig; @Override public boolean canRespond(ModuleConfiguration config) { // this will only be executed with null module configurations return config == null; } @Override public Order calculateTaxForOrder(Order order, ModuleConfiguration config) throws TaxException { if (!order.getCustomer().isTaxExempt()) { for (FulfillmentGroup fulfillmentGroup : order.getFulfillmentGroups()) { // Set taxes on the fulfillment group items for (FulfillmentGroupItem fgItem : fulfillmentGroup.getFulfillmentGroupItems()) { if (isItemTaxable(fgItem)) { BigDecimal factor = determineItemTaxRate(fulfillmentGroup.getAddress()); if (factor != null && factor.compareTo(BigDecimal.ZERO) != 0) { TaxDetail tax; checkDetail: { for (TaxDetail detail : fgItem.getTaxes()) { if (detail.getType().equals(TaxType.COMBINED)) { tax = detail; break checkDetail; } } tax = entityConfig.createEntityInstance(TaxDetail.class.getName(), TaxDetail.class); tax.setType(TaxType.COMBINED); fgItem.getTaxes().add(tax); } tax.setRate(factor); tax.setAmount(fgItem.getTotalItemTaxableAmount().multiply(factor)); } } } for (FulfillmentGroupFee fgFee : fulfillmentGroup.getFulfillmentGroupFees()) { if (isFeeTaxable(fgFee)) { BigDecimal factor = determineItemTaxRate(fulfillmentGroup.getAddress()); if (factor != null && factor.compareTo(BigDecimal.ZERO) != 0) { TaxDetail tax; checkDetail: { for (TaxDetail detail : fgFee.getTaxes()) { if (detail.getType().equals(TaxType.COMBINED)) { tax = detail; break checkDetail; } } tax = entityConfig.createEntityInstance(TaxDetail.class.getName(), TaxDetail.class); tax.setType(TaxType.COMBINED); fgFee.getTaxes().add(tax); } tax.setRate(factor); tax.setAmount(fgFee.getAmount().multiply(factor)); } } } BigDecimal factor = determineTaxRateForFulfillmentGroup(fulfillmentGroup); if (factor != null && factor.compareTo(BigDecimal.ZERO) != 0) { TaxDetail tax; checkDetail: { for (TaxDetail detail : fulfillmentGroup.getTaxes()) { if (detail.getType().equals(TaxType.COMBINED)) { tax = detail; break checkDetail; } } tax = entityConfig.createEntityInstance(TaxDetail.class.getName(), TaxDetail.class); tax.setType(TaxType.COMBINED); fulfillmentGroup.getTaxes().add(tax); } tax.setRate(factor); tax.setAmount(fulfillmentGroup.getFulfillmentPrice().multiply(factor)); } } } return order; } @Override public Order commitTaxForOrder(Order order, ModuleConfiguration config) throws TaxException { // intentionally left blank; no tax needs to be committed as this already has the tax details on the order return order; } @Override public void cancelTax(Order order, ModuleConfiguration config) throws TaxException { // intentionally left blank; tax never got committed so it never gets cancelled } /** * Returns the taxAmount for the passed in postal code or * null if no match is found. * * @param postalCode * @return */ public Double lookupPostalCodeRate(Map postalCodeTaxRateMap, String postalCode) { if (postalCodeTaxRateMap != null && postalCode != null) { return postalCodeTaxRateMap.get(postalCode); } return null; } /** * Changes the city to upper case before checking the * configuration. * * Return null if no match is found. * * @param cityTaxRateMap, city * @return */ public Double lookupCityRate(Map cityTaxRateMap, String city) { if (cityTaxRateMap != null && city != null) { city = city.toUpperCase(); return cityTaxRateMap.get(city); } return null; } /** * Returns the taxAmount for the passed in state or * null if no match is found. * * First checks the abbreviation (uppercase) followed by the name (uppercase). * * @param stateTaxRateMap, state * @return */ public Double lookupStateRate(Map stateTaxRateMap, State state) { if (stateTaxRateMap != null && state != null && state.getAbbreviation() != null) { String stateAbbr = state.getAbbreviation().toUpperCase(); Double rate = stateTaxRateMap.get(stateAbbr); if (rate == null && state.getName() != null) { String stateName = state.getName().toUpperCase(); return stateTaxRateMap.get(stateName); } else { return rate; } } return null; } /** * Returns the taxAmount for the passed in country or * null if no match is found. * * First checks the abbreviation (uppercase) followed by the name (uppercase). * * @param countryTaxRateMap, state * @return */ public Double lookupCountryRate(Map countryTaxRateMap, Country country) { if (countryTaxRateMap != null && country != null && country.getAbbreviation() != null) { String cntryAbbr = country.getAbbreviation().toUpperCase(); Double rate = countryTaxRateMap.get(cntryAbbr); if (rate == null && country.getName() != null) { String countryName = country.getName().toUpperCase(); return countryTaxRateMap.get(countryName); } else { return rate; } } return null; } protected boolean isItemTaxable(FulfillmentGroupItem item) { return item.getOrderItem().isTaxable(); } protected boolean isFeeTaxable(FulfillmentGroupFee fee) { return fee.isTaxable(); } /** * Uses the passed in address to determine if the item is taxable. * * Checks the configured maps in order - (postal code, city, state, country) * * @param address * @return */ public BigDecimal determineItemTaxRate(Address address) { if (address != null) { Double postalCodeRate = lookupPostalCodeRate(itemPostalCodeTaxRateMap, address.getPostalCode()); if (postalCodeRate != null) { return BigDecimal.valueOf(postalCodeRate); } Double cityCodeRate = lookupCityRate(itemCityTaxRateMap, address.getCity()); if (cityCodeRate != null) { return BigDecimal.valueOf(cityCodeRate); } Double stateCodeRate = lookupStateRate(itemStateTaxRateMap, address.getState()); if (stateCodeRate != null) { return BigDecimal.valueOf(stateCodeRate); } Double countryCodeRate = lookupCountryRate(itemCountryTaxRateMap, address.getCountry()); if (countryCodeRate != null) { return BigDecimal.valueOf(countryCodeRate); } } if (defaultItemTaxRate != null) { return BigDecimal.valueOf(defaultItemTaxRate); } else { return BigDecimal.ZERO; } } /** * Uses the passed in address to determine if the item is taxable. * * Checks the configured maps in order - (postal code, city, state, country) * * @param fulfillmentGroup * @return */ public BigDecimal determineTaxRateForFulfillmentGroup(FulfillmentGroup fulfillmentGroup) { boolean isTaxable = true; if (fulfillmentGroup.isShippingPriceTaxable() != null) { isTaxable = fulfillmentGroup.isShippingPriceTaxable(); } if (isTaxable) { Address address = fulfillmentGroup.getAddress(); if (address != null) { Double postalCodeRate = lookupPostalCodeRate(fulfillmentGroupPostalCodeTaxRateMap, address.getPostalCode()); if (postalCodeRate != null) { return BigDecimal.valueOf(postalCodeRate); } Double cityCodeRate = lookupCityRate(fulfillmentGroupCityTaxRateMap, address.getCity()); if (cityCodeRate != null) { return BigDecimal.valueOf(cityCodeRate); } Double stateCodeRate = lookupStateRate(fulfillmentGroupStateTaxRateMap, address.getState()); if (stateCodeRate != null) { return BigDecimal.valueOf(stateCodeRate); } Double countryCodeRate = lookupCountryRate(fulfillmentGroupCountryTaxRateMap, address.getCountry()); if (countryCodeRate != null) { return BigDecimal.valueOf(countryCodeRate); } } if (defaultFulfillmentGroupTaxRate != null) { return BigDecimal.valueOf(defaultFulfillmentGroupTaxRate); } } return BigDecimal.ZERO; } public Map getItemPostalCodeTaxRateMap() { return itemPostalCodeTaxRateMap; } public void setItemPostalCodeTaxRateMap(Map itemPostalCodeTaxRateMap) { this.itemPostalCodeTaxRateMap = itemPostalCodeTaxRateMap; } public Map getItemCityTaxRateMap() { return itemCityTaxRateMap; } public void setItemCityTaxRateMap(Map itemCityTaxRateMap) { this.itemCityTaxRateMap = itemCityTaxRateMap; } public Map getItemStateTaxRateMap() { return itemStateTaxRateMap; } public void setItemStateTaxRateMap(Map itemStateTaxRateMap) { this.itemStateTaxRateMap = itemStateTaxRateMap; } public Map getItemCountryTaxRateMap() { return itemCountryTaxRateMap; } public void setItemCountryTaxRateMap(Map itemCountryTaxRateMap) { this.itemCountryTaxRateMap = itemCountryTaxRateMap; } public Map getFulfillmentGroupPostalCodeTaxRateMap() { return fulfillmentGroupPostalCodeTaxRateMap; } public void setFulfillmentGroupPostalCodeTaxRateMap(Map fulfillmentGroupPostalCodeTaxRateMap) { this.fulfillmentGroupPostalCodeTaxRateMap = fulfillmentGroupPostalCodeTaxRateMap; } public Map getFulfillmentGroupCityTaxRateMap() { return fulfillmentGroupCityTaxRateMap; } public void setFulfillmentGroupCityTaxRateMap(Map fulfillmentGroupCityTaxRateMap) { this.fulfillmentGroupCityTaxRateMap = fulfillmentGroupCityTaxRateMap; } public Map getFulfillmentGroupStateTaxRateMap() { return fulfillmentGroupStateTaxRateMap; } public void setFulfillmentGroupStateTaxRateMap(Map fulfillmentGroupStateTaxRateMap) { this.fulfillmentGroupStateTaxRateMap = fulfillmentGroupStateTaxRateMap; } public Map getFulfillmentGroupCountryTaxRateMap() { return fulfillmentGroupCountryTaxRateMap; } public void setFulfillmentGroupCountryTaxRateMap(Map fulfillmentGroupCountryTaxRateMap) { this.fulfillmentGroupCountryTaxRateMap = fulfillmentGroupCountryTaxRateMap; } public Double getDefaultItemTaxRate() { return defaultItemTaxRate; } public void setDefaultItemTaxRate(Double defaultItemTaxRate) { this.defaultItemTaxRate = defaultItemTaxRate; } public Double getDefaultFulfillmentGroupTaxRate() { return defaultFulfillmentGroupTaxRate; } public void setDefaultFulfillmentGroupTaxRate(Double defaultFulfillmentGroupTaxRate) { this.defaultFulfillmentGroupTaxRate = defaultFulfillmentGroupTaxRate; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy