Class SimpleTaxProvider<T1 extends TaxRequest,T2 extends TaxResponse>

java.lang.Object
com.broadleafcommerce.tax.simple.SimpleTaxProvider<T1,T2>
All Implemented Interfaces:
TaxAccessor<T1,T2>, TaxProvider<T1,T2>, org.springframework.core.Ordered

public class SimpleTaxProvider<T1 extends TaxRequest,T2 extends TaxResponse> extends Object implements TaxProvider<T1,T2>
Simple implementation of TaxProvider primarily used for estimating taxes, but can be used for providing full taxes for implementors without complex tax needs. Otherwise, a TaxProvider integrated with a 3rd party, such as Avalara, is preferred. If this simple provider is intended to be used in a live production environment, the implementor must be aware that they own the consequences of tax law and must maintain the tax configuration details. This TaxProvider can also act as a fallback tax provider when used with Circuit Breaker functionality as is the case with DefaultTaxDelegate.
Author:
Chad Harchar (charchar), Kelly Tisdell (ktisdell)
  • Field Details

  • Constructor Details

    • SimpleTaxProvider

      public SimpleTaxProvider(@NonNull @NonNull com.fasterxml.jackson.databind.ObjectMapper objectMapper, @NonNull @NonNull com.broadleafcommerce.common.extension.TypeFactory typeFactory, @NonNull @NonNull SimpleTaxProperties properties)
    • SimpleTaxProvider

      public SimpleTaxProvider(@NonNull @NonNull com.fasterxml.jackson.databind.ObjectMapper objectMapper, @NonNull @NonNull com.broadleafcommerce.common.extension.TypeFactory typeFactory, @NonNull @NonNull SimpleTaxProperties properties, @Nullable org.springframework.core.io.ResourceLoader resourceLoader)
  • Method Details

    • calculateTaxes

      @Deprecated public T2 calculateTaxes(T1 taxRequest)
      Deprecated.
      Description copied from interface: TaxAccessor
      Calculate taxes for a request that includes a list of items and address(es).
      Specified by:
      calculateTaxes in interface TaxAccessor<T1 extends TaxRequest,T2 extends TaxResponse>
      Parameters:
      taxRequest - The request for which to calculate taxes.
    • getTaxResponse

      @Deprecated protected T2 getTaxResponse(T1 taxRequest)
      Deprecated.
    • isEstimator

      public boolean isEstimator()
      Description copied from interface: TaxProvider
      Indicates (or hints) if this provider estimates taxes. This is similar to (or could be the same as) calculating taxes. This is usually a consideration where a provider prefers not to make a remote call, or where the provider can operate on limited info (e.g. just a state or province or country and not a full address).

      The default is false.

      Specified by:
      isEstimator in interface TaxProvider<T1 extends TaxRequest,T2 extends TaxResponse>
      Returns:
    • calculateTaxes

      @Deprecated public List<T2> calculateTaxes(List<T1> taxRequests, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Deprecated.
      The simple tax provider determines tax rates by looking at SimpleTaxProperties.getConfigPath(ContextInfo) or SimpleTaxProperties.getConfigJsonString(ContextInfo) and mapping it into the data structure SimpleTaxConfig. This is then used to determine the most accurate corresponding SimpleTaxRecord by the following priority, moving to the next item if no matching tax record is found:
      1. Postal code
      2. City and subdivision (i.e. state, province, or region)
      3. Subdivision (i.e. state, province, or region)
      4. Country
      Specified by:
      calculateTaxes in interface TaxAccessor<T1 extends TaxRequest,T2 extends TaxResponse>
      Parameters:
      taxRequests - The request for which to calculate taxes.
      contextInfo - Context information. May be null.
      Returns:
      The TaxResponse response containing calculated taxes.
    • getTaxConfig

      @Deprecated protected SimpleTaxRecord getTaxConfig(T1 taxRequest, TaxItem item)
      Deprecated.
      use resolveSimpleTaxConfig
      Determines the key to use for looking up tax records. This will use the tax code from the item if available. Otherwise, it will use the country code from the taxRequest address. If there is no configuration for the tax code, it will try the country code before returning the default configuration.
      Parameters:
      taxRequest - Represents a fulfillment group for tax calculations.
      item - The item to be taxed.
      Returns:
      A SimpleTaxRecord with a tax rate.
    • calculateTaxes

      public TaxCalculationResponse calculateTaxes(TaxCalculationRequest request, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: TaxAccessor
      Takes the TaxCalculationRequest and computes sales tax. The details of the tax determination are returned via the TaxCalculationResponse.
      Specified by:
      calculateTaxes in interface TaxAccessor<T1 extends TaxRequest,T2 extends TaxResponse>
      Parameters:
      request - TaxCalculationRequest, or details about what needs to be taxes
      contextInfo - The ContextInfo that determines which tenant and application are making the request
      Returns:
    • adjustTaxes

      public TaxCalculationResponse adjustTaxes(AdjustTaxTransactionRequest request, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: TaxAccessor
      For Tax Accessors that support "commitTaxes", this allows for adjustments after taxes have been committed.
      Specified by:
      adjustTaxes in interface TaxAccessor<T1 extends TaxRequest,T2 extends TaxResponse>
      Returns:
    • commitTaxes

      public CommitTaxResponse commitTaxes(CommitTaxRequest request, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: TaxAccessor
      Some TaxAccessor instances allow clients to "commit" taxes, which essentially marks them as being collected and owed to a jurisdiction or tax authority. This is basically a way of saying, "We collected this much taxes for these products... and therefore we are saving these details for reporting and remittance."
      Specified by:
      commitTaxes in interface TaxAccessor<T1 extends TaxRequest,T2 extends TaxResponse>
      Returns:
    • reverseTaxTransaction

      public ReverseTaxTransactionResponse reverseTaxTransaction(ReverseTaxTransactionRequest request, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: TaxAccessor
      For Tax Accessors that support "commitTaxes", this allows for reversal after taxes have been committed.
      Specified by:
      reverseTaxTransaction in interface TaxAccessor<T1 extends TaxRequest,T2 extends TaxResponse>
      Returns:
    • voidTaxTransaction

      public void voidTaxTransaction(VoidTransactionRequest voidTransactionRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: TaxAccessor
      Typically used in the case of full order cancellations. Completely voids a committed tax transaction.
      Specified by:
      voidTaxTransaction in interface TaxAccessor<T1 extends TaxRequest,T2 extends TaxResponse>
      Parameters:
      voidTransactionRequest - The void transaction request
      contextInfo - The ContextInfo that determines which tenant and application are making the request
    • defaultIfNoneFound

      protected SimpleTaxRecord defaultIfNoneFound(SimpleTaxConfig simpleTaxConfig)
    • getNoDefaultRateFound

      protected SimpleTaxRecord getNoDefaultRateFound()
    • populateTaxResponse

      protected void populateTaxResponse(@NonNull @NonNull TaxCalculationRequest request, @NonNull @NonNull TaxCalculationResponse response, @NonNull @NonNull SimpleTaxConfig config, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • populateTaxResponseGroup

      protected <R extends TaxCalculationRequest> void populateTaxResponseGroup(@NonNull @NonNull TaxResponseGroup taxResponseGroup, @NonNull R request, @NonNull @NonNull TaxCalculationGroup calculationGroup, @NonNull @NonNull SimpleTaxConfig config, @NonNull @NonNull javax.money.CurrencyUnit currency, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • getTaxRecord

      protected SimpleTaxRecord getTaxRecord(TaxCalculationGroup group, TaxItem item, SimpleTaxConfig config)
    • getTaxResponse

      @Deprecated protected T2 getTaxResponse(T1 taxRequest, SimpleTaxConfig config)
      Deprecated.
    • getTaxRecord

      @Deprecated protected SimpleTaxRecord getTaxRecord(T1 taxRequest, TaxItem item, SimpleTaxConfig config)
      Deprecated.
      Determines the key to use for looking up tax records. This will use the tax code from the item if available. Otherwise, it will use the country code from the taxRequest address. If there is no configuration for the tax code, it will try the country code before returning the default configuration.
      Parameters:
      taxRequest - Represents a fulfillment group for tax calculations.
      item - The item to be taxed.
      Returns:
      A SimpleTaxRecord with a tax rate.
    • isTaxExempt

      protected <R extends TaxCalculationRequest> boolean isTaxExempt(R request, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • getTaxInfo

      protected <R extends TaxCalculationRequest> TaxInfo getTaxInfo(R request, SimpleTaxRecord chosenConfig, TaxItem item, javax.money.CurrencyUnit currencyUnit, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Create and populate a TaxInfo for this TaxItem. This form will determine if the item is tax-exempt based on the given TaxCalculationRequest.
      Type Parameters:
      R - TaxCalculationRequest or a subclass.
      Parameters:
      request - The TaxCalculationRequest to process.
      chosenConfig - The SimpleTaxRecord that will provide the tax rate.
      item - The TaxItem whose tax is being calculated.
      currencyUnit - The CurrencyUnit of the tax calculation.
      contextInfo - The ContextInfo of the request.
      Returns:
      A TaxInfo calculated for the given TaxItem with the given SimpleTaxRecord.
    • getTaxInfo

      @Deprecated protected TaxInfo getTaxInfo(SimpleTaxRecord chosenConfig, TaxItem item, javax.money.CurrencyUnit currencyUnit)
      Create and populate a TaxInfo for this TaxItem.
      Parameters:
      chosenConfig - The tax config to use during calculations.
      item - The item to be taxed.
      currencyUnit - The currency of the monetary amounts.
      Returns:
      A TaxInfo with details about this TaxItem taxes.
    • getTaxInfo

      protected TaxInfo getTaxInfo(SimpleTaxRecord chosenConfig, TaxItem item, boolean taxExempt, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Create and populate a TaxInfo for this TaxItem. This overload accepts a boolean for tax-exempt status. Use getTaxInfo(TaxCalculationRequest, SimpleTaxRecord, TaxItem, CurrencyUnit, ContextInfo) to determine tax-exemption for items from the TaxRequest.
      Parameters:
      chosenConfig - The tax config to use during calculations.
      item - The item to be taxed.
      taxExempt - Indicate if the item is tax-exempt.
      contextInfo - The ContextInfo of the request.
      Returns:
      A TaxInfo calculated for the given TaxItem with the given SimpleTaxRecord.
    • calculateIncludedTax

      protected void calculateIncludedTax(javax.money.MonetaryAmount subtotal, BigDecimal rate, TaxInfo taxInfo, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Calculate tax and taxable amounts for included taxes. Included taxes are taxes that are already included in the retail price of an item.

      For example, a $10 item with a 5% included tax will have a taxable amount of $9.52, a tax amount of $0.48, to total $10.00 at checkout.

      Parameters:
      subtotal - The extended price of the item.
      rate - The tax rate
      taxInfo - The TaxInfo to hold the values calculated
      contextInfo - The ContextInfo of the request.
    • calculateExcludedTax

      protected void calculateExcludedTax(javax.money.MonetaryAmount subtotal, BigDecimal rate, TaxInfo taxInfo, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Calculate tax and taxable amounts for excluded taxes. Excluded taxes should be added to the subtotal price of an item.

      For example, a $10 item with a 5% excluded tax will have a taxable amount of $10, a tax amount of $0.50, to total $10.50 at checkout.

      Parameters:
      subtotal - The extended price of the item.
      rate - The tax rate
      taxInfo - The TaxInfo to hold the values calculated
      contextInfo - The ContextInfo of the request.
    • addTaxDetail

      protected void addTaxDetail(SimpleTaxRecord chosenConfig, TaxItem item, TaxInfo taxInfo, BigDecimal rate, boolean taxExempt)
    • determineRate

      protected BigDecimal determineRate(TaxItem item, SimpleTaxRecord chosenConfig, boolean taxExempt)
    • determineRate

      @Deprecated protected BigDecimal determineRate(TaxItem item, SimpleTaxRecord chosenConfig)
      Deprecated.
    • getTaxInfo

      @Deprecated protected TaxInfo getTaxInfo(BigDecimal rate, TaxItem item, javax.money.CurrencyUnit currencyUnit)
      Create and populate a TaxInfo for this TaxItem.
      Parameters:
      rate - The tax rate to use during calculations.
      item - The item to be taxed.
      currencyUnit - The currency of the monetary amounts.
    • lookupTaxConfig

      protected Optional<SimpleTaxRecord> lookupTaxConfig(SimpleTaxConfig simpleTaxConfig, TaxAddress toAddress)
    • lookupTaxConfig

      protected Optional<SimpleTaxRecord> lookupTaxConfig(SimpleTaxConfig simpleTaxConfig, TaxAddress toAddress, String lookupKey)
    • findByCountry

      protected Optional<SimpleTaxRecord> findByCountry(List<SimpleTaxRecord> taxTable, TaxAddress toAddress)
    • findBySubdivision

      protected Optional<SimpleTaxRecord> findBySubdivision(List<SimpleTaxRecord> taxTable, TaxAddress toAddress)
    • findByPostalCode

      protected Optional<SimpleTaxRecord> findByPostalCode(List<SimpleTaxRecord> taxTable, TaxAddress toAddress)
    • findBySubdivisionAndCity

      protected Optional<SimpleTaxRecord> findBySubdivisionAndCity(List<SimpleTaxRecord> taxTable, TaxAddress toAddress)
    • isSubdivisionMatch

      protected boolean isSubdivisionMatch(TaxAddress address, SimpleTaxRecord taxRecord)
    • getProviderId

      public final String getProviderId()
      Description copied from interface: TaxProvider
      This returns a string that is unique to identify each TaxProvider. Broadleaf implementations will use "BLC_" as a prefix. Custom implementations should NOT use this prefix.
      Specified by:
      getProviderId in interface TaxProvider<T1 extends TaxRequest,T2 extends TaxResponse>
      Returns:
    • canHandle

      public <R extends TaxCalculationRequest> boolean canHandle(R request, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: TaxProvider
      Indicates if this TaxProvider can handle requests for the given TaxCalculationRequest and ContextInfo, which can be null.
      Specified by:
      canHandle in interface TaxProvider<T1 extends TaxRequest,T2 extends TaxResponse>
      Parameters:
      request - the tax request being
      Returns:
    • resolveSimpleTaxConfig

      protected SimpleTaxConfig resolveSimpleTaxConfig(@Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • createSimpleTaxConfigFromJson

      protected SimpleTaxConfig createSimpleTaxConfigFromJson(String json)
    • createSimpleTaxConfigFromResourcePath

      protected SimpleTaxConfig createSimpleTaxConfigFromResourcePath(String resourcePath)
    • determineIsTaxIncluded

      @Deprecated protected boolean determineIsTaxIncluded(@Nullable Boolean isTaxIncludedInItemPrice, @Nullable Boolean isVATTaxAccordingToConfig)
      Deprecated.
      Use the overload that accepts a ContextInfo, determineIsTaxIncluded(Boolean, Boolean, ContextInfo).
      Returns true if either of the TaxItem.getTaxIncluded() and SimpleTaxRecord.getVat() flags are true.
      Parameters:
      isTaxIncludedInItemPrice - The isTaxIncludedInItemPrice tag of the given TaxItem
      isVATTaxAccordingToConfig - The isVATTaxAccordingToConfig flag of the chosenConfig
      Returns:
      Whether tax is included or not
    • determineIsTaxIncluded

      protected boolean determineIsTaxIncluded(@Nullable Boolean isTaxIncludedInItemPrice, @Nullable Boolean isVATTaxAccordingToConfig, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Returns true if either of the TaxItem.getTaxIncluded() and SimpleTaxRecord.getVat() flags are true.
      Parameters:
      isTaxIncludedInItemPrice - The isTaxIncludedInItemPrice tag of the given TaxItem
      isVATTaxAccordingToConfig - The isVATTaxAccordingToConfig flag of the chosenConfig
      Returns:
      Whether tax is included or not
    • putConfigInCache

      protected void putConfigInCache(@NonNull @NonNull String key, @NonNull @NonNull SimpleTaxConfig config)
      Puts the SimpleTaxConfig in a cache so that it does not have to be deserialized every time. This can be overridden to use a different cache implementation.
      Parameters:
      key - usually a combination of tenantId and applicationId or placeholders
      config -
      See Also:
    • getConfigFromCache

      @Nullable protected SimpleTaxConfig getConfigFromCache(String key)
      Fetches the SimpleTaxConfig from cache so that it does not have to be deserialized every time. This can be overridden to use a different cache implementation.
      Parameters:
      key -
      Returns:
      See Also:
    • buildCacheKey

      protected String buildCacheKey(@Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • createDefaultConfigCache

      protected Map<String,SimpleTaxConfig> createDefaultConfigCache()
      Creates a LRUMap to contain SimpleTaxConfig instances for different applications and / or tenants. Default max size of the cache is 5000. Default initial size is 10. Note that if you plan to use a different cache mechanism, you can optionally override this method to return null as it will no longer be used.
      Returns:
      See Also:
    • getOrder

      public int getOrder()
      Order this component with a low precedence. However, since we want to give others room to inject or order another component with lower precedence, this is defined as Ordered.LOWEST_PRECEDENCE minus 1000, which allows for 1000 spots to be lower precedence, if needed.
      Specified by:
      getOrder in interface org.springframework.core.Ordered
      Specified by:
      getOrder in interface TaxProvider<T1 extends TaxRequest,T2 extends TaxResponse>
      Returns:
    • validate

      public void validate(@Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: TaxProvider
      This can be used to determine if configurations, credential, and connections are correct and working properly together. This should be called by the Admin UI or other methods to simply validate whether connection and credential details are correct. If everything is working, this is a pass-through method. If something is not working, then a RuntimeException should be thrown, typically an IllegalStateException, IllegalArgumentException, or UnsupportedOperationException. This method may be invoked by a call from the Admin or other systems to ensure that the configuration is correct.
      Specified by:
      validate in interface TaxProvider<T1 extends TaxRequest,T2 extends TaxResponse>
    • getObjectMapper

      protected com.fasterxml.jackson.databind.ObjectMapper getObjectMapper()
    • getTypeFactory

      protected com.broadleafcommerce.common.extension.TypeFactory getTypeFactory()
    • getSimpleTaxProps

      protected SimpleTaxProperties getSimpleTaxProps()
    • getResourceLoader

      protected org.springframework.core.io.ResourceLoader getResourceLoader()
    • getExampleSimpleTaxConfig

      protected SimpleTaxConfig getExampleSimpleTaxConfig()
    • getDefaultSimpleTaxConfig

      protected SimpleTaxConfig getDefaultSimpleTaxConfig()
    • getDefaultConfigCache

      protected Map<String,SimpleTaxConfig> getDefaultConfigCache()