Class DefaultPriceInfoService

java.lang.Object
com.broadleafcommerce.pricing.service.DefaultPriceInfoService
All Implemented Interfaces:
PriceInfoService

public class DefaultPriceInfoService extends Object implements PriceInfoService
Author:
Chad Harchar (charchar), Nathan Moore (nathanmoore)
  • Field Details

    • DEFAULT_PRICE_DETAIL_COMPARATOR

      protected static final Comparator<com.broadleafcommerce.pricing.client.domain.PriceDetailComparable> DEFAULT_PRICE_DETAIL_COMPARATOR
    • DEFAULT_PRICE_LIST_TYPES

      protected static final List<String> DEFAULT_PRICE_LIST_TYPES
  • Constructor Details

    • DefaultPriceInfoService

      public DefaultPriceInfoService(PriceDataService<PriceData> priceDataService, com.broadleafcommerce.rulesengine.expression.service.RuleEvaluationService ruleEvaluationService, PriceableFieldProperties priceableFields, PriceListService<PriceList> priceListService, com.broadleafcommerce.data.tracking.core.mapping.validation.EntityValidator validator, com.broadleafcommerce.common.extension.TypeFactory typeFactory)
  • Method Details

    • getPriceDetailComparator

      protected Comparator<com.broadleafcommerce.pricing.client.domain.PriceDetailComparable> getPriceDetailComparator()
      Retrieves priceDetailComparator if not null; else, DEFAULT_PRICE_DETAIL_COMPARATOR.
      Returns:
      priceDetailComparator if not null; else, DEFAULT_PRICE_DETAIL_COMPARATOR.
    • retrievePriceInfosByPriceContext

      @Transactional("pricingTransactionManager") public org.springframework.data.domain.Page<com.broadleafcommerce.pricing.client.domain.PriceInfo> retrievePriceInfosByPriceContext(com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, com.broadleafcommerce.pricing.client.domain.context.PriceContext priceContext, com.broadleafcommerce.pricing.client.domain.context.PriceInfoContext priceInfoContext)
      Description copied from interface: PriceInfoService

      First retrieves the PriceListRefs for the PriceContext then retrieves the PriceInfo associated thereto.

      Calls PriceInfoService.retrievePriceInfosByPriceLists(ContextInfo, PriceInfoContext)

      Specified by:
      retrievePriceInfosByPriceContext in interface PriceInfoService
    • updateContextInfoCurrency

      protected void updateContextInfoCurrency(List<PriceList> priceLists, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • retrievePriceInfosByPriceLists

      public org.springframework.data.domain.Page<com.broadleafcommerce.pricing.client.domain.PriceInfo> retrievePriceInfosByPriceLists(com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, com.broadleafcommerce.pricing.client.domain.context.PriceInfoContext priceInfoContext)
      Description copied from interface: PriceInfoService
      Retrieves PriceData for the provided PriceInfoContext.getPriceLists() and PriceInfoContext.getPriceableTargets(), then translates them into a list of PriceInfo.
      Specified by:
      retrievePriceInfosByPriceLists in interface PriceInfoService
    • retrievePriceInfosByPriceLists

      protected org.springframework.data.domain.Page<com.broadleafcommerce.pricing.client.domain.PriceInfo> retrievePriceInfosByPriceLists(com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, com.broadleafcommerce.pricing.client.domain.context.PriceInfoContext priceInfoContext, List<PriceList> priceLists)
    • modifyPriceContext

      protected void modifyPriceContext(com.broadleafcommerce.pricing.client.domain.context.PriceContext priceContext)
      Extend this if you want to modify the provided price context, for example removing certain attributes for security reasons. Left blank by default.
    • prepareEligiblePriceLists

      protected List<PriceList> prepareEligiblePriceLists(com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, com.broadleafcommerce.pricing.client.domain.context.PriceInfoContext priceInfoContext)
      Reads all priceLists that are in scope for the priceInfo request and splits them in
      Parameters:
      contextInfo -
      priceInfoContext -
      Returns:
    • splitPriceListsByType

      protected Map<String,List<PriceList>> splitPriceListsByType(List<PriceList> priceLists)
    • getPriceListTypes

      protected List<String> getPriceListTypes()
    • getPriceListAndTargetPriceDataMap

      protected Map<org.apache.commons.lang3.tuple.Pair<String,com.broadleafcommerce.pricing.client.domain.PriceableTargetRef>,PriceData> getPriceListAndTargetPriceDataMap(com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, Set<com.broadleafcommerce.pricing.client.domain.PriceableTarget> priceableTargets, List<PriceList> priceLists)
    • getPriceKey

      protected String getPriceKey(String type)
    • putPricesForType

      protected void putPricesForType(com.broadleafcommerce.pricing.client.domain.PriceableTarget target, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, Map<String,List<PriceList>> listsByType, String type, PriceableTargetPriceState priceState)
    • getPriceFromListForTarget

      @NonNull @Deprecated(forRemoval=true, since="1.7.14, 2.0.1") protected Optional<javax.money.MonetaryAmount> getPriceFromListForTarget(com.broadleafcommerce.pricing.client.domain.PriceableTarget target, PriceList priceList, PriceableTargetPriceState priceState, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Deprecated, for removal: This API element is subject to removal in a future version.
    • getPriceDetailFromListForTarget

      @NonNull protected Optional<PriceListPriceDetail> getPriceDetailFromListForTarget(com.broadleafcommerce.pricing.client.domain.PriceableTarget target, PriceList priceList, PriceableTargetPriceState priceState, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      1. Checks for PriceData for the PriceableTarget
      2. If none, checks for PriceModifiers
      3. If none, works up the PriceList hierarchy look for #1 or #2.
      4. If still none, checks for custom logic to get the price from somewhere else (getPriceFromElsewhere(PriceableTarget, PriceList, ContextInfo))
      5. If still none, returns the PriceableFieldProperties.getBasePrice() (also see PriceableFieldType.BASE_PRICE
    • populatePriceDetailFromSummary

      protected void populatePriceDetailFromSummary(@NonNull @NonNull PriceListPriceDetail priceDetail, @NonNull @NonNull PriceSummary summary)
      Populates fields onto a PriceListPriceDetail from a PriceSummary.
      Parameters:
      priceDetail - Price detail to populate
      summary - Source of price details
      Since:
      Pricing Service 2.1.0, Release Train 2.2.0
    • convertPriceListsToPriceListIds

      protected List<String> convertPriceListsToPriceListIds(Collection<PriceList> priceLists)
    • getPriceFromPriceData

      @Deprecated(since="Pricing Service 2.1.0", forRemoval=true) protected Optional<javax.money.MonetaryAmount> getPriceFromPriceData(com.broadleafcommerce.pricing.client.domain.PriceableTarget target, String priceListId, PriceableTargetPriceState priceState)
      Deprecated, for removal: This API element is subject to removal in a future version.
      Use getPriceSummaryFromPriceData(PriceableTarget, String, PriceableTargetPriceState). This will return new fields for recurring and usage prices rather than a singel price.
      Gets the price from a matching price data.

      For a PriceableTarget that has a vendorRef, if the exact match of target's type, id, and vendorRef cannot be found, it will fall back to a price data that has only has the match of target's type and id with null vendorRef. If both price data exist, then the exact match takes precedence.

      Parameters:
      target - the PriceableTarget to match
      priceListId - the PriceList.getId() to look for
      priceState - the current PriceableTargetPriceState
      Returns:
      an Optional of the price found.
    • getPriceSummaryFromPriceData

      protected Optional<PriceSummary> getPriceSummaryFromPriceData(com.broadleafcommerce.pricing.client.domain.PriceableTarget target, String priceListId, PriceableTargetPriceState priceState)
      Gets the PriceSummary from a matching PriceData.

      For a PriceableTarget that has a vendorRef, if the exact match of target's type, id, and vendorRef cannot be found, it will fall back to a price data that has only has the match of target's type and id with null vendorRef. If both price data exist, then the exact match takes precedence.

      Parameters:
      target - the PriceableTarget to match
      priceListId - the PriceList.getId() to look for
      priceState - the current PriceableTargetPriceState
      Returns:
      an Optional<PriceSummary>.
    • priceDataMatchesTarget

      protected boolean priceDataMatchesTarget(@NonNull @NonNull com.broadleafcommerce.pricing.client.domain.PriceableTarget target, @NonNull @NonNull PriceData priceData, @NonNull @NonNull PriceableTargetPriceState priceState)
      Compares the terms and characteristics of the priceData to those requested on the target to ensure it matches. The priceData should already match the target's id and type by this point.
      Parameters:
      target - The requested target to be priced
      priceData - The potential PriceData matching the target
      Returns:
      Whether priceData matches the terms and characteristics on the target.
      Since:
      Pricing Service 2.1.0, Release Train 2.2.0
    • targetsAreEquivalent

      protected boolean targetsAreEquivalent(@NonNull @NonNull com.broadleafcommerce.pricing.client.domain.BasePriceableTarget a, @NonNull @NonNull com.broadleafcommerce.pricing.client.domain.BasePriceableTarget b)
      Method allowing comparisons between BasePriceableTargets using only core fields—ignores vendor ref.
      Parameters:
      a - The first target.
      b - The other target.
      Returns:
      Whether the targets are equal when comparing core fields.
    • areCharacteristicsEquivalent

      protected boolean areCharacteristicsEquivalent(@NonNull @NonNull com.broadleafcommerce.pricing.client.domain.BasePriceableTarget a, @NonNull @NonNull com.broadleafcommerce.pricing.client.domain.BasePriceableTarget b)
    • getFallbackPriceData

      protected Optional<PriceData> getFallbackPriceData(com.broadleafcommerce.pricing.client.domain.PriceableTargetRef targetRef, String priceListId, PriceableTargetPriceState priceState)
    • buildSummaryFromPriceData

      protected PriceSummary buildSummaryFromPriceData(@NonNull @NonNull com.broadleafcommerce.pricing.client.domain.PriceableTarget target, @NonNull @NonNull PriceData data)
      Builds a PriceSummary of data. This was introduced along with the new fields for recurring and usage prices.
      Parameters:
      target - The requested target to be priced
      data - The PriceData matching the target
      Returns:
      A PriceSummary of the data that matched target
      Since:
      Pricing Service 2.1.0, Release Train 2.2.0
      See Also:
    • determineMaxTier

      protected Optional<PriceDataTier> determineMaxTier(com.broadleafcommerce.pricing.client.domain.PriceableTarget priceableTarget, List<PriceDataTier> priceDataTiers)
    • getPriceFromModifier

      protected Optional<javax.money.MonetaryAmount> getPriceFromModifier(com.broadleafcommerce.pricing.client.domain.PriceableTarget target, PriceList priceList, PriceableTargetPriceState priceState, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • getPriceModifierForTarget

      protected Optional<PriceModifier> getPriceModifierForTarget(com.broadleafcommerce.pricing.client.domain.PriceableTarget target, PriceList priceList, PriceableTargetPriceState priceState, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • modifyPrice

      protected javax.money.MonetaryAmount modifyPrice(javax.money.MonetaryAmount baseAmount, PriceModifier priceModifier)
      Performs the PriceModifier.getModificationType() on the base price.
    • performOtherOperation

      protected javax.money.MonetaryAmount performOtherOperation(String modificationType, BigDecimal modificationAmount, javax.money.MonetaryAmount baseAmount)
      Extension point for performing custom PriceModifier operations
    • getPriceFromElsewhere

      protected Optional<javax.money.MonetaryAmount> getPriceFromElsewhere(com.broadleafcommerce.pricing.client.domain.PriceableTarget target, PriceList priceList, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Extension point for getting a PriceSummary from somewhere other than a PriceData or PriceList.getPriceModifier().
      See Also:
    • getPriceSummaryFromElsewhere

      protected Optional<PriceSummary> getPriceSummaryFromElsewhere(com.broadleafcommerce.pricing.client.domain.PriceableTarget target, PriceList priceList, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Extension point for getting a PriceSummary from somewhere other than a PriceData or PriceList.getPriceModifier().
      Since:
      Pricing Service 2.1.0, Release Train 2.2.0
    • getTargetsBaseDetails

      @NonNull protected Map<String,com.broadleafcommerce.pricing.client.domain.PriceDetail> getTargetsBaseDetails(@NonNull @NonNull @NonNull com.broadleafcommerce.pricing.client.domain.PriceableTarget target, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Builds a map of PriceDetails for each field of PriceableTarget.getPriceableFields() where the key is the type.
      Parameters:
      target - The PriceableTarget
      contextInfo - Additional tenant and sandbox info
      Returns:
      A map of PriceDetails for each field of target#priceableFields where the key is the type.
    • addBasePriceDetail

      @Deprecated protected void addBasePriceDetail(com.broadleafcommerce.pricing.client.domain.PriceableTarget target, PriceableTargetPriceState priceState, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • addBaseCostPriceDetail

      @Deprecated protected void addBaseCostPriceDetail(com.broadleafcommerce.pricing.client.domain.PriceableTarget target, PriceableTargetPriceState priceState, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • getBasePrice

      @Nullable protected javax.money.MonetaryAmount getBasePrice(com.broadleafcommerce.pricing.client.domain.PriceableTarget target, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • getBaseCost

      @Nullable protected javax.money.MonetaryAmount getBaseCost(com.broadleafcommerce.pricing.client.domain.PriceableTarget target, com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • putBestPriceForType

      protected void putBestPriceForType(String type, String priceKey, PriceableTargetPriceState priceState)
      Records the highest-priority best (lowest) price for the price list type out of all the matches found.
    • formatPrice

      protected String formatPrice(javax.money.MonetaryAmount price)
      Helper method to format a MonetaryAmount as a price string
    • getBestPriceForType

      @Deprecated protected Optional<com.broadleafcommerce.pricing.client.domain.PriceDetail> getBestPriceForType(Map<PriceList,javax.money.MonetaryAmount> pricesMap)
      Deprecated.
      in favor of getBestPriceFromPriceLists(Map) in order to hold & pass on more details than just MonetaryAmount.
    • getBestPriceFromPriceLists

      protected Optional<com.broadleafcommerce.pricing.client.domain.PriceDetail> getBestPriceFromPriceLists(Map<PriceList,PriceListPriceDetail> priceListPriceDetailMap)
      Picks the best (lowest) price for the price list type out of all the matches found.
    • noCurrency

      @Deprecated(since="Pricing Service 2.1.0", forRemoval=true) public boolean noCurrency(AtomicReference<javax.money.MonetaryAmount> refAmount)
      Deprecated, for removal: This API element is subject to removal in a future version.
      Unused
    • getBestPriceOverall

      @Nullable protected com.broadleafcommerce.pricing.client.domain.PriceDetail getBestPriceOverall(@Nullable Map<String,com.broadleafcommerce.pricing.client.domain.PriceDetail> prices, @Nullable Currency defaultCurrency)
      Retrieves all of the PriceableFieldTypes in ascending order by PriceableFieldType.order(). Then, returns a PriceDetail for the best price found for the type.

      Out of the box, if a price with currency matching the default is found, we want to prioritize that. Otherwise, the lowest price is chosen.

      If there are more than one price that are equal to the lowest price (i.e. standard and sale price are equally the lowest), then we want to prioritize whichever PriceDetail that is not a sale price.

      Parameters:
      prices - map of price type (e.g., standardPrice, salePrice, contractPrice) to its corresponding PriceDetail
      defaultCurrency - default currency in the current context
      Returns:
      PriceDetail for the best price found
    • getBackupPrice

      protected Optional<com.broadleafcommerce.pricing.client.domain.PriceDetail> getBackupPrice(com.broadleafcommerce.pricing.client.domain.PriceDetail currentBestPrice, PriceableTargetPriceState priceState)
      Gets the backup price for the current limited best price.

      This is for "flash sale" concept where a sale price has a limited quantity. To support cases where the PriceData.getAvailableQuantity() is not sufficient for the target quantity, a backup price is provided, which out of box is the second best price that does not have a limit.

      Parameters:
      currentBestPrice - the current best price
      priceState - the current price state
      Returns:
      the backup price for the current limited best price
    • isEqualPrice

      protected boolean isEqualPrice(com.broadleafcommerce.pricing.client.domain.PriceDetail priceDetail1, com.broadleafcommerce.pricing.client.domain.PriceDetail priceDetail2)
      Checks if the given PriceDetails have the same price.
      Parameters:
      priceDetail1 - the first PriceDetail to compare
      priceDetail2 - the second PriceDetail to compare
      Returns:
      true if both PriceDetails have the same price, otherwise false
    • isSalePrice

      protected boolean isSalePrice(com.broadleafcommerce.pricing.client.domain.PriceDetail priceDetail)
      Checks if the given PriceDetail is of type PriceableFieldType.SALE_PRICE.
      Parameters:
      priceDetail - the PriceDetail to check against
      Returns:
      true of the given PriceDetail is of type PriceableFieldType.SALE_PRICE, otherwise false
    • getBestPriceOverall

      @Deprecated protected com.broadleafcommerce.pricing.client.domain.PriceDetail getBestPriceOverall(Map<String,com.broadleafcommerce.pricing.client.domain.PriceDetail> prices)
      Deprecated.
      in favor of getBestPriceOverall(Map, Currency)

      Retrieves all of the PriceableFieldTypes in ascending order by PriceableFieldType.order(). Then, returns a PriceDetail for the best price found for the type.

      Out of the box, the lowest price is chosen.

    • addPriceInfoForTarget

      protected void addPriceInfoForTarget(List<com.broadleafcommerce.pricing.client.domain.PriceInfo> priceInfos, com.broadleafcommerce.pricing.client.domain.PriceableTarget priceableTarget, com.broadleafcommerce.pricing.client.domain.PriceDetail bestPriceDetail, PriceableTargetPriceState priceState, boolean skipDetails)
      Uses the best price detail found for the target and creates a PriceInfo for it. Then, adds PriceTypeDetails for each type of price found. Optionally, this also adds PriceDetails for all candidate prices found besides the best one, if skipDetails == false.
      Parameters:
      priceInfos - The current list of PriceInfos into which to add a new PriceInfo.
      priceableTarget - The PriceableTarget for which the new PriceInfo corresponds.
      bestPriceDetail - The PriceDetail of the best overall price from amongst all types of prices.
      priceState - The current PriceableTargetPriceState with fall the important pricing info discovered for the targets.
      skipDetails - Whether to not include PriceDetails in the PriceInfo
    • addPriceTypeDetail

      protected void addPriceTypeDetail(com.broadleafcommerce.pricing.client.domain.PriceInfo priceInfo, String type, com.broadleafcommerce.pricing.client.domain.PriceDetail detail)
    • addPriceDetail

      @Deprecated(forRemoval=true, since="1.7.14, 2.0.1") protected void addPriceDetail(com.broadleafcommerce.pricing.client.domain.PriceInfo priceInfo, PriceList priceList, javax.money.MonetaryAmount price, Map<String,List<PriceDataTier>> priceTiers)
      Deprecated, for removal: This API element is subject to removal in a future version.
    • addPriceDetail

      protected void addPriceDetail(com.broadleafcommerce.pricing.client.domain.PriceInfo priceInfo, PriceList priceList, PriceListPriceDetail listPriceDetail, Map<String,List<PriceDataTier>> priceTiers)
    • populatePriceDataTierRef

      protected com.broadleafcommerce.pricing.client.domain.PriceDataTierRef populatePriceDataTierRef(PriceDataTier priceDataTier)
    • getErrors

      protected org.springframework.validation.Errors getErrors(com.broadleafcommerce.pricing.client.domain.context.PriceInfoContext priceInfoContext)
      Parameters:
      priceInfoContext - The price info context to bind an errors object to.
      Returns:
      An errors object bound to priceInfoContext
    • getPriceDataService

      protected PriceDataService<PriceData> getPriceDataService()
    • getRuleEvaluationService

      protected com.broadleafcommerce.rulesengine.expression.service.RuleEvaluationService getRuleEvaluationService()
    • getPriceableFields

      protected PriceableFieldProperties getPriceableFields()
    • getPriceListService

      protected PriceListService<PriceList> getPriceListService()
    • getValidator

      protected com.broadleafcommerce.data.tracking.core.mapping.validation.EntityValidator getValidator()
    • getTypeFactory

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

      @Autowired(required=false) public void setPriceDetailComparator(PriceDetailComparator priceDetailComparator)