Package org.broadleafcommerce.core.pricing.service.tax.provider

Source Code of org.broadleafcommerce.core.pricing.service.tax.provider.SimpleTaxProvider

/*
* #%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;

/**
* <p>
* Simple factor-based tax module that can be configured by adding rates for
* specific postalCodes, city, state, or country.
*
* <p>
* 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.
*
* <p>
* Utilizes the fulfillment group's address to determine the tax location.
*
* <p>
* 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<String, Double> itemPostalCodeTaxRateMap;
    protected Map<String, Double> itemCityTaxRateMap;
    protected Map<String, Double> itemStateTaxRateMap;
    protected Map<String, Double> itemCountryTaxRateMap;

    protected Map<String, Double> fulfillmentGroupPostalCodeTaxRateMap;
    protected Map<String, Double> fulfillmentGroupCityTaxRateMap;
    protected Map<String, Double> fulfillmentGroupStateTaxRateMap;
    protected Map<String, Double> 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<String,Double> 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<String,Double> 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<String,Double> 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<String,Double> 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<String, Double> getItemPostalCodeTaxRateMap() {
        return itemPostalCodeTaxRateMap;
    }

    public void setItemPostalCodeTaxRateMap(Map<String, Double> itemPostalCodeTaxRateMap) {
        this.itemPostalCodeTaxRateMap = itemPostalCodeTaxRateMap;
    }

    public Map<String, Double> getItemCityTaxRateMap() {
        return itemCityTaxRateMap;
    }

    public void setItemCityTaxRateMap(Map<String, Double> itemCityTaxRateMap) {
        this.itemCityTaxRateMap = itemCityTaxRateMap;
    }

    public Map<String, Double> getItemStateTaxRateMap() {
        return itemStateTaxRateMap;
    }

    public void setItemStateTaxRateMap(Map<String, Double> itemStateTaxRateMap) {
        this.itemStateTaxRateMap = itemStateTaxRateMap;
    }

    public Map<String, Double> getItemCountryTaxRateMap() {
        return itemCountryTaxRateMap;
    }

    public void setItemCountryTaxRateMap(Map<String, Double> itemCountryTaxRateMap) {
        this.itemCountryTaxRateMap = itemCountryTaxRateMap;
    }

    public Map<String, Double> getFulfillmentGroupPostalCodeTaxRateMap() {
        return fulfillmentGroupPostalCodeTaxRateMap;
    }

    public void setFulfillmentGroupPostalCodeTaxRateMap(Map<String, Double> fulfillmentGroupPostalCodeTaxRateMap) {
        this.fulfillmentGroupPostalCodeTaxRateMap = fulfillmentGroupPostalCodeTaxRateMap;
    }

    public Map<String, Double> getFulfillmentGroupCityTaxRateMap() {
        return fulfillmentGroupCityTaxRateMap;
    }

    public void setFulfillmentGroupCityTaxRateMap(Map<String, Double> fulfillmentGroupCityTaxRateMap) {
        this.fulfillmentGroupCityTaxRateMap = fulfillmentGroupCityTaxRateMap;
    }

    public Map<String, Double> getFulfillmentGroupStateTaxRateMap() {
        return fulfillmentGroupStateTaxRateMap;
    }

    public void setFulfillmentGroupStateTaxRateMap(Map<String, Double> fulfillmentGroupStateTaxRateMap) {
        this.fulfillmentGroupStateTaxRateMap = fulfillmentGroupStateTaxRateMap;
    }

    public Map<String, Double> getFulfillmentGroupCountryTaxRateMap() {
        return fulfillmentGroupCountryTaxRateMap;
    }

    public void setFulfillmentGroupCountryTaxRateMap(Map<String, Double> 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;
    }

}
TOP

Related Classes of org.broadleafcommerce.core.pricing.service.tax.provider.SimpleTaxProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.